summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorjsmall-nvidia <jsmall@nvidia.com>2018-04-17 16:59:03 -0400
committerGitHub <noreply@github.com>2018-04-17 16:59:03 -0400
commit00389a127af8db18a3ec8fe7ad2dd114a65ac024 (patch)
tree7fa57f2f30a399f03a7967a8534eb212744de5cc /tools
parent15bff9162530113b426664eb0c1deb7ea9e3a90d (diff)
Feature/renderer binding (#489)
* Dx12 rendering works in test framework. * Turn on dx12 render tests. * First pass at Resource and TextureResource/BufferResource types. * Fix bug in Dx11 impl for BufferResource. * Dx12 supports TextureResource and binds using TextureResource type, and all tests pass. * Added TextureBuffer::Size type to make handling mips a little simpler. * Small improvements to Dx12 constant buffer binding Removed k prefix on an enum * First pass impl of dx11 createTextureResource Added setDefaults to TextureResource::Desc and BufferResource::Desc to simplify setup accessFlags -> cpuAccessFlags desc -> srcDesc * Split out generateTextureResource - can produce the texture using createTextureResource on the Renderer. * Added support for read mapping to Dx11 accessFlags -> cpuAccessFlags First pass at using TextureResource/BufferResource on Dx11 Some tests fail with this checkin * TextureResource working on all tests on dx11. * Construct ResourceBuffers on Dx11 and Dx12 using utility function createInputBufferResource. * First pass at OpenGl TextureResource * Small fixes to dx12 and dx11 setup. Gl working working using BufferResource and TextureResource * Tidy up around the compareSampler - looks like the previous test was incorrect. * Small documentation /naming improvements. * Fix some more small documentation issues.
Diffstat (limited to 'tools')
-rw-r--r--tools/render-test/d3d-util.cpp11
-rw-r--r--tools/render-test/main.cpp26
-rw-r--r--tools/render-test/render-d3d11.cpp536
-rw-r--r--tools/render-test/render-d3d12.cpp902
-rw-r--r--tools/render-test/render-gl.cpp554
-rw-r--r--tools/render-test/render-test.vcxproj1
-rw-r--r--tools/render-test/render-test.vcxproj.filters3
-rw-r--r--tools/render-test/render-vk.cpp141
-rw-r--r--tools/render-test/render.cpp203
-rw-r--r--tools/render-test/render.h267
-rw-r--r--tools/render-test/slang-support.cpp120
-rw-r--r--tools/render-test/slang-support.h8
12 files changed, 1931 insertions, 841 deletions
diff --git a/tools/render-test/d3d-util.cpp b/tools/render-test/d3d-util.cpp
index 09e0891f9..70ccadddb 100644
--- a/tools/render-test/d3d-util.cpp
+++ b/tools/render-test/d3d-util.cpp
@@ -26,12 +26,11 @@ using namespace Slang;
{
switch (format)
{
- case Format::RGB_Float32:
- return DXGI_FORMAT_R32G32B32_FLOAT;
- case Format::RG_Float32:
- return DXGI_FORMAT_R32G32_FLOAT;
- default:
- return DXGI_FORMAT_UNKNOWN;
+ case Format::RGB_Float32: return DXGI_FORMAT_R32G32B32_FLOAT;
+ case Format::RG_Float32: return DXGI_FORMAT_R32G32_FLOAT;
+ case Format::R_Float32: return DXGI_FORMAT_R32_FLOAT;
+ case Format::RGBA_Unorm_UInt8: return DXGI_FORMAT_R8G8B8A8_UNORM;
+ default: return DXGI_FORMAT_UNKNOWN;
}
}
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index 12160ae78..acc7ffb78 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -73,11 +73,11 @@ class RenderTestApp
RefPtr<Renderer> m_renderer;
- RefPtr<Buffer> m_constantBuffer;
- RefPtr<InputLayout> m_inputLayout;
- RefPtr<Buffer> m_vertexBuffer;
- RefPtr<ShaderProgram> m_shaderProgram;
- RefPtr<BindingState> m_bindingState;
+ RefPtr<BufferResource> m_constantBuffer;
+ RefPtr<InputLayout> m_inputLayout;
+ RefPtr<BufferResource> m_vertexBuffer;
+ RefPtr<ShaderProgram> m_shaderProgram;
+ RefPtr<BindingState> m_bindingState;
ShaderInputLayout m_shaderInputLayout;
};
@@ -106,11 +106,11 @@ SlangResult RenderTestApp::initialize(Renderer* renderer, ShaderCompiler* shader
// TODO(tfoley): use each API's reflection interface to query the constant-buffer size needed
m_constantBufferSize = 16 * sizeof(float);
- BufferDesc constantBufferDesc;
- constantBufferDesc.size = m_constantBufferSize;
- constantBufferDesc.flavor = BufferFlavor::Constant;
+ BufferResource::Desc constantBufferDesc;
+ constantBufferDesc.init(m_constantBufferSize);
+ constantBufferDesc.cpuAccessFlags = Resource::AccessFlag::Write;
- m_constantBuffer = renderer->createBuffer(constantBufferDesc);
+ m_constantBuffer = renderer->createBufferResource(Resource::Usage::ConstantBuffer, constantBufferDesc);
if(!m_constantBuffer)
return SLANG_FAIL;
@@ -126,12 +126,10 @@ SlangResult RenderTestApp::initialize(Renderer* renderer, ShaderCompiler* shader
if(!m_inputLayout)
return SLANG_FAIL;
- BufferDesc vertexBufferDesc;
- vertexBufferDesc.size = kVertexCount * sizeof(Vertex);
- vertexBufferDesc.flavor = BufferFlavor::Vertex;
- vertexBufferDesc.initData = &kVertexData[0];
+ BufferResource::Desc vertexBufferDesc;
+ vertexBufferDesc.init(kVertexCount * sizeof(Vertex));
- m_vertexBuffer = renderer->createBuffer(vertexBufferDesc);
+ m_vertexBuffer = renderer->createBufferResource(Resource::Usage::VertexBuffer, vertexBufferDesc, kVertexData);
if(!m_vertexBuffer)
return SLANG_FAIL;
diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp
index e65b12b2c..18e41db7e 100644
--- a/tools/render-test/render-d3d11.cpp
+++ b/tools/render-test/render-d3d11.cpp
@@ -9,6 +9,8 @@
#include <slang.h>
+#include "slang-support.h"
+
#include "../../source/core/slang-com-ptr.h"
#ifdef _MSC_VER
@@ -51,20 +53,21 @@ public:
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
+ virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
+ virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
virtual SlangResult captureScreenShot(char const* outputPath) override;
virtual void serializeOutput(BindingState* state, const char* fileName) override;
- virtual Buffer* createBuffer(const BufferDesc& desc) override;
virtual InputLayout* createInputLayout( const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState * createBindingState(const ShaderInputLayout& layout) override;
virtual ShaderCompiler* getShaderCompiler() override;
- virtual void* map(Buffer* buffer, MapFlavor flavor) override;
- virtual void unmap(Buffer* buffer) override;
+ virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
+ virtual void unmap(BufferResource* buffer) override;
virtual void setInputLayout(InputLayout* inputLayout) override;
virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
virtual void setBindingState(BindingState * state);
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets) override;
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
virtual void setShaderProgram(ShaderProgram* inProgram) override;
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets) override;
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets) override;
virtual void draw(UInt vertexCount, UInt startVertex) override;
virtual void dispatchCompute(int x, int y, int z) override;
virtual void submitGpuWork() override {}
@@ -79,13 +82,15 @@ public:
{
ShaderInputType type;
InputBufferType bufferType; // Only valid if `type` is `Buffer`
+
ComPtr<ID3D11ShaderResourceView> srv;
ComPtr<ID3D11UnorderedAccessView> uav;
- ComPtr<ID3D11Buffer> buffer;
ComPtr<ID3D11SamplerState> samplerState;
+
+ RefPtr<Resource> resource; /// Can hold texture of buffer
+
int binding = 0;
bool isOutput = false;
- int bufferLength = 0;
};
class BindingStateImpl: public BindingState
@@ -102,10 +107,34 @@ public:
ComPtr<ID3D11ComputeShader> m_computeShader;
};
- class BufferImpl: public Buffer
+ class BufferResourceImpl: public BufferResource
{
public:
+ typedef BufferResource Parent;
+
+ BufferResourceImpl(const Desc& desc, Usage initialUsage):
+ Parent(desc),
+ m_initialUsage(initialUsage)
+ {
+ }
+
+ MapFlavor m_mapFlavor;
+ Usage m_initialUsage;
ComPtr<ID3D11Buffer> m_buffer;
+ ComPtr<ID3D11Buffer> m_staging;
+ };
+ class TextureResourceImpl : public TextureResource
+ {
+ public:
+ typedef TextureResource Parent;
+
+ TextureResourceImpl(Type type, const Desc& desc, Usage initialUsage) :
+ Parent(type, desc),
+ m_initialUsage(initialUsage)
+ {
+ }
+ Usage m_initialUsage;
+ ComPtr<ID3D11Resource> m_resource;
};
class InputLayoutImpl: public InputLayout
@@ -117,13 +146,13 @@ public:
/// Capture a texture to a file
static HRESULT captureTextureToFile(ID3D11Device* device, ID3D11DeviceContext* context, ID3D11Texture2D* texture, char const* outputPath);
- void* map(ID3D11Buffer* buffer, MapFlavor flavor);
- void unmap(ID3D11Buffer* buffer);
+ //void* map(ID3D11Buffer* buffer, MapFlavor flavor);
+ //void unmap(ID3D11Buffer* buffer);
- Result createInputBuffer(const InputBufferDesc& bufferDesc, const List<unsigned int>& bufferData,
- ComPtr<ID3D11Buffer>& bufferOut, ComPtr<ID3D11UnorderedAccessView>& viewOut, ComPtr<ID3D11ShaderResourceView>& srvOut);
+ Result createInputBuffer(const InputBufferDesc& bufferDesc, bool isOutput, const List<unsigned int>& bufferData,
+ RefPtr<Resource>& resourceOut, ComPtr<ID3D11UnorderedAccessView>& viewOut, ComPtr<ID3D11ShaderResourceView>& srvOut);
- Result createInputTexture(const InputTextureDesc& inputDesc, ComPtr<ID3D11ShaderResourceView>& viewOut);
+ Result createInputTexture(const InputTextureDesc& inputDesc, RefPtr<Resource>& resourceOut, ComPtr<ID3D11ShaderResourceView>& viewOut);
Result createInputSampler(const InputSamplerDesc& inputDesc, ComPtr<ID3D11SamplerState>& stateOut);
@@ -387,37 +416,242 @@ ShaderCompiler* D3D11Renderer::getShaderCompiler()
return this;
}
-Buffer* D3D11Renderer::createBuffer(const BufferDesc& desc)
+static D3D11_BIND_FLAG _calcResourceFlag(Resource::BindFlag::Enum bindFlag)
{
- D3D11_BUFFER_DESC bufferDesc = { 0 };
- bufferDesc.ByteWidth = (UINT)D3DUtil::calcAligned(desc.size, 256);
+ typedef Resource::BindFlag BindFlag;
+ switch (bindFlag)
+ {
+ case BindFlag::VertexBuffer: return D3D11_BIND_VERTEX_BUFFER;
+ case BindFlag::IndexBuffer: return D3D11_BIND_INDEX_BUFFER;
+ case BindFlag::ConstantBuffer: return D3D11_BIND_CONSTANT_BUFFER;
+ case BindFlag::StreamOutput: return D3D11_BIND_STREAM_OUTPUT;
+ case BindFlag::RenderTarget: return D3D11_BIND_RENDER_TARGET;
+ case BindFlag::DepthStencil: return D3D11_BIND_DEPTH_STENCIL;
+ case BindFlag::UnorderedAccess: return D3D11_BIND_UNORDERED_ACCESS;
+ case BindFlag::PixelShaderResource: return D3D11_BIND_SHADER_RESOURCE;
+ case BindFlag::NonPixelShaderResource: return D3D11_BIND_SHADER_RESOURCE;
+ default: return D3D11_BIND_FLAG(0);
+ }
+}
+
+static int _calcResourceBindFlags(int bindFlags)
+{
+ int dstFlags = 0;
+ while (bindFlags)
+ {
+ int lsb = bindFlags & -bindFlags;
+
+ dstFlags |= _calcResourceFlag(Resource::BindFlag::Enum(lsb));
+ bindFlags &= ~lsb;
+ }
+ return dstFlags;
+}
- switch (desc.flavor)
+static int _calcResourceAccessFlags(int accessFlags)
+{
+ switch (accessFlags)
{
- case BufferFlavor::Constant:
- bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ case 0: return 0;
+ case Resource::AccessFlag::Read: return D3D11_CPU_ACCESS_READ;
+ case Resource::AccessFlag::Write: return D3D11_CPU_ACCESS_WRITE;
+ case Resource::AccessFlag::Read |
+ Resource::AccessFlag::Write: return D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ default: assert(!"Invalid flags"); return 0;
+ }
+}
+
+TextureResource* D3D11Renderer::createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
+{
+ TextureResource::Desc srcDesc(descIn);
+ srcDesc.setDefaults(type, initialUsage);
+
+ const int effectiveArraySize = srcDesc.calcEffectiveArraySize(type);
+
+ assert(initData);
+ assert(initData->numSubResources == srcDesc.numMipLevels * effectiveArraySize * srcDesc.size.depth);
+
+ const DXGI_FORMAT format = D3DUtil::getMapFormat(srcDesc.format);
+ if (format == DXGI_FORMAT_UNKNOWN)
+ {
+ return nullptr;
+ }
+
+ const int bindFlags = _calcResourceBindFlags(srcDesc.bindFlags);
+
+ // Set up the initialize data
+ List<D3D11_SUBRESOURCE_DATA> subRes;
+ subRes.SetSize(srcDesc.numMipLevels * effectiveArraySize);
+ {
+ int subResourceIndex = 0;
+ for (int i = 0; i < effectiveArraySize; i++)
+ {
+ for (int j = 0; j < srcDesc.numMipLevels; j++)
+ {
+ const int mipHeight = TextureResource::calcMipSize(srcDesc.size.height, j);
+
+ D3D11_SUBRESOURCE_DATA& data = subRes[subResourceIndex];
+
+ data.pSysMem = initData->subResources[subResourceIndex];
+
+ data.SysMemPitch = UINT(initData->mipRowStrides[j]);
+ data.SysMemSlicePitch = UINT(initData->mipRowStrides[j] * mipHeight);
+
+ subResourceIndex++;
+ }
+ }
+ }
+
+ const int accessFlags = _calcResourceAccessFlags(srcDesc.cpuAccessFlags);
+
+ RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(type, srcDesc, initialUsage));
+
+ switch (type)
+ {
+ case Resource::Type::Texture1D:
+ {
+ D3D11_TEXTURE1D_DESC desc = { 0 };
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = accessFlags;
+ desc.Format = format;
+ desc.MiscFlags = 0;
+ desc.MipLevels = srcDesc.numMipLevels;
+ desc.ArraySize = effectiveArraySize;
+ desc.Width = srcDesc.size.width;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+
+ ComPtr<ID3D11Texture1D> texture1D;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture1D(&desc, subRes.Buffer(), texture1D.writeRef()));
+
+ texture->m_resource = texture1D;
break;
+ }
+ case Resource::Type::TextureCube:
+ case Resource::Type::Texture2D:
+ {
+ D3D11_TEXTURE2D_DESC desc = { 0 };
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = accessFlags;
+ desc.Format = format;
+ desc.MiscFlags = 0;
+ desc.MipLevels = srcDesc.numMipLevels;
+ desc.ArraySize = effectiveArraySize;
+
+ desc.Width = srcDesc.size.width;
+ desc.Height = srcDesc.size.height;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.SampleDesc.Count = srcDesc.sampleDesc.numSamples;
+ desc.SampleDesc.Quality = srcDesc.sampleDesc.quality;
+
+ if (type == Resource::Type::TextureCube)
+ {
+ desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
+ }
+
+ ComPtr<ID3D11Texture2D> texture2D;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture2D(&desc, subRes.Buffer(), texture2D.writeRef()));
+
+ texture->m_resource = texture2D;
+ break;
+ }
+ case Resource::Type::Texture3D:
+ {
+ D3D11_TEXTURE3D_DESC desc = { 0 };
+ desc.BindFlags = bindFlags;
+ desc.CPUAccessFlags = accessFlags;
+ desc.Format = format;
+ desc.MiscFlags = 0;
+ desc.MipLevels = srcDesc.numMipLevels;
+ desc.Width = srcDesc.size.width;
+ desc.Height = srcDesc.size.height;
+ desc.Depth = srcDesc.size.depth;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+
+ ComPtr<ID3D11Texture3D> texture3D;
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateTexture3D(&desc, subRes.Buffer(), texture3D.writeRef()));
+
+ texture->m_resource = texture3D;
+ break;
+ }
+ default: return nullptr;
+ }
+
+ return texture.detach();
+}
+
+BufferResource* D3D11Renderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
+{
+ BufferResource::Desc srcDesc(descIn);
+ srcDesc.setDefaults(initialUsage);
+
+ // Make aligned to 256 bytes... not sure why, but if you remove this the tests do fail.
+ const size_t alignedSizeInBytes = D3DUtil::calcAligned(srcDesc.sizeInBytes, 256);
+
+ // Hack to make the initialization never read from out of bounds memory, by copying into a buffer
+ List<uint8_t> initDataBuffer;
+ if (initData && alignedSizeInBytes > srcDesc.sizeInBytes)
+ {
+ initDataBuffer.SetSize(alignedSizeInBytes);
+ ::memcpy(initDataBuffer.Buffer(), initData, srcDesc.sizeInBytes);
+ initData = initDataBuffer.Buffer();
+ }
+
+ D3D11_BUFFER_DESC bufferDesc = { 0 };
+ bufferDesc.ByteWidth = UINT(alignedSizeInBytes);
+ bufferDesc.BindFlags = _calcResourceBindFlags(srcDesc.bindFlags);
+ // For read we'll need to do some staging
+ bufferDesc.CPUAccessFlags = _calcResourceAccessFlags(descIn.cpuAccessFlags & Resource::AccessFlag::Write);
+ bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+
+ // If written by CPU, make it dynamic
+ if (descIn.cpuAccessFlags & Resource::AccessFlag::Write)
+ {
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ }
- case BufferFlavor::Vertex:
+ switch (initialUsage)
+ {
+ case Resource::Usage::ConstantBuffer:
+ {
+ // We'll just assume ConstantBuffers are dynamic for now
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
- bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
- bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
break;
- default:
- return nullptr;
+ }
+ default: break;
+ }
+
+ if (bufferDesc.BindFlags & (D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE))
+ {
+ //desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
+ if (srcDesc.elementSize != 0)
+ {
+ bufferDesc.StructureByteStride = srcDesc.elementSize;
+ bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
+ }
+ else
+ {
+ bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
+ }
}
D3D11_SUBRESOURCE_DATA subResourceData = { 0 };
- subResourceData.pSysMem = desc.initData;
+ subResourceData.pSysMem = initData;
- ComPtr<ID3D11Buffer> buffer;
- SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufferDesc, desc.initData ? &subResourceData : nullptr, buffer.writeRef()));
+ RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(srcDesc, initialUsage));
+
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufferDesc, initData ? &subResourceData : nullptr, buffer->m_buffer.writeRef()));
- BufferImpl* rs = new BufferImpl;
- rs->m_buffer = buffer;
- return rs;
+ if (srcDesc.cpuAccessFlags & Resource::AccessFlag::Read)
+ {
+ D3D11_BUFFER_DESC bufDesc = {};
+ bufDesc.BindFlags = 0;
+ bufDesc.ByteWidth = (UINT)alignedSizeInBytes;
+ bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ bufDesc.Usage = D3D11_USAGE_STAGING;
+
+ SLANG_RETURN_NULL_ON_FAIL(m_device->CreateBuffer(&bufDesc, nullptr, buffer->m_staging.writeRef()));
+ }
+
+ return buffer.detach();
}
InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputElementsIn, UInt inputElementCount)
@@ -453,6 +687,9 @@ InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputEleme
case Format::RG_Float32:
typeName = "float2";
break;
+ case Format::R_Float32:
+ typeName = "float";
+ break;
default:
return nullptr;
}
@@ -479,10 +716,14 @@ InputLayout* D3D11Renderer::createInputLayout(const InputElementDesc* inputEleme
return impl;
}
-void* D3D11Renderer::map(ID3D11Buffer* buffer, MapFlavor flavorIn)
+void* D3D11Renderer::map(BufferResource* bufferIn, MapFlavor flavor)
{
+ BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(bufferIn);
+
D3D11_MAP mapType;
- switch (flavorIn)
+ ID3D11Buffer* buffer = bufferResource->m_buffer;
+
+ switch (flavor)
{
case MapFlavor::WriteDiscard:
mapType = D3D11_MAP_WRITE_DISCARD;
@@ -492,6 +733,16 @@ void* D3D11Renderer::map(ID3D11Buffer* buffer, MapFlavor flavorIn)
break;
case MapFlavor::HostRead:
mapType = D3D11_MAP_READ;
+
+ buffer = bufferResource->m_staging;
+ if (!buffer)
+ {
+ return nullptr;
+ }
+
+ // Okay copy the data over
+ m_immediateContext->CopyResource(buffer, bufferResource->m_buffer);
+
break;
default:
return nullptr;
@@ -502,23 +753,17 @@ void* D3D11Renderer::map(ID3D11Buffer* buffer, MapFlavor flavorIn)
// per-frame (we always use an identity projection).
D3D11_MAPPED_SUBRESOURCE mappedSub;
SLANG_RETURN_NULL_ON_FAIL(m_immediateContext->Map(buffer, 0, mapType, 0, &mappedSub));
-
- return mappedSub.pData;
-}
-void* D3D11Renderer::map(Buffer* buffer, MapFlavor flavor)
-{
- return map(((BufferImpl*)buffer)->m_buffer, flavor);
-}
+ bufferResource->m_mapFlavor = flavor;
-void D3D11Renderer::unmap(ID3D11Buffer* buffer)
-{
- m_immediateContext->Unmap(buffer, 0);
+ return mappedSub.pData;
}
-void D3D11Renderer::unmap(Buffer* bufferIn)
+void D3D11Renderer::unmap(BufferResource* bufferIn)
{
- unmap(((BufferImpl*)bufferIn)->m_buffer);
+ BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(bufferIn);
+ ID3D11Buffer* buffer = (bufferResource->m_mapFlavor == MapFlavor::HostRead) ? bufferResource->m_staging : bufferResource->m_buffer;
+ m_immediateContext->Unmap(buffer, 0);
}
void D3D11Renderer::setInputLayout(InputLayout* inputLayoutIn)
@@ -532,7 +777,7 @@ void D3D11Renderer::setPrimitiveTopology(PrimitiveTopology topology)
m_immediateContext->IASetPrimitiveTopology(D3DUtil::getPrimitiveTopology(topology));
}
-void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffersIn, const UInt* stridesIn, const UInt* offsetsIn)
+void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffersIn, const UInt* stridesIn, const UInt* offsetsIn)
{
static const int kMaxVertexBuffers = 16;
assert(slotCount <= kMaxVertexBuffers);
@@ -541,7 +786,7 @@ void D3D11Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*cons
UINT vertexOffsets[kMaxVertexBuffers];
ID3D11Buffer* dxBuffers[kMaxVertexBuffers];
- auto buffers = (BufferImpl*const*)buffersIn;
+ auto buffers = (BufferResourceImpl*const*)buffersIn;
for (UInt ii = 0; ii < slotCount; ++ii)
{
@@ -561,14 +806,14 @@ void D3D11Renderer::setShaderProgram(ShaderProgram* programIn)
m_immediateContext->PSSetShader(program->m_pixelShader, nullptr, 0);
}
-void D3D11Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffersIn, const UInt* offsetsIn)
+void D3D11Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffersIn, const UInt* offsetsIn)
{
static const int kMaxConstantBuffers = 16;
assert(slotCount <= kMaxConstantBuffers);
// TODO: actually use those offsets
- auto buffers = (BufferImpl*const*)buffersIn;
+ auto buffers = (BufferResourceImpl*const*)buffersIn;
// Copy out the actual dx buffers
ID3D11Buffer* dxBuffers[kMaxConstantBuffers];
@@ -626,38 +871,16 @@ void D3D11Renderer::dispatchCompute(int x, int y, int z)
m_immediateContext->Dispatch(x, y, z);
}
-Result D3D11Renderer::createInputBuffer(const InputBufferDesc& bufferDesc, const List<unsigned int>& bufferData,
- ComPtr<ID3D11Buffer>& bufferOut, ComPtr<ID3D11UnorderedAccessView>& viewOut, ComPtr<ID3D11ShaderResourceView>& srvOut)
+Result D3D11Renderer::createInputBuffer(const InputBufferDesc& bufferDesc, bool isOutput, const List<unsigned int>& bufferData,
+ RefPtr<Resource>& resourceOut, ComPtr<ID3D11UnorderedAccessView>& viewOut, ComPtr<ID3D11ShaderResourceView>& srvOut)
{
- D3D11_BUFFER_DESC desc = { 0 };
- List<unsigned int> newBuffer;
- desc.ByteWidth = (UINT)D3DUtil::calcAligned((bufferData.Count() * sizeof(unsigned int)), 256);
- newBuffer.SetSize(desc.ByteWidth / sizeof(unsigned int));
- for (UInt i = 0; i < bufferData.Count(); i++)
- newBuffer[i] = bufferData[i];
- if (bufferDesc.type == InputBufferType::ConstantBuffer)
- {
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
- }
- else
- {
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
- if (bufferDesc.stride != 0)
- {
- desc.StructureByteStride = bufferDesc.stride;
- desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
- }
- else
- {
- desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- }
- }
- D3D11_SUBRESOURCE_DATA data = { 0 };
- data.pSysMem = newBuffer.Buffer();
- SLANG_RETURN_ON_FAIL(m_device->CreateBuffer(&desc, &data, bufferOut.writeRef()));
- int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
+ const size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
+ RefPtr<BufferResource> bufferResource;
+ SLANG_RETURN_ON_FAIL(createInputBufferResource(bufferDesc, isOutput, bufferSize, bufferData.Buffer(), this, bufferResource));
+
+ BufferResourceImpl* bufferImpl = static_cast<BufferResourceImpl*>(bufferResource.Ptr());
+
+ const int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
if (bufferDesc.type == InputBufferType::StorageBuffer)
{
D3D11_UNORDERED_ACCESS_VIEW_DESC viewDesc;
@@ -677,7 +900,7 @@ Result D3D11Renderer::createInputBuffer(const InputBufferDesc& bufferDesc, const
viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
}
- SLANG_RETURN_ON_FAIL(m_device->CreateUnorderedAccessView(bufferOut, &viewDesc, viewOut.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_device->CreateUnorderedAccessView(bufferImpl->m_buffer, &viewDesc, viewOut.writeRef()));
}
if (bufferDesc.type != InputBufferType::ConstantBuffer)
{
@@ -695,78 +918,55 @@ Result D3D11Renderer::createInputBuffer(const InputBufferDesc& bufferDesc, const
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
}
- SLANG_RETURN_ON_FAIL(m_device->CreateShaderResourceView(bufferOut, &srvDesc, srvOut.writeRef()));
+ SLANG_RETURN_ON_FAIL(m_device->CreateShaderResourceView(bufferImpl->m_buffer, &srvDesc, srvOut.writeRef()));
}
+ resourceOut = bufferResource;
+
return SLANG_OK;
}
-Result D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ComPtr<ID3D11ShaderResourceView>& viewOut)
+Result D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, RefPtr<Resource>& resourceOut, ComPtr<ID3D11ShaderResourceView>& viewOut)
{
ComPtr<ID3D11ShaderResourceView> view;
- TextureData texData;
- generateTextureData(texData, inputDesc);
- List<D3D11_SUBRESOURCE_DATA> subRes;
- for (int i = 0; i < texData.arraySize; i++)
- {
- int slice = 0;
- for (int j = 0; j < texData.mipLevels; j++)
- {
- int size = texData.textureSize >> j;
- D3D11_SUBRESOURCE_DATA res;
- res.pSysMem = texData.dataBuffer[slice].Buffer();
- res.SysMemPitch = sizeof(unsigned int) * size;
- res.SysMemSlicePitch = sizeof(unsigned int) * size * size;
- subRes.Add(res);
- slice++;
- }
- }
- if (inputDesc.dimension == 1)
- {
- D3D11_TEXTURE1D_DESC desc = { 0 };
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.MiscFlags = 0;
- desc.MipLevels = texData.mipLevels;
- desc.ArraySize = texData.arraySize;
- desc.Width = texData.textureSize;
- desc.Usage = D3D11_USAGE_DEFAULT;
+ int bindFlags = 0;
+
+ RefPtr<TextureResource> texture;
+ SLANG_RETURN_ON_FAIL(generateTextureResource(inputDesc, bindFlags, this, texture));
- ComPtr<ID3D11Texture1D> texture;
- SLANG_RETURN_ON_FAIL(m_device->CreateTexture1D(&desc, subRes.Buffer(), texture.writeRef()));
+ //DXGI_FORMAT format = textureImpl->m_resource->GetD
+ const TextureResource::Desc& textureDesc = texture->getDesc();
+ DXGI_FORMAT format = D3DUtil::getMapFormat(textureDesc.format);
+
+ TextureResourceImpl* textureImpl = static_cast<TextureResourceImpl*>(texture.Ptr());
+
+ if (inputDesc.dimension == 1)
+ {
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
if (inputDesc.arrayLength != 0)
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY;
- viewDesc.Texture1D.MipLevels = texData.mipLevels;
+ viewDesc.Texture1D.MipLevels = textureDesc.numMipLevels;
viewDesc.Texture1D.MostDetailedMip = 0;
- viewDesc.Texture1DArray.ArraySize = texData.arraySize;
+ viewDesc.Texture1DArray.ArraySize = textureDesc.arraySize;
viewDesc.Texture1DArray.FirstArraySlice = 0;
- viewDesc.Texture1DArray.MipLevels = texData.mipLevels;
+ viewDesc.Texture1DArray.MipLevels = textureDesc.numMipLevels;
viewDesc.Texture1DArray.MostDetailedMip = 0;
- viewDesc.Format = desc.Format;
- m_device->CreateShaderResourceView(texture, &viewDesc, view.writeRef());
+ viewDesc.Format = format;
+ m_device->CreateShaderResourceView(textureImpl->m_resource, &viewDesc, view.writeRef());
}
else if (inputDesc.dimension == 2)
{
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- D3D11_TEXTURE2D_DESC desc = { 0 };
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.MiscFlags = 0;
- desc.MipLevels = texData.mipLevels;
- desc.ArraySize = texData.arraySize;
+
if (inputDesc.isCube)
{
- desc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
- viewDesc.TextureCube.MipLevels = texData.mipLevels;
+ viewDesc.TextureCube.MipLevels = textureDesc.numMipLevels;
viewDesc.TextureCube.MostDetailedMip = 0;
- viewDesc.TextureCubeArray.MipLevels = texData.mipLevels;
+ viewDesc.TextureCubeArray.MipLevels = textureDesc.numMipLevels;
viewDesc.TextureCubeArray.MostDetailedMip = 0;
viewDesc.TextureCubeArray.First2DArrayFace = 0;
viewDesc.TextureCubeArray.NumCubes = inputDesc.arrayLength;
@@ -774,49 +974,31 @@ Result D3D11Renderer::createInputTexture(const InputTextureDesc& inputDesc, ComP
else
{
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- viewDesc.Texture2D.MipLevels = texData.mipLevels;
+ viewDesc.Texture2D.MipLevels = textureDesc.numMipLevels;
viewDesc.Texture2D.MostDetailedMip = 0;
- viewDesc.Texture2DArray.ArraySize = texData.arraySize;
+ viewDesc.Texture2DArray.ArraySize = textureDesc.arraySize;
viewDesc.Texture2DArray.FirstArraySlice = 0;
- viewDesc.Texture2DArray.MipLevels = texData.mipLevels;
+ viewDesc.Texture2DArray.MipLevels = textureDesc.numMipLevels;
viewDesc.Texture2DArray.MostDetailedMip = 0;
}
if (inputDesc.arrayLength != 0)
viewDesc.ViewDimension = (D3D11_SRV_DIMENSION)(int)(viewDesc.ViewDimension + 1);
- desc.Width = texData.textureSize;
- desc.Height = texData.textureSize;
- desc.Usage = D3D11_USAGE_DEFAULT;
- desc.SampleDesc.Count = 1;
- desc.SampleDesc.Quality = 0;
- viewDesc.Format = desc.Format;
- ComPtr<ID3D11Texture2D> texture;
- SLANG_RETURN_ON_FAIL(m_device->CreateTexture2D(&desc, subRes.Buffer(), texture.writeRef()));
- SLANG_RETURN_ON_FAIL(m_device->CreateShaderResourceView(texture, &viewDesc, view.writeRef()));
+ viewDesc.Format = format;
+
+ SLANG_RETURN_ON_FAIL(m_device->CreateShaderResourceView(textureImpl->m_resource, &viewDesc, view.writeRef()));
}
else if (inputDesc.dimension == 3)
{
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
- D3D11_TEXTURE3D_DESC desc = { 0 };
- desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
- desc.CPUAccessFlags = 0;
- desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- desc.MiscFlags = 0;
- desc.MipLevels = 1;
viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
- desc.Width = texData.textureSize;
- desc.Height = texData.textureSize;
- desc.Depth = texData.textureSize;
- desc.Usage = D3D11_USAGE_DEFAULT;
-
- ComPtr<ID3D11Texture3D> texture;
- m_device->CreateTexture3D(&desc, subRes.Buffer(), texture.writeRef());
- viewDesc.Texture3D.MipLevels = 1;
+ viewDesc.Texture3D.MipLevels = 1;
viewDesc.Texture3D.MostDetailedMip = 0;
- viewDesc.Format = desc.Format;
- m_device->CreateShaderResourceView(texture, &viewDesc, view.writeRef());
+ viewDesc.Format = format;
+ m_device->CreateShaderResourceView(textureImpl->m_resource, &viewDesc, view.writeRef());
}
+ resourceOut = texture;
viewOut.swap(view);
return SLANG_OK;
}
@@ -866,15 +1048,13 @@ BindingState* D3D11Renderer::createBindingState(const ShaderInputLayout& layout)
{
case ShaderInputType::Buffer:
{
- SLANG_RETURN_NULL_ON_FAIL(createInputBuffer(srcBinding.bufferDesc, srcBinding.bufferData, dstBinding.buffer, dstBinding.uav, dstBinding.srv));
-
- dstBinding.bufferLength = (int)(srcBinding.bufferData.Count() * sizeof(unsigned int));
+ SLANG_RETURN_NULL_ON_FAIL(createInputBuffer(srcBinding.bufferDesc, srcBinding.isOutput, srcBinding.bufferData, dstBinding.resource, dstBinding.uav, dstBinding.srv));
dstBinding.bufferType = srcBinding.bufferDesc.type;
break;
}
case ShaderInputType::Texture:
{
- SLANG_RETURN_NULL_ON_FAIL(createInputTexture(srcBinding.textureDesc, dstBinding.srv));
+ SLANG_RETURN_NULL_ON_FAIL(createInputTexture(srcBinding.textureDesc, dstBinding.resource, dstBinding.srv));
break;
}
case ShaderInputType::Sampler:
@@ -902,14 +1082,18 @@ void D3D11Renderer::applyBindingState(bool isCompute)
{
if (binding.type == ShaderInputType::Buffer)
{
+
if (binding.bufferType == InputBufferType::ConstantBuffer)
{
+ BufferResourceImpl* bufferResource = static_cast<BufferResourceImpl*>(binding.resource.Ptr());
+ ID3D11Buffer* buffer = bufferResource->m_buffer;
+
if (isCompute)
- context->CSSetConstantBuffers(binding.binding, 1, binding.buffer.readRef());
+ context->CSSetConstantBuffers(binding.binding, 1, &buffer);
else
{
- context->VSSetConstantBuffers(binding.binding, 1, binding.buffer.readRef());
- context->PSSetConstantBuffers(binding.binding, 1, binding.buffer.readRef());
+ context->VSSetConstantBuffers(binding.binding, 1, &buffer);
+ context->PSSetConstantBuffers(binding.binding, 1, &buffer);
}
}
else if (binding.uav)
@@ -981,25 +1165,17 @@ void D3D11Renderer::serializeOutput(BindingState* stateIn, const char* fileName)
{
if (binding.isOutput)
{
- if (binding.buffer)
+ if (binding.resource && binding.resource->isBuffer())
{
- // create staging buffer
- ComPtr<ID3D11Buffer> stageBuf;
-
- D3D11_BUFFER_DESC bufDesc;
- memset(&bufDesc, 0, sizeof(bufDesc));
- bufDesc.BindFlags = 0;
- bufDesc.ByteWidth = (UINT)D3DUtil::calcAligned(binding.bufferLength, 256);
- bufDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
- bufDesc.Usage = D3D11_USAGE_STAGING;
+ BufferResource* bufferResource = static_cast<BufferResource*>(binding.resource.Ptr());
+ const size_t bufferSize = bufferResource->getDesc().sizeInBytes;
- SLANG_RETURN_VOID_ON_FAIL(m_device->CreateBuffer(&bufDesc, nullptr, stageBuf.writeRef()));
- m_immediateContext->CopyResource(stageBuf, binding.buffer);
-
- auto ptr = (unsigned int *)map(stageBuf, MapFlavor::HostRead);
- for (auto i = 0u; i < binding.bufferLength / sizeof(unsigned int); i++)
+ unsigned int* ptr = (unsigned int*)map(bufferResource, MapFlavor::HostRead);
+ for (auto i = 0u; i < bufferSize / sizeof(unsigned int); i++)
+ {
fprintf(f, "%X\n", ptr[i]);
- unmap(stageBuf);
+ }
+ unmap(bufferResource);
}
else
{
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
index 9d4fdf03c..2d024396a 100644
--- a/tools/render-test/render-d3d12.cpp
+++ b/tools/render-test/render-d3d12.cpp
@@ -3,6 +3,7 @@
#include "options.h"
#include "render.h"
+#include "slang-support.h"
// In order to use the Slang API, we need to include its header
@@ -60,20 +61,21 @@ public:
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
+ virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
+ virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
virtual SlangResult captureScreenShot(const char* outputPath) override;
virtual void serializeOutput(BindingState* state, const char* fileName) override;
- virtual Buffer* createBuffer(const BufferDesc& desc) override;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState* createBindingState(const ShaderInputLayout& layout) override;
virtual ShaderCompiler* getShaderCompiler() override;
- virtual void* map(Buffer* buffer, MapFlavor flavor) override;
- virtual void unmap(Buffer* buffer) override;
+ virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
+ virtual void unmap(BufferResource* buffer) override;
virtual void setInputLayout(InputLayout* inputLayout) override;
virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
virtual void setBindingState(BindingState* state);
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets) override;
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
virtual void setShaderProgram(ShaderProgram* inProgram) override;
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets) override;
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets) override;
virtual void draw(UInt vertexCount, UInt startVertex) override;
virtual void dispatchCompute(int x, int y, int z) override;
virtual void submitGpuWork() override;
@@ -90,8 +92,15 @@ protected:
enum class ProgramType
{
- kCompute,
- kGraphics,
+ Compute,
+ Graphics,
+ };
+
+ struct Submitter
+ {
+ virtual void setRootConstantBufferView(int index, D3D12_GPU_VIRTUAL_ADDRESS gpuBufferLocation) = 0;
+ virtual void setRootDescriptorTable(int index, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor) = 0;
+ virtual void setRootSignature(ID3D12RootSignature* rootSignature) = 0;
};
struct FrameInfo
@@ -113,22 +122,81 @@ protected:
List<uint8_t> m_pixelShader;
List<uint8_t> m_computeShader;
};
- class BufferImpl: public Buffer
+
+ class BufferResourceImpl: public BufferResource
{
public:
- BufferImpl(const BufferDesc& desc):
- m_desc(desc),
- m_mapFlavor(MapFlavor::HostRead)
+ typedef BufferResource Parent;
+
+ enum class BackingStyle
{
+ Unknown,
+ ResourceBacked, ///< The contents is only held within the resource
+ MemoryBacked, ///< The current contents is held in m_memory and copied to GPU every time it's used (typically used for constant buffers)
+ };
+
+ void bindConstantBufferView(D3D12CircularResourceHeap& circularHeap, int index, Submitter* submitter) const
+ {
+ switch (m_backingStyle)
+ {
+ case BackingStyle::MemoryBacked:
+ {
+ const size_t bufferSize = m_memory.Count();
+ D3D12CircularResourceHeap::Cursor cursor = circularHeap.allocateConstantBuffer(bufferSize);
+ ::memcpy(cursor.m_position, m_memory.Buffer(), bufferSize);
+ // Set the constant buffer
+ submitter->setRootConstantBufferView(index, circularHeap.getGpuHandle(cursor));
+ break;
+ }
+ case BackingStyle::ResourceBacked:
+ {
+ // Set the constant buffer
+ submitter->setRootConstantBufferView(index, m_resource.getResource()->GetGPUVirtualAddress());
+ break;
+ }
+ default: break;
+ }
}
- D3D12Resource m_resource;
- D3D12Resource m_uploadResource;
+ BufferResourceImpl(Resource::Usage initialUsage, const Desc& desc):
+ Parent(desc),
+ m_mapFlavor(MapFlavor::HostRead),
+ m_initialUsage(initialUsage)
+ {
+ }
+
+ static BackingStyle _calcResourceBackingStyle(Usage usage)
+ {
+ switch (usage)
+ {
+ case Usage::ConstantBuffer: return BackingStyle::MemoryBacked;
+ default: return BackingStyle::ResourceBacked;
+ }
+ }
- BufferDesc m_desc;
- List<uint8_t> m_memory;
- MapFlavor m_mapFlavor;
+ BackingStyle m_backingStyle; ///< How the resource is 'backed' - either as a resource or cpu memory. Cpu memory is typically used for constant buffers.
+ D3D12Resource m_resource; ///< The resource typically in gpu memory
+ D3D12Resource m_uploadResource; ///< If the resource can be written to, and is in gpu memory (ie not Memory backed), will have upload resource
+
+ Usage m_initialUsage;
+
+ List<uint8_t> m_memory; ///< Cpu memory buffer, used if the m_backingStyle is MemoryBacked
+ MapFlavor m_mapFlavor; ///< If the resource is mapped holds the current mapping flavor
+ };
+
+ class TextureResourceImpl: public TextureResource
+ {
+ public:
+ typedef TextureResource Parent;
+
+ TextureResourceImpl(Type type, const Desc& desc):
+ Parent(type, desc)
+ {
+ }
+
+ D3D12Resource m_resource;
};
+
class InputLayoutImpl: public InputLayout
{
public:
@@ -144,11 +212,10 @@ protected:
int m_uavIndex = -1;
int m_samplerIndex = -1;
- D3D12Resource m_resource;
-
+ RefPtr<Resource> m_resource;
+
int m_binding = 0;
bool m_isOutput = false;
- int m_bufferLength = 0;
};
class BindingStateImpl: public BindingState
@@ -184,18 +251,11 @@ protected:
struct BoundVertexBuffer
{
- RefPtr<BufferImpl> m_buffer;
+ RefPtr<BufferResourceImpl> m_buffer;
int m_stride;
int m_offset;
};
- struct Submitter
- {
- virtual void setRootConstantBufferView(int index, D3D12_GPU_VIRTUAL_ADDRESS gpuBufferLocation) = 0;
- virtual void setRootDescriptorTable(int index, D3D12_GPU_DESCRIPTOR_HANDLE BaseDescriptor) = 0;
- virtual void setRootSignature(ID3D12RootSignature* rootSignature) = 0;
- };
-
struct BindParameters
{
enum
@@ -270,12 +330,11 @@ protected:
void releaseFrameResources();
Result createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, const void* srcData, D3D12Resource& uploadResource, D3D12_RESOURCE_STATES finalState, D3D12Resource& resourceOut);
- Result createTexture(const InputTextureDesc& inputDesc, const TextureData& texData, D3D12Resource& resourceOut);
-
+
Result createInputSampler(const InputSamplerDesc& inputDesc, D3D12DescriptorHeap& samplerHeap, int samplerIndex);
- Result createInputTexture(const InputTextureDesc& inputDesc, D3D12DescriptorHeap& viewHeap, int srvIndex, D3D12Resource& resourceOut);
- Result createInputBuffer(InputBufferDesc& bufferDesc, const List<unsigned int>& bufferData, D3D12DescriptorHeap& viewHeap, int uavIndex, int srvIndex,
- D3D12Resource& resourceOut);
+ Result createInputTexture(const InputTextureDesc& inputDesc, D3D12DescriptorHeap& viewHeap, int srvIndex, RefPtr<Resource>& resourceOut);
+ Result createInputBuffer(InputBufferDesc& bufferDesc, bool isOutput, const List<unsigned int>& bufferData, D3D12DescriptorHeap& viewHeap, int uavIndex, int srvIndex,
+ RefPtr<Resource>& resourceOut);
void beginRender();
@@ -308,7 +367,7 @@ protected:
int m_commandListOpenCount = 0; ///< If >0 the command list should be open
List<BoundVertexBuffer> m_boundVertexBuffers;
- List<RefPtr<BufferImpl> > m_boundConstantBuffers;
+ List<RefPtr<BufferResourceImpl> > m_boundConstantBuffers;
RefPtr<ShaderProgramImpl> m_boundShaderProgram;
RefPtr<InputLayoutImpl> m_boundInputLayout;
@@ -595,253 +654,44 @@ Result D3D12Renderer::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, cons
return SLANG_OK;
}
-Result D3D12Renderer::createTexture(const InputTextureDesc& inputDesc, const TextureData& texData, D3D12Resource& resourceOut)
+Result D3D12Renderer::createInputTexture(const InputTextureDesc& inputDesc, D3D12DescriptorHeap& viewHeap, int srvIndex, RefPtr<Resource>& resourceOut)
{
- // Description of uploading on Dx12
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899215%28v=vs.85%29.aspx
-
- const DXGI_FORMAT pixelFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
- const int numMipMaps = texData.mipLevels;
-
- const int width = inputDesc.size;
- // If the dimension is 1, then we have no height
- const int height = (inputDesc.dimension <= 1) ? 1 : width;
- const int depth = (inputDesc.dimension <= 2) ? 1 : width;
-
- // Setup desc
- D3D12_RESOURCE_DESC resourceDesc;
-
- resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
- resourceDesc.Format = pixelFormat;
- resourceDesc.Width = width;
- resourceDesc.Height = height;
- resourceDesc.DepthOrArraySize = (depth > 1) ? depth : texData.arraySize;
-
- resourceDesc.MipLevels = numMipMaps;
- resourceDesc.SampleDesc.Count = 1;
- resourceDesc.SampleDesc.Quality = 0;
- resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
- resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
- resourceDesc.Alignment = 0;
-
- switch (inputDesc.dimension)
- {
- case 1: resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D; break;
- case 2: resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; break;
- case 3: resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; break;
- default: return SLANG_FAIL;
- }
-
- // Create the target resource
- {
- D3D12_HEAP_PROPERTIES heapProps;
-
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- SLANG_RETURN_ON_FAIL(resourceOut.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
-
- resourceOut.setDebugName(L"Texture");
- }
-
- // Calculate the layout
- List<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> layouts;
- layouts.SetSize(numMipMaps);
- List<UInt64> mipRowSizeInBytes;
- mipRowSizeInBytes.SetSize(numMipMaps);
- List<UInt32> mipNumRows;
- mipNumRows.SetSize(numMipMaps);
-
- UInt64 requiredSize = 0;
- m_device->GetCopyableFootprints(&resourceDesc, 0, texData.mipLevels, 0, layouts.begin(), mipNumRows.begin(), mipRowSizeInBytes.begin(), &requiredSize);
-
-#if 0
- List<D3D12_SUBRESOURCE_DATA> subData;
- subData.SetSize(numMipMaps);
- // Zero it all initially
- ::memset(subData.Buffer(), 0, numMipMaps * sizeof(D3D12_SUBRESOURCE_DATA));
-#endif
-
- //
- assert(texData.dataBuffer.Count() == numMipMaps * texData.arraySize);
-
- // Sub resource indexing
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn705766(v=vs.85).aspx#subresource_indexing
-
- int subResourceIndex = 0;
- for (int i = 0; i < texData.arraySize; i++)
+ int bindFlags = 0;
+ if (srvIndex >= 0)
{
- // Create the upload texture
- D3D12Resource uploadTexture;
- {
- D3D12_HEAP_PROPERTIES heapProps;
-
- heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
- D3D12_RESOURCE_DESC uploadResourceDesc;
-
- uploadResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- uploadResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
- uploadResourceDesc.Width = requiredSize;
- uploadResourceDesc.Height = 1;
- uploadResourceDesc.DepthOrArraySize = 1;
- uploadResourceDesc.MipLevels = 1;
- uploadResourceDesc.SampleDesc.Count = 1;
- uploadResourceDesc.SampleDesc.Quality = 0;
- uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
- uploadResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- uploadResourceDesc.Alignment = 0;
-
- SLANG_RETURN_ON_FAIL(uploadTexture.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
-
- uploadTexture.setDebugName(L"TextureUpload");
- }
-
- ID3D12Resource* uploadResource = uploadTexture;
-
- uint8_t* p;
- uploadResource->Map(0, nullptr, reinterpret_cast<void**>(&p));
-
- for (int j = 0; j < numMipMaps; ++j)
- {
- const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& layout = layouts[j];
- const D3D12_SUBRESOURCE_FOOTPRINT& footprint = layout.Footprint;
-
- int mipWidth = width >> j;
- mipWidth = (mipWidth <= 0) ? 1 : mipWidth;
-
- int mipHeight = height >> j;
- mipHeight = (mipHeight <= 0) ? 1 : mipHeight;
-
- int mipDepth = depth >> j;
- mipDepth = (mipDepth <= 0) ? 1 : mipDepth;
-
- assert(footprint.Width == mipWidth && footprint.Height == mipHeight && footprint.Depth == mipDepth);
-
- // NOTE! Like the D3D11 implementation -> this repeats the same mip pixels to every target (!)
- const List<uint32_t>& srcMip = texData.dataBuffer[j];
-
- // Check the input data is the same size as expected
- assert(mipWidth * mipHeight * mipDepth == srcMip.Count());
-
- const ptrdiff_t dstMipRowPitch = ptrdiff_t(layouts[j].Footprint.RowPitch);
- const ptrdiff_t srcMipRowPitch = ptrdiff_t(sizeof(uint32_t) * mipWidth);
-
- assert(dstMipRowPitch >= srcMipRowPitch);
-
- const uint8_t* srcRow = (const uint8_t*)srcMip.Buffer();
- uint8_t* dstRow = p + layouts[j].Offset;
-
- // Copy the depth each mip
- for (int l = 0; l < mipDepth; l++)
- {
- // Copy rows
- for (int k = 0; k < mipHeight; ++k)
- {
- ::memcpy(dstRow, srcRow, srcMipRowPitch);
-
- srcRow += srcMipRowPitch;
- dstRow += dstMipRowPitch;
- }
- }
-
- assert(srcRow == (const uint8_t*)(srcMip.Buffer() + srcMip.Count()));
- }
- uploadResource->Unmap(0, nullptr);
-
- for (int mipIndex = 0; mipIndex < numMipMaps; ++mipIndex)
- {
- // https://msdn.microsoft.com/en-us/library/windows/desktop/dn903862(v=vs.85).aspx
-
- D3D12_TEXTURE_COPY_LOCATION src;
- src.pResource = uploadTexture;
- src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- src.PlacedFootprint = layouts[mipIndex];
-
- D3D12_TEXTURE_COPY_LOCATION dst;
- dst.pResource = resourceOut;
- dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- dst.SubresourceIndex = subResourceIndex;
- m_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
-
- subResourceIndex++;
- }
-
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resourceOut.transition(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, submitter);
- }
-
- // Block - waiting for copy to complete (so can drop upload texture)
- submitGpuWorkAndWait();
+ bindFlags |= Resource::BindFlag::NonPixelShaderResource | Resource::BindFlag::PixelShaderResource;
}
- return SLANG_OK;
-}
-
-Result D3D12Renderer::createInputTexture(const InputTextureDesc& inputDesc, D3D12DescriptorHeap& viewHeap, int srvIndex, D3D12Resource& resourceOut)
-{
- TextureData texData;
- generateTextureData(texData, inputDesc);
+ RefPtr<TextureResource> texture;
+ SLANG_RETURN_ON_FAIL(generateTextureResource(inputDesc, bindFlags, this, texture));
- SLANG_RETURN_ON_FAIL(createTexture(inputDesc, texData, resourceOut));
+ TextureResourceImpl* textureImpl = static_cast<TextureResourceImpl*>(texture.Ptr());
if (srvIndex >= 0)
{
- const D3D12_RESOURCE_DESC resourceDesc = resourceOut.getResource()->GetDesc();
-
- DXGI_FORMAT pixelFormat = resourceDesc.Format;
+ const D3D12_RESOURCE_DESC resourceDesc = textureImpl->m_resource.getResource()->GetDesc();
+ const DXGI_FORMAT pixelFormat = resourceDesc.Format;
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
_initSrvDesc(inputDesc, resourceDesc, pixelFormat, srvDesc);
// Copy to the descriptor
- m_device->CreateShaderResourceView(resourceOut, &srvDesc, viewHeap.getCpuHandle(srvIndex));
+ m_device->CreateShaderResourceView(textureImpl->m_resource, &srvDesc, viewHeap.getCpuHandle(srvIndex));
}
+ resourceOut = texture.Ptr();
return SLANG_OK;
}
-Result D3D12Renderer::createInputBuffer(InputBufferDesc& bufferDesc, const List<unsigned int>& bufferData, D3D12DescriptorHeap& viewHeap, int uavIndex, int srvIndex,
- D3D12Resource& bufferOut)
+Result D3D12Renderer::createInputBuffer(InputBufferDesc& bufferDesc, bool isOutput, const List<unsigned int>& bufferData, D3D12DescriptorHeap& viewHeap, int uavIndex, int srvIndex,
+ RefPtr<Resource>& bufferOut)
{
const size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
- //bufferSize = D3DUtil::calcAligned(bufferSize, 256);
-
- D3D12_RESOURCE_DESC resourceDesc;
- _initBufferResourceDesc(bufferSize, resourceDesc);
-
- D3D12_RESOURCE_STATES finalState = D3D12_RESOURCE_STATE_GENERIC_READ;
-
- if (bufferDesc.type == InputBufferType::ConstantBuffer)
- {
- finalState = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
- }
- else
- {
- finalState = D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
- resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
-
- /* if (bufferDesc.stride != 0)
- {
- desc.StructureByteStride = bufferDesc.stride;
- desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
- }
- else
- {
- desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
- } */
- }
+
+ RefPtr<BufferResource> resource;
+ SLANG_RETURN_ON_FAIL(createInputBufferResource(bufferDesc, isOutput, bufferSize, bufferData.Buffer(), this, resource));
- D3D12Resource uploadBuffer;
- SLANG_RETURN_ON_FAIL(createBuffer(resourceDesc, bufferData.Buffer(), uploadBuffer, finalState, bufferOut));
+ BufferResourceImpl* resourceImpl = static_cast<BufferResourceImpl*>(resource.Ptr());
const int elemSize = bufferDesc.stride <= 0 ? sizeof(uint32_t) : bufferDesc.stride;
@@ -870,7 +720,7 @@ Result D3D12Renderer::createInputBuffer(InputBufferDesc& bufferDesc, const List<
uavDesc.Buffer.StructureByteStride = 0;
}
- m_device->CreateUnorderedAccessView(bufferOut.getResource(), nullptr, &uavDesc, viewHeap.getCpuHandle(uavIndex));
+ m_device->CreateUnorderedAccessView(resourceImpl->m_resource, nullptr, &uavDesc, viewHeap.getCpuHandle(uavIndex));
}
if (srvIndex >= 0)
@@ -893,9 +743,11 @@ Result D3D12Renderer::createInputBuffer(InputBufferDesc& bufferDesc, const List<
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
}
- m_device->CreateShaderResourceView(bufferOut.getResource(), &srvDesc, viewHeap.getCpuHandle(srvIndex));
+ m_device->CreateShaderResourceView(resourceImpl->m_resource, &srvDesc, viewHeap.getCpuHandle(srvIndex));
}
+ bufferOut = resource.detach();
+
return SLANG_OK;
}
@@ -1251,7 +1103,7 @@ D3D12Renderer::RenderState* D3D12Renderer::findRenderState(ProgramType programTy
{
switch (programType)
{
- case ProgramType::kCompute:
+ case ProgramType::Compute:
{
// Check if current state is a match
if (m_currentRenderState)
@@ -1275,7 +1127,7 @@ D3D12Renderer::RenderState* D3D12Renderer::findRenderState(ProgramType programTy
}
break;
}
- case ProgramType::kGraphics:
+ case ProgramType::Graphics:
{
if (m_currentRenderState)
{
@@ -1327,7 +1179,7 @@ D3D12Renderer::RenderState* D3D12Renderer::calcRenderState()
switch (m_boundShaderProgram->m_programType)
{
- case ProgramType::kCompute:
+ case ProgramType::Compute:
{
if (SLANG_FAILED(calcComputePipelineState(rootSignature, pipelineState)))
{
@@ -1335,7 +1187,7 @@ D3D12Renderer::RenderState* D3D12Renderer::calcRenderState()
}
break;
}
- case ProgramType::kGraphics:
+ case ProgramType::Graphics:
{
if (SLANG_FAILED(calcGraphicsPipelineState(rootSignature, pipelineState)))
{
@@ -1367,14 +1219,13 @@ Result D3D12Renderer::_calcBindParameters(BindParameters& params)
{
int numConstantBuffers = 0;
{
-
-
if (m_boundBindingState)
{
const int numBoundConstantBuffers = numConstantBuffers;
for (int i = 0; i < int(m_boundBindingState->m_bindings.Count()); i++)
{
const Binding& binding = m_boundBindingState->m_bindings[i];
+
if (binding.m_type == ShaderInputType::Buffer && binding.m_bufferType == InputBufferType::ConstantBuffer)
{
// Make sure it's not overlapping the ones we just statically defined
@@ -1390,7 +1241,7 @@ Result D3D12Renderer::_calcBindParameters(BindParameters& params)
numConstantBuffers++;
}
-
+
if (binding.m_srvIndex >= 0)
{
D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
@@ -1438,9 +1289,11 @@ Result D3D12Renderer::_calcBindParameters(BindParameters& params)
// Okay we need to try and create a render state
for (int i = 0; i < int(m_boundConstantBuffers.Count()); i++)
{
- const BufferImpl* buffer = m_boundConstantBuffers[i];
+ const BufferResourceImpl* buffer = m_boundConstantBuffers[i];
if (buffer)
{
+ assert(buffer->m_backingStyle == BufferResourceImpl::BackingStyle::MemoryBacked);
+
D3D12_ROOT_PARAMETER& param = params.nextParameter();
param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
@@ -1510,9 +1363,11 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
for (int i = 0; i < int(bindingState->m_bindings.Count()); i++)
{
const Binding& binding = bindingState->m_bindings[i];
+
if (binding.m_type == ShaderInputType::Buffer && binding.m_bufferType == InputBufferType::ConstantBuffer)
{
- submitter->setRootConstantBufferView(index++, binding.m_resource.getResource()->GetGPUVirtualAddress());
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(binding.m_resource.Ptr());
+ buffer->bindConstantBufferView(m_circularResourceHeap, index++, submitter);
numConstantBuffers++;
}
@@ -1531,16 +1386,10 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
// Okay we need to try and create a render state
for (int i = 0; i < int(m_boundConstantBuffers.Count()); i++)
{
- const BufferImpl* buffer = m_boundConstantBuffers[i];
+ const BufferResourceImpl* buffer = m_boundConstantBuffers[i];
if (buffer)
{
- size_t bufferSize = buffer->m_memory.Count();
-
- D3D12CircularResourceHeap::Cursor cursor = m_circularResourceHeap.allocateConstantBuffer(bufferSize);
- ::memcpy(cursor.m_position, buffer->m_memory.Buffer(), bufferSize);
- // Set the constant buffer
- submitter->setRootConstantBufferView(index++, m_circularResourceHeap.getGpuHandle(cursor));
-
+ buffer->bindConstantBufferView(m_circularResourceHeap, index++, submitter);
numConstantBuffers++;
}
}
@@ -1552,8 +1401,6 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
}
}
-
-
return SLANG_OK;
}
@@ -2001,32 +1848,290 @@ ShaderCompiler* D3D12Renderer::getShaderCompiler()
return this;
}
-Buffer* D3D12Renderer::createBuffer(const BufferDesc& desc)
+static D3D12_RESOURCE_STATES _calcResourceState(Resource::Usage usage)
+{
+ typedef Resource::Usage Usage;
+ switch (usage)
+ {
+ case Usage::VertexBuffer: return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
+ case Usage::IndexBuffer: return D3D12_RESOURCE_STATE_INDEX_BUFFER;
+ case Usage::ConstantBuffer: return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
+ case Usage::StreamOutput: return D3D12_RESOURCE_STATE_STREAM_OUT;
+ case Usage::RenderTarget: return D3D12_RESOURCE_STATE_RENDER_TARGET;
+ case Usage::DepthWrite: return D3D12_RESOURCE_STATE_DEPTH_WRITE;
+ case Usage::DepthRead: return D3D12_RESOURCE_STATE_DEPTH_READ;
+ case Usage::UnorderedAccess: return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
+ case Usage::PixelShaderResource: return D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
+ case Usage::NonPixelShaderResource: return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ case Usage::GenericRead: return D3D12_RESOURCE_STATE_GENERIC_READ;
+ default: return D3D12_RESOURCE_STATES(0);
+ }
+}
+
+static D3D12_RESOURCE_FLAGS _calcResourceFlag(Resource::BindFlag::Enum bindFlag)
{
- RefPtr<BufferImpl> buffer(new BufferImpl(desc));
- const size_t bufferSize = desc.size;
+ typedef Resource::BindFlag BindFlag;
+ switch (bindFlag)
+ {
+ case BindFlag::RenderTarget: return D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+ case BindFlag::DepthStencil: return D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+ case BindFlag::UnorderedAccess: return D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+ default: return D3D12_RESOURCE_FLAG_NONE;
+ }
+}
- switch (desc.flavor)
+static D3D12_RESOURCE_FLAGS _calcResourceBindFlags(Resource::Usage initialUsage, int bindFlags)
+{
+ int dstFlags = 0;
+ while (bindFlags)
{
- case BufferFlavor::Constant:
+ int lsb = bindFlags & -bindFlags;
+
+ dstFlags |= _calcResourceFlag(Resource::BindFlag::Enum(lsb));
+ bindFlags &= ~lsb;
+ }
+ return D3D12_RESOURCE_FLAGS(dstFlags);
+}
+
+static D3D12_RESOURCE_DIMENSION _calcResourceDimension(Resource::Type type)
+{
+ switch (type)
+ {
+ case Resource::Type::Buffer: return D3D12_RESOURCE_DIMENSION_BUFFER;
+ case Resource::Type::Texture1D: return D3D12_RESOURCE_DIMENSION_TEXTURE1D;
+ case Resource::Type::TextureCube:
+ case Resource::Type::Texture2D:
+ {
+ return D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ }
+ case Resource::Type::Texture3D: return D3D12_RESOURCE_DIMENSION_TEXTURE3D;
+ default: return D3D12_RESOURCE_DIMENSION_UNKNOWN;
+ }
+}
+
+TextureResource* D3D12Renderer::createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
+{
+ // Description of uploading on Dx12
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899215%28v=vs.85%29.aspx
+
+ TextureResource::Desc srcDesc(descIn);
+ srcDesc.setDefaults(type, initialUsage);
+
+ const DXGI_FORMAT pixelFormat = D3DUtil::getMapFormat(srcDesc.format);
+ if (pixelFormat == DXGI_FORMAT_UNKNOWN)
+ {
+ return nullptr;
+ }
+
+ const int arraySize = srcDesc.calcEffectiveArraySize(type);
+
+ const D3D12_RESOURCE_DIMENSION dimension = _calcResourceDimension(type);
+ if (dimension == D3D12_RESOURCE_DIMENSION_UNKNOWN)
+ {
+ return nullptr;
+ }
+
+ const int numMipMaps = srcDesc.numMipLevels;
+
+ // Setup desc
+ D3D12_RESOURCE_DESC resourceDesc;
+
+ resourceDesc.Dimension = dimension;
+ resourceDesc.Format = pixelFormat;
+ resourceDesc.Width = srcDesc.size.width;
+ resourceDesc.Height = srcDesc.size.height;
+ resourceDesc.DepthOrArraySize = (srcDesc.size.depth > 1) ? srcDesc.size.depth : arraySize;
+
+ resourceDesc.MipLevels = numMipMaps;
+ resourceDesc.SampleDesc.Count = srcDesc.sampleDesc.numSamples;
+ resourceDesc.SampleDesc.Quality = srcDesc.sampleDesc.quality;
+
+ resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc.Alignment = 0;
+
+ RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(type, srcDesc));
+
+ // Create the target resource
+ {
+ D3D12_HEAP_PROPERTIES heapProps;
+
+ heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 1;
+ heapProps.VisibleNodeMask = 1;
+
+ SLANG_RETURN_NULL_ON_FAIL(texture->m_resource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
+
+ texture->m_resource.setDebugName(L"Texture");
+ }
+
+ // Calculate the layout
+ List<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> layouts;
+ layouts.SetSize(numMipMaps);
+ List<UInt64> mipRowSizeInBytes;
+ mipRowSizeInBytes.SetSize(numMipMaps);
+ List<UInt32> mipNumRows;
+ mipNumRows.SetSize(numMipMaps);
+
+ // Since textures are effectively immutable currently initData must be set
+ assert(initData);
+ // We should have this many sub resources
+ assert(initData->numSubResources == numMipMaps * srcDesc.size.depth * arraySize);
+
+ // This is just the size for one array upload -> not for the whole texure
+ UInt64 requiredSize = 0;
+ m_device->GetCopyableFootprints(&resourceDesc, 0, numMipMaps, 0, layouts.begin(), mipNumRows.begin(), mipRowSizeInBytes.begin(), &requiredSize);
+
+ // Sub resource indexing
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn705766(v=vs.85).aspx#subresource_indexing
+
+ int subResourceIndex = 0;
+ for (int i = 0; i < arraySize; i++)
+ {
+ // Create the upload texture
+ D3D12Resource uploadTexture;
+ {
+ D3D12_HEAP_PROPERTIES heapProps;
+
+ heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 1;
+ heapProps.VisibleNodeMask = 1;
+
+ D3D12_RESOURCE_DESC uploadResourceDesc;
+
+ uploadResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ uploadResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
+ uploadResourceDesc.Width = requiredSize;
+ uploadResourceDesc.Height = 1;
+ uploadResourceDesc.DepthOrArraySize = 1;
+ uploadResourceDesc.MipLevels = 1;
+ uploadResourceDesc.SampleDesc.Count = 1;
+ uploadResourceDesc.SampleDesc.Quality = 0;
+ uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ uploadResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ uploadResourceDesc.Alignment = 0;
+
+ SLANG_RETURN_NULL_ON_FAIL(uploadTexture.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
+
+ uploadTexture.setDebugName(L"TextureUpload");
+ }
+
+ ID3D12Resource* uploadResource = uploadTexture;
+
+ uint8_t* p;
+ uploadResource->Map(0, nullptr, reinterpret_cast<void**>(&p));
+
+ for (int j = 0; j < numMipMaps; ++j)
+ {
+ const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& layout = layouts[j];
+ const D3D12_SUBRESOURCE_FOOTPRINT& footprint = layout.Footprint;
+
+ const TextureResource::Size mipSize = srcDesc.size.calcMipSize(j);
+
+ assert(footprint.Width == mipSize.width && footprint.Height == mipSize.height && footprint.Depth == mipSize.depth);
+
+ const ptrdiff_t dstMipRowPitch = ptrdiff_t(layouts[j].Footprint.RowPitch);
+ const ptrdiff_t srcMipRowPitch = ptrdiff_t(initData->mipRowStrides[j]);
+
+ assert(dstMipRowPitch >= srcMipRowPitch);
+
+ const uint8_t* srcRow = (const uint8_t*)initData->subResources[subResourceIndex];
+ uint8_t* dstRow = p + layouts[j].Offset;
+
+ // Copy the depth each mip
+ for (int l = 0; l < mipSize.depth; l++)
+ {
+ // Copy rows
+ for (int k = 0; k < mipSize.height; ++k)
+ {
+ ::memcpy(dstRow, srcRow, srcMipRowPitch);
+
+ srcRow += srcMipRowPitch;
+ dstRow += dstMipRowPitch;
+ }
+ }
+
+ //assert(srcRow == (const uint8_t*)(srcMip.Buffer() + srcMip.Count()));
+ }
+ uploadResource->Unmap(0, nullptr);
+
+ for (int mipIndex = 0; mipIndex < numMipMaps; ++mipIndex)
+ {
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn903862(v=vs.85).aspx
+
+ D3D12_TEXTURE_COPY_LOCATION src;
+ src.pResource = uploadTexture;
+ src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+ src.PlacedFootprint = layouts[mipIndex];
+
+ D3D12_TEXTURE_COPY_LOCATION dst;
+ dst.pResource = texture->m_resource;
+ dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+ dst.SubresourceIndex = subResourceIndex;
+ m_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
+
+ subResourceIndex++;
+ }
+
+ {
+ // const D3D12_RESOURCE_STATES finalState = D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+ const D3D12_RESOURCE_STATES finalState = _calcResourceState(initialUsage);
+
+ D3D12BarrierSubmitter submitter(m_commandList);
+ texture->m_resource.transition(finalState, submitter);
+ }
+
+ // Block - waiting for copy to complete (so can drop upload texture)
+ submitGpuWorkAndWait();
+ }
+
+ return texture.detach();
+}
+
+BufferResource* D3D12Renderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
+{
+ typedef BufferResourceImpl::BackingStyle Style;
+
+ BufferResource::Desc srcDesc(descIn);
+ srcDesc.setDefaults(initialUsage);
+
+ RefPtr<BufferResourceImpl> buffer(new BufferResourceImpl(initialUsage, srcDesc));
+
+ // Save the style
+ buffer->m_backingStyle = BufferResourceImpl::_calcResourceBackingStyle(initialUsage);
+
+ D3D12_RESOURCE_DESC bufferDesc;
+ _initBufferResourceDesc(srcDesc.sizeInBytes, bufferDesc);
+
+ bufferDesc.Flags = _calcResourceBindFlags(initialUsage, srcDesc.bindFlags);
+
+ switch (buffer->m_backingStyle)
+ {
+ case Style::MemoryBacked:
{
// Assume the constant buffer will change every frame. We'll just keep a copy of the contents
// in regular memory until it needed
- buffer->m_memory.SetSize(UInt(bufferSize));
- break;
+ buffer->m_memory.SetSize(UInt(srcDesc.sizeInBytes));
+ // Initialize
+ if (initData)
+ {
+ ::memcpy(buffer->m_memory.Buffer(), initData, srcDesc.sizeInBytes);
+ }
+ break;
}
- case BufferFlavor::Vertex:
+ case Style::ResourceBacked:
{
- D3D12_RESOURCE_DESC bufferDesc;
- _initBufferResourceDesc(bufferSize, bufferDesc);
-
- SLANG_RETURN_NULL_ON_FAIL(createBuffer(bufferDesc, desc.initData, buffer->m_uploadResource, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, buffer->m_resource));
+ const D3D12_RESOURCE_STATES initialState = _calcResourceState(initialUsage);
+ SLANG_RETURN_NULL_ON_FAIL(createBuffer(bufferDesc, initData, buffer->m_uploadResource, initialState, buffer->m_resource));
break;
}
- default:
- return nullptr;
+ default: return nullptr;
}
-
+
return buffer.detach();
}
@@ -2076,17 +2181,19 @@ InputLayout* D3D12Renderer::createInputLayout(const InputElementDesc* inputEleme
return layout.detach();
}
-void* D3D12Renderer::map(Buffer* bufferIn, MapFlavor flavor)
+void* D3D12Renderer::map(BufferResource* bufferIn, MapFlavor flavor)
{
- BufferImpl* buffer = static_cast<BufferImpl*>(bufferIn);
+ typedef BufferResourceImpl::BackingStyle Style;
+
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
buffer->m_mapFlavor = flavor;
- switch (buffer->m_desc.flavor)
+ const size_t bufferSize = buffer->getDesc().sizeInBytes;
+
+ switch (buffer->m_backingStyle)
{
- case BufferFlavor::Vertex:
+ case Style::ResourceBacked:
{
- D3D12_RANGE readRange = {}; // We do not intend to read from this resource on the CPU.
-
// We need this in a state so we can upload
switch (flavor)
{
@@ -2096,72 +2203,129 @@ void* D3D12Renderer::map(Buffer* bufferIn, MapFlavor flavor)
D3D12BarrierSubmitter submitter(m_commandList);
buffer->m_uploadResource.transition(D3D12_RESOURCE_STATE_GENERIC_READ, submitter);
buffer->m_resource.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter);
+
+ const D3D12_RANGE readRange = {};
+
+ void* uploadData;
+ SLANG_RETURN_NULL_ON_FAIL(buffer->m_uploadResource.getResource()->Map(0, &readRange, reinterpret_cast<void**>(&uploadData)));
+ return uploadData;
+
break;
}
- case MapFlavor::HostRead:
+ case MapFlavor::HostRead:
{
- // Lock whole of the buffer
- readRange.End = buffer->m_desc.size;
- break;
+ // This will be slow!!! - it blocks CPU on GPU completion
+ D3D12Resource& resource = buffer->m_resource;
+
+ // Readback heap
+ D3D12_HEAP_PROPERTIES heapProps;
+ heapProps.Type = D3D12_HEAP_TYPE_READBACK;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 1;
+ heapProps.VisibleNodeMask = 1;
+
+ // Resource to readback to
+ D3D12_RESOURCE_DESC stagingDesc;
+ _initBufferResourceDesc(bufferSize, stagingDesc);
+
+ D3D12Resource stageBuf;
+ SLANG_RETURN_NULL_ON_FAIL(stageBuf.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, stagingDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
+
+ const D3D12_RESOURCE_STATES initialState = resource.getState();
+
+ // Make it a source
+ {
+ D3D12BarrierSubmitter submitter(m_commandList);
+ resource.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, submitter);
+ }
+ // Do the copy
+ m_commandList->CopyBufferRegion(stageBuf, 0, resource, 0, bufferSize);
+ // Switch it back
+ {
+ D3D12BarrierSubmitter submitter(m_commandList);
+ resource.transition(initialState, submitter);
+ }
+
+ // Wait until complete
+ submitGpuWorkAndWait();
+
+ // Map and copy
+ {
+ UINT8* data;
+ D3D12_RANGE readRange = { 0, bufferSize };
+
+ SLANG_RETURN_NULL_ON_FAIL(stageBuf.getResource()->Map(0, &readRange, reinterpret_cast<void**>(&data)));
+
+ // Copy to memory buffer
+ buffer->m_memory.SetSize(bufferSize);
+ ::memcpy(buffer->m_memory.Buffer(), data, bufferSize);
+
+ stageBuf.getResource()->Unmap(0, nullptr);
+ }
+
+ return buffer->m_memory.Buffer();
}
}
-
- // Lock it
- void* uploadData;
- SLANG_RETURN_NULL_ON_FAIL(buffer->m_uploadResource.getResource()->Map(0, &readRange, reinterpret_cast<void**>(&uploadData)));
- return uploadData;
+ break;
}
- case BufferFlavor::Constant:
+ case Style::MemoryBacked:
{
return buffer->m_memory.Buffer();
}
+ default: return nullptr;
}
return nullptr;
}
-void D3D12Renderer::unmap(Buffer* buffer)
+void D3D12Renderer::unmap(BufferResource* bufferIn)
{
- BufferImpl* impl = static_cast<BufferImpl*>(buffer);
+ typedef BufferResourceImpl::BackingStyle Style;
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
- switch (impl->m_desc.flavor)
+ switch (buffer->m_backingStyle)
{
- case BufferFlavor::Vertex:
+ case Style::MemoryBacked:
+ {
+ // Don't need to do anything, as will be uploaded automatically when used
+ break;
+ }
+ case Style::ResourceBacked:
{
- // Unmap
- ID3D12Resource* uploadResource = impl->m_uploadResource;
- ID3D12Resource* resource = impl->m_resource;
-
- uploadResource->Unmap(0, nullptr);
-
// We need this in a state so we can upload
- switch (impl->m_mapFlavor)
+ switch (buffer->m_mapFlavor)
{
case MapFlavor::HostWrite:
case MapFlavor::WriteDiscard:
{
+ // Unmap
+ ID3D12Resource* uploadResource = buffer->m_uploadResource;
+ ID3D12Resource* resource = buffer->m_resource;
+
+ uploadResource->Unmap(0, nullptr);
+
+ const D3D12_RESOURCE_STATES initialState = buffer->m_resource.getState();
+
{
D3D12BarrierSubmitter submitter(m_commandList);
- impl->m_uploadResource.transition(D3D12_RESOURCE_STATE_GENERIC_READ, submitter);
- impl->m_resource.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter);
+ buffer->m_uploadResource.transition(D3D12_RESOURCE_STATE_GENERIC_READ, submitter);
+ buffer->m_resource.transition(D3D12_RESOURCE_STATE_COPY_DEST, submitter);
}
- m_commandList->CopyBufferRegion(resource, 0, uploadResource, 0, impl->m_desc.size);
+ m_commandList->CopyBufferRegion(resource, 0, uploadResource, 0, buffer->getDesc().sizeInBytes);
{
D3D12BarrierSubmitter submitter(m_commandList);
- impl->m_resource.transition(D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, submitter);
+ buffer->m_resource.transition(initialState, submitter);
}
-
break;
}
- case MapFlavor::HostRead: break;
+ case MapFlavor::HostRead:
+ {
+ break;
+ }
}
- break;
- }
- case BufferFlavor::Constant:
- {
- break;
}
}
}
@@ -2188,7 +2352,7 @@ void D3D12Renderer::setPrimitiveTopology(PrimitiveTopology topology)
}
}
-void D3D12Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets)
+void D3D12Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets)
{
{
const UInt num = startSlot + slotCount;
@@ -2200,10 +2364,10 @@ void D3D12Renderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*cons
for (UInt i = 0; i < slotCount; i++)
{
- BufferImpl* buffer = static_cast<BufferImpl*>(buffers[i]);
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]);
if (buffer)
{
- assert(buffer->m_desc.flavor == BufferFlavor::Vertex);
+ assert(buffer->m_initialUsage == Resource::Usage::VertexBuffer);
}
BoundVertexBuffer& boundBuffer = m_boundVertexBuffers[startSlot + i];
@@ -2218,7 +2382,7 @@ void D3D12Renderer::setShaderProgram(ShaderProgram* inProgram)
m_boundShaderProgram = static_cast<ShaderProgramImpl*>(inProgram);
}
-void D3D12Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets)
+void D3D12Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets)
{
{
const UInt num = startSlot + slotCount;
@@ -2230,10 +2394,10 @@ void D3D12Renderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*co
for (UInt i = 0; i < slotCount; i++)
{
- BufferImpl* buffer = static_cast<BufferImpl*>(buffers[i]);
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[i]);
if (buffer)
{
- assert(buffer->m_desc.flavor == BufferFlavor::Constant);
+ assert(buffer->m_initialUsage == Resource::Usage::ConstantBuffer);
}
m_boundConstantBuffers[startSlot + i] = buffer;
}
@@ -2267,12 +2431,12 @@ void D3D12Renderer::draw(UInt vertexCount, UInt startVertex)
for (int i = 0; i < int(m_boundVertexBuffers.Count()); i++)
{
const BoundVertexBuffer& boundVertexBuffer = m_boundVertexBuffers[i];
- BufferImpl* buffer = boundVertexBuffer.m_buffer;
+ BufferResourceImpl* buffer = boundVertexBuffer.m_buffer;
if (buffer)
{
D3D12_VERTEX_BUFFER_VIEW& vertexView = vertexViews[numVertexViews++];
vertexView.BufferLocation = buffer->m_resource.getResource()->GetGPUVirtualAddress();
- vertexView.SizeInBytes = int(buffer->m_desc.size);
+ vertexView.SizeInBytes = int(buffer->getDesc().sizeInBytes);
vertexView.StrideInBytes = boundVertexBuffer.m_stride;
}
}
@@ -2335,9 +2499,8 @@ BindingState* D3D12Renderer::createBindingState(const ShaderInputLayout& layout)
}
}
- SLANG_RETURN_NULL_ON_FAIL(createInputBuffer(srcEntry.bufferDesc, srcEntry.bufferData, bindingState->m_viewHeap, dstEntry.m_uavIndex, dstEntry.m_srvIndex, dstEntry.m_resource));
+ SLANG_RETURN_NULL_ON_FAIL(createInputBuffer(srcEntry.bufferDesc, srcEntry.isOutput, srcEntry.bufferData, bindingState->m_viewHeap, dstEntry.m_uavIndex, dstEntry.m_srvIndex, dstEntry.m_resource));
- dstEntry.m_bufferLength = (int)(srcEntry.bufferData.Count() * sizeof(unsigned int));
dstEntry.m_bufferType = srcEntry.bufferDesc.type;
break;
}
@@ -2384,58 +2547,23 @@ void D3D12Renderer::serializeOutput(BindingState* stateIn, const char* fileName)
auto bindingState = static_cast<BindingStateImpl*>(stateIn);
FILE * f = fopen(fileName, "wb");
- D3D12_HEAP_PROPERTIES heapProps;
- heapProps.Type = D3D12_HEAP_TYPE_READBACK;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
-
int id = 0;
for (auto & binding : bindingState->m_bindings)
{
if (binding.m_isOutput)
{
- if (binding.m_resource.getResource())
+ if (binding.m_resource && binding.m_resource->isBuffer())
{
- // create staging buffer
- //size_t bufferSize = D3DUtil::calcAligned(binding.m_bufferLength, 256);
- const size_t bufferSize = binding.m_bufferLength;
-
- D3D12_RESOURCE_DESC stagingDesc;
- _initBufferResourceDesc(bufferSize, stagingDesc);
-
- D3D12Resource stageBuf;
- SLANG_RETURN_VOID_ON_FAIL(stageBuf.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, stagingDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
-
- const D3D12_RESOURCE_STATES initialState = binding.m_resource.getState();
-
- // Make it a source
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- binding.m_resource.transition(D3D12_RESOURCE_STATE_COPY_SOURCE, submitter);
- }
- // Do the copy
- m_commandList->CopyBufferRegion(stageBuf, 0, binding.m_resource, 0, bufferSize);
- // Switch it back
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- binding.m_resource.transition(initialState, submitter);
- }
+ BufferResource* bufferResource = static_cast<BufferResource*>(binding.m_resource.Ptr());
+ const size_t bufferSize = bufferResource->getDesc().sizeInBytes;
- // Wait until complete
- submitGpuWorkAndWait();
+ unsigned int* ptr = (unsigned int*)map(bufferResource, MapFlavor::HostRead);
- UINT8* data;
- D3D12_RANGE readRange = {0, bufferSize};
-
- SLANG_RETURN_VOID_ON_FAIL(stageBuf.getResource()->Map(0, &readRange, reinterpret_cast<void**>(&data)));
+ for (auto i = 0u; i < bufferSize / sizeof(unsigned int); i++)
{
- auto ptr = (unsigned int *)data;
- for (auto i = 0u; i < binding.m_bufferLength / sizeof(unsigned int); i++)
- fprintf(f, "%X\n", ptr[i]);
+ fprintf(f, "%X\n", ptr[i]);
}
- stageBuf.getResource()->Unmap(0, nullptr);
+ unmap(bufferResource);
}
else
{
@@ -2455,7 +2583,7 @@ ShaderProgram* D3D12Renderer::compileProgram(const ShaderCompileRequest& request
if (request.computeShader.name)
{
- program->m_programType = ProgramType::kCompute;
+ program->m_programType = ProgramType::Compute;
ComPtr<ID3DBlob> computeShaderBlob;
SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.computeShader.source.path, request.computeShader.source.dataBegin, request.computeShader.name, request.computeShader.profile, computeShaderBlob));
@@ -2463,7 +2591,7 @@ ShaderProgram* D3D12Renderer::compileProgram(const ShaderCompileRequest& request
}
else
{
- program->m_programType = ProgramType::kGraphics;
+ program->m_programType = ProgramType::Graphics;
ComPtr<ID3DBlob> vertexShaderBlob, fragmentShaderBlob;
SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.vertexShader.source.path, request.vertexShader.source.dataBegin, request.vertexShader.name, request.vertexShader.profile, vertexShaderBlob));
SLANG_RETURN_NULL_ON_FAIL(D3DUtil::compileHLSLShader(request.fragmentShader.source.path, request.fragmentShader.source.dataBegin, request.fragmentShader.name, request.fragmentShader.profile, fragmentShaderBlob));
diff --git a/tools/render-test/render-gl.cpp b/tools/render-test/render-gl.cpp
index f888e72a2..27c3cdab4 100644
--- a/tools/render-test/render-gl.cpp
+++ b/tools/render-test/render-gl.cpp
@@ -11,6 +11,8 @@
#include "core/secure-crt.h"
#include "external/stb/stb_image_write.h"
+#include "slang-support.h"
+
// TODO(tfoley): eventually we should be able to run these
// tests on non-Windows targets to confirm that cross-compilation
// at least *works* on those platforms...
@@ -82,20 +84,21 @@ public:
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
+ virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
+ virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData) override;
virtual SlangResult captureScreenShot(char const* outputPath) override;
virtual void serializeOutput(BindingState* state, const char* fileName) override;
- virtual Buffer* createBuffer(const BufferDesc& desc) override;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState * createBindingState(const ShaderInputLayout& layout) override;
virtual ShaderCompiler* getShaderCompiler() override;
- virtual void* map(Buffer* buffer, MapFlavor flavor) override;
- virtual void unmap(Buffer* buffer) override;
+ virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
+ virtual void unmap(BufferResource* buffer) override;
virtual void setInputLayout(InputLayout* inputLayout) override;
virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
virtual void setBindingState(BindingState* state);
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets) override;
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
virtual void setShaderProgram(ShaderProgram* inProgram) override;
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets) override;
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets) override;
virtual void draw(UInt vertexCount, UInt startVertex) override;
virtual void dispatchCompute(int x, int y, int z) override;
virtual void submitGpuWork() override {}
@@ -131,34 +134,69 @@ public:
UInt m_attributeCount = 0;
};
- class BufferImpl: public Buffer
+ class BufferResourceImpl: public BufferResource
{
public:
- BufferImpl(GLRenderer* renderer, GLuint id):
+ typedef BufferResource Parent;
+
+ BufferResourceImpl(Usage initialUsage, const Desc& desc, GLRenderer* renderer, GLuint id, GLenum target):
+ Parent(desc),
m_renderer(renderer),
- m_id(id)
+ m_handle(id),
+ m_initialUsage(initialUsage),
+ m_target(target)
{}
- ~BufferImpl()
+ ~BufferResourceImpl()
{
if (m_renderer)
{
- m_renderer->glDeleteBuffers(1, &m_id);
+ m_renderer->glDeleteBuffers(1, &m_handle);
}
}
+ Usage m_initialUsage;
GLRenderer* m_renderer;
- GLuint m_id;
+ GLuint m_handle;
+ GLenum m_target;
};
+ class TextureResourceImpl: public TextureResource
+ {
+ public:
+ typedef TextureResource Parent;
+
+ TextureResourceImpl(Type type, Usage initialUsage, const Desc& desc, GLRenderer* renderer):
+ Parent(type, desc),
+ m_initialUsage(initialUsage),
+ m_renderer(renderer)
+ {
+ m_target = 0;
+ m_handle = 0;
+ }
+
+ ~TextureResourceImpl()
+ {
+ if (m_handle)
+ {
+ glDeleteTextures(1, &m_handle);
+ }
+ }
+
+ Usage m_initialUsage;
+ GLRenderer* m_renderer;
+ GLenum m_target;
+ GLuint m_handle;
+ };
+
struct BindingEntry
{
ShaderInputType type;
- GLuint handle;
+ RefPtr<Resource> resource;
+ GLuint samplerHandle = 0;
List<int> binding;
- int bindTarget;
- int bufferSize;
bool isOutput = false;
};
+
class BindingStateImpl: public BindingState
{
public:
@@ -199,17 +237,31 @@ public:
GLRenderer* m_renderer;
};
- void destroyBindingEntry(const BindingEntry& entry);
+ enum class GlPixelFormat
+ {
+ Unknown,
+ RGBA_Unorm_UInt8,
+ CountOf,
+ };
+
+ struct GlPixelFormatInfo
+ {
+ GLint internalFormat; // such as GL_RGBA8
+ GLenum format; // such as GL_RGBA
+ GLenum formatType; // such as GL_UNSIGNED_BYTE
+ };
+
void destroyBindingEntries(const BindingEntry* entries, int numEntries);
- void bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets);
+ void bindBufferImpl(int target, UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets);
void flushStateForDraw();
GLuint loadShader(GLenum stage, char const* source);
- void createInputBuffer(BindingEntry& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData);
void debugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message);
- void createInputTexture(BindingEntry& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc);
void createInputSampler(BindingEntry& rs, InputSamplerDesc samplerDesc);
+ /// Returns GlPixelFormat::Unknown if not an equivalent
+ static GlPixelFormat _getGlPixelFormat(Format format);
+
static void APIENTRY staticDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
static VertexAttributeFormat getVertexAttributeFormat(Format format);
@@ -230,6 +282,24 @@ public:
#define DECLARE_GL_EXTENSION_FUNC(NAME, TYPE) TYPE NAME;
MAP_GL_EXTENSION_FUNCS(DECLARE_GL_EXTENSION_FUNC)
#undef DECLARE_GL_EXTENSION_FUNC
+
+ static const GlPixelFormatInfo s_pixelFormatInfos[int(GlPixelFormat::CountOf)];
+};
+
+/* static */GLRenderer::GlPixelFormat GLRenderer::_getGlPixelFormat(Format format)
+{
+ switch (format)
+ {
+ case Format::RGBA_Unorm_UInt8: return GlPixelFormat::RGBA_Unorm_UInt8;
+ default: return GlPixelFormat::Unknown;
+ }
+}
+
+/* static */ const GLRenderer::GlPixelFormatInfo GLRenderer::s_pixelFormatInfos[int(GlPixelFormat::CountOf)] =
+{
+ // internalType, format, formatType
+ { 0, 0, 0}, // GlPixelFormat::Unknown
+ { GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE }, // GlPixelFormat::RGBA_Unorm_UInt8
};
Renderer* createGLRenderer()
@@ -268,18 +338,19 @@ void GLRenderer::debugCallback(GLenum source, GLenum type, GLuint id, GLenum sev
CASE(RGB_Float32, 3, GL_FLOAT, GL_FALSE);
CASE(RG_Float32, 2, GL_FLOAT, GL_FALSE);
+ CASE(R_Float32, 1, GL_FLOAT, GL_FALSE);
#undef CASE
}
}
-void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets)
+void GLRenderer::bindBufferImpl(int target, UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets)
{
for (UInt ii = 0; ii < slotCount; ++ii)
{
UInt slot = startSlot + ii;
- BufferImpl* buffer = static_cast<BufferImpl*>(buffers[ii]);
- GLuint bufferID = buffer ? buffer->m_id : 0;
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[ii]);
+ GLuint bufferID = buffer ? buffer->m_handle : 0;
assert(!offsets || !offsets[ii]);
@@ -426,158 +497,44 @@ GLuint GLRenderer::loadShader(GLenum stage, const char* source)
return shaderID;
}
-void GLRenderer::destroyBindingEntry(const BindingEntry& entry)
-{
- switch (entry.type)
- {
- case ShaderInputType::Buffer:
- {
- glDeleteBuffers(1, &entry.handle);
- break;
- }
- case ShaderInputType::Texture:
- case ShaderInputType::CombinedTextureSampler:
- {
- glDeleteTextures(1, &entry.handle);
- break;
- }
- case ShaderInputType::Sampler:
- {
- glDeleteSamplers(1, &entry.handle);
- break;
- }
- default: break;
- }
-}
-
void GLRenderer::destroyBindingEntries(const BindingEntry* entries, int numEntries)
{
for (int i = 0; i < numEntries; ++i)
{
- destroyBindingEntry(entries[i]);
+ const BindingEntry& entry = entries[i];
+ if (entry.type == ShaderInputType::Sampler && entry.samplerHandle != 0)
+ {
+ glDeleteSamplers(1, &entry.samplerHandle);
+ }
}
}
-void GLRenderer::createInputBuffer(BindingEntry& rs, InputBufferDesc bufDesc, List<unsigned int>& bufferData)
+void GLRenderer::createInputSampler(BindingEntry& entry, InputSamplerDesc samplerDesc)
{
- rs.bindTarget = (bufDesc.type == InputBufferType::StorageBuffer ? GL_SHADER_STORAGE_BUFFER : GL_UNIFORM_BUFFER);
- glGenBuffers(1, &rs.handle);
- glBindBuffer(rs.bindTarget, rs.handle);
- glBufferData(rs.bindTarget, bufferData.Count() * sizeof(unsigned int), bufferData.Buffer(), GL_STATIC_READ);
- glBindBuffer(rs.bindTarget, 0);
-}
+ GLuint handle;
-void GLRenderer::createInputTexture(BindingEntry& rs, InputTextureDesc texDesc, InputSamplerDesc samplerDesc)
-{
- TextureData texData;
- generateTextureData(texData, texDesc);
- glGenTextures(1, &rs.handle);
- switch (texDesc.dimension)
- {
- case 1:
- if (texDesc.arrayLength > 0)
- {
- rs.bindTarget = GL_TEXTURE_1D_ARRAY;
- glBindTexture(rs.bindTarget, rs.handle);
- int slice = 0;
- for (int i = 0; i < texData.arraySize; i++)
- {
- for (int j = 0; j < texData.mipLevels; j++)
- {
- glTexImage2D(rs.bindTarget, j, GL_RGBA8, texData.textureSize, i, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[slice].Buffer());
- slice++;
- }
- }
- }
- else
- {
- rs.bindTarget = GL_TEXTURE_1D;
- glBindTexture(rs.bindTarget, rs.handle);
- for (int i = 0; i < texData.mipLevels; i++)
- glTexImage1D(rs.bindTarget, i, GL_RGBA8, texData.textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[i].Buffer());
- }
- break;
- case 2:
- if (texDesc.arrayLength > 0)
- {
- if (texDesc.isCube)
- rs.bindTarget = GL_TEXTURE_CUBE_MAP_ARRAY;
- else
- rs.bindTarget = GL_TEXTURE_2D_ARRAY;
- glBindTexture(rs.bindTarget, rs.handle);
- for (auto i = 0u; i < texData.dataBuffer.Count(); i++)
- glTexImage3D(rs.bindTarget, i % texData.mipLevels, GL_RGBA8, texData.textureSize, texData.textureSize, i, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[i].Buffer());
- }
- else
- {
- if (texDesc.isCube)
- {
- rs.bindTarget = GL_TEXTURE_CUBE_MAP;
- glBindTexture(rs.bindTarget, rs.handle);
- for (int j = 0; j < 6; j++)
- {
- for (int i = 0; i < texData.mipLevels; i++)
- glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, GL_RGBA8, texData.textureSize, texData.textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[i + j*texData.mipLevels].Buffer());
- }
- }
- else
- {
- rs.bindTarget = GL_TEXTURE_2D;
- glBindTexture(rs.bindTarget, rs.handle);
- for (int i = 0; i < texData.mipLevels; i++)
- glTexImage2D(rs.bindTarget, i, GL_RGBA8, texData.textureSize, texData.textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[i].Buffer());
- }
- }
- break;
- case 3:
- rs.bindTarget = GL_TEXTURE_3D;
- glBindTexture(rs.bindTarget, rs.handle);
- for (int i = 0; i < texData.mipLevels; i++)
- glTexImage3D(rs.bindTarget, i, GL_RGBA8, texData.textureSize, texData.textureSize, texData.textureSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData.dataBuffer[i].Buffer());
- break;
- }
- glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_WRAP_R, GL_REPEAT);
+ glCreateSamplers(1, &handle);
+ glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, GL_REPEAT);
if (samplerDesc.isCompareSampler)
{
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(rs.bindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
+ glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
}
else
{
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glTexParameteri(rs.bindTarget, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glSamplerParameteri(handle, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
}
-}
-void GLRenderer::createInputSampler(BindingEntry& rs, InputSamplerDesc samplerDesc)
-{
- glCreateSamplers(1, &rs.handle);
- glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glSamplerParameteri(rs.handle, GL_TEXTURE_WRAP_R, GL_REPEAT);
-
- if (samplerDesc.isCompareSampler)
- {
- glSamplerParameteri(rs.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
- }
- else
- {
- glSamplerParameteri(rs.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glSamplerParameteri(rs.handle, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
- glSamplerParameteri(rs.handle, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
+ entry.samplerHandle = handle;
}
-
// !!!!!!!!!!!!!!!!!!!!!!!!!!!! Renderer interface !!!!!!!!!!!!!!!!!!!!!!!!!!
SlangResult GLRenderer::initialize(void* inWindowHandle)
@@ -691,21 +648,187 @@ ShaderCompiler* GLRenderer::getShaderCompiler()
return this;
}
-Buffer* GLRenderer::createBuffer(const BufferDesc& desc)
+TextureResource* GLRenderer::createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& descIn, const TextureResource::Data* initData)
{
- // TODO: should derive target from desc...
- GLenum target = GL_UNIFORM_BUFFER;
+ TextureResource::Desc srcDesc(descIn);
+ srcDesc.setDefaults(type, initialUsage);
- // TODO: should derive from desc...
- GLenum usage = GL_DYNAMIC_DRAW;
+ GlPixelFormat pixelFormat = _getGlPixelFormat(srcDesc.format);
+ if (pixelFormat == GlPixelFormat::Unknown)
+ {
+ return nullptr;
+ }
+
+ const GlPixelFormatInfo& info = s_pixelFormatInfos[int(pixelFormat)];
+
+ const GLint internalFormat = info.internalFormat;
+ const GLenum format = info.format;
+ const GLenum formatType = info.formatType;
+
+ RefPtr<TextureResourceImpl> texture(new TextureResourceImpl(type, initialUsage, srcDesc, this));
+
+ GLenum target = 0;
+ GLuint handle = 0;
+ glGenTextures(1, &handle);
+
+ const int effectiveArraySize = srcDesc.calcEffectiveArraySize(type);
+
+ assert(initData);
+ assert(initData->numSubResources == srcDesc.numMipLevels * srcDesc.size.depth * effectiveArraySize);
+
+ // Set on texture so will be freed if failure
+ texture->m_handle = handle;
+ const void*const*const data = initData->subResources;
+
+ switch (type)
+ {
+ case Resource::Type::Texture1D:
+ {
+ if (srcDesc.arraySize > 0)
+ {
+ target = GL_TEXTURE_1D_ARRAY;
+ glBindTexture(target, handle);
+ int slice = 0;
+ for (int i = 0; i < effectiveArraySize; i++)
+ {
+ for (int j = 0; j < srcDesc.numMipLevels; j++)
+ {
+ glTexImage2D(target, j, internalFormat, srcDesc.size.width, i, 0, format, formatType, data[slice++]);
+ }
+ }
+ }
+ else
+ {
+ target = GL_TEXTURE_1D;
+ glBindTexture(target, handle);
+ for (int i = 0; i < srcDesc.numMipLevels; i++)
+ {
+ glTexImage1D(target, i, internalFormat, srcDesc.size.width, 0, format, formatType, data[i]);
+ }
+ }
+ break;
+ }
+ case Resource::Type::TextureCube:
+ case Resource::Type::Texture2D:
+ {
+ if (srcDesc.arraySize > 0)
+ {
+ if (type == Resource::Type::TextureCube)
+ {
+ target = GL_TEXTURE_CUBE_MAP_ARRAY;
+ }
+ else
+ {
+ target = GL_TEXTURE_2D_ARRAY;
+ }
+
+ glBindTexture(target, handle);
+
+ int slice = 0;
+ for (int i = 0; i < effectiveArraySize; i++)
+ {
+ for (int j = 0; j < srcDesc.numMipLevels; j++)
+ {
+ glTexImage3D(target, j, internalFormat, srcDesc.size.width, srcDesc.size.height, slice, 0, format, formatType, data[slice++]);
+ }
+ }
+ }
+ else
+ {
+ if (type == Resource::Type::TextureCube)
+ {
+ target = GL_TEXTURE_CUBE_MAP;
+ glBindTexture(target, handle);
+
+ int slice = 0;
+ for (int j = 0; j < 6; j++)
+ {
+ for (int i = 0; i < srcDesc.numMipLevels; i++)
+ {
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[slice++]);
+ }
+ }
+ }
+ else
+ {
+ target = GL_TEXTURE_2D;
+ glBindTexture(target, handle);
+ for (int i = 0; i < srcDesc.numMipLevels; i++)
+ {
+ glTexImage2D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, 0, format, formatType, data[i]);
+ }
+ }
+ }
+ break;
+ }
+ case Resource::Type::Texture3D:
+ {
+ target = GL_TEXTURE_3D;
+ glBindTexture(target, handle);
+ for (int i = 0; i < srcDesc.numMipLevels; i++)
+ {
+ glTexImage3D(target, i, internalFormat, srcDesc.size.width, srcDesc.size.height, srcDesc.size.depth, 0, format, formatType, data[i]);
+ }
+ break;
+ }
+ default: return nullptr;
+ }
+
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
+
+ // Assume regular sampling (might be superseded - if a combined sampler wanted)
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f);
+
+ texture->m_target = target;
+
+ return texture.detach();
+}
+
+static GLenum _calcUsage(Resource::Usage usage)
+{
+ typedef Resource::Usage Usage;
+ switch (usage)
+ {
+ case Usage::ConstantBuffer: return GL_DYNAMIC_DRAW;
+ default: return GL_STATIC_READ;
+ }
+}
+
+static GLenum _calcTarget(Resource::Usage usage)
+{
+ typedef Resource::Usage Usage;
+ switch (usage)
+ {
+ case Usage::ConstantBuffer: return GL_UNIFORM_BUFFER;
+ default: return GL_SHADER_STORAGE_BUFFER;
+ }
+}
+
+BufferResource* GLRenderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
+{
+ BufferResource::Desc desc(descIn);
+
+ if (desc.bindFlags == 0)
+ {
+ desc.bindFlags = Resource::s_requiredBinding[int(initialUsage)];
+ }
+
+ const GLenum target = _calcTarget(initialUsage);
+ // TODO: should derive from desc...
+ const GLenum usage = _calcUsage(initialUsage);
+
GLuint bufferID = 0;
glGenBuffers(1, &bufferID);
glBindBuffer(target, bufferID);
- glBufferData(target, desc.size, desc.initData, usage);
+ glBufferData(target, descIn.sizeInBytes, initData, usage);
- return new BufferImpl(this, bufferID);
+ return new BufferResourceImpl(initialUsage, desc, this, bufferID, target);
}
InputLayout* GLRenderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount)
@@ -726,11 +849,11 @@ InputLayout* GLRenderer::createInputLayout(const InputElementDesc* inputElements
return (InputLayout*)inputLayout;
}
-void* GLRenderer::map(Buffer* bufferIn, MapFlavor flavor)
+void* GLRenderer::map(BufferResource* bufferIn, MapFlavor flavor)
{
- BufferImpl* buffer = static_cast<BufferImpl*>(bufferIn);
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
- GLenum target = GL_UNIFORM_BUFFER;
+ //GLenum target = GL_UNIFORM_BUFFER;
GLuint access = 0;
switch (flavor)
@@ -744,18 +867,15 @@ void* GLRenderer::map(Buffer* bufferIn, MapFlavor flavor)
break;
}
- auto bufferID = buffer ? buffer->m_id : 0;
- glBindBuffer(target, bufferID);
+ glBindBuffer(buffer->m_target, buffer->m_handle);
- return glMapBuffer(target, access);
+ return glMapBuffer(buffer->m_target, access);
}
-void GLRenderer::unmap(Buffer* bufferIn)
+void GLRenderer::unmap(BufferResource* bufferIn)
{
- BufferImpl* buffer = static_cast<BufferImpl*>(bufferIn);
- GLenum target = GL_UNIFORM_BUFFER;
- auto bufferID = buffer ? buffer->m_id : 0;
- glUnmapBuffer(target);
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(bufferIn);
+ glUnmapBuffer(buffer->m_target);
}
void GLRenderer::setInputLayout(InputLayout* inputLayout)
@@ -777,14 +897,14 @@ void GLRenderer::setPrimitiveTopology(PrimitiveTopology topology)
m_boundPrimitiveTopology = glTopology;
}
-void GLRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets)
+void GLRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets)
{
for (UInt ii = 0; ii < slotCount; ++ii)
{
UInt slot = startSlot + ii;
- BufferImpl* buffer = static_cast<BufferImpl*>(buffers[ii]);
- GLuint bufferID = buffer ? buffer->m_id : 0;
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(buffers[ii]);
+ GLuint bufferID = buffer ? buffer->m_handle : 0;
m_boundVertexStreamBuffers[slot] = bufferID;
m_boundVertexStreamStrides[slot] = strides[ii];
@@ -800,7 +920,7 @@ void GLRenderer::setShaderProgram(ShaderProgram* programIn)
glUseProgram(programID);
}
-void GLRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets)
+void GLRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets)
{
bindBufferImpl(GL_UNIFORM_BUFFER, startSlot, slotCount, buffers, offsets);
}
@@ -820,28 +940,51 @@ void GLRenderer::dispatchCompute(int x, int y, int z)
BindingState* GLRenderer::createBindingState(const ShaderInputLayout& layout)
{
BindingStateImpl* state = new BindingStateImpl(this);
- for (auto & entry : layout.entries)
+ for (auto & srcEntry : layout.entries)
{
- BindingEntry rsEntry;
- rsEntry.isOutput = entry.isOutput;
- rsEntry.binding = entry.glslBinding;
- rsEntry.type = entry.type;
- switch (entry.type)
+ BindingEntry dstEntry;
+ dstEntry.isOutput = srcEntry.isOutput;
+ dstEntry.binding = srcEntry.glslBinding;
+ dstEntry.type = srcEntry.type;
+
+ switch (srcEntry.type)
{
case ShaderInputType::Buffer:
- createInputBuffer(rsEntry, entry.bufferDesc, entry.bufferData);
+ {
+ RefPtr<BufferResource> bufferResource;
+ SLANG_RETURN_NULL_ON_FAIL(createInputBufferResource(srcEntry.bufferDesc, srcEntry.isOutput, srcEntry.bufferData.Count() * sizeof(uint32_t), srcEntry.bufferData.Buffer(), this, bufferResource));
+ dstEntry.resource = bufferResource;
break;
+ }
case ShaderInputType::Texture:
- createInputTexture(rsEntry, entry.textureDesc, InputSamplerDesc());
- break;
case ShaderInputType::CombinedTextureSampler:
- createInputTexture(rsEntry, entry.textureDesc, entry.samplerDesc);
+ {
+ RefPtr<TextureResource> textureResource;
+
+ int bindFlags = 0;
+ SLANG_RETURN_NULL_ON_FAIL(generateTextureResource(srcEntry.textureDesc, bindFlags, this, textureResource));
+
+ // Handle if combined
+ if (srcEntry.type == ShaderInputType::CombinedTextureSampler && srcEntry.samplerDesc.isCompareSampler)
+ {
+ TextureResourceImpl* texture = static_cast<TextureResourceImpl*>(textureResource.Ptr());
+ auto target = texture->m_target;
+
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
+ glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ }
+
break;
+ }
case ShaderInputType::Sampler:
- createInputSampler(rsEntry, entry.samplerDesc);
+ {
+ createInputSampler(dstEntry, srcEntry.samplerDesc);
break;
+ }
}
- state->m_entries.Add(rsEntry);
+ state->m_entries.Add(dstEntry);
}
return state;
}
@@ -854,17 +997,28 @@ void GLRenderer::setBindingState(BindingState* stateIn)
switch (entry.type)
{
case ShaderInputType::Buffer:
- glBindBufferBase(entry.bindTarget, entry.binding[0], entry.handle);
+ {
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(entry.resource.Ptr());
+ glBindBufferBase(buffer->m_target, entry.binding[0], buffer->m_handle);
break;
+ }
case ShaderInputType::Sampler:
+ {
for (auto b : entry.binding)
- glBindSampler(b, entry.handle);
+ {
+ glBindSampler(b, entry.samplerHandle);
+ }
break;
+ }
case ShaderInputType::Texture:
case ShaderInputType::CombinedTextureSampler:
+ {
+ BufferResourceImpl* buffer = static_cast<BufferResourceImpl*>(entry.resource.Ptr());
+
glActiveTexture(GL_TEXTURE0 + entry.binding[0]);
- glBindTexture(entry.bindTarget, entry.handle);
+ glBindTexture(buffer->m_target, buffer->m_handle);
break;
+ }
}
}
}
@@ -878,11 +1032,19 @@ void GLRenderer::serializeOutput(BindingState* stateIn, const char* fileName)
{
if (entry.isOutput)
{
- glBindBuffer(entry.bindTarget, entry.handle);
- auto ptr = (unsigned int *)glMapBuffer(entry.bindTarget, GL_READ_ONLY);
- for (auto i = 0u; i < entry.bufferSize / sizeof(unsigned int); i++)
- fprintf(f, "%X\n", ptr[i]);
- glUnmapBuffer(entry.bindTarget);
+ if (entry.resource && entry.resource->isBuffer())
+ {
+ BufferResource* bufferResource = static_cast<BufferResource*>(entry.resource.Ptr());
+ size_t bufferSize = bufferResource->getDesc().sizeInBytes;
+
+ unsigned int* ptr = (unsigned int*)map(bufferResource, MapFlavor::HostRead);
+
+ for (auto i = 0u; i < bufferSize / sizeof(unsigned int); i++)
+ {
+ fprintf(f, "%X\n", ptr[i]);
+ }
+ unmap(bufferResource);
+ }
}
}
fclose(f);
diff --git a/tools/render-test/render-test.vcxproj b/tools/render-test/render-test.vcxproj
index 59ae16a14..2106bb9c2 100644
--- a/tools/render-test/render-test.vcxproj
+++ b/tools/render-test/render-test.vcxproj
@@ -175,6 +175,7 @@
<ClCompile Include="render-d3d12.cpp" />
<ClCompile Include="render-gl.cpp" />
<ClCompile Include="render-vk.cpp" />
+ <ClCompile Include="render.cpp" />
<ClCompile Include="resource-d3d12.cpp" />
<ClCompile Include="shader-input-layout.cpp" />
<ClCompile Include="slang-support.cpp" />
diff --git a/tools/render-test/render-test.vcxproj.filters b/tools/render-test/render-test.vcxproj.filters
index c0a24b015..640f132a2 100644
--- a/tools/render-test/render-test.vcxproj.filters
+++ b/tools/render-test/render-test.vcxproj.filters
@@ -51,6 +51,9 @@
<ClCompile Include="descriptor-heap-d3d12.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="render.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="options.h">
diff --git a/tools/render-test/render-vk.cpp b/tools/render-test/render-vk.cpp
index 97da0bc40..13e67c132 100644
--- a/tools/render-test/render-vk.cpp
+++ b/tools/render-test/render-vk.cpp
@@ -89,20 +89,21 @@ public:
virtual void setClearColor(const float color[4]) override;
virtual void clearFrame() override;
virtual void presentFrame() override;
+ virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData) override;
+ virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& bufferDesc, const void* initData) override;
virtual SlangResult captureScreenShot(const char* outputPath) override;
virtual void serializeOutput(BindingState* state, const char * fileName) override;
- virtual Buffer* createBuffer(const BufferDesc& desc) override;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) override;
virtual BindingState * createBindingState(const ShaderInputLayout& layout) override;
virtual ShaderCompiler* getShaderCompiler() override;
- virtual void* map(Buffer* buffer, MapFlavor flavor) override;
- virtual void unmap(Buffer* buffer) override;
+ virtual void* map(BufferResource* buffer, MapFlavor flavor) override;
+ virtual void unmap(BufferResource* buffer) override;
virtual void setInputLayout(InputLayout* inputLayout) override;
virtual void setPrimitiveTopology(PrimitiveTopology topology) override;
virtual void setBindingState(BindingState* state);
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets) override;
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) override;
virtual void setShaderProgram(ShaderProgram* inProgram) override;
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets) override;
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets) override;
virtual void draw(UInt vertexCount, UInt startVertex) override;
virtual void dispatchCompute(int x, int y, int z) override;
virtual void submitGpuWork() override {}
@@ -113,19 +114,22 @@ public:
protected:
- class BufferImpl: public Buffer
+ class BufferResourceImpl: public BufferResource
{
public:
+ typedef BufferResource Parent;
- BufferImpl(VKRenderer* renderer, VkBuffer buffer, VkDeviceMemory memory):
+ BufferResourceImpl(Resource::Usage initialUsage, const BufferResource::Desc& desc, VKRenderer* renderer, VkBuffer buffer, VkDeviceMemory memory):
+ Parent(desc),
m_renderer(renderer),
m_buffer(buffer),
- m_memory(memory)
+ m_memory(memory),
+ m_initialUsage(initialUsage)
{
assert(renderer);
}
- ~BufferImpl()
+ ~BufferResourceImpl()
{
// Now destroy the staging buffer
if (m_renderer)
@@ -135,6 +139,7 @@ public:
}
}
+ Resource::Usage m_initialUsage;
VKRenderer* m_renderer;
VkBuffer m_buffer;
VkDeviceMemory m_memory;
@@ -187,7 +192,7 @@ public:
VkBool32 handleDebugMessage(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject,
size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg);
- BufferImpl* createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData = nullptr);
+ BufferResourceImpl* createBufferResourceImpl(Resource::Usage initialUsage, const BufferResource::Desc& desc, size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData = nullptr);
VkCommandBuffer getCommandBuffer();
VkCommandBuffer beginCommandBuffer();
@@ -315,7 +320,7 @@ void VKRenderer::flushCommandBuffer(VkCommandBuffer commandBuffer)
vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
}
-VKRenderer::BufferImpl* VKRenderer::createBufferImpl(size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData)
+VKRenderer::BufferResourceImpl* VKRenderer::createBufferResourceImpl(Resource::Usage initialUsage, const BufferResource::Desc& desc, size_t bufferSize, VkBufferUsageFlags usage, VkMemoryPropertyFlags reqMemoryProperties, const void* initData)
{
if (initData)
{
@@ -352,7 +357,7 @@ VKRenderer::BufferImpl* VKRenderer::createBufferImpl(size_t bufferSize, VkBuffer
// used for the buffer doesn't let us fill things in
// directly.
- RefPtr<BufferImpl> staging = createBufferImpl(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+ RefPtr<BufferResourceImpl> staging = createBufferResourceImpl(initialUsage, desc, bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
// Copy into staging buffer
@@ -371,7 +376,7 @@ VKRenderer::BufferImpl* VKRenderer::createBufferImpl(size_t bufferSize, VkBuffer
flushCommandBuffer(commandBuffer);
}
- return new BufferImpl(this, buffer, memory);
+ return new BufferResourceImpl(initialUsage, desc, this, buffer, memory);
}
uint32_t VKRenderer::getMemoryTypeIndex(uint32_t inTypeBits, VkMemoryPropertyFlags properties)
@@ -413,19 +418,29 @@ void VKRenderer::createInputBuffer(const ShaderInputLayoutEntry& entry, const In
VkBufferUsageFlags usage = 0;
VkMemoryPropertyFlags reqMemoryProperties = 0;
+ Resource::Usage initialUsage = Resource::Usage::Unknown;
switch (bufferDesc.type)
{
case InputBufferType::ConstantBuffer:
usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ initialUsage = Resource::Usage::ConstantBuffer;
break;
case InputBufferType::StorageBuffer:
usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
reqMemoryProperties = 0;
+ initialUsage = Resource::Usage::PixelShaderResource;
break;
}
+ BufferResource::Desc bufferResourceDesc;
+
+ bufferResourceDesc.cpuAccessFlags = (entry.isOutput) ? Resource::AccessFlag::Read : 0;
+ bufferResourceDesc.bindFlags = Resource::s_requiredBinding[int(initialUsage)];
+ bufferResourceDesc.elementSize = 0;
+ bufferResourceDesc.sizeInBytes = bufferSize;
+
// If we are going to read back from the buffer, be sure to request
// the required access.
if (entry.isOutput)
@@ -433,7 +448,7 @@ void VKRenderer::createInputBuffer(const ShaderInputLayoutEntry& entry, const In
usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
}
- RefPtr<BufferImpl> bufferImpl(createBufferImpl(bufferSize, usage, reqMemoryProperties, initData));
+ RefPtr<BufferResourceImpl> bufferImpl(createBufferResourceImpl(initialUsage, bufferResourceDesc, bufferSize, usage, reqMemoryProperties, initData));
// TODO: need to hang onto the `memory` field so
// that we can release it when we are done.
@@ -676,27 +691,80 @@ ShaderCompiler* VKRenderer::getShaderCompiler()
return this;
}
-Buffer* VKRenderer::createBuffer(const BufferDesc& desc)
+TextureResource* VKRenderer::createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData)
{
- size_t bufferSize = desc.size;
+ return nullptr;
+}
- VkBufferUsageFlags usage = 0;
+static VkBufferUsageFlagBits _calcUsageFlagBit(Resource::BindFlag::Enum bind)
+{
+ typedef Resource::BindFlag BindFlag;
+
+ switch (bind)
+ {
+ case BindFlag::VertexBuffer: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ case BindFlag::IndexBuffer: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+ case BindFlag::ConstantBuffer: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ case BindFlag::StreamOutput:
+ case BindFlag::RenderTarget:
+ case BindFlag::DepthStencil:
+ {
+ assert(!"Not supported yet");
+ return VkBufferUsageFlagBits(0);
+ }
+ case BindFlag::UnorderedAccess: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ case BindFlag::PixelShaderResource: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ case BindFlag::NonPixelShaderResource: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+ default: return VkBufferUsageFlagBits(0);
+ }
+}
+
+static VkBufferUsageFlagBits _calcUsageFlagBit(int bindFlags)
+{
+ int dstFlags = 0;
+ while (bindFlags)
+ {
+ int lsb = bindFlags & -bindFlags;
+ dstFlags |= _calcUsageFlagBit(Resource::BindFlag::Enum(lsb));
+ bindFlags &= ~lsb;
+ }
+ return VkBufferUsageFlagBits(dstFlags);
+}
+
+BufferResource* VKRenderer::createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& descIn, const void* initData)
+{
+ BufferResource::Desc desc(descIn);
+ if (desc.bindFlags == 0)
+ {
+ desc.bindFlags = Resource::s_requiredBinding[int(initialUsage)];
+ }
+
+ const size_t bufferSize = desc.sizeInBytes;
+
+ VkBufferUsageFlags usage = _calcUsageFlagBit(desc.bindFlags);
VkMemoryPropertyFlags reqMemoryProperties = 0;
- switch (desc.flavor)
+ if (desc.cpuAccessFlags & Resource::AccessFlag::Read)
{
- case BufferFlavor::Constant:
- usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
- reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- break;
+ // If it can be read from, set this
+ usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+ }
+ if (desc.cpuAccessFlags & Resource::AccessFlag::Write)
+ {
+ usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+ }
- case BufferFlavor::Vertex:
- usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
- reqMemoryProperties = 0;
+ switch (initialUsage)
+ {
+ case Resource::Usage::ConstantBuffer:
+ {
+ reqMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
break;
+ }
+ default: break;
}
- return createBufferImpl(bufferSize, usage, reqMemoryProperties, desc.initData);
+ return createBufferResourceImpl(initialUsage, desc, bufferSize, usage, reqMemoryProperties, initData);
}
InputLayout* VKRenderer::createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount)
@@ -708,12 +776,12 @@ InputLayout* VKRenderer::createInputLayout(const InputElementDesc* inputElements
return (InputLayout*)impl;
}
-void* VKRenderer::map(Buffer* buffer, MapFlavor flavor)
+void* VKRenderer::map(BufferResource* buffer, MapFlavor flavor)
{
return nullptr;
}
-void VKRenderer::unmap(Buffer* buffer)
+void VKRenderer::unmap(BufferResource* buffer)
{
}
@@ -725,7 +793,7 @@ void VKRenderer::setPrimitiveTopology(PrimitiveTopology topology)
{
}
-void VKRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets)
+void VKRenderer::setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets)
{
}
@@ -734,7 +802,7 @@ void VKRenderer::setShaderProgram(ShaderProgram* program)
m_currentProgram = (ShaderProgramImpl*)program;
}
-void VKRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets)
+void VKRenderer::setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets)
{
}
@@ -800,9 +868,18 @@ void VKRenderer::serializeOutput(BindingState* s, const char* fileName)
{
if (bb.buffer)
{
- // create staging buffer
+ Resource::Usage initialUsage = Resource::Usage::NonPixelShaderResource;
+ BufferResource::Desc bufferResourceDesc;
+
size_t bufferSize = bb.bufferLength;
- RefPtr<BufferImpl> staging(createBufferImpl(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
+
+ bufferResourceDesc.cpuAccessFlags = Resource::AccessFlag::Read;
+ bufferResourceDesc.bindFlags = 0;
+ bufferResourceDesc.elementSize = 0;
+ bufferResourceDesc.sizeInBytes = bufferSize;
+
+ // create staging buffer
+ RefPtr<BufferResourceImpl> staging(createBufferResourceImpl(initialUsage, bufferResourceDesc, bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT));
// Copy from real buffer to staging buffer
diff --git a/tools/render-test/render.cpp b/tools/render-test/render.cpp
new file mode 100644
index 000000000..292aa75f7
--- /dev/null
+++ b/tools/render-test/render.cpp
@@ -0,0 +1,203 @@
+// render.cpp
+#include "render.h"
+
+#include "../../source/core/slang-math.h"
+
+namespace renderer_test {
+using namespace Slang;
+
+/* static */const Resource::BindFlag::Enum Resource::s_requiredBinding[int(Usage::CountOf)] =
+{
+ BindFlag::VertexBuffer, // VertexBuffer
+ BindFlag::IndexBuffer, // IndexBuffer
+ BindFlag::ConstantBuffer, // ConstantBuffer
+ BindFlag::StreamOutput, // StreamOut
+ BindFlag::RenderTarget, // RenderTager
+ BindFlag::DepthStencil, // DepthRead
+ BindFlag::DepthStencil, // DepthWrite
+ BindFlag::UnorderedAccess, // UnorderedAccess
+ BindFlag::PixelShaderResource, // PixelShaderResource
+ BindFlag::NonPixelShaderResource, // NonPixelShaderResource
+ BindFlag::Enum(BindFlag::PixelShaderResource | BindFlag::NonPixelShaderResource), // GenericRead
+};
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!! TextureResource::Size !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+int TextureResource::Size::calcMaxDimension(Type type) const
+{
+ switch (type)
+ {
+ case Resource::Type::Texture1D: return this->width;
+ case Resource::Type::Texture3D: return std::max(std::max(this->width, this->height), this->depth);
+ case Resource::Type::TextureCube: // fallthru
+ case Resource::Type::Texture2D:
+ {
+ return std::max(this->width, this->height);
+ }
+ default: return 0;
+ }
+}
+
+TextureResource::Size TextureResource::Size::calcMipSize(int mipLevel) const
+{
+ Size size;
+ size.width = TextureResource::calcMipSize(this->width, mipLevel);
+ size.height = TextureResource::calcMipSize(this->height, mipLevel);
+ size.depth = TextureResource::calcMipSize(this->depth, mipLevel);
+ return size;
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!! BufferResource::Desc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+void BufferResource::Desc::setDefaults(Usage initialUsage)
+{
+ if (this->bindFlags == 0)
+ {
+ this->bindFlags = Resource::s_requiredBinding[int(initialUsage)];
+ }
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!! TextureResource::Desc !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+int TextureResource::Desc::calcNumMipLevels(Type type) const
+{
+ const int maxDimensionSize = this->size.calcMaxDimension(type);
+ return (maxDimensionSize > 0) ? (Math::Log2Floor(maxDimensionSize) + 1) : 0;
+}
+
+int TextureResource::Desc::calcNumSubResources(Type type) const
+{
+ const int numMipMaps = (this->numMipLevels > 0) ? this->numMipLevels : calcNumMipLevels(type);
+ const int arrSize = (this->arraySize > 0) ? this->arraySize : 1;
+
+ switch (type)
+ {
+ case Resource::Type::Texture1D:
+ case Resource::Type::Texture2D:
+ {
+ return numMipMaps * arrSize;
+ }
+ case Resource::Type::Texture3D:
+ {
+ // can't have arrays of 3d textures
+ assert(this->arraySize <= 1);
+ return numMipMaps * this->size.depth;
+ }
+ case Resource::Type::TextureCube:
+ {
+ // There are 6 faces to a cubemap
+ return numMipMaps * arrSize * 6;
+ }
+ default: return 0;
+ }
+}
+
+void TextureResource::Desc::fixSize(Type type)
+{
+ switch (type)
+ {
+ case Resource::Type::Texture1D:
+ {
+ this->size.height = 1;
+ this->size.depth = 1;
+ break;
+ }
+ case Resource::Type::TextureCube:
+ case Resource::Type::Texture2D:
+ {
+ this->size.depth = 1;
+ break;
+ }
+ case Resource::Type::Texture3D:
+ {
+ // Can't have an array
+ this->arraySize = 0;
+ break;
+ }
+ default: break;
+ }
+}
+
+void TextureResource::Desc::setDefaults(Type type, Usage initialUsage)
+{
+ fixSize(type);
+ if (this->bindFlags == 0)
+ {
+ this->bindFlags = Resource::s_requiredBinding[int(initialUsage)];
+ }
+ if (this->numMipLevels <= 0)
+ {
+ this->numMipLevels = calcNumMipLevels(type);
+ }
+}
+
+int TextureResource::Desc::calcEffectiveArraySize(Type type) const
+{
+ const int arrSize = (this->arraySize > 0) ? this->arraySize : 1;
+
+ switch (type)
+ {
+ case Resource::Type::Texture1D: // fallthru
+ case Resource::Type::Texture2D:
+ {
+ return arrSize;
+ }
+ case Resource::Type::TextureCube: return arrSize * 6;
+ case Resource::Type::Texture3D: return 1;
+ default: return 0;
+ }
+}
+
+void TextureResource::Desc::init()
+{
+ this->size.init();
+
+ this->format = Format::Unknown;
+ this->arraySize = 0;
+ this->numMipLevels = 0;
+ this->sampleDesc.init();
+
+ this->bindFlags = 0;
+ this->cpuAccessFlags = 0;
+}
+
+void TextureResource::Desc::init1D(Format formatIn, int widthIn, int numMipMapsIn)
+{
+ this->size.init(widthIn);
+
+ this->format = format;
+ this->arraySize = 0;
+ this->numMipLevels = numMipMapsIn;
+ this->sampleDesc.init();
+
+ this->bindFlags = 0;
+ this->cpuAccessFlags = 0;
+}
+
+void TextureResource::Desc::init2D(Format formatIn, int widthIn, int heightIn, int numMipMapsIn)
+{
+ this->size.init(widthIn, heightIn);
+
+ this->format = format;
+ this->arraySize = 0;
+ this->numMipLevels = numMipMapsIn;
+ this->sampleDesc.init();
+
+ this->bindFlags = 0;
+ this->cpuAccessFlags = 0;
+}
+
+void TextureResource::Desc::init3D(Format formatIn, int widthIn, int heightIn, int depthIn, int numMipMapsIn)
+{
+ this->size.init(widthIn, heightIn, depthIn);
+
+ this->format = format;
+ this->arraySize = 0;
+ this->numMipLevels = numMipMapsIn;
+ this->sampleDesc.init();
+
+ this->bindFlags = 0;
+ this->cpuAccessFlags = 0;
+}
+
+} // renderer_test
diff --git a/tools/render-test/render.h b/tools/render-test/render.h
index 761f9e759..2800e069b 100644
--- a/tools/render-test/render.h
+++ b/tools/render-test/render.h
@@ -11,10 +11,6 @@
namespace renderer_test {
// Declare opaque type
-class Buffer: public Slang::RefObject
-{
- public:
-};
class InputLayout: public Slang::RefObject
{
public:
@@ -71,19 +67,10 @@ enum class Format
Unknown,
RGB_Float32,
RG_Float32,
-};
+ R_Float32,
-enum class BufferFlavor
-{
- Constant,
- Vertex
-};
-
-struct BufferDesc
-{
- UInt size = 0;
- BufferFlavor flavor = BufferFlavor::Constant;
- void const* initData = nullptr;
+ RGBA_Unorm_UInt8,
+ CountOf,
};
struct InputElementDesc
@@ -106,6 +93,231 @@ enum class PrimitiveTopology
TriangleList,
};
+class Resource: public Slang::RefObject
+{
+ public:
+
+ /// The type of resource.
+ /// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise isTexture won't work correctly)
+ enum class Type
+ {
+ Unknown, ///< Unknown
+ Buffer, ///< A buffer (like a constant/index/vertex buffer)
+ Texture1D, ///< A 1d texture
+ Texture2D, ///< A 2d texture
+ Texture3D, ///< A 3d texture
+ TextureCube, ///< A cubemap consists of 6 Texture2D like faces
+ CountOf,
+ };
+
+ /// Describes how a resource is to be used
+ enum class Usage
+ {
+ Unknown = -1,
+ VertexBuffer = 0,
+ IndexBuffer,
+ ConstantBuffer,
+ StreamOutput,
+ RenderTarget,
+ DepthRead,
+ DepthWrite,
+ UnorderedAccess,
+ PixelShaderResource,
+ NonPixelShaderResource,
+ GenericRead,
+ CountOf,
+ };
+
+ /// Binding flags describe all of the ways a resource can be bound - and therefore used
+ struct BindFlag
+ {
+ enum Enum
+ {
+ VertexBuffer = 0x001,
+ IndexBuffer = 0x002,
+ ConstantBuffer = 0x004,
+ StreamOutput = 0x008,
+ RenderTarget = 0x010,
+ DepthStencil = 0x020,
+ UnorderedAccess = 0x040,
+ PixelShaderResource = 0x080,
+ NonPixelShaderResource = 0x100,
+ };
+ };
+
+ /// Combinations describe how a resource can be accessed (typically by the host/cpu)
+ struct AccessFlag
+ {
+ enum Enum
+ {
+ Read = 0x1,
+ Write = 0x2
+ };
+ };
+
+ /// Get the type
+ SLANG_FORCE_INLINE Type getType() const { return m_type; }
+ /// True if it's a texture derived type
+ SLANG_FORCE_INLINE bool isTexture() const { return int(m_type) >= int(Type::Texture1D); }
+ /// True if it's a buffer derived type
+ SLANG_FORCE_INLINE bool isBuffer() const { return m_type == Type::Buffer; }
+
+ /// For a usage gives the required binding flags
+ static const BindFlag::Enum s_requiredBinding[int(Usage::CountOf)];
+
+ protected:
+ Resource(Type type):
+ m_type(type)
+ {}
+
+ Type m_type;
+};
+
+class BufferResource: public Resource
+{
+ public:
+ typedef Resource Parent;
+
+ struct Desc
+ {
+ void init(size_t sizeInBytesIn)
+ {
+ bindFlags = 0;
+ cpuAccessFlags = 0;
+ sizeInBytes = sizeInBytesIn;
+ elementSize = 0;
+ }
+ /// Set up default parameters based on usage
+ void setDefaults(Usage initialUsage);
+
+ int bindFlags; ///< Combination of Resource::BindFlag or 0 (and will use initialUsage to set)
+ int cpuAccessFlags; ///< Combination of Resource::AccessFlag
+
+ size_t sizeInBytes; ///< Total size in bytes
+ int elementSize; ///< Get the element stride. If > 0, this is a structured buffer
+ };
+
+ /// Get the buffer description
+ SLANG_FORCE_INLINE const Desc& getDesc() const { return m_desc; }
+
+ /// Ctor
+ BufferResource(const Desc& desc):
+ Parent(Type::Buffer),
+ m_desc(desc)
+ {
+ }
+
+ protected:
+ Desc m_desc;
+};
+
+class TextureResource: public Resource
+{
+ public:
+ typedef Resource Parent;
+
+ struct SampleDesc
+ {
+ void init()
+ {
+ numSamples = 1;
+ quality = 0;
+ }
+ int numSamples; ///< Number of samples per pixel
+ int quality; ///< The quality measure for the samples
+ };
+
+ struct Size
+ {
+ void init()
+ {
+ width = height = depth = 1;
+ }
+ void init(int widthIn, int heightIn = 1, int depthIn = 1)
+ {
+ width = widthIn;
+ height = heightIn;
+ depth = depthIn;
+ }
+ /// Given the type works out the maximum dimension size
+ int calcMaxDimension(Type type) const;
+ /// Given a size, calculates the size at a mip level
+ Size calcMipSize(int mipLevel) const;
+
+ int width; ///< Width in pixels
+ int height; ///< Height in pixels (if 2d or 3d)
+ int depth; ///< Depth (if 3d)
+ };
+
+ struct Desc
+ {
+ /// Initialize with default values
+ void init();
+ /// Initialize different dimensions. For cubemap, use init2D
+ void init1D(Format format, int width, int numMipMaps = 0);
+ void init2D(Format format, int width, int height, int numMipMaps = 0);
+ void init3D(Format format, int width, int height, int depth, int numMipMaps = 0);
+
+ /// Given the type, calculates the number of mip maps. 0 on error
+ int calcNumMipLevels(Type type) const;
+ /// Calculate the total number of sub resources. 0 on error.
+ int calcNumSubResources(Type type) const;
+
+ /// Calculate the effective array size - in essence the amount if mip map sets needed.
+ /// In practice takes into account if the arraySize is 0 (it's not an array, but it will still have at least one mip set)
+ /// and if the type is a cubemap (multiplies the amount of mip sets by 6)
+ int calcEffectiveArraySize(Type type) const;
+
+ ///
+ void fixSize(Type type);
+
+ /// Set up default parameters based on type and usage
+ void setDefaults(Type type, Usage initialUsage);
+
+ int bindFlags; ///< Combination of Resource::BindFlag or 0 (and will use initialUsage to set)
+ int cpuAccessFlags; ///< Combination of Resource::AccessFlag
+
+ Size size;
+
+ int arraySize; ///< Array size
+
+ int numMipLevels; ///< Number of mip levels - if 0 will generate all mip levels
+ Format format; ///< The resources format
+ SampleDesc sampleDesc; ///< How the resource is sampled
+ };
+
+ /// The ordering of the subResources is
+ /// forall (cube faces (6) * arraySize / arraySize)
+ /// forall (mip levels)
+ /// forall (depth levels)
+ struct Data
+ {
+ ptrdiff_t* mipRowStrides; /// The row stride for a mip map
+ int numMips; ///< The number of mip maps
+ const void*const* subResources; ///< Pointers to each full mip subResource
+ int numSubResources; /// The total amount of subResources. Typically = numMips * depth * arraySize
+ };
+
+ /// Get the description of the texture
+ SLANG_FORCE_INLINE const Desc& getDesc() const { return m_desc; }
+
+ /// Ctor
+ TextureResource(Type type, const Desc& desc):
+ Parent(type),
+ m_desc(desc)
+ {
+ }
+
+ SLANG_FORCE_INLINE static int calcMipSize(int width, int mipLevel)
+ {
+ width = width >> mipLevel;
+ return width > 0 ? width : 1;
+ }
+
+ protected:
+ Desc m_desc;
+};
+
class Renderer: public Slang::RefObject
{
public:
@@ -116,28 +328,32 @@ public:
virtual void presentFrame() = 0;
+ /// Create a texture resource. initData holds the initialize data to set the contents of the texture when constructed.
+ virtual TextureResource* createTextureResource(Resource::Type type, Resource::Usage initialUsage, const TextureResource::Desc& desc, const TextureResource::Data* initData = nullptr) { return nullptr; }
+ /// Create a buffer resource
+ virtual BufferResource* createBufferResource(Resource::Usage initialUsage, const BufferResource::Desc& desc, const void* initData = nullptr) { return nullptr; }
+
virtual SlangResult captureScreenShot(const char* outputPath) = 0;
virtual void serializeOutput(BindingState* state, const char* outputPath) = 0;
- virtual Buffer* createBuffer(const BufferDesc& desc) = 0;
virtual InputLayout* createInputLayout(const InputElementDesc* inputElements, UInt inputElementCount) = 0;
virtual BindingState* createBindingState(const ShaderInputLayout& shaderInput) = 0;
virtual ShaderCompiler* getShaderCompiler() = 0;
- virtual void* map(Buffer* buffer, MapFlavor flavor) = 0;
- virtual void unmap(Buffer* buffer) = 0;
+ virtual void* map(BufferResource* buffer, MapFlavor flavor) = 0;
+ virtual void unmap(BufferResource* buffer) = 0;
virtual void setInputLayout(InputLayout* inputLayout) = 0;
virtual void setPrimitiveTopology(PrimitiveTopology topology) = 0;
virtual void setBindingState(BindingState* state) = 0;
- virtual void setVertexBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* strides, const UInt* offsets) = 0;
+ virtual void setVertexBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* strides, const UInt* offsets) = 0;
- inline void setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset = 0);
+ inline void setVertexBuffer(UInt slot, BufferResource* buffer, UInt stride, UInt offset = 0);
virtual void setShaderProgram(ShaderProgram* program) = 0;
- virtual void setConstantBuffers(UInt startSlot, UInt slotCount, Buffer*const* buffers, const UInt* offsets) = 0;
- inline void setConstantBuffer(UInt slot, Buffer* buffer, UInt offset = 0);
+ virtual void setConstantBuffers(UInt startSlot, UInt slotCount, BufferResource*const* buffers, const UInt* offsets) = 0;
+ inline void setConstantBuffer(UInt slot, BufferResource* buffer, UInt offset = 0);
virtual void draw(UInt vertexCount, UInt startVertex = 0) = 0;
virtual void dispatchCompute(int x, int y, int z) = 0;
@@ -149,14 +365,13 @@ public:
virtual void waitForGpu() = 0;
};
-
// ----------------------------------------------------------------------------------------
-inline void Renderer::setVertexBuffer(UInt slot, Buffer* buffer, UInt stride, UInt offset)
+inline void Renderer::setVertexBuffer(UInt slot, BufferResource* buffer, UInt stride, UInt offset)
{
setVertexBuffers(slot, 1, &buffer, &stride, &offset);
}
// ----------------------------------------------------------------------------------------
-inline void Renderer::setConstantBuffer(UInt slot, Buffer* buffer, UInt offset)
+inline void Renderer::setConstantBuffer(UInt slot, BufferResource* buffer, UInt offset)
{
setConstantBuffers(slot, 1, &buffer, &offset);
}
diff --git a/tools/render-test/slang-support.cpp b/tools/render-test/slang-support.cpp
index aa097bb44..d45ce55a4 100644
--- a/tools/render-test/slang-support.cpp
+++ b/tools/render-test/slang-support.cpp
@@ -172,5 +172,125 @@ ShaderCompiler* createSlangShaderCompiler(
return result;
}
+SlangResult generateTextureResource(const InputTextureDesc& inputDesc, int bindFlags, Renderer* renderer, Slang::RefPtr<TextureResource>& textureOut)
+{
+ using namespace Slang;
+
+ TextureData texData;
+ generateTextureData(texData, inputDesc);
+
+ TextureResource::Desc textureResourceDesc;
+ textureResourceDesc.init();
+
+ textureResourceDesc.format = Format::RGBA_Unorm_UInt8;
+ textureResourceDesc.numMipLevels = texData.mipLevels;
+ textureResourceDesc.arraySize = inputDesc.arrayLength;
+ textureResourceDesc.bindFlags = bindFlags;
+
+ // It's the same size in all dimensions
+ Resource::Type type = Resource::Type::Unknown;
+ switch (inputDesc.dimension)
+ {
+ case 1:
+ {
+ type = Resource::Type::Texture1D;
+ textureResourceDesc.size.init(inputDesc.size);
+ break;
+ }
+ case 2:
+ {
+ type = inputDesc.isCube ? Resource::Type::TextureCube : Resource::Type::Texture2D;
+ textureResourceDesc.size.init(inputDesc.size, inputDesc.size);
+ break;
+ }
+ case 3:
+ {
+ type = Resource::Type::Texture3D;
+ textureResourceDesc.size.init(inputDesc.size, inputDesc.size, inputDesc.size);
+ break;
+ }
+ }
+
+ const int effectiveArraySize = textureResourceDesc.calcEffectiveArraySize(type);
+ const int numSubResources = textureResourceDesc.calcNumSubResources(type);
+
+ Resource::Usage initialUsage = Resource::Usage::GenericRead;
+ TextureResource::Data initData;
+
+ List<ptrdiff_t> mipRowStrides;
+ mipRowStrides.SetSize(textureResourceDesc.numMipLevels);
+ List<const void*> subResources;
+ subResources.SetSize(numSubResources);
+
+ // Set up the src row strides
+ for (int i = 0; i < textureResourceDesc.numMipLevels; i++)
+ {
+ const int mipWidth = TextureResource::calcMipSize(textureResourceDesc.size.width, i);
+ mipRowStrides[i] = mipWidth * sizeof(uint32_t);
+ }
+
+ // Set up pointers the the data
+ {
+ int subResourceIndex = 0;
+ const int numGen = int(texData.dataBuffer.Count());
+ for (int i = 0; i < numSubResources; i++)
+ {
+ subResources[i] = texData.dataBuffer[subResourceIndex].Buffer();
+ // Wrap around
+ subResourceIndex = (subResourceIndex + 1 >= numGen) ? 0 : (subResourceIndex + 1);
+ }
+ }
+
+ initData.mipRowStrides = mipRowStrides.Buffer();
+ initData.numMips = textureResourceDesc.numMipLevels;
+ initData.numSubResources = numSubResources;
+ initData.subResources = subResources.Buffer();
+
+ textureOut = renderer->createTextureResource(type, Resource::Usage::GenericRead, textureResourceDesc, &initData);
+
+ return textureOut ? SLANG_OK : SLANG_FAIL;
+}
+
+SlangResult createInputBufferResource(const InputBufferDesc& inputDesc, bool isOutput, size_t bufferSize, const void* initData, Renderer* renderer, Slang::RefPtr<BufferResource>& bufferOut)
+{
+ using namespace Slang;
+
+ Resource::Usage initialUsage = Resource::Usage::GenericRead;
+
+ BufferResource::Desc srcDesc;
+ srcDesc.init(bufferSize);
+
+ int bindFlags = 0;
+ if (inputDesc.type == InputBufferType::ConstantBuffer)
+ {
+ bindFlags |= Resource::BindFlag::ConstantBuffer;
+ srcDesc.cpuAccessFlags |= Resource::AccessFlag::Write;
+ initialUsage = Resource::Usage::ConstantBuffer;
+ }
+ else
+ {
+ bindFlags |= Resource::BindFlag::UnorderedAccess | Resource::BindFlag::PixelShaderResource | Resource::BindFlag::NonPixelShaderResource;
+ srcDesc.elementSize = inputDesc.stride;
+ initialUsage = Resource::Usage::UnorderedAccess;
+ }
+
+ if (isOutput)
+ {
+ srcDesc.cpuAccessFlags |= Resource::AccessFlag::Read;
+ }
+
+ srcDesc.bindFlags = bindFlags;
+
+ RefPtr<BufferResource> bufferResource = renderer->createBufferResource(initialUsage, srcDesc, initData);
+ if (!bufferResource)
+ {
+ return SLANG_FAIL;
+ }
+
+ bufferOut = bufferResource;
+ return SLANG_OK;
+}
+
+
} // renderer_test
diff --git a/tools/render-test/slang-support.h b/tools/render-test/slang-support.h
index d2e32c52a..b5b56c295 100644
--- a/tools/render-test/slang-support.h
+++ b/tools/render-test/slang-support.h
@@ -5,6 +5,8 @@
#include <slang.h>
+#include "shader-input-layout.h"
+
namespace renderer_test {
ShaderCompiler* createSlangShaderCompiler(
@@ -12,4 +14,10 @@ ShaderCompiler* createSlangShaderCompiler(
SlangSourceLanguage sourceLanguage,
SlangCompileTarget target);
+ /// Create the texture resource using the renderer
+SlangResult generateTextureResource(const InputTextureDesc& inputDesc, int bindFlags, Renderer* renderer, Slang::RefPtr<TextureResource>& textureOut);
+
+ /// Create the buffer resource using the renderer
+SlangResult createInputBufferResource(const InputBufferDesc& inputDesc, bool isOutput, size_t bufferSize, const void* initData, Renderer* renderer, Slang::RefPtr<BufferResource>& bufferOut);
+
} // renderer_test