summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-08-11 19:48:23 +0000
committerazhirnov <zh1dron@gmail.com>2020-08-11 19:49:36 +0000
commitdc9a4e784c8bb97fbb16a01624c7b8f0544977a4 (patch)
treeb4a07f6e2029ca9d20999acfd940ea8e2556cb9d /Graphics/GraphicsEngineD3D12
parentBash function for format validation in submodules (#155) (diff)
downloadDiligentCore-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')
-rw-r--r--Graphics/GraphicsEngineD3D12/CMakeLists.txt8
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandContext.hpp12
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp5
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp1
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourcesD3D12.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp34
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp309
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp41
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootSignature.cpp64
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp15
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp36
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);