diff options
Diffstat (limited to 'tools/render-test/render-d3d12.cpp')
| -rw-r--r-- | tools/render-test/render-d3d12.cpp | 902 |
1 files changed, 515 insertions, 387 deletions
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)); |
