From 3b41c818a46cb7761e5a5f2878ceb76d9aef1a20 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 19 Jan 2022 10:15:30 -0800 Subject: Fixes to GFX. (#2083) * Fix binding null resource views in d3d12. * Fix array render target view creation. * Add support for more primitive topologies. Co-authored-by: Yong He --- slang-gfx.h | 18 ++--- tools/gfx/d3d/d3d-util.cpp | 32 +++++++- tools/gfx/d3d/d3d-util.h | 2 + tools/gfx/d3d12/render-d3d12.cpp | 171 ++++++++++++++++++++++++++++++++------- 4 files changed, 181 insertions(+), 42 deletions(-) diff --git a/slang-gfx.h b/slang-gfx.h index 5b8ccf05e..010459326 100644 --- a/slang-gfx.h +++ b/slang-gfx.h @@ -371,7 +371,7 @@ enum class PrimitiveType enum class PrimitiveTopology { - TriangleList, + TriangleList, TriangleStrip, PointList, LineList, LineStrip }; enum class ResourceState @@ -668,14 +668,14 @@ public: enum class ComparisonFunc : uint8_t { - Never = 0, - Less = 0x01, - Equal = 0x02, - LessEqual = 0x03, - Greater = 0x04, - NotEqual = 0x05, - GreaterEqual = 0x06, - Always = 0x07, + Never = 0x0, + Less = 0x1, + Equal = 0x2, + LessEqual = 0x3, + Greater = 0x4, + NotEqual = 0x5, + GreaterEqual = 0x6, + Always = 0x7, }; enum class TextureFilteringMode diff --git a/tools/gfx/d3d/d3d-util.cpp b/tools/gfx/d3d/d3d-util.cpp index 860649be4..5d7aa4dd8 100644 --- a/tools/gfx/d3d/d3d-util.cpp +++ b/tools/gfx/d3d/d3d-util.cpp @@ -18,12 +18,36 @@ using namespace Slang; switch (topology) { case PrimitiveTopology::TriangleList: - { - return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - } + return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + case PrimitiveTopology::TriangleStrip: + return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + case PrimitiveTopology::LineList: + return D3D_PRIMITIVE_TOPOLOGY_LINELIST; + case PrimitiveTopology::LineStrip: + return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; + case PrimitiveTopology::PointList: + return D3D_PRIMITIVE_TOPOLOGY_POINTLIST; default: break; } - return D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + return D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + +D3D12_PRIMITIVE_TOPOLOGY_TYPE D3DUtil::getPrimitiveType(PrimitiveTopology topology) +{ + switch (topology) + { + case PrimitiveTopology::TriangleList: + case PrimitiveTopology::TriangleStrip: + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + case PrimitiveTopology::LineList: + case PrimitiveTopology::LineStrip: + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; + case PrimitiveTopology::PointList: + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; + default: + break; + } + return D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED; } D3D12_PRIMITIVE_TOPOLOGY_TYPE D3DUtil::getPrimitiveType(PrimitiveType type) diff --git a/tools/gfx/d3d/d3d-util.h b/tools/gfx/d3d/d3d-util.h index dd22bfcdd..34feabc7f 100644 --- a/tools/gfx/d3d/d3d-util.h +++ b/tools/gfx/d3d/d3d-util.h @@ -50,6 +50,8 @@ class D3DUtil static D3D12_PRIMITIVE_TOPOLOGY_TYPE getPrimitiveType(PrimitiveType type); + static D3D12_PRIMITIVE_TOPOLOGY_TYPE getPrimitiveType(PrimitiveTopology topology); + static D3D12_COMPARISON_FUNC getComparisonFunc(ComparisonFunc func); static D3D12_DEPTH_STENCILOP_DESC translateStencilOpDesc(DepthStencilOpDesc desc); diff --git a/tools/gfx/d3d12/render-d3d12.cpp b/tools/gfx/d3d12/render-d3d12.cpp index c30389ec2..c551796c4 100644 --- a/tools/gfx/d3d12/render-d3d12.cpp +++ b/tools/gfx/d3d12/render-d3d12.cpp @@ -981,6 +981,9 @@ public: /// The type of binding in this range. slang::BindingType bindingType; + /// The shape of the resource + SlangResourceShape resourceShape; + /// The number of distinct bindings in this range. uint32_t count; @@ -1118,6 +1121,7 @@ public: typeLayout->getBindingRangeLeafTypeLayout(r); BindingRangeInfo bindingRangeInfo = {}; bindingRangeInfo.bindingType = slangBindingType; + bindingRangeInfo.resourceShape = slangLeafTypeLayout->getResourceShape(); bindingRangeInfo.count = count; switch (slangBindingType) @@ -3343,19 +3347,8 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL setPrimitiveTopology(PrimitiveTopology topology) override { - switch (topology) - { - case PrimitiveTopology::TriangleList: - { - m_primitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - m_primitiveTopology = D3DUtil::getPrimitiveTopology(topology); - break; - } - default: - { - assert(!"Unhandled type"); - } - } + m_primitiveTopologyType = D3DUtil::getPrimitiveType(topology); + m_primitiveTopology = D3DUtil::getPrimitiveTopology(topology); } virtual SLANG_NO_THROW void SLANG_MCALL setVertexBuffers( @@ -4726,8 +4719,8 @@ Result D3D12Device::PipelineCommandEncoder::_bindRenderState(Submitter* submitte auto commandList = m_d3dCmdList; auto pipelineTypeIndex = (int)newPipelineImpl->desc.type; auto programImpl = static_cast(newPipelineImpl->m_program.Ptr()); - submitter->setPipelineState(newPipelineImpl); submitter->setRootSignature(programImpl->m_rootObjectLayout->m_rootSignature); + submitter->setPipelineState(newPipelineImpl); RefPtr specializedRootLayout; SLANG_RETURN_ON_FAIL(rootObjectImpl->getSpecializedLayout(specializedRootLayout.writeRef())); RootShaderObjectLayoutImpl* rootLayoutImpl = @@ -5481,13 +5474,13 @@ Result D3D12Device::initialize(const Desc& desc) // Allocate a D3D12 "command signature" object that matches the behavior // of a D3D11-style `DrawInstancedIndirect` operation. { - D3D12_INDIRECT_ARGUMENT_DESC args[1]; - args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW; + D3D12_INDIRECT_ARGUMENT_DESC args; + args.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW; D3D12_COMMAND_SIGNATURE_DESC desc; - desc.ByteStride = 36; + desc.ByteStride = sizeof(D3D12_DRAW_ARGUMENTS); desc.NumArgumentDescs = 1; - desc.pArgumentDescs = args; + desc.pArgumentDescs = &args; desc.NodeMask = 0; SLANG_RETURN_ON_FAIL(m_device->CreateCommandSignature(&desc, nullptr, IID_PPV_ARGS(drawIndirectCmdSignature.writeRef()))); @@ -5496,13 +5489,13 @@ Result D3D12Device::initialize(const Desc& desc) // Allocate a D3D12 "command signature" object that matches the behavior // of a D3D11-style `DrawIndexedInstancedIndirect` operation. { - D3D12_INDIRECT_ARGUMENT_DESC args[1]; - args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; + D3D12_INDIRECT_ARGUMENT_DESC args; + args.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED; D3D12_COMMAND_SIGNATURE_DESC desc; - desc.ByteStride = 36; + desc.ByteStride = sizeof(D3D12_DRAW_INDEXED_ARGUMENTS); desc.NumArgumentDescs = 1; - desc.pArgumentDescs = args; + desc.pArgumentDescs = &args; desc.NodeMask = 0; SLANG_RETURN_ON_FAIL(m_device->CreateCommandSignature(&desc, nullptr, IID_PPV_ARGS(drawIndexedIndirectCmdSignature.writeRef()))); @@ -6059,6 +6052,7 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: viewImpl->m_allocator = m_rtvAllocator; D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; rtvDesc.Format = D3DUtil::getMapFormat(desc.format); + isArray = desc.renderTarget.arraySize > 1; switch (desc.renderTarget.shape) { case IResource::Type::Texture1D: @@ -6078,8 +6072,8 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: { rtvDesc.ViewDimension = isArray ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY : D3D12_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = desc.renderTarget.mipSlice; - rtvDesc.Texture2D.PlaneSlice = desc.renderTarget.planeIndex; + rtvDesc.Texture2DArray.MipSlice = desc.renderTarget.mipSlice; + rtvDesc.Texture2DArray.PlaneSlice = desc.renderTarget.planeIndex; rtvDesc.Texture2DArray.ArraySize = desc.renderTarget.arraySize; rtvDesc.Texture2DArray.FirstArraySlice = desc.renderTarget.arrayIndex; } @@ -6104,6 +6098,7 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: viewImpl->m_allocator = m_dsvAllocator; D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = {}; dsvDesc.Format = D3DUtil::getMapFormat(desc.format); + isArray = desc.renderTarget.arraySize > 1; switch (desc.renderTarget.shape) { case IResource::Type::Texture1D: @@ -6111,8 +6106,21 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: dsvDesc.Texture1D.MipSlice = desc.renderTarget.mipSlice; break; case IResource::Type::Texture2D: - dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = desc.renderTarget.mipSlice; + if (resourceImpl->getDesc()->sampleDesc.numSamples > 1) + { + dsvDesc.ViewDimension = isArray ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY + : D3D12_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2DMSArray.ArraySize = desc.renderTarget.arraySize; + dsvDesc.Texture2DMSArray.FirstArraySlice = desc.renderTarget.arrayIndex; + } + else + { + dsvDesc.ViewDimension = isArray ? D3D12_DSV_DIMENSION_TEXTURE2DARRAY + : D3D12_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2DArray.MipSlice = desc.renderTarget.mipSlice; + dsvDesc.Texture2DArray.ArraySize = desc.renderTarget.arraySize; + dsvDesc.Texture2DArray.FirstArraySlice = desc.renderTarget.arrayIndex; + } break; default: return SLANG_FAIL; @@ -6183,8 +6191,7 @@ Result D3D12Device::createTextureView(ITextureResource* texture, IResourceView:: // Need to construct the D3D12_SHADER_RESOURCE_VIEW_DESC because otherwise TextureCube is not accessed // appropriately (rather than just passing nullptr to CreateShaderResourceView) const D3D12_RESOURCE_DESC resourceDesc = resourceImpl->m_resource.getResource()->GetDesc(); - const DXGI_FORMAT pixelFormat = - gfxIsTypelessFormat(texture->getDesc()->format) ? D3DUtil::getMapFormat(desc.format) : resourceDesc.Format; + const DXGI_FORMAT pixelFormat = desc.format == Format::Unknown ? resourceDesc.Format : D3DUtil::getMapFormat(desc.format); D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc; _initSrvDesc( @@ -7517,6 +7524,103 @@ Result D3D12Device::RayTracingPipelineStateImpl::createShaderTables( #endif // SLANG_GFX_HAS_DXR_SUPPORT +Result createNullDescriptor( + ID3D12Device* d3dDevice, + D3D12_CPU_DESCRIPTOR_HANDLE destDescriptor, + const D3D12Device::ShaderObjectLayoutImpl::BindingRangeInfo& bindingRange) +{ + switch (bindingRange.bindingType) + { + case slang::BindingType::ConstantBuffer: + { + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = 0; + cbvDesc.SizeInBytes = 0; + d3dDevice->CreateConstantBufferView(&cbvDesc, destDescriptor); + } + break; + case slang::BindingType::MutableRawBuffer: + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; + uavDesc.Format = DXGI_FORMAT_R32_TYPELESS; + d3dDevice->CreateUnorderedAccessView(nullptr, nullptr, &uavDesc, destDescriptor); + } + break; + case slang::BindingType::MutableTypedBuffer: + { + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + uavDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + d3dDevice->CreateUnorderedAccessView(nullptr, nullptr, &uavDesc, destDescriptor); + } + break; + case slang::BindingType::RawBuffer: + { + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; + srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + d3dDevice->CreateShaderResourceView(nullptr, &srvDesc, destDescriptor); + } + break; + case slang::BindingType::TypedBuffer: + { + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + d3dDevice->CreateShaderResourceView(nullptr, &srvDesc, destDescriptor); + } + break; + case slang::BindingType::Texture: + { + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + switch (bindingRange.resourceShape) + { + case SLANG_TEXTURE_1D: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + break; + case SLANG_TEXTURE_1D_ARRAY: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + break; + case SLANG_TEXTURE_2D: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + break; + case SLANG_TEXTURE_2D_ARRAY: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + break; + case SLANG_TEXTURE_3D: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + break; + case SLANG_TEXTURE_CUBE: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + break; + case SLANG_TEXTURE_CUBE_ARRAY: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; + break; + case SLANG_TEXTURE_2D_MULTISAMPLE: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; + break; + case SLANG_TEXTURE_2D_MULTISAMPLE_ARRAY: + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; + break; + default: + return SLANG_OK; + } + d3dDevice->CreateShaderResourceView(nullptr, &srvDesc, destDescriptor); + } + break; + default: + break; + } + return SLANG_OK; +} + Result D3D12Device::ShaderObjectImpl::setResource(ShaderOffset const& offset, IResourceView* resourceView) { if (offset.bindingRangeIndex < 0) @@ -7525,8 +7629,18 @@ Result D3D12Device::ShaderObjectImpl::setResource(ShaderOffset const& offset, IR if (offset.bindingRangeIndex >= layout->getBindingRangeCount()) return SLANG_E_INVALID_ARG; + ID3D12Device* d3dDevice = static_cast(getDevice())->m_device; + auto& bindingRange = layout->getBindingRange(offset.bindingRangeIndex); + if (resourceView == nullptr) + { + // Create null descriptor for the binding. + auto destDescriptor = m_descriptorSet.resourceTable.getCpuHandle( + bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex); + return createNullDescriptor(d3dDevice, destDescriptor, bindingRange); + } + ResourceViewInternalImpl* internalResourceView = nullptr; switch (resourceView->getViewDesc()->type) { @@ -7552,7 +7666,6 @@ Result D3D12Device::ShaderObjectImpl::setResource(ShaderOffset const& offset, IR } auto descriptorSlotIndex = bindingRange.baseIndex + (int32_t)offset.bindingArrayIndex; - ID3D12Device* d3dDevice = static_cast(getDevice())->m_device; d3dDevice->CopyDescriptorsSimple( 1, m_descriptorSet.resourceTable.getCpuHandle( -- cgit v1.2.3