diff options
| author | azhirnov <zh1dron@gmail.com> | 2020-08-11 19:48:23 +0000 |
|---|---|---|
| committer | azhirnov <zh1dron@gmail.com> | 2020-08-11 19:49:36 +0000 |
| commit | dc9a4e784c8bb97fbb16a01624c7b8f0544977a4 (patch) | |
| tree | b4a07f6e2029ca9d20999acfd940ea8e2556cb9d /Graphics/GraphicsEngineD3D12 | |
| parent | Bash function for format validation in submodules (#155) (diff) | |
| download | DiligentCore-dc9a4e784c8bb97fbb16a01624c7b8f0544977a4.tar.gz DiligentCore-dc9a4e784c8bb97fbb16a01624c7b8f0544977a4.zip | |
Added mesh shader
added mesh shader support to DX12 and Vulkan, added DXIL compiler for Shader Model 6.x
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
11 files changed, 396 insertions, 131 deletions
diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index 6ea2fc22..4fe2a6c3 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -171,6 +171,14 @@ PUBLIC ) target_compile_definitions(Diligent-GraphicsEngineD3D12-shared PUBLIC ENGINE_DLL=1) +if(${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} STRGREATER_EQUAL "10.0.19041.0") + target_compile_definitions(Diligent-GraphicsEngineD3D12-static PRIVATE D12_H_HAS_MESH_SHADER) +endif() +if(${HAS_DXIL_COMPILER}) + target_compile_definitions(Diligent-GraphicsEngineD3D12-static PRIVATE HAS_DXIL_COMPILER) + target_link_libraries(Diligent-GraphicsEngineD3D12-static PRIVATE dxcompiler.lib) +endif() + # Set output name to GraphicsEngineD3D12_{32|64}{r|d} set_dll_output_name(Diligent-GraphicsEngineD3D12-shared GraphicsEngineD3D12) diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp index a8211db6..f5e3e681 100644 --- a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp +++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp @@ -339,6 +339,18 @@ public: FlushResourceBarriers(); m_pCommandList->DrawIndexedInstanced(IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation); } + + void DrawMesh(UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ) + { +#ifdef D12_H_HAS_MESH_SHADER + FlushResourceBarriers(); + CComPtr<ID3D12GraphicsCommandList6> CmdList; + if (SUCCEEDED(m_pCommandList->QueryInterface(__uuidof(CmdList), reinterpret_cast<void **>(&CmdList)))) + CmdList->DispatchMesh(ThreadGroupCountX, ThreadGroupCountY, ThreadGroupCountZ); +#else + UNSUPPORTED("DrawMesh is not supported in current D3D12 header"); +#endif + } }; class ComputeContext : public CommandContext diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp index 5c6912b6..f7359ec8 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp @@ -131,6 +131,10 @@ public: virtual void DILIGENT_CALL_TYPE DrawIndirect (const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; /// Implementation of IDeviceContext::DrawIndexedIndirect() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; + /// Implementation of IDeviceContext::DrawMesh() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final; + /// Implementation of IDeviceContext::DrawMeshIndirect() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final; /// Implementation of IDeviceContext::DispatchCompute() in Direct3D12 backend. @@ -382,6 +386,7 @@ private: CComPtr<ID3D12CommandSignature> m_pDrawIndirectSignature; CComPtr<ID3D12CommandSignature> m_pDrawIndexedIndirectSignature; CComPtr<ID3D12CommandSignature> m_pDispatchIndirectSignature; + CComPtr<ID3D12CommandSignature> m_pDrawMeshIndirectSignature; D3D12DynamicHeap m_DynamicHeap; diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp index 303f8bfb..7f4446ac 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -143,6 +143,7 @@ public: const GenerateMipsHelper& GetMipsGenerator() const { return m_MipsGenerator; } QueryManagerD3D12& GetQueryManager() { return m_QueryMgr; } + D3D_SHADER_MODEL GetShaderModel() const; D3D_FEATURE_LEVEL GetD3DFeatureLevel() const; private: diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp index 23f9882b..88c1cdc5 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp @@ -92,7 +92,7 @@ class ShaderResourcesD3D12 final : public ShaderResources { public: // Loads shader resources from the compiled shader bytecode - ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix); + ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, bool isDXIL, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix); // clang-format off ShaderResourcesD3D12 (const ShaderResourcesD3D12&) = delete; diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 5fa7f8e1..b351713c 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -204,7 +204,7 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) // This is necessary because if the command list had been flushed // and the first PSO set on the command list was a compute pipeline, // the states would otherwise never be committed (since m_pPipelineState != nullptr) - CommitStates = OldPSODesc.IsComputePipeline; + CommitStates = OldPSODesc.IsComputePipeline(); // We also need to update scissor rect if ScissorEnable state has changed CommitScissor = OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable != PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable; } @@ -214,7 +214,7 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) auto& CmdCtx = GetCmdContext(); auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState(); - if (PSODesc.IsComputePipeline) + if (PSODesc.IsComputePipeline()) { CmdCtx.AsComputeContext().SetPipelineState(pd3d12PSO); } @@ -541,6 +541,34 @@ void DeviceContextD3D12Impl::DrawIndexedIndirect(const DrawIndexedIndirectAttrib ++m_State.NumCommands; } +void DeviceContextD3D12Impl::DrawMesh(const DrawMeshAttribs& Attribs) +{ + if (!DvpVerifyDrawMeshArguments(Attribs)) + return; + + auto& GraphCtx = GetCmdContext().AsGraphicsContext(); + PrepareForDraw(GraphCtx, Attribs.Flags); + + GraphCtx.DrawMesh(Attribs.ThreadGroupCount, 1, 1); + ++m_State.NumCommands; +} + +void DeviceContextD3D12Impl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) +{ + if (!DvpVerifyDrawMeshIndirectArguments(Attribs, pAttribsBuffer)) + return; + + auto& GraphCtx = GetCmdContext().AsGraphicsContext(); + PrepareForDraw(GraphCtx, Attribs.Flags); + + ID3D12Resource* pd3d12ArgsBuff; + Uint64 BuffDataStartByteOffset; + PrepareDrawIndirectBuffer(GraphCtx, pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode, pd3d12ArgsBuff, BuffDataStartByteOffset); + + GraphCtx.ExecuteIndirect(m_pDrawMeshIndirectSignature, pd3d12ArgsBuff, Attribs.IndirectDrawArgsOffset + BuffDataStartByteOffset); + ++m_State.NumCommands; +} + void DeviceContextD3D12Impl::PrepareForDispatchCompute(ComputeContext& ComputeCtx) { ComputeCtx.SetRootSignature(m_pPipelineState->GetD3D12RootSignature()); @@ -894,7 +922,7 @@ void DeviceContextD3D12Impl::SetScissorRects(Uint32 NumRects, const Rect* pRects if (m_pPipelineState) { const auto& PSODesc = m_pPipelineState->GetDesc(); - if (!PSODesc.IsComputePipeline && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable) + if (PSODesc.IsAnyGraphicsPipeline() && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable) { VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects"); auto& Ctx = GetCmdContext().AsGraphicsContext(); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 168736a0..bf6c3ae5 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -40,6 +40,33 @@ namespace Diligent { +namespace +{ +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4324) +#endif + + template <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE SubObjType> + struct alignas(void*) PSS_SubObject + { + const D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type {SubObjType}; + InnerStructType Obj {}; + + PSS_SubObject() {} + + PSS_SubObject& operator= (const InnerStructType &obj) { Obj = obj; return *this; } + + InnerStructType* operator-> () { return &Obj; } + InnerStructType* operator& () { return &Obj; } + InnerStructType& operator* () { return Obj; } + }; + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +} // namespace class PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE { @@ -158,121 +185,221 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR } m_RootSig.Finalize(pd3d12Device); - if (m_Desc.IsComputePipeline) + switch (m_Desc.PipelineType) { - auto& ComputePipeline = m_Desc.ComputePipeline; + case COMPUTE_PIPELINE: + { + auto& ComputePipeline = m_Desc.ComputePipeline; - if (ComputePipeline.pCS == nullptr) - LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc"); + if (ComputePipeline.pCS == nullptr) + LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc"); - D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; + D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; - d3d12PSODesc.pRootSignature = nullptr; + d3d12PSODesc.pRootSignature = nullptr; - auto* pByteCode = ValidatedCast<ShaderD3D12Impl>(ComputePipeline.pCS)->GetShaderByteCode(); - d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); - d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); + auto* pByteCode = ValidatedCast<ShaderD3D12Impl>(ComputePipeline.pCS)->GetShaderByteCode(); + d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); + d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>(static_cast<ID3D12PipelineState**>(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); - } - else - { - const auto& GraphicsPipeline = m_Desc.GraphicsPipeline; - - D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; + HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>(static_cast<ID3D12PipelineState**>(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + break; + } - for (Uint32 s = 0; s < m_NumShaders; ++s) + case GRAPHICS_PIPELINE: { - auto* pShaderD3D12 = GetShader<ShaderD3D12Impl>(s); - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + const auto& GraphicsPipeline = m_Desc.GraphicsPipeline; + + D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) + for (Uint32 s = 0; s < m_NumShaders; ++s) { - // clang-format off - case SHADER_TYPE_VERTEX: pd3d12ShaderBytecode = &d3d12PSODesc.VS; break; - case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; - case SHADER_TYPE_GEOMETRY: pd3d12ShaderBytecode = &d3d12PSODesc.GS; break; - case SHADER_TYPE_HULL: pd3d12ShaderBytecode = &d3d12PSODesc.HS; break; - case SHADER_TYPE_DOMAIN: pd3d12ShaderBytecode = &d3d12PSODesc.DS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); + auto* pShaderD3D12 = GetShader<ShaderD3D12Impl>(s); + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off + case SHADER_TYPE_VERTEX: pd3d12ShaderBytecode = &d3d12PSODesc.VS; break; + case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; + case SHADER_TYPE_GEOMETRY: pd3d12ShaderBytecode = &d3d12PSODesc.GS; break; + case SHADER_TYPE_HULL: pd3d12ShaderBytecode = &d3d12PSODesc.HS; break; + case SHADER_TYPE_DOMAIN: pd3d12ShaderBytecode = &d3d12PSODesc.DS; break; + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); - memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); + // The sample mask for the blend state. + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); - // The sample mask for the blend state. - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); + std::vector<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC>> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D12_INPUT_ELEMENT_DESC>")); - std::vector<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC>> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D12_INPUT_ELEMENT_DESC>")); + const auto& InputLayout = m_Desc.GraphicsPipeline.InputLayout; + if (InputLayout.NumElements > 0) + { + LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); + d3d12PSODesc.InputLayout.NumElements = static_cast<UINT>(d312InputElements.size()); + d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); + } + else + { + d3d12PSODesc.InputLayout.NumElements = 0; + d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; + } - const auto& InputLayout = m_Desc.GraphicsPipeline.InputLayout; - if (InputLayout.NumElements > 0) - { - LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); - d3d12PSODesc.InputLayout.NumElements = static_cast<UINT>(d312InputElements.size()); - d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); - } - else - { - d3d12PSODesc.InputLayout.NumElements = 0; - d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; - } + d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; + d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; - d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; - static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; - d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; + d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < 8; ++rt) + d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < 8; ++rt) - d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; - d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>(static_cast<ID3D12PipelineState**>(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + break; + } + +#ifdef D12_H_HAS_MESH_SHADER + case MESH_PIPELINE: + { + const auto& GraphicsPipeline = m_Desc.GraphicsPipeline; + + struct MESH_SHADER_PIPELINE_STATE_DESC + { + PSS_SubObject<D3D12_PIPELINE_STATE_FLAGS, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS> Flags; + PSS_SubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK> NodeMask; + PSS_SubObject<ID3D12RootSignature*, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> pRootSignature; + PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> PS; + PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS> AS; + PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS> MS; + PSS_SubObject<D3D12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND> BlendState; + PSS_SubObject<D3D12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL> DepthStencilState; + PSS_SubObject<D3D12_RASTERIZER_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER> RasterizerState; + PSS_SubObject<DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC> SampleDesc; + PSS_SubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK> SampleMask; + PSS_SubObject<DXGI_FORMAT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT> DSVFormat; + PSS_SubObject<D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> RTVFormatArray; + PSS_SubObject<D3D12_CACHED_PIPELINE_STATE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO> CachedPSO; + }; + MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; + + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + auto* pShaderD3D12 = GetShader<ShaderD3D12Impl>(s); + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off + case SHADER_TYPE_AMPLIFICATION: pd3d12ShaderBytecode = &d3d12PSODesc.AS; break; + case SHADER_TYPE_MESH: pd3d12ShaderBytecode = &d3d12PSODesc.MS; break; + case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } + + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); + // The sample mask for the blend state. + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); + + d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < 8; ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + + d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; + + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; + + d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; + + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; + streamDesc.SizeInBytes = sizeof(d3d12PSODesc); + streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; + + CComPtr<ID3D12Device2> device2; + HRESULT hr = pd3d12Device->QueryInterface(IID_PPV_ARGS(&device2)); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to get ID3D12Device2"); + + hr = device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + break; + } +#endif // D12_H_HAS_MESH_SHADER - HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast<void**>(static_cast<ID3D12PipelineState**>(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); + default: + LOG_ERROR_AND_THROW("Unknown shader type"); } if (*m_Desc.Name != 0) @@ -402,7 +529,7 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou { if (Attrib.CommitResources) { - if (m_Desc.IsComputePipeline) + if (m_Desc.IsComputePipeline()) CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); else CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature()); @@ -431,18 +558,18 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou auto& ResourceCache = pResBindingD3D12Impl->GetResourceCache(); if (Attrib.CommitResources) { - if (m_Desc.IsComputePipeline) + if (m_Desc.IsComputePipeline()) CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); else CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature()); if (Attrib.TransitionResources) { - (m_RootSig.*m_RootSig.TransitionAndCommitDescriptorHandles)(m_pDevice, ResourceCache, CmdCtx, m_Desc.IsComputePipeline, Attrib.ValidateStates); + (m_RootSig.*m_RootSig.TransitionAndCommitDescriptorHandles)(m_pDevice, ResourceCache, CmdCtx, m_Desc.IsComputePipeline(), Attrib.ValidateStates); } else { - (m_RootSig.*m_RootSig.CommitDescriptorHandles)(m_pDevice, ResourceCache, CmdCtx, m_Desc.IsComputePipeline, Attrib.ValidateStates); + (m_RootSig.*m_RootSig.CommitDescriptorHandles)(m_pDevice, ResourceCache, CmdCtx, m_Desc.IsComputePipeline(), Attrib.ValidateStates); } } else @@ -454,7 +581,7 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou // Process only non-dynamic buffers at this point. Dynamic buffers will be handled by the Draw/Dispatch command. m_RootSig.CommitRootViews(ResourceCache, CmdCtx, - m_Desc.IsComputePipeline, + m_Desc.IsComputePipeline(), Attrib.CtxId, pDeviceCtx, Attrib.CommitResources, // CommitViews diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 0315f7f0..2f061df3 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -63,6 +63,34 @@ static CComPtr<IDXGIAdapter1> DXGIAdapterFromD3D12Device(ID3D12Device* pd3d12Dev return nullptr; } +D3D_SHADER_MODEL RenderDeviceD3D12Impl::GetShaderModel() const +{ +#ifdef HAS_DXIL_COMPILER + // Header may not have constants for D3D_SHADER_MODEL_6_5 and above. + const D3D_SHADER_MODEL Models[] = { + D3D_SHADER_MODEL(0x65), // for mesh shader + D3D_SHADER_MODEL(0x64), + D3D_SHADER_MODEL(0x60) + }; + + // Get maximum supported shader model + D3D12_FEATURE_DATA_SHADER_MODEL ShaderModel = {}; + if (m_pd3d12Device) + { + for (auto Model : Models) + { + ShaderModel.HighestShaderModel = Model; + if (SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_SHADER_MODEL, &ShaderModel, sizeof(ShaderModel)))) + return ShaderModel.HighestShaderModel; + } + } +#endif + + // Direct3D12 supports shader model 5.1 on all feature levels. + // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels#feature-level-support + return D3D_SHADER_MODEL_5_1; +} + D3D_FEATURE_LEVEL RenderDeviceD3D12Impl::GetD3DFeatureLevel() const { D3D_FEATURE_LEVEL FeatureLevels[] = @@ -180,6 +208,19 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo m_DeviceCaps.Features.BindlessResources = True; m_DeviceCaps.Features.VertexPipelineUAVWritesAndAtomics = True; + + const D3D_SHADER_MODEL ShaderModel = GetShaderModel(); + + // Check if mesh shader is supported. +#ifdef D12_H_HAS_MESH_SHADER + { + D3D12_FEATURE_DATA_D3D12_OPTIONS7 FeatureData = {}; + bool SupportsMeshShader = SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &FeatureData, sizeof(FeatureData))) && + FeatureData.MeshShaderTier != D3D12_MESH_SHADER_TIER_NOT_SUPPORTED; + + m_DeviceCaps.Features.MeshShaders = (ShaderModel >= D3D_SHADER_MODEL_6_5 && SupportsMeshShader); + } +#endif auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 958df523..f5eeceb1 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -177,12 +177,16 @@ RootSignature::RootSignature() : // clang-format off static D3D12_SHADER_VISIBILITY ShaderTypeInd2ShaderVisibilityMap[] { - D3D12_SHADER_VISIBILITY_VERTEX, // 0 - D3D12_SHADER_VISIBILITY_PIXEL, // 1 - D3D12_SHADER_VISIBILITY_GEOMETRY, // 2 - D3D12_SHADER_VISIBILITY_HULL, // 3 - D3D12_SHADER_VISIBILITY_DOMAIN, // 4 - D3D12_SHADER_VISIBILITY_ALL // 5 + D3D12_SHADER_VISIBILITY_VERTEX, // 0 + D3D12_SHADER_VISIBILITY_PIXEL, // 1 + D3D12_SHADER_VISIBILITY_GEOMETRY, // 2 + D3D12_SHADER_VISIBILITY_HULL, // 3 + D3D12_SHADER_VISIBILITY_DOMAIN, // 4 + D3D12_SHADER_VISIBILITY_ALL, // 5 +#ifdef D12_H_HAS_MESH_SHADER + D3D12_SHADER_VISIBILITY_AMPLIFICATION, // 6 + D3D12_SHADER_VISIBILITY_MESH // 7 +#endif }; // clang-format on D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType) @@ -193,12 +197,16 @@ D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType) switch (ShaderType) { // clang-format off - case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_VERTEX); break; - case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL); break; - case SHADER_TYPE_GEOMETRY: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_GEOMETRY); break; - case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_HULL); break; - case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_DOMAIN); break; - case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL); break; + case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_VERTEX); break; + case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL); break; + case SHADER_TYPE_GEOMETRY: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_GEOMETRY); break; + case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_HULL); break; + case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_DOMAIN); break; + case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL); break; +# ifdef D12_H_HAS_MESH_SHADER + case SHADER_TYPE_AMPLIFICATION: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_AMPLIFICATION); break; + case SHADER_TYPE_MESH: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_MESH); break; +# endif // clang-format on default: LOG_ERROR("Unknown shader type (", ShaderType, ")"); break; } @@ -209,29 +217,35 @@ D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType) // clang-format off static SHADER_TYPE ShaderVisibility2ShaderTypeMap[] = { - SHADER_TYPE_COMPUTE, // D3D12_SHADER_VISIBILITY_ALL = 0 - SHADER_TYPE_VERTEX, // D3D12_SHADER_VISIBILITY_VERTEX = 1 - SHADER_TYPE_HULL, // D3D12_SHADER_VISIBILITY_HULL = 2 - SHADER_TYPE_DOMAIN, // D3D12_SHADER_VISIBILITY_DOMAIN = 3 - SHADER_TYPE_GEOMETRY, // D3D12_SHADER_VISIBILITY_GEOMETRY = 4 - SHADER_TYPE_PIXEL // D3D12_SHADER_VISIBILITY_PIXEL = 5 + SHADER_TYPE_COMPUTE, // D3D12_SHADER_VISIBILITY_ALL = 0 + SHADER_TYPE_VERTEX, // D3D12_SHADER_VISIBILITY_VERTEX = 1 + SHADER_TYPE_HULL, // D3D12_SHADER_VISIBILITY_HULL = 2 + SHADER_TYPE_DOMAIN, // D3D12_SHADER_VISIBILITY_DOMAIN = 3 + SHADER_TYPE_GEOMETRY, // D3D12_SHADER_VISIBILITY_GEOMETRY = 4 + SHADER_TYPE_PIXEL, // D3D12_SHADER_VISIBILITY_PIXEL = 5 + SHADER_TYPE_AMPLIFICATION, // D3D12_SHADER_VISIBILITY_AMPLIFICATION = 6 + SHADER_TYPE_MESH // D3D12_SHADER_VISIBILITY_MESH = 7 }; // clang-format on SHADER_TYPE ShaderTypeFromShaderVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility) { - VERIFY_EXPR(ShaderVisibility >= D3D12_SHADER_VISIBILITY_ALL && ShaderVisibility <= D3D12_SHADER_VISIBILITY_PIXEL); + VERIFY_EXPR(uint32_t(ShaderVisibility) < std::size(ShaderVisibility2ShaderTypeMap)); auto ShaderType = ShaderVisibility2ShaderTypeMap[ShaderVisibility]; #ifdef DILIGENT_DEBUG switch (ShaderVisibility) { // clang-format off - case D3D12_SHADER_VISIBILITY_VERTEX: VERIFY_EXPR(ShaderType == SHADER_TYPE_VERTEX); break; - case D3D12_SHADER_VISIBILITY_PIXEL: VERIFY_EXPR(ShaderType == SHADER_TYPE_PIXEL); break; - case D3D12_SHADER_VISIBILITY_GEOMETRY: VERIFY_EXPR(ShaderType == SHADER_TYPE_GEOMETRY); break; - case D3D12_SHADER_VISIBILITY_HULL: VERIFY_EXPR(ShaderType == SHADER_TYPE_HULL); break; - case D3D12_SHADER_VISIBILITY_DOMAIN: VERIFY_EXPR(ShaderType == SHADER_TYPE_DOMAIN); break; - case D3D12_SHADER_VISIBILITY_ALL: VERIFY_EXPR(ShaderType == SHADER_TYPE_COMPUTE); break; + case D3D12_SHADER_VISIBILITY_VERTEX: VERIFY_EXPR(ShaderType == SHADER_TYPE_VERTEX); break; + case D3D12_SHADER_VISIBILITY_PIXEL: VERIFY_EXPR(ShaderType == SHADER_TYPE_PIXEL); break; + case D3D12_SHADER_VISIBILITY_GEOMETRY: VERIFY_EXPR(ShaderType == SHADER_TYPE_GEOMETRY); break; + case D3D12_SHADER_VISIBILITY_HULL: VERIFY_EXPR(ShaderType == SHADER_TYPE_HULL); break; + case D3D12_SHADER_VISIBILITY_DOMAIN: VERIFY_EXPR(ShaderType == SHADER_TYPE_DOMAIN); break; + case D3D12_SHADER_VISIBILITY_ALL: VERIFY_EXPR(ShaderType == SHADER_TYPE_COMPUTE); break; +# ifdef D12_H_HAS_MESH_SHADER + case D3D12_SHADER_VISIBILITY_AMPLIFICATION: VERIFY_EXPR(ShaderType == SHADER_TYPE_AMPLIFICATION); break; + case D3D12_SHADER_VISIBILITY_MESH: VERIFY_EXPR(ShaderType == SHADER_TYPE_MESH); break; +# endif // clang-format on default: LOG_ERROR("Unknown shader visibility (", ShaderVisibility, ")"); break; } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp index 859a1a3d..dc723614 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp @@ -36,19 +36,16 @@ namespace Diligent { -static const std::string GetD3D12ShaderModel(RenderDeviceD3D12Impl* /*pDevice*/, const ShaderVersion& HLSLVersion) +static const Uint8 GetD3D12ShaderModel(RenderDeviceD3D12Impl* pDevice, const ShaderVersion& HLSLVersion) { if (HLSLVersion.Major == 0 && HLSLVersion.Minor == 0) { - //auto d3dDeviceFeatureLevel = pDevice->GetD3DFeatureLevel(); - - // Direct3D12 supports shader model 5.1 on all feature levels. - // https://docs.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels#feature-level-support - return "5_1"; + D3D_SHADER_MODEL ver = pDevice->GetShaderModel(); + return Uint8((ver & 0xF0) | (ver & 0x0F)); } else { - return std::to_string(Uint32{HLSLVersion.Major}) + '_' + std::to_string(Uint32{HLSLVersion.Minor}); + return Uint8(((HLSLVersion.Major & 0xF) << 4) | (HLSLVersion.Minor & 0xF)); } } @@ -62,13 +59,13 @@ ShaderD3D12Impl::ShaderD3D12Impl(IReferenceCounters* pRefCounters, pRenderDeviceD3D12, ShaderCI.Desc }, - ShaderD3DBase{ShaderCI, GetD3D12ShaderModel(pRenderDeviceD3D12, ShaderCI.HLSLVersion).c_str()} + ShaderD3DBase{ShaderCI, GetD3D12ShaderModel(pRenderDeviceD3D12, ShaderCI.HLSLVersion)} // clang-format on { // Load shader resources auto& Allocator = GetRawAllocator(); auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", ShaderResourcesD3D12, 1); - auto* pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_Desc, ShaderCI.UseCombinedTextureSamplers ? ShaderCI.CombinedSamplerSuffix : nullptr); + auto* pResources = new (pRawMem) ShaderResourcesD3D12(m_pShaderByteCode, m_isDXIL, m_Desc, ShaderCI.UseCombinedTextureSamplers ? ShaderCI.CombinedSamplerSuffix : nullptr); m_pShaderResources.reset(pResources, STDDeleterRawMem<ShaderResourcesD3D12>(Allocator)); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp index edf818cc..8c7d554c 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp @@ -32,11 +32,15 @@ #include "ShaderD3DBase.hpp" #include "ShaderBase.hpp" +#ifdef HAS_DXIL_COMPILER +#include "dxcapi.h" +#endif + namespace Diligent { -ShaderResourcesD3D12::ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix) : +ShaderResourcesD3D12::ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, bool isDXIL, const ShaderDesc& ShdrDesc, const char* CombinedSamplerSuffix) : ShaderResources{ShdrDesc.ShaderType} { class NewResourceHandler @@ -51,8 +55,36 @@ ShaderResourcesD3D12::ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, const Shad void OnNewTexSRV (const D3DShaderResourceAttribs& TexAttribs) {} // clang-format on }; + + CComPtr<ID3D12ShaderReflection> pShaderReflection; + + HRESULT hr; + + if (isDXIL) + { +#ifdef HAS_DXIL_COMPILER + const uint32_t DFCC_DXIL = uint32_t('D') | (uint32_t('X') << 8) | (uint32_t('I') << 16) | (uint32_t('L') << 24); + CComPtr<IDxcContainerReflection> pReflection; + UINT32 shaderIdx; + DxcCreateInstance(CLSID_DxcContainerReflection, IID_PPV_ARGS(&pReflection)); + hr = pReflection->Load(reinterpret_cast<IDxcBlob*>(pShaderBytecode)); + CHECK_D3D_RESULT_THROW(hr, "Failed to create shader reflection instance"); + hr = pReflection->FindFirstPartKind(DFCC_DXIL, &shaderIdx); + CHECK_D3D_RESULT_THROW(hr, "Failed to find DXIL part"); + hr = pReflection->GetPartReflection(shaderIdx, __uuidof(pShaderReflection), reinterpret_cast<void**>(&pShaderReflection)); + CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection"); +#else + LOG_ERROR_AND_THROW("DXIL compiler is not supported"); +#endif + } + else + { + hr = D3DReflect(pShaderBytecode->GetBufferPointer(), pShaderBytecode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(&pShaderReflection)); + CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection"); + } + Initialize<D3D12_SHADER_DESC, D3D12_SHADER_INPUT_BIND_DESC, ID3D12ShaderReflection>( - pShaderBytecode, + static_cast<ID3D12ShaderReflection*>(pShaderReflection), NewResourceHandler{}, ShdrDesc.Name, CombinedSamplerSuffix); |
