summaryrefslogtreecommitdiffstats
path: root/Graphics
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
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')
-rw-r--r--Graphics/GLSLTools/src/GLSLSourceBuilder.cpp7
-rw-r--r--Graphics/GLSLTools/src/SPIRVShaderResources.cpp16
-rw-r--r--Graphics/GLSLTools/src/SPIRVUtils.cpp14
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp18
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp90
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.hpp42
-rw-r--r--Graphics/GraphicsEngine/include/ShaderBase.hpp18
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceCaps.h3
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h85
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h2
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h36
-rw-r--r--Graphics/GraphicsEngine/interface/Shader.h17
-rw-r--r--Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp4
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp12
-rw-r--r--Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp24
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp889
-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
-rw-r--r--Graphics/GraphicsEngineD3DBase/CMakeLists.txt8
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp9
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp3
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp8
-rw-r--r--Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp361
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp4
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp12
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp26
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp24
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp31
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp16
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp21
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp31
49 files changed, 1663 insertions, 757 deletions
diff --git a/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp b/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp
index 8b369954..da1b6fec 100644
--- a/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp
+++ b/Graphics/GLSLTools/src/GLSLSourceBuilder.cpp
@@ -64,6 +64,13 @@ const char* GetShaderTypeDefines(SHADER_TYPE Type)
case SHADER_TYPE_COMPUTE:
return "#define COMPUTE_SHADER 1\n";
+
+ case SHADER_TYPE_AMPLIFICATION:
+ return "#define TASK_SHADER 1\n"
+ "#define AMPLIFICATION_SHADER 1\n";
+
+ case SHADER_TYPE_MESH:
+ return "#define MESH_SHADER 1\n";
default:
UNEXPECTED("Unexpected shader type");
diff --git a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp
index 46705ace..bf92e84b 100644
--- a/Graphics/GLSLTools/src/SPIRVShaderResources.cpp
+++ b/Graphics/GLSLTools/src/SPIRVShaderResources.cpp
@@ -149,13 +149,15 @@ static spv::ExecutionModel ShaderTypeToExecutionModel(SHADER_TYPE ShaderType)
switch (ShaderType)
{
// clang-format off
- case SHADER_TYPE_VERTEX: return spv::ExecutionModelVertex;
- case SHADER_TYPE_HULL: return spv::ExecutionModelTessellationControl;
- case SHADER_TYPE_DOMAIN: return spv::ExecutionModelTessellationEvaluation;
- case SHADER_TYPE_GEOMETRY: return spv::ExecutionModelGeometry;
- case SHADER_TYPE_PIXEL: return spv::ExecutionModelFragment;
- case SHADER_TYPE_COMPUTE: return spv::ExecutionModelGLCompute;
- // clang-format on
+ case SHADER_TYPE_VERTEX: return spv::ExecutionModelVertex;
+ case SHADER_TYPE_HULL: return spv::ExecutionModelTessellationControl;
+ case SHADER_TYPE_DOMAIN: return spv::ExecutionModelTessellationEvaluation;
+ case SHADER_TYPE_GEOMETRY: return spv::ExecutionModelGeometry;
+ case SHADER_TYPE_PIXEL: return spv::ExecutionModelFragment;
+ case SHADER_TYPE_COMPUTE: return spv::ExecutionModelGLCompute;
+ case SHADER_TYPE_AMPLIFICATION: return spv::ExecutionModelTaskNV;
+ case SHADER_TYPE_MESH: return spv::ExecutionModelMeshNV;
+ // clang-format on
default:
UNEXPECTED("Unexpected shader type");
diff --git a/Graphics/GLSLTools/src/SPIRVUtils.cpp b/Graphics/GLSLTools/src/SPIRVUtils.cpp
index e02bc34e..5ae9d3a1 100644
--- a/Graphics/GLSLTools/src/SPIRVUtils.cpp
+++ b/Graphics/GLSLTools/src/SPIRVUtils.cpp
@@ -72,12 +72,14 @@ EShLanguage ShaderTypeToShLanguage(SHADER_TYPE ShaderType)
switch (ShaderType)
{
// clang-format off
- case SHADER_TYPE_VERTEX: return EShLangVertex;
- case SHADER_TYPE_HULL: return EShLangTessControl;
- case SHADER_TYPE_DOMAIN: return EShLangTessEvaluation;
- case SHADER_TYPE_GEOMETRY: return EShLangGeometry;
- case SHADER_TYPE_PIXEL: return EShLangFragment;
- case SHADER_TYPE_COMPUTE: return EShLangCompute;
+ case SHADER_TYPE_VERTEX: return EShLangVertex;
+ case SHADER_TYPE_HULL: return EShLangTessControl;
+ case SHADER_TYPE_DOMAIN: return EShLangTessEvaluation;
+ case SHADER_TYPE_GEOMETRY: return EShLangGeometry;
+ case SHADER_TYPE_PIXEL: return EShLangFragment;
+ case SHADER_TYPE_COMPUTE: return EShLangCompute;
+ case SHADER_TYPE_AMPLIFICATION: return EShLangTaskNV;
+ case SHADER_TYPE_MESH: return EShLangMeshNV;
// clang-format on
default:
UNEXPECTED("Unexpected shader type");
diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
index fff50193..de16b059 100644
--- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
+++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
@@ -480,13 +480,15 @@ const Char* GetShaderTypeLiteralName(SHADER_TYPE ShaderType)
#define RETURN_SHADER_TYPE_NAME(ShaderType)\
case ShaderType: return #ShaderType;
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_UNKNOWN )
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_VERTEX )
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_PIXEL )
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_GEOMETRY)
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_HULL )
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_DOMAIN )
- RETURN_SHADER_TYPE_NAME( SHADER_TYPE_COMPUTE )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_UNKNOWN )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_VERTEX )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_PIXEL )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_GEOMETRY )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_HULL )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_DOMAIN )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_COMPUTE )
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_AMPLIFICATION)
+ RETURN_SHADER_TYPE_NAME( SHADER_TYPE_MESH )
#undef RETURN_SHADER_TYPE_NAME
// clang-format on
@@ -497,7 +499,7 @@ const Char* GetShaderTypeLiteralName(SHADER_TYPE ShaderType)
String GetShaderStagesString(SHADER_TYPE ShaderStages)
{
String StagesStr;
- for (Uint32 Stage = SHADER_TYPE_VERTEX; ShaderStages != 0 && Stage <= SHADER_TYPE_COMPUTE; Stage <<= 1)
+ for (Uint32 Stage = SHADER_TYPE_VERTEX; ShaderStages != 0 && Stage < SHADER_TYPE_LAST; Stage <<= 1)
{
if (ShaderStages & Stage)
{
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index b4c271fa..d547ca6f 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -229,8 +229,10 @@ protected:
// clang-format off
bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const;
bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const;
+ bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const;
bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
+ bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const;
bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const;
@@ -242,8 +244,10 @@ protected:
#else
bool DvpVerifyDrawArguments (const DrawAttribs& Attribs)const {return true;}
bool DvpVerifyDrawIndexedArguments (const DrawIndexedAttribs& Attribs)const {return true;}
+ bool DvpVerifyDrawMeshArguments (const DrawMeshAttribs& Attribs)const {return true;}
bool DvpVerifyDrawIndirectArguments (const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
bool DvpVerifyDrawIndexedIndirectArguments(const DrawIndexedIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
+ bool DvpVerifyDrawMeshIndirectArguments (const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
bool DvpVerifyDispatchArguments (const DispatchComputeAttribs& Attribs)const {return true;}
bool DvpVerifyDispatchIndirectArguments(const DispatchComputeIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer)const {return true;}
@@ -1175,7 +1179,7 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return false;
}
- if (m_pPipelineState->GetDesc().IsComputePipeline)
+ if (m_pPipelineState->GetDesc().PipelineType != GRAPHICS_PIPELINE)
{
LOG_ERROR_MESSAGE("Draw command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name, "' is a compute pipeline.");
return false;
@@ -1201,8 +1205,8 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: no pipeline state is bound.");
return false;
}
-
- if (m_pPipelineState->GetDesc().IsComputePipeline)
+
+ if (m_pPipelineState->GetDesc().PipelineType != GRAPHICS_PIPELINE)
{
LOG_ERROR_MESSAGE("DrawIndexed command arguments are invalid: pipeline state '",
m_pPipelineState->GetDesc().Name, "' is a compute pipeline.");
@@ -1232,6 +1236,34 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
template <typename BaseInterface, typename ImplementationTraits>
inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
+ DvpVerifyDrawMeshArguments(const DrawMeshAttribs& Attribs)const
+{
+ if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
+ return true;
+
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: no pipeline state is bound.");
+ return false;
+ }
+
+ if (m_pPipelineState->GetDesc().PipelineType != MESH_PIPELINE)
+ {
+ LOG_ERROR_MESSAGE("DrawMesh command arguments are invalid: pipeline state '",
+ m_pPipelineState->GetDesc().Name, "' is a compute pipeline.");
+ return false;
+ }
+
+ if (Attribs.ThreadGroupCount == 0)
+ {
+ LOG_WARNING_MESSAGE("DrawMesh command arguments are invalid: number of groups to dispatch is zero.");
+ }
+
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
DvpVerifyDrawIndirectArguments(const DrawIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
{
if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
@@ -1242,8 +1274,8 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: no pipeline state is bound.");
return false;
}
-
- if (m_pPipelineState->GetDesc().IsComputePipeline)
+
+ if (m_pPipelineState->GetDesc().PipelineType != GRAPHICS_PIPELINE)
{
LOG_ERROR_MESSAGE("DrawIndirect command arguments are invalid: pipeline state '",
@@ -1281,8 +1313,8 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: no pipeline state is bound.");
return false;
}
-
- if (m_pPipelineState->GetDesc().IsComputePipeline)
+
+ if (m_pPipelineState->GetDesc().PipelineType != GRAPHICS_PIPELINE)
{
LOG_ERROR_MESSAGE("DrawIndexedIndirect command arguments are invalid: pipeline state '",
m_pPipelineState->GetDesc().Name, "' is a compute pipeline.");
@@ -1321,6 +1353,44 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
}
template <typename BaseInterface, typename ImplementationTraits>
+inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
+ DvpVerifyDrawMeshIndirectArguments(const DrawMeshIndirectAttribs& Attribs, const IBuffer* pAttribsBuffer) const
+{
+ if ((Attribs.Flags & DRAW_FLAG_VERIFY_DRAW_ATTRIBS) == 0)
+ return true;
+
+ if (!m_pPipelineState)
+ {
+ LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: no pipeline state is bound.");
+ return false;
+ }
+
+ if (m_pPipelineState->GetDesc().PipelineType != MESH_PIPELINE)
+ {
+ LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: pipeline state '",
+ m_pPipelineState->GetDesc().Name, "' is a compute pipeline.");
+ return false;
+ }
+
+ if (pAttribsBuffer != nullptr)
+ {
+ if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0)
+ {
+ LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer '",
+ pAttribsBuffer->GetDesc().Name, "' was not created with BIND_INDIRECT_DRAW_ARGS flag.");
+ return false;
+ }
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("DrawMeshIndirect command arguments are invalid: indirect draw arguments buffer is null.");
+ return false;
+ }
+
+ return true;
+}
+
+template <typename BaseInterface, typename ImplementationTraits>
inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
DvpVerifyRenderTargets() const
{
@@ -1384,7 +1454,7 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
return false;
}
- if (!m_pPipelineState->GetDesc().IsComputePipeline)
+ if (m_pPipelineState->GetDesc().PipelineType != COMPUTE_PIPELINE)
{
LOG_ERROR_MESSAGE("DispatchCompute command arguments are invalid: pipeline state '", m_pPipelineState->GetDesc().Name,
"' is a graphics pipeline.");
@@ -1412,8 +1482,8 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::
LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: no pipeline state is bound.");
return false;
}
-
- if (!m_pPipelineState->GetDesc().IsComputePipeline)
+
+ if (m_pPipelineState->GetDesc().PipelineType != COMPUTE_PIPELINE)
{
LOG_ERROR_MESSAGE("DispatchComputeIndirect command arguments are invalid: pipeline state '",
m_pPipelineState->GetDesc().Name, "' is a graphics pipeline.");
diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
index 6d70f4da..37d4e7cd 100644
--- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
+++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
@@ -83,7 +83,7 @@ public:
StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1;
}
- if (!PSODesc.IsComputePipeline)
+ if (PSODesc.IsAnyGraphicsPipeline())
{
CheckAndCorrectBlendStateDesc();
CheckRasterizerStateDesc();
@@ -142,7 +142,7 @@ public:
}
- if (this->m_Desc.IsComputePipeline)
+ if (this->m_Desc.IsComputePipeline())
{
const auto& ComputePipeline = PSODesc.ComputePipeline;
if (ComputePipeline.pCS == nullptr)
@@ -171,20 +171,40 @@ public:
VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry")
VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull")
VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain")
+ VALIDATE_SHADER_TYPE(GraphicsPipeline.pAS, SHADER_TYPE_AMPLIFICATION, "amplification")
+ VALIDATE_SHADER_TYPE(GraphicsPipeline.pMS, SHADER_TYPE_MESH, "mesh")
#undef VALIDATE_SHADER_TYPE
- m_pVS = GraphicsPipeline.pVS;
- m_pPS = GraphicsPipeline.pPS;
- m_pGS = GraphicsPipeline.pGS;
- m_pDS = GraphicsPipeline.pDS;
- m_pHS = GraphicsPipeline.pHS;
+ if (PSODesc.PipelineType == GRAPHICS_PIPELINE)
+ {
+ CHECK_THROW(GraphicsPipeline.pVS, "Vertex shader must be defined");
+ CHECK_THROW(!GraphicsPipeline.pAS && !GraphicsPipeline.pMS, "Mesh shaders are not supported in graphics pipeline");
+ m_pVS = GraphicsPipeline.pVS;
+ m_pPS = GraphicsPipeline.pPS;
+ m_pGS = GraphicsPipeline.pGS;
+ m_pDS = GraphicsPipeline.pDS;
+ m_pHS = GraphicsPipeline.pHS;
+ }
+ else
+ if (PSODesc.PipelineType == MESH_PIPELINE)
+ {
+ CHECK_THROW(GraphicsPipeline.pMS, "Mesh shader must be defined");
+ CHECK_THROW(!GraphicsPipeline.pVS && !GraphicsPipeline.pGS && !GraphicsPipeline.pDS && !GraphicsPipeline.pHS,
+ "Vertex, geometry and tessellation shaders are not supported in mesh pipeline");
+ DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader");
+ m_pAS = GraphicsPipeline.pAS;
+ m_pMS = GraphicsPipeline.pMS;
+ m_pPS = GraphicsPipeline.pPS;
+ }
if (GraphicsPipeline.pVS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS;
if (GraphicsPipeline.pPS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS;
if (GraphicsPipeline.pGS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS;
if (GraphicsPipeline.pHS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS;
if (GraphicsPipeline.pDS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS;
-
+ if (GraphicsPipeline.pAS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pAS;
+ if (GraphicsPipeline.pMS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pMS;
+
DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State");
for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt)
@@ -388,9 +408,11 @@ protected:
RefCntAutoPtr<IShader> m_pDS; ///< Strong reference to the domain shader
RefCntAutoPtr<IShader> m_pHS; ///< Strong reference to the hull shader
RefCntAutoPtr<IShader> m_pCS; ///< Strong reference to the compute shader
+ RefCntAutoPtr<IShader> m_pAS; ///< Strong reference to the amplification shader
+ RefCntAutoPtr<IShader> m_pMS; ///< Strong reference to the mesh shader
- IShader* m_ppShaders[5] = {}; ///< Array of pointers to the shaders used by this PSO
- size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
+ IShader* m_ppShaders[MAX_SHADERS_IN_PIPELINE] = {}; ///< Array of pointers to the shaders used by this PSO
+ size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
private:
void CheckRasterizerStateDesc() const
diff --git a/Graphics/GraphicsEngine/include/ShaderBase.hpp b/Graphics/GraphicsEngine/include/ShaderBase.hpp
index 9874206a..5462c7a4 100644
--- a/Graphics/GraphicsEngine/include/ShaderBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderBase.hpp
@@ -57,13 +57,15 @@ inline Int32 GetShaderTypeIndex(SHADER_TYPE Type)
switch (Type)
{
// clang-format off
- case SHADER_TYPE_UNKNOWN: VERIFY_EXPR(ShaderIndex == -1); break;
- case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderIndex == 0); break;
- case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderIndex == 1); break;
- case SHADER_TYPE_GEOMETRY:VERIFY_EXPR(ShaderIndex == 2); break;
- case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderIndex == 3); break;
- case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderIndex == 4); break;
- case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderIndex == 5); break;
+ case SHADER_TYPE_UNKNOWN: VERIFY_EXPR(ShaderIndex == -1); break;
+ case SHADER_TYPE_VERTEX: VERIFY_EXPR(ShaderIndex == 0); break;
+ case SHADER_TYPE_PIXEL: VERIFY_EXPR(ShaderIndex == 1); break;
+ case SHADER_TYPE_GEOMETRY: VERIFY_EXPR(ShaderIndex == 2); break;
+ case SHADER_TYPE_HULL: VERIFY_EXPR(ShaderIndex == 3); break;
+ case SHADER_TYPE_DOMAIN: VERIFY_EXPR(ShaderIndex == 4); break;
+ case SHADER_TYPE_COMPUTE: VERIFY_EXPR(ShaderIndex == 5); break;
+ case SHADER_TYPE_AMPLIFICATION: VERIFY_EXPR(ShaderIndex == 6); break;
+ case SHADER_TYPE_MESH: VERIFY_EXPR(ShaderIndex == 7); break;
// clang-format on
default: UNEXPECTED("Unexpected shader type (", Type, ")"); break;
}
@@ -78,6 +80,8 @@ static const int GSInd = GetShaderTypeIndex(SHADER_TYPE_GEOMETRY);
static const int HSInd = GetShaderTypeIndex(SHADER_TYPE_HULL);
static const int DSInd = GetShaderTypeIndex(SHADER_TYPE_DOMAIN);
static const int CSInd = GetShaderTypeIndex(SHADER_TYPE_COMPUTE);
+static const int ASInd = GetShaderTypeIndex(SHADER_TYPE_AMPLIFICATION);
+static const int MSInd = GetShaderTypeIndex(SHADER_TYPE_MESH);
/// Template class implementing base functionality for a shader object
diff --git a/Graphics/GraphicsEngine/interface/DeviceCaps.h b/Graphics/GraphicsEngine/interface/DeviceCaps.h
index 1f0dc257..77095307 100644
--- a/Graphics/GraphicsEngine/interface/DeviceCaps.h
+++ b/Graphics/GraphicsEngine/interface/DeviceCaps.h
@@ -164,6 +164,9 @@ struct DeviceFeatures
/// Specifies whether all the extended UAV texture formats are available in shader code.
Bool TextureUAVExtendedFormats DEFAULT_INITIALIZER(False);
+
+ /// Indicates if device supports mesh and amplification shaders
+ Bool MeshShaders DEFAULT_INITIALIZER(False);
};
typedef struct DeviceFeatures DeviceFeatures;
diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h
index 79f8bd39..db1c0175 100644
--- a/Graphics/GraphicsEngine/interface/DeviceContext.h
+++ b/Graphics/GraphicsEngine/interface/DeviceContext.h
@@ -362,6 +362,68 @@ struct DrawIndexedIndirectAttribs
};
typedef struct DrawIndexedIndirectAttribs DrawIndexedIndirectAttribs;
+/// Defines the mesh draw command attributes.
+
+/// This structure is used by IDeviceContext::DrawMesh().
+struct DrawMeshAttribs
+{
+ ///< Number of dispatched groups
+ Uint32 ThreadGroupCount DEFAULT_INITIALIZER(1);
+
+ /// Additional flags, see Diligent::DRAW_FLAGS.
+ DRAW_FLAGS Flags DEFAULT_INITIALIZER(DRAW_FLAG_NONE);
+
+#if DILIGENT_CPP_INTERFACE
+ /// Initializes the structure members with default values.
+ DrawMeshAttribs()noexcept{}
+
+ /// Initializes the structure with user-specified values.
+ DrawMeshAttribs(Uint32 _ThreadGroupCount,
+ DRAW_FLAGS _Flags)noexcept :
+ ThreadGroupCount {_ThreadGroupCount},
+ Flags {_Flags}
+ {}
+#endif
+};
+typedef struct DrawMeshAttribs DrawMeshAttribs;
+
+/// Defines the mesh indirect draw command attributes.
+
+/// This structure is used by IDeviceContext::DrawMeshIndirect().
+struct DrawMeshIndirectAttribs
+{
+ /// Additional flags, see Diligent::DRAW_FLAGS.
+ DRAW_FLAGS Flags DEFAULT_INITIALIZER(DRAW_FLAG_NONE);
+
+ /// State transition mode for indirect draw arguments buffer.
+ RESOURCE_STATE_TRANSITION_MODE IndirectAttribsBufferStateTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE);
+
+ /// Offset from the beginning of the buffer to the location of draw command attributes.
+ Uint32 IndirectDrawArgsOffset DEFAULT_INITIALIZER(0);
+
+#if DILIGENT_CPP_INTERFACE
+ /// Initializes the structure members with default values
+
+ /// Default values:
+ /// Member | Default value
+ /// -----------------------------------------|--------------------------------------
+ /// Flags | DRAW_FLAG_NONE
+ /// IndirectAttribsBufferStateTransitionMode | RESOURCE_STATE_TRANSITION_MODE_NONE
+ /// IndirectDrawArgsOffset | 0
+ DrawMeshIndirectAttribs()noexcept{}
+
+ /// Initializes the structure members with user-specified values.
+ DrawMeshIndirectAttribs(DRAW_FLAGS _Flags,
+ RESOURCE_STATE_TRANSITION_MODE _IndirectAttribsBufferStateTransitionMode,
+ Uint32 _IndirectDrawArgsOffset = 0)noexcept :
+ Flags {_Flags },
+ IndirectAttribsBufferStateTransitionMode{_IndirectAttribsBufferStateTransitionMode},
+ IndirectDrawArgsOffset {_IndirectDrawArgsOffset }
+ {}
+#endif
+};
+typedef struct DrawMeshIndirectAttribs DrawMeshIndirectAttribs;
+
/// Defines which parts of the depth-stencil buffer to clear.
/// These flags are used by IDeviceContext::ClearDepthStencil().
@@ -930,6 +992,29 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject)
VIRTUAL void METHOD(DrawIndexedIndirect)(THIS_
const DrawIndexedIndirectAttribs REF Attribs,
IBuffer* pAttribsBuffer) PURE;
+
+
+ /// Executes an mesh draw command.
+
+ /// \param [in] Attribs - Draw command attributes, see Diligent::DrawMeshAttribs for details.
+ VIRTUAL void METHOD(DrawMesh)(THIS_
+ const DrawMeshAttribs REF Attribs) PURE;
+
+
+ /// Executes an mesh indirect draw command.
+
+ /// \param [in] Attribs - Structure describing the command attributes, see Diligent::DrawMeshIndirectAttribs for details.
+ /// \param [in] pAttribsBuffer - Pointer to the buffer, from which indirect draw attributes will be read.
+ ///
+ /// \remarks If IndirectAttribsBufferStateTransitionMode member is Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
+ /// the method may transition the state of the indirect draw arguments buffer. This is not a thread safe operation,
+ /// so no other thread is allowed to read or write the state of the buffer.
+ ///
+ /// If the application intends to use the same resources in other threads simultaneously, it needs to
+ /// explicitly manage the states using IDeviceContext::TransitionResourceStates() method.
+ VIRTUAL void METHOD(DrawMeshIndirect)(THIS_
+ const DrawMeshIndirectAttribs REF Attribs,
+ IBuffer* pAttribsBuffer) PURE;
/// Executes a dispatch compute command.
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index 0d0631b7..b54ac7cb 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -920,7 +920,7 @@ DEFINE_FLAG_ENUM_OPERATORS(MISC_TEXTURE_FLAGS)
/// Input primitive topology.
-/// This enumeration is used by DrawAttribs structure to define input primitive topology.
+/// This enumeration is used by GraphicsPipelineDesc structure to define input primitive topology.
DILIGENT_TYPED_ENUM(PRIMITIVE_TOPOLOGY, Uint8)
{
/// Undefined topology
diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h
index 5e99a392..6daa74b6 100644
--- a/Graphics/GraphicsEngine/interface/PipelineState.h
+++ b/Graphics/GraphicsEngine/interface/PipelineState.h
@@ -165,6 +165,12 @@ struct GraphicsPipelineDesc
/// Geometry shader to be used with the pipeline
IShader* pGS DEFAULT_INITIALIZER(nullptr);
+ /// Amplification shader to be used with the pipeline
+ IShader* pAS DEFAULT_INITIALIZER(nullptr);
+
+ /// Mesh shader to be used with the pipeline
+ IShader* pMS DEFAULT_INITIALIZER(nullptr);
+
//D3D12_STREAM_OUTPUT_DESC StreamOutput;
/// Blend state description
@@ -182,11 +188,11 @@ struct GraphicsPipelineDesc
/// Depth-stencil state description
DepthStencilStateDesc DepthStencilDesc;
- /// Input layout
+ /// Input layout, ignored in mesh pipeline
InputLayoutDesc InputLayout;
//D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue;
- /// Primitive topology type
+ /// Primitive topology type, ignored in mesh pipeline
PRIMITIVE_TOPOLOGY PrimitiveTopology DEFAULT_INITIALIZER(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
/// Number of viewports used by this pipeline
@@ -223,12 +229,25 @@ struct ComputePipelineDesc
};
typedef struct ComputePipelineDesc ComputePipelineDesc;
+/// Pipeline type
+DILIGENT_TYPED_ENUM(PIPELINE_TYPE, Uint8)
+{
+ /// Graphics pipeline used in IDeviceContext::Draw(), IDeviceContext::DrawIndexed(),
+ /// IDeviceContext::DrawIndirect(), IDeviceContext::DrawIndexedIndirect().
+ GRAPHICS_PIPELINE,
+
+ /// Compute pipeline used in IDeviceContext::DispatchCompute(), IDeviceContext::DispatchComputeIndirect().
+ COMPUTE_PIPELINE,
+
+ // Mesh pipeline used in IDeviceContext::DrawMesh(), IDeviceContext::DrawMeshIndirect().
+ MESH_PIPELINE,
+};
/// Pipeline state description
struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs)
- /// Flag indicating if pipeline state is a compute pipeline state
- bool IsComputePipeline DEFAULT_INITIALIZER(false);
+ /// Pipeline type
+ PIPELINE_TYPE PipelineType DEFAULT_INITIALIZER(GRAPHICS_PIPELINE);
/// Shader resource binding allocation granularity
@@ -242,11 +261,16 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs)
/// Pipeline layout description
PipelineResourceLayoutDesc ResourceLayout;
- /// Graphics pipeline state description. This memeber is ignored if IsComputePipeline == True
+ /// Graphics pipeline state description. This memeber is ignored if PipelineType == GRAPHICS_PIPELINE or MESH_PIPELINE
GraphicsPipelineDesc GraphicsPipeline;
- /// Compute pipeline state description. This memeber is ignored if IsComputePipeline == False
+ /// Compute pipeline state description. This memeber is ignored if PipelineType == COMPUTE_PIPELINE
ComputePipelineDesc ComputePipeline;
+
+#if DILIGENT_CPP_INTERFACE
+ bool IsAnyGraphicsPipeline() const { return PipelineType == GRAPHICS_PIPELINE || PipelineType == MESH_PIPELINE; }
+ bool IsComputePipeline () const { return PipelineType == COMPUTE_PIPELINE; }
+#endif
};
typedef struct PipelineStateDesc PipelineStateDesc;
diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h
index eacd35f0..867335a9 100644
--- a/Graphics/GraphicsEngine/interface/Shader.h
+++ b/Graphics/GraphicsEngine/interface/Shader.h
@@ -45,13 +45,16 @@ static const INTERFACE_ID IID_Shader =
/// Describes the shader type
DILIGENT_TYPED_ENUM(SHADER_TYPE, Uint32)
{
- SHADER_TYPE_UNKNOWN = 0x000, ///< Unknown shader type
- SHADER_TYPE_VERTEX = 0x001, ///< Vertex shader
- SHADER_TYPE_PIXEL = 0x002, ///< Pixel (fragment) shader
- SHADER_TYPE_GEOMETRY = 0x004, ///< Geometry shader
- SHADER_TYPE_HULL = 0x008, ///< Hull (tessellation control) shader
- SHADER_TYPE_DOMAIN = 0x010, ///< Domain (tessellation evaluation) shader
- SHADER_TYPE_COMPUTE = 0x020 ///< Compute shader
+ SHADER_TYPE_UNKNOWN = 0x000, ///< Unknown shader type
+ SHADER_TYPE_VERTEX = 0x001, ///< Vertex shader
+ SHADER_TYPE_PIXEL = 0x002, ///< Pixel (fragment) shader
+ SHADER_TYPE_GEOMETRY = 0x004, ///< Geometry shader
+ SHADER_TYPE_HULL = 0x008, ///< Hull (tessellation control) shader
+ SHADER_TYPE_DOMAIN = 0x010, ///< Domain (tessellation evaluation) shader
+ SHADER_TYPE_COMPUTE = 0x020, ///< Compute shader
+ SHADER_TYPE_AMPLIFICATION = 0x040, ///< Amplification (task) shader
+ SHADER_TYPE_MESH = 0x080, ///< Mesh shader
+ SHADER_TYPE_LAST
};
DEFINE_FLAG_ENUM_OPERATORS(SHADER_TYPE);
diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
index f8db6f23..5230b833 100644
--- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp
@@ -130,6 +130,10 @@ public:
virtual void DILIGENT_CALL_TYPE DrawIndirect(const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
/// Implementation of IDeviceContext::DrawIndexedIndirect() in Direct3D11 backend.
virtual void DILIGENT_CALL_TYPE DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
+ /// Implementation of IDeviceContext::DrawMesh() in Direct3D11 backend.
+ virtual void DILIGENT_CALL_TYPE DrawMesh(const DrawMeshAttribs& Attribs) override final;
+ /// Implementation of IDeviceContext::DrawMeshIndirect() in Direct3D11 backend.
+ virtual void DILIGENT_CALL_TYPE DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
/// Implementation of IDeviceContext::DispatchCompute() in Direct3D11 backend.
virtual void DILIGENT_CALL_TYPE DispatchCompute(const DispatchComputeAttribs& Attribs) override final;
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index 0ff2227d..d936b247 100755
--- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
@@ -75,7 +75,7 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState)
TDeviceContextBase::SetPipelineState(pPipelineStateD3D11, 0 /*Dummy*/);
auto& Desc = pPipelineStateD3D11->GetDesc();
- if (Desc.IsComputePipeline)
+ if (Desc.IsComputePipeline())
{
auto* pd3d11CS = pPipelineStateD3D11->GetD3D11ComputeShader();
if (pd3d11CS == nullptr)
@@ -870,6 +870,16 @@ void DeviceContextD3D11Impl::DrawIndexedIndirect(const DrawIndexedIndirectAttrib
m_pd3d11DeviceContext->DrawIndexedInstancedIndirect(pd3d11ArgsBuff, Attribs.IndirectDrawArgsOffset);
}
+void DeviceContextD3D11Impl::DrawMesh(const DrawMeshAttribs& Attribs)
+{
+ UNSUPPORTED("DrawMesh is not supported in DirectX 11");
+}
+
+void DeviceContextD3D11Impl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ UNSUPPORTED("DrawMeshIndirect is not supported in DirectX 11");
+}
+
void DeviceContextD3D11Impl::DispatchCompute(const DispatchComputeAttribs& Attribs)
{
if (!DvpVerifyDispatchArguments(Attribs))
diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp
index 3b787039..97d76fde 100644
--- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp
@@ -50,7 +50,7 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR
m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector<StaticSamplerInfo>"))
// clang-format on
{
- if (m_Desc.IsComputePipeline)
+ if (m_Desc.IsComputePipeline())
{
auto* pCS = ValidatedCast<ShaderD3D11Impl>(m_Desc.ComputePipeline.pCS);
m_pCS = pCS;
diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp
index b5b0194f..8bf17567 100644
--- a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp
@@ -34,24 +34,24 @@
namespace Diligent
{
-static const std::string HLSLVersionToShaderModelString(const ShaderVersion& Version, Uint8 MaxMajorRevision, Uint8 MaxMinorRevision)
+static const Uint8 HLSLVersionToShaderModelString(const ShaderVersion& Version, Uint8 MaxMajorRevision, Uint8 MaxMinorRevision)
{
- std::string ModelStr;
+ Uint8 ModelVer;
if (Version.Major > MaxMajorRevision || Version.Major == MaxMajorRevision && Version.Minor > MaxMinorRevision)
{
- ModelStr = std::to_string(Uint32{MaxMajorRevision}) + '_' + std::to_string(Uint32{MaxMinorRevision});
+ ModelVer = Uint8((MaxMajorRevision << 4) | MaxMinorRevision);
LOG_ERROR_MESSAGE("Shader model ", Uint32{Version.Major}, "_", Uint32{Version.Minor},
" is not supported by this device. Maximum supported model: ",
- ModelStr, ". Attempting to use ", ModelStr, '.');
+ MaxMajorRevision, "_", MaxMinorRevision, ". Attempting to use ", MaxMajorRevision, "_", MaxMinorRevision, '.');
}
else
{
- ModelStr = std::to_string(Uint32{Version.Major}) + '_' + std::to_string(Uint32{Version.Minor});
+ ModelVer = Uint8((Version.Major << 4) | Version.Minor);
}
- return ModelStr;
+ return ModelVer;
}
-static const std::string GetD3D11ShaderModel(ID3D11Device* pd3d11Device, const ShaderVersion& HLSLVersion)
+static const Uint8 GetD3D11ShaderModel(ID3D11Device* pd3d11Device, const ShaderVersion& HLSLVersion)
{
auto d3dDeviceFeatureLevel = pd3d11Device->GetFeatureLevel();
switch (d3dDeviceFeatureLevel)
@@ -66,22 +66,22 @@ static const std::string GetD3D11ShaderModel(ID3D11Device* pd3d11Device, const S
case D3D_FEATURE_LEVEL_11_1:
case D3D_FEATURE_LEVEL_11_0:
return (HLSLVersion.Major == 0 && HLSLVersion.Minor == 0) ?
- std::string{"5_0"} :
+ Uint8(0x50) :
HLSLVersionToShaderModelString(HLSLVersion, 5, 0);
case D3D_FEATURE_LEVEL_10_1:
return (HLSLVersion.Major == 0 && HLSLVersion.Minor == 0) ?
- std::string{"4_1"} :
+ Uint8(0x41) :
HLSLVersionToShaderModelString(HLSLVersion, 4, 1);
case D3D_FEATURE_LEVEL_10_0:
return (HLSLVersion.Major == 0 && HLSLVersion.Minor == 0) ?
- std::string{"4_0"} :
+ Uint8(0x40) :
HLSLVersionToShaderModelString(HLSLVersion, 4, 0);
default:
UNEXPECTED("Unexpected D3D feature level ", static_cast<Uint32>(d3dDeviceFeatureLevel));
- return "4_0";
+ return Uint8(0x40);
}
}
@@ -95,7 +95,7 @@ ShaderD3D11Impl::ShaderD3D11Impl(IReferenceCounters* pRefCounters,
pRenderDeviceD3D11,
ShaderCI.Desc
},
- ShaderD3DBase{ShaderCI, GetD3D11ShaderModel(pRenderDeviceD3D11->GetD3D11Device(), ShaderCI.HLSLVersion).c_str()}
+ ShaderD3DBase{ShaderCI, GetD3D11ShaderModel(pRenderDeviceD3D11->GetD3D11Device(), ShaderCI.HLSLVersion)}
// clang-format on
{
auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device();
diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp
index 769c91e2..779ce893 100755
--- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp
@@ -1,442 +1,447 @@
-/*
- * Copyright 2019-2020 Diligent Graphics LLC
- * Copyright 2015-2019 Egor Yusov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * In no event and under no legal theory, whether in tort (including negligence),
- * contract, or otherwise, unless required by applicable law (such as deliberate
- * and grossly negligent acts) or agreed to in writing, shall any Contributor be
- * liable for any damages, including any direct, indirect, special, incidental,
- * or consequential damages of any character arising as a result of this License or
- * out of the use or inability to use the software (including but not limited to damages
- * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
- * all other commercial damages or losses), even if such Contributor has been advised
- * of the possibility of such damages.
- */
-
-#include "pch.h"
-
-#include <d3dcompiler.h>
-#include "ShaderResourcesD3D11.hpp"
-#include "ShaderBase.hpp"
-#include "ShaderResourceCacheD3D11.hpp"
-#include "RenderDeviceD3D11Impl.hpp"
-
-namespace Diligent
-{
-
-
-ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Impl,
- ID3DBlob* pShaderBytecode,
- const ShaderDesc& ShdrDesc,
- const char* CombinedSamplerSuffix) :
- ShaderResources{ShdrDesc.ShaderType}
-{
- class NewResourceHandler
- {
- public:
- NewResourceHandler(RenderDeviceD3D11Impl* const _pDeviceD3D11Impl,
- const ShaderDesc& _ShdrDesc,
- const char* _CombinedSamplerSuffix,
- ShaderResourcesD3D11& _Resources) :
- // clang-format off
- pDeviceD3D11Impl {_pDeviceD3D11Impl },
- ShdrDesc {_ShdrDesc },
- CombinedSamplerSuffix{_CombinedSamplerSuffix},
- Resources {_Resources }
- // clang-format on
- {}
-
- void OnNewCB(const D3DShaderResourceAttribs& CBAttribs)
- {
- VERIFY(CBAttribs.BindPoint + CBAttribs.BindCount - 1 <= MaxAllowedBindPoint, "CB bind point exceeds supported range");
- Resources.m_MaxCBBindPoint = std::max(Resources.m_MaxCBBindPoint, static_cast<MaxBindPointType>(CBAttribs.BindPoint + CBAttribs.BindCount - 1));
- }
-
- void OnNewTexUAV(const D3DShaderResourceAttribs& TexUAV)
- {
- VERIFY(TexUAV.BindPoint + TexUAV.BindCount - 1 <= MaxAllowedBindPoint, "Tex UAV bind point exceeds supported range");
- Resources.m_MaxUAVBindPoint = std::max(Resources.m_MaxUAVBindPoint, static_cast<MaxBindPointType>(TexUAV.BindPoint + TexUAV.BindCount - 1));
- }
-
- void OnNewBuffUAV(const D3DShaderResourceAttribs& BuffUAV)
- {
- VERIFY(BuffUAV.BindPoint + BuffUAV.BindCount - 1 <= MaxAllowedBindPoint, "Buff UAV bind point exceeds supported range");
- Resources.m_MaxUAVBindPoint = std::max(Resources.m_MaxUAVBindPoint, static_cast<MaxBindPointType>(BuffUAV.BindPoint + BuffUAV.BindCount - 1));
- }
-
- void OnNewBuffSRV(const D3DShaderResourceAttribs& BuffSRV)
- {
- VERIFY(BuffSRV.BindPoint + BuffSRV.BindCount - 1 <= MaxAllowedBindPoint, "Buff SRV bind point exceeds supported range");
- Resources.m_MaxSRVBindPoint = std::max(Resources.m_MaxSRVBindPoint, static_cast<MaxBindPointType>(BuffSRV.BindPoint + BuffSRV.BindCount - 1));
- }
-
- void OnNewSampler(const D3DShaderResourceAttribs& SamplerAttribs)
- {
- VERIFY(SamplerAttribs.BindPoint + SamplerAttribs.BindCount - 1 <= MaxAllowedBindPoint, "Sampler bind point exceeds supported range");
- Resources.m_MaxSamplerBindPoint = std::max(Resources.m_MaxSamplerBindPoint, static_cast<MaxBindPointType>(SamplerAttribs.BindPoint + SamplerAttribs.BindCount - 1));
- }
-
- void OnNewTexSRV(const D3DShaderResourceAttribs& TexAttribs)
- {
- VERIFY(TexAttribs.BindPoint + TexAttribs.BindCount - 1 <= MaxAllowedBindPoint, "Tex SRV bind point exceeds supported range");
- Resources.m_MaxSRVBindPoint = std::max(Resources.m_MaxSRVBindPoint, static_cast<MaxBindPointType>(TexAttribs.BindPoint + TexAttribs.BindCount - 1));
- }
-
- ~NewResourceHandler()
- {
- }
-
- private:
- RenderDeviceD3D11Impl* const pDeviceD3D11Impl;
- const ShaderDesc& ShdrDesc;
- const char* CombinedSamplerSuffix;
- ShaderResourcesD3D11& Resources;
- };
-
- Initialize<D3D11_SHADER_DESC, D3D11_SHADER_INPUT_BIND_DESC, ID3D11ShaderReflection>(
- pShaderBytecode,
- NewResourceHandler{pDeviceD3D11Impl, ShdrDesc, CombinedSamplerSuffix, *this},
- ShdrDesc.Name,
- CombinedSamplerSuffix);
-}
-
-
-ShaderResourcesD3D11::~ShaderResourcesD3D11()
-{
-}
-
-
-#ifdef DILIGENT_DEVELOPMENT
-static String DbgMakeResourceName(const D3DShaderResourceAttribs& Attr, Uint32 BindPoint)
-{
- VERIFY(BindPoint >= Uint32{Attr.BindPoint} && BindPoint < Uint32{Attr.BindPoint} + Attr.BindCount, "Bind point is out of allowed range");
- if (Attr.BindCount == 1)
- return Attr.Name;
- else
- return String(Attr.Name) + '[' + std::to_string(BindPoint - Attr.BindPoint) + ']';
-}
-
-void ShaderResourcesD3D11::dvpVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[],
- ID3D11ShaderResourceView* CommittedD3D11SRVs[],
- ID3D11Resource* CommittedD3D11SRVResources[],
- ID3D11SamplerState* CommittedD3D11Samplers[],
- ID3D11UnorderedAccessView* CommittedD3D11UAVs[],
- ID3D11Resource* CommittedD3D11UAVResources[],
- ShaderResourceCacheD3D11& ResourceCache) const
-{
- ShaderResourceCacheD3D11::CachedCB* CachedCBs = nullptr;
- ID3D11Buffer** d3d11CBs = nullptr;
- ShaderResourceCacheD3D11::CachedResource* CachedSRVResources = nullptr;
- ID3D11ShaderResourceView** d3d11SRVs = nullptr;
- ShaderResourceCacheD3D11::CachedSampler* CachedSamplers = nullptr;
- ID3D11SamplerState** d3d11Samplers = nullptr;
- ShaderResourceCacheD3D11::CachedResource* CachedUAVResources = nullptr;
- ID3D11UnorderedAccessView** d3d11UAVs = nullptr;
- // clang-format off
- ResourceCache.GetCBArrays (CachedCBs, d3d11CBs);
- ResourceCache.GetSRVArrays (CachedSRVResources, d3d11SRVs);
- ResourceCache.GetSamplerArrays(CachedSamplers, d3d11Samplers);
- ResourceCache.GetUAVArrays (CachedUAVResources, d3d11UAVs);
- // clang-format on
-
- ProcessResources(
- [&](const D3DShaderResourceAttribs& cb, Uint32) //
- {
- for (auto BindPoint = cb.BindPoint; BindPoint < cb.BindPoint + cb.BindCount; ++BindPoint)
- {
- if (BindPoint >= ResourceCache.GetCBCount())
- {
- LOG_ERROR_MESSAGE("Unable to find constant buffer '", DbgMakeResourceName(cb, BindPoint), "' (slot ",
- BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetCBCount(),
- " CB slots only. This should never happen and may be the result of using wrong resource cache.");
- continue;
- }
- auto& CB = CachedCBs[BindPoint];
- if (CB.pBuff == nullptr)
- {
- LOG_ERROR_MESSAGE("Constant buffer '", DbgMakeResourceName(cb, BindPoint), "' (slot ",
- BindPoint, ") is not initialized in the resource cache.");
- continue;
- }
-
- if (!(CB.pBuff->GetDesc().BindFlags & BIND_UNIFORM_BUFFER))
- {
- LOG_ERROR_MESSAGE("Buffer '", CB.pBuff->GetDesc().Name,
- "' committed in the device context as constant buffer to variable '",
- DbgMakeResourceName(cb, BindPoint), "' (slot ", BindPoint,
- ") in shader '", GetShaderName(), "' was not created with BIND_UNIFORM_BUFFER flag");
- continue;
- }
-
- VERIFY_EXPR(d3d11CBs[BindPoint] == CB.pBuff->GetD3D11Buffer());
-
- if (CommittedD3D11CBs[BindPoint] == nullptr)
- {
- LOG_ERROR_MESSAGE("No D3D11 resource committed to constant buffer '", DbgMakeResourceName(cb, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
- continue;
- }
-
- if (CommittedD3D11CBs[BindPoint] != d3d11CBs[BindPoint])
- {
- LOG_ERROR_MESSAGE("D3D11 resource committed to constant buffer '", DbgMakeResourceName(cb, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' does not match the resource in the resource cache");
- continue;
- }
- }
- },
-
- [&](const D3DShaderResourceAttribs& sam, Uint32) //
- {
- for (auto BindPoint = sam.BindPoint; BindPoint < sam.BindPoint + sam.BindCount; ++BindPoint)
- {
- if (BindPoint >= ResourceCache.GetSamplerCount())
- {
- LOG_ERROR_MESSAGE("Unable to find sampler '", DbgMakeResourceName(sam, BindPoint), "' (slot ", BindPoint,
- ") in the resource cache: the cache reserves ", ResourceCache.GetSamplerCount(),
- " Sampler slots only. This should never happen and may be the result of using wrong resource cache.");
- continue;
- }
- auto& Sam = CachedSamplers[BindPoint];
- if (Sam.pSampler == nullptr)
- {
- LOG_ERROR_MESSAGE("Sampler '", DbgMakeResourceName(sam, BindPoint), "' (slot ", BindPoint,
- ") is not initialized in the resource cache.");
- continue;
- }
- VERIFY_EXPR(d3d11Samplers[BindPoint] == Sam.pSampler->GetD3D11SamplerState());
-
- if (CommittedD3D11Samplers[BindPoint] == nullptr)
- {
- LOG_ERROR_MESSAGE("No D3D11 sampler committed to variable '", DbgMakeResourceName(sam, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
- continue;
- }
-
- if (CommittedD3D11Samplers[BindPoint] != d3d11Samplers[BindPoint])
- {
- LOG_ERROR_MESSAGE("D3D11 sampler committed to variable '", DbgMakeResourceName(sam, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' does not match the resource in the resource cache");
- continue;
- }
- }
- },
-
- [&](const D3DShaderResourceAttribs& tex, Uint32) //
- {
- for (auto BindPoint = tex.BindPoint; BindPoint < tex.BindPoint + tex.BindCount; ++BindPoint)
- {
- if (BindPoint >= ResourceCache.GetSRVCount())
- {
- LOG_ERROR_MESSAGE("Unable to find texture SRV '", DbgMakeResourceName(tex, BindPoint), "' (slot ",
- BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetSRVCount(),
- " SRV slots only. This should never happen and may be the result of using wrong resource cache.");
- continue;
- }
- auto& SRVRes = CachedSRVResources[BindPoint];
- if (SRVRes.pBuffer != nullptr)
- {
- LOG_ERROR_MESSAGE("Unexpected buffer bound to variable '", DbgMakeResourceName(tex, BindPoint), "' (slot ",
- BindPoint, "). Texture is expected.");
- continue;
- }
- if (SRVRes.pTexture == nullptr)
- {
- LOG_ERROR_MESSAGE("Texture '", DbgMakeResourceName(tex, BindPoint), "' (slot ", BindPoint,
- ") is not initialized in the resource cache.");
- continue;
- }
-
- if (!(SRVRes.pTexture->GetDesc().BindFlags & BIND_SHADER_RESOURCE))
- {
- LOG_ERROR_MESSAGE("Texture '", SRVRes.pTexture->GetDesc().Name,
- "' committed in the device context as SRV to variable '", DbgMakeResourceName(tex, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' was not created with BIND_SHADER_RESOURCE flag");
- }
-
- if (CommittedD3D11SRVs[BindPoint] == nullptr)
- {
- LOG_ERROR_MESSAGE("No D3D11 resource committed to texture SRV '", DbgMakeResourceName(tex, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
- continue;
- }
-
- if (CommittedD3D11SRVs[BindPoint] != d3d11SRVs[BindPoint])
- {
- LOG_ERROR_MESSAGE("D3D11 resource committed to texture SRV '", DbgMakeResourceName(tex, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(),
- "' does not match the resource in the resource cache");
- continue;
- }
- }
-
- if (tex.IsCombinedWithSampler())
- {
- const auto& SamAttribs = GetCombinedSampler(tex);
- VERIFY_EXPR(SamAttribs.IsValidBindPoint());
- VERIFY_EXPR(SamAttribs.BindCount == 1 || SamAttribs.BindCount == tex.BindCount);
- }
- },
-
- [&](const D3DShaderResourceAttribs& uav, Uint32) //
- {
- for (auto BindPoint = uav.BindPoint; BindPoint < uav.BindPoint + uav.BindCount; ++BindPoint)
- {
- if (BindPoint >= ResourceCache.GetUAVCount())
- {
- LOG_ERROR_MESSAGE("Unable to find texture UAV '", DbgMakeResourceName(uav, BindPoint), "' (slot ",
- BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetUAVCount(),
- " UAV slots only. This should never happen and may be the result of using wrong resource cache.");
- continue;
- }
- auto& UAVRes = CachedUAVResources[BindPoint];
- if (UAVRes.pBuffer != nullptr)
- {
- LOG_ERROR_MESSAGE("Unexpected buffer bound to variable '", DbgMakeResourceName(uav, BindPoint),
- "' (slot ", BindPoint, "). Texture is expected.");
- continue;
- }
- if (UAVRes.pTexture == nullptr)
- {
- LOG_ERROR_MESSAGE("Texture '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint,
- ") is not initialized in the resource cache.");
- continue;
- }
-
- if (!(UAVRes.pTexture->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Texture '", UAVRes.pTexture->GetDesc().Name,
- "' committed in the device context as UAV to variable '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' was not created with BIND_UNORDERED_ACCESS flag");
- }
-
- if (CommittedD3D11UAVs[BindPoint] == nullptr)
- {
- LOG_ERROR_MESSAGE("No D3D11 resource committed to texture UAV '", DbgMakeResourceName(uav, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
- continue;
- }
-
- if (CommittedD3D11UAVs[BindPoint] != d3d11UAVs[BindPoint])
- {
- LOG_ERROR_MESSAGE("D3D11 resource committed to texture UAV '", DbgMakeResourceName(uav, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' does not match the resource in the resource cache");
- continue;
- }
- }
- },
-
-
- [&](const D3DShaderResourceAttribs& buf, Uint32) //
- {
- for (auto BindPoint = buf.BindPoint; BindPoint < buf.BindPoint + buf.BindCount; ++BindPoint)
- {
- if (BindPoint >= ResourceCache.GetSRVCount())
- {
- LOG_ERROR_MESSAGE("Unable to find buffer SRV '", DbgMakeResourceName(buf, BindPoint), "' (slot ", BindPoint,
- ") in the resource cache: the cache reserves ", ResourceCache.GetSRVCount(),
- " SRV slots only. This should never happen and may be the result of using wrong resource cache.");
- continue;
- }
- auto& SRVRes = CachedSRVResources[BindPoint];
- if (SRVRes.pTexture != nullptr)
- {
- LOG_ERROR_MESSAGE("Unexpected texture bound to variable '", DbgMakeResourceName(buf, BindPoint),
- "' (slot ", BindPoint, "). Buffer is expected.");
- continue;
- }
- if (SRVRes.pBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("Buffer '", DbgMakeResourceName(buf, BindPoint), "' (slot ", BindPoint,
- ") is not initialized in the resource cache.");
- continue;
- }
-
- if (!(SRVRes.pBuffer->GetDesc().BindFlags & BIND_SHADER_RESOURCE))
- {
- LOG_ERROR_MESSAGE("Buffer '", SRVRes.pBuffer->GetDesc().Name,
- "' committed in the device context as SRV to variable '", DbgMakeResourceName(buf, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(),
- "' was not created with BIND_SHADER_RESOURCE flag");
- }
-
- if (CommittedD3D11SRVs[BindPoint] == nullptr)
- {
- LOG_ERROR_MESSAGE("No D3D11 resource committed to buffer SRV '", DbgMakeResourceName(buf, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
- continue;
- }
-
- if (CommittedD3D11SRVs[BindPoint] != d3d11SRVs[BindPoint])
- {
- LOG_ERROR_MESSAGE("D3D11 resource committed to buffer SRV '", DbgMakeResourceName(buf, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(),
- "' does not match the resource in the resource cache");
- continue;
- }
- }
- },
-
- [&](const D3DShaderResourceAttribs& uav, Uint32) //
- {
- for (auto BindPoint = uav.BindPoint; BindPoint < uav.BindPoint + uav.BindCount; ++BindPoint)
- {
- if (BindPoint >= ResourceCache.GetUAVCount())
- {
- LOG_ERROR_MESSAGE("Unable to find buffer UAV '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint,
- ") in the resource cache: the cache reserves ", ResourceCache.GetUAVCount(),
- " UAV slots only. This should never happen and may be the result of using wrong resource cache.");
- continue;
- }
- auto& UAVRes = CachedUAVResources[BindPoint];
- if (UAVRes.pTexture != nullptr)
- {
- LOG_ERROR_MESSAGE("Unexpected texture bound to variable '", DbgMakeResourceName(uav, BindPoint),
- "' (slot ", BindPoint, "). Buffer is expected.");
- return;
- }
- if (UAVRes.pBuffer == nullptr)
- {
- LOG_ERROR_MESSAGE("Buffer UAV '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint,
- ") is not initialized in the resource cache.");
- return;
- }
-
- if (!(UAVRes.pBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
- {
- LOG_ERROR_MESSAGE("Buffer '", UAVRes.pBuffer->GetDesc().Name,
- "' committed in the device context as UAV to variable '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' was not created with BIND_UNORDERED_ACCESS flag");
- }
-
- if (CommittedD3D11UAVs[BindPoint] == nullptr)
- {
- LOG_ERROR_MESSAGE("No D3D11 resource committed to buffer UAV '", DbgMakeResourceName(uav, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
- return;
- }
-
- if (CommittedD3D11UAVs[BindPoint] != d3d11UAVs[BindPoint])
- {
- LOG_ERROR_MESSAGE("D3D11 resource committed to buffer UAV '", DbgMakeResourceName(uav, BindPoint),
- "' (slot ", BindPoint, ") in shader '", GetShaderName(),
- "' does not match the resource in the resource cache");
- return;
- }
- }
- } // clang-format off
- ); // clang-format on
-}
-#endif
-
-} // namespace Diligent
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include <d3dcompiler.h>
+#include "ShaderResourcesD3D11.hpp"
+#include "ShaderBase.hpp"
+#include "ShaderResourceCacheD3D11.hpp"
+#include "RenderDeviceD3D11Impl.hpp"
+
+namespace Diligent
+{
+
+
+ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Impl,
+ ID3DBlob* pShaderBytecode,
+ const ShaderDesc& ShdrDesc,
+ const char* CombinedSamplerSuffix) :
+ ShaderResources{ShdrDesc.ShaderType}
+{
+ class NewResourceHandler
+ {
+ public:
+ NewResourceHandler(RenderDeviceD3D11Impl* const _pDeviceD3D11Impl,
+ const ShaderDesc& _ShdrDesc,
+ const char* _CombinedSamplerSuffix,
+ ShaderResourcesD3D11& _Resources) :
+ // clang-format off
+ pDeviceD3D11Impl {_pDeviceD3D11Impl },
+ ShdrDesc {_ShdrDesc },
+ CombinedSamplerSuffix{_CombinedSamplerSuffix},
+ Resources {_Resources }
+ // clang-format on
+ {}
+
+ void OnNewCB(const D3DShaderResourceAttribs& CBAttribs)
+ {
+ VERIFY(CBAttribs.BindPoint + CBAttribs.BindCount - 1 <= MaxAllowedBindPoint, "CB bind point exceeds supported range");
+ Resources.m_MaxCBBindPoint = std::max(Resources.m_MaxCBBindPoint, static_cast<MaxBindPointType>(CBAttribs.BindPoint + CBAttribs.BindCount - 1));
+ }
+
+ void OnNewTexUAV(const D3DShaderResourceAttribs& TexUAV)
+ {
+ VERIFY(TexUAV.BindPoint + TexUAV.BindCount - 1 <= MaxAllowedBindPoint, "Tex UAV bind point exceeds supported range");
+ Resources.m_MaxUAVBindPoint = std::max(Resources.m_MaxUAVBindPoint, static_cast<MaxBindPointType>(TexUAV.BindPoint + TexUAV.BindCount - 1));
+ }
+
+ void OnNewBuffUAV(const D3DShaderResourceAttribs& BuffUAV)
+ {
+ VERIFY(BuffUAV.BindPoint + BuffUAV.BindCount - 1 <= MaxAllowedBindPoint, "Buff UAV bind point exceeds supported range");
+ Resources.m_MaxUAVBindPoint = std::max(Resources.m_MaxUAVBindPoint, static_cast<MaxBindPointType>(BuffUAV.BindPoint + BuffUAV.BindCount - 1));
+ }
+
+ void OnNewBuffSRV(const D3DShaderResourceAttribs& BuffSRV)
+ {
+ VERIFY(BuffSRV.BindPoint + BuffSRV.BindCount - 1 <= MaxAllowedBindPoint, "Buff SRV bind point exceeds supported range");
+ Resources.m_MaxSRVBindPoint = std::max(Resources.m_MaxSRVBindPoint, static_cast<MaxBindPointType>(BuffSRV.BindPoint + BuffSRV.BindCount - 1));
+ }
+
+ void OnNewSampler(const D3DShaderResourceAttribs& SamplerAttribs)
+ {
+ VERIFY(SamplerAttribs.BindPoint + SamplerAttribs.BindCount - 1 <= MaxAllowedBindPoint, "Sampler bind point exceeds supported range");
+ Resources.m_MaxSamplerBindPoint = std::max(Resources.m_MaxSamplerBindPoint, static_cast<MaxBindPointType>(SamplerAttribs.BindPoint + SamplerAttribs.BindCount - 1));
+ }
+
+ void OnNewTexSRV(const D3DShaderResourceAttribs& TexAttribs)
+ {
+ VERIFY(TexAttribs.BindPoint + TexAttribs.BindCount - 1 <= MaxAllowedBindPoint, "Tex SRV bind point exceeds supported range");
+ Resources.m_MaxSRVBindPoint = std::max(Resources.m_MaxSRVBindPoint, static_cast<MaxBindPointType>(TexAttribs.BindPoint + TexAttribs.BindCount - 1));
+ }
+
+ ~NewResourceHandler()
+ {
+ }
+
+ private:
+ RenderDeviceD3D11Impl* const pDeviceD3D11Impl;
+ const ShaderDesc& ShdrDesc;
+ const char* CombinedSamplerSuffix;
+ ShaderResourcesD3D11& Resources;
+ };
+
+ CComPtr<ID3D11ShaderReflection> pShaderReflection;
+ HRESULT hr = D3DReflect(pShaderBytecode->GetBufferPointer(), pShaderBytecode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(&pShaderReflection));
+ CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection");
+
+
+ Initialize<D3D11_SHADER_DESC, D3D11_SHADER_INPUT_BIND_DESC>(
+ static_cast<ID3D11ShaderReflection*>(pShaderReflection),
+ NewResourceHandler{pDeviceD3D11Impl, ShdrDesc, CombinedSamplerSuffix, *this},
+ ShdrDesc.Name,
+ CombinedSamplerSuffix);
+}
+
+
+ShaderResourcesD3D11::~ShaderResourcesD3D11()
+{
+}
+
+
+#ifdef DILIGENT_DEVELOPMENT
+static String DbgMakeResourceName(const D3DShaderResourceAttribs& Attr, Uint32 BindPoint)
+{
+ VERIFY(BindPoint >= Uint32{Attr.BindPoint} && BindPoint < Uint32{Attr.BindPoint} + Attr.BindCount, "Bind point is out of allowed range");
+ if (Attr.BindCount == 1)
+ return Attr.Name;
+ else
+ return String(Attr.Name) + '[' + std::to_string(BindPoint - Attr.BindPoint) + ']';
+}
+
+void ShaderResourcesD3D11::dvpVerifyCommittedResources(ID3D11Buffer* CommittedD3D11CBs[],
+ ID3D11ShaderResourceView* CommittedD3D11SRVs[],
+ ID3D11Resource* CommittedD3D11SRVResources[],
+ ID3D11SamplerState* CommittedD3D11Samplers[],
+ ID3D11UnorderedAccessView* CommittedD3D11UAVs[],
+ ID3D11Resource* CommittedD3D11UAVResources[],
+ ShaderResourceCacheD3D11& ResourceCache) const
+{
+ ShaderResourceCacheD3D11::CachedCB* CachedCBs = nullptr;
+ ID3D11Buffer** d3d11CBs = nullptr;
+ ShaderResourceCacheD3D11::CachedResource* CachedSRVResources = nullptr;
+ ID3D11ShaderResourceView** d3d11SRVs = nullptr;
+ ShaderResourceCacheD3D11::CachedSampler* CachedSamplers = nullptr;
+ ID3D11SamplerState** d3d11Samplers = nullptr;
+ ShaderResourceCacheD3D11::CachedResource* CachedUAVResources = nullptr;
+ ID3D11UnorderedAccessView** d3d11UAVs = nullptr;
+ // clang-format off
+ ResourceCache.GetCBArrays (CachedCBs, d3d11CBs);
+ ResourceCache.GetSRVArrays (CachedSRVResources, d3d11SRVs);
+ ResourceCache.GetSamplerArrays(CachedSamplers, d3d11Samplers);
+ ResourceCache.GetUAVArrays (CachedUAVResources, d3d11UAVs);
+ // clang-format on
+
+ ProcessResources(
+ [&](const D3DShaderResourceAttribs& cb, Uint32) //
+ {
+ for (auto BindPoint = cb.BindPoint; BindPoint < cb.BindPoint + cb.BindCount; ++BindPoint)
+ {
+ if (BindPoint >= ResourceCache.GetCBCount())
+ {
+ LOG_ERROR_MESSAGE("Unable to find constant buffer '", DbgMakeResourceName(cb, BindPoint), "' (slot ",
+ BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetCBCount(),
+ " CB slots only. This should never happen and may be the result of using wrong resource cache.");
+ continue;
+ }
+ auto& CB = CachedCBs[BindPoint];
+ if (CB.pBuff == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Constant buffer '", DbgMakeResourceName(cb, BindPoint), "' (slot ",
+ BindPoint, ") is not initialized in the resource cache.");
+ continue;
+ }
+
+ if (!(CB.pBuff->GetDesc().BindFlags & BIND_UNIFORM_BUFFER))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", CB.pBuff->GetDesc().Name,
+ "' committed in the device context as constant buffer to variable '",
+ DbgMakeResourceName(cb, BindPoint), "' (slot ", BindPoint,
+ ") in shader '", GetShaderName(), "' was not created with BIND_UNIFORM_BUFFER flag");
+ continue;
+ }
+
+ VERIFY_EXPR(d3d11CBs[BindPoint] == CB.pBuff->GetD3D11Buffer());
+
+ if (CommittedD3D11CBs[BindPoint] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No D3D11 resource committed to constant buffer '", DbgMakeResourceName(cb, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
+ continue;
+ }
+
+ if (CommittedD3D11CBs[BindPoint] != d3d11CBs[BindPoint])
+ {
+ LOG_ERROR_MESSAGE("D3D11 resource committed to constant buffer '", DbgMakeResourceName(cb, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' does not match the resource in the resource cache");
+ continue;
+ }
+ }
+ },
+
+ [&](const D3DShaderResourceAttribs& sam, Uint32) //
+ {
+ for (auto BindPoint = sam.BindPoint; BindPoint < sam.BindPoint + sam.BindCount; ++BindPoint)
+ {
+ if (BindPoint >= ResourceCache.GetSamplerCount())
+ {
+ LOG_ERROR_MESSAGE("Unable to find sampler '", DbgMakeResourceName(sam, BindPoint), "' (slot ", BindPoint,
+ ") in the resource cache: the cache reserves ", ResourceCache.GetSamplerCount(),
+ " Sampler slots only. This should never happen and may be the result of using wrong resource cache.");
+ continue;
+ }
+ auto& Sam = CachedSamplers[BindPoint];
+ if (Sam.pSampler == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Sampler '", DbgMakeResourceName(sam, BindPoint), "' (slot ", BindPoint,
+ ") is not initialized in the resource cache.");
+ continue;
+ }
+ VERIFY_EXPR(d3d11Samplers[BindPoint] == Sam.pSampler->GetD3D11SamplerState());
+
+ if (CommittedD3D11Samplers[BindPoint] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No D3D11 sampler committed to variable '", DbgMakeResourceName(sam, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
+ continue;
+ }
+
+ if (CommittedD3D11Samplers[BindPoint] != d3d11Samplers[BindPoint])
+ {
+ LOG_ERROR_MESSAGE("D3D11 sampler committed to variable '", DbgMakeResourceName(sam, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' does not match the resource in the resource cache");
+ continue;
+ }
+ }
+ },
+
+ [&](const D3DShaderResourceAttribs& tex, Uint32) //
+ {
+ for (auto BindPoint = tex.BindPoint; BindPoint < tex.BindPoint + tex.BindCount; ++BindPoint)
+ {
+ if (BindPoint >= ResourceCache.GetSRVCount())
+ {
+ LOG_ERROR_MESSAGE("Unable to find texture SRV '", DbgMakeResourceName(tex, BindPoint), "' (slot ",
+ BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetSRVCount(),
+ " SRV slots only. This should never happen and may be the result of using wrong resource cache.");
+ continue;
+ }
+ auto& SRVRes = CachedSRVResources[BindPoint];
+ if (SRVRes.pBuffer != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Unexpected buffer bound to variable '", DbgMakeResourceName(tex, BindPoint), "' (slot ",
+ BindPoint, "). Texture is expected.");
+ continue;
+ }
+ if (SRVRes.pTexture == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Texture '", DbgMakeResourceName(tex, BindPoint), "' (slot ", BindPoint,
+ ") is not initialized in the resource cache.");
+ continue;
+ }
+
+ if (!(SRVRes.pTexture->GetDesc().BindFlags & BIND_SHADER_RESOURCE))
+ {
+ LOG_ERROR_MESSAGE("Texture '", SRVRes.pTexture->GetDesc().Name,
+ "' committed in the device context as SRV to variable '", DbgMakeResourceName(tex, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' was not created with BIND_SHADER_RESOURCE flag");
+ }
+
+ if (CommittedD3D11SRVs[BindPoint] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No D3D11 resource committed to texture SRV '", DbgMakeResourceName(tex, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
+ continue;
+ }
+
+ if (CommittedD3D11SRVs[BindPoint] != d3d11SRVs[BindPoint])
+ {
+ LOG_ERROR_MESSAGE("D3D11 resource committed to texture SRV '", DbgMakeResourceName(tex, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(),
+ "' does not match the resource in the resource cache");
+ continue;
+ }
+ }
+
+ if (tex.IsCombinedWithSampler())
+ {
+ const auto& SamAttribs = GetCombinedSampler(tex);
+ VERIFY_EXPR(SamAttribs.IsValidBindPoint());
+ VERIFY_EXPR(SamAttribs.BindCount == 1 || SamAttribs.BindCount == tex.BindCount);
+ }
+ },
+
+ [&](const D3DShaderResourceAttribs& uav, Uint32) //
+ {
+ for (auto BindPoint = uav.BindPoint; BindPoint < uav.BindPoint + uav.BindCount; ++BindPoint)
+ {
+ if (BindPoint >= ResourceCache.GetUAVCount())
+ {
+ LOG_ERROR_MESSAGE("Unable to find texture UAV '", DbgMakeResourceName(uav, BindPoint), "' (slot ",
+ BindPoint, ") in the resource cache: the cache reserves ", ResourceCache.GetUAVCount(),
+ " UAV slots only. This should never happen and may be the result of using wrong resource cache.");
+ continue;
+ }
+ auto& UAVRes = CachedUAVResources[BindPoint];
+ if (UAVRes.pBuffer != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Unexpected buffer bound to variable '", DbgMakeResourceName(uav, BindPoint),
+ "' (slot ", BindPoint, "). Texture is expected.");
+ continue;
+ }
+ if (UAVRes.pTexture == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Texture '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint,
+ ") is not initialized in the resource cache.");
+ continue;
+ }
+
+ if (!(UAVRes.pTexture->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Texture '", UAVRes.pTexture->GetDesc().Name,
+ "' committed in the device context as UAV to variable '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' was not created with BIND_UNORDERED_ACCESS flag");
+ }
+
+ if (CommittedD3D11UAVs[BindPoint] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No D3D11 resource committed to texture UAV '", DbgMakeResourceName(uav, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
+ continue;
+ }
+
+ if (CommittedD3D11UAVs[BindPoint] != d3d11UAVs[BindPoint])
+ {
+ LOG_ERROR_MESSAGE("D3D11 resource committed to texture UAV '", DbgMakeResourceName(uav, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' does not match the resource in the resource cache");
+ continue;
+ }
+ }
+ },
+
+
+ [&](const D3DShaderResourceAttribs& buf, Uint32) //
+ {
+ for (auto BindPoint = buf.BindPoint; BindPoint < buf.BindPoint + buf.BindCount; ++BindPoint)
+ {
+ if (BindPoint >= ResourceCache.GetSRVCount())
+ {
+ LOG_ERROR_MESSAGE("Unable to find buffer SRV '", DbgMakeResourceName(buf, BindPoint), "' (slot ", BindPoint,
+ ") in the resource cache: the cache reserves ", ResourceCache.GetSRVCount(),
+ " SRV slots only. This should never happen and may be the result of using wrong resource cache.");
+ continue;
+ }
+ auto& SRVRes = CachedSRVResources[BindPoint];
+ if (SRVRes.pTexture != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Unexpected texture bound to variable '", DbgMakeResourceName(buf, BindPoint),
+ "' (slot ", BindPoint, "). Buffer is expected.");
+ continue;
+ }
+ if (SRVRes.pBuffer == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Buffer '", DbgMakeResourceName(buf, BindPoint), "' (slot ", BindPoint,
+ ") is not initialized in the resource cache.");
+ continue;
+ }
+
+ if (!(SRVRes.pBuffer->GetDesc().BindFlags & BIND_SHADER_RESOURCE))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", SRVRes.pBuffer->GetDesc().Name,
+ "' committed in the device context as SRV to variable '", DbgMakeResourceName(buf, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(),
+ "' was not created with BIND_SHADER_RESOURCE flag");
+ }
+
+ if (CommittedD3D11SRVs[BindPoint] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No D3D11 resource committed to buffer SRV '", DbgMakeResourceName(buf, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
+ continue;
+ }
+
+ if (CommittedD3D11SRVs[BindPoint] != d3d11SRVs[BindPoint])
+ {
+ LOG_ERROR_MESSAGE("D3D11 resource committed to buffer SRV '", DbgMakeResourceName(buf, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(),
+ "' does not match the resource in the resource cache");
+ continue;
+ }
+ }
+ },
+
+ [&](const D3DShaderResourceAttribs& uav, Uint32) //
+ {
+ for (auto BindPoint = uav.BindPoint; BindPoint < uav.BindPoint + uav.BindCount; ++BindPoint)
+ {
+ if (BindPoint >= ResourceCache.GetUAVCount())
+ {
+ LOG_ERROR_MESSAGE("Unable to find buffer UAV '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint,
+ ") in the resource cache: the cache reserves ", ResourceCache.GetUAVCount(),
+ " UAV slots only. This should never happen and may be the result of using wrong resource cache.");
+ continue;
+ }
+ auto& UAVRes = CachedUAVResources[BindPoint];
+ if (UAVRes.pTexture != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Unexpected texture bound to variable '", DbgMakeResourceName(uav, BindPoint),
+ "' (slot ", BindPoint, "). Buffer is expected.");
+ return;
+ }
+ if (UAVRes.pBuffer == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Buffer UAV '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint,
+ ") is not initialized in the resource cache.");
+ return;
+ }
+
+ if (!(UAVRes.pBuffer->GetDesc().BindFlags & BIND_UNORDERED_ACCESS))
+ {
+ LOG_ERROR_MESSAGE("Buffer '", UAVRes.pBuffer->GetDesc().Name,
+ "' committed in the device context as UAV to variable '", DbgMakeResourceName(uav, BindPoint), "' (slot ", BindPoint, ") in shader '", GetShaderName(), "' was not created with BIND_UNORDERED_ACCESS flag");
+ }
+
+ if (CommittedD3D11UAVs[BindPoint] == nullptr)
+ {
+ LOG_ERROR_MESSAGE("No D3D11 resource committed to buffer UAV '", DbgMakeResourceName(uav, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(), "'");
+ return;
+ }
+
+ if (CommittedD3D11UAVs[BindPoint] != d3d11UAVs[BindPoint])
+ {
+ LOG_ERROR_MESSAGE("D3D11 resource committed to buffer UAV '", DbgMakeResourceName(uav, BindPoint),
+ "' (slot ", BindPoint, ") in shader '", GetShaderName(),
+ "' does not match the resource in the resource cache");
+ return;
+ }
+ }
+ } // clang-format off
+ ); // clang-format on
+}
+#endif
+
+} // namespace Diligent
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);
diff --git a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt
index 4b8f046f..f95d6f39 100644
--- a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt
+++ b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt
@@ -69,6 +69,14 @@ PUBLIC
set_common_target_properties(Diligent-GraphicsEngineD3DBase)
+if(${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} STRGREATER_EQUAL "10.0.17763.0")
+ set(HAS_DXIL_COMPILER TRUE CACHE INTERNAL "" FORCE)
+ target_compile_definitions(Diligent-GraphicsEngineD3DBase PRIVATE HAS_DXIL_COMPILER)
+ target_link_libraries(Diligent-GraphicsEngineD3DBase PRIVATE dxcompiler.lib)
+else()
+ set(HAS_DXIL_COMPILER FALSE CACHE INTERNAL "" FORCE)
+endif()
+
source_group("src" FILES ${SOURCE})
source_group("include" FILES ${INCLUDE})
source_group("interface" FILES ${INTERFACE})
diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp
index ea3a9f3e..f63aa8ad 100644
--- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp
+++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp
@@ -52,8 +52,8 @@ struct D3DShaderResourceCounters
template <typename D3D_SHADER_DESC,
typename D3D_SHADER_INPUT_BIND_DESC,
- typename TShaderReflection,
+ typename TShaderReflection,
typename THandleShaderDesc,
typename TOnResourcesCounted,
typename TOnNewCB,
@@ -62,7 +62,7 @@ template <typename D3D_SHADER_DESC,
typename TOnNewBuffSRV,
typename TOnNewSampler,
typename TOnNewTexSRV>
-void LoadD3DShaderResources(ID3DBlob* pShaderByteCode,
+void LoadD3DShaderResources(TShaderReflection* pShaderReflection,
THandleShaderDesc HandleShaderDesc,
TOnResourcesCounted OnResourcesCounted,
TOnNewCB OnNewCB,
@@ -72,11 +72,6 @@ void LoadD3DShaderResources(ID3DBlob* pShaderByteCode,
TOnNewSampler OnNewSampler,
TOnNewTexSRV OnNewTexSRV)
{
- CComPtr<TShaderReflection> pShaderReflection;
-
- auto hr = D3DReflect(pShaderByteCode->GetBufferPointer(), pShaderByteCode->GetBufferSize(), __uuidof(pShaderReflection), reinterpret_cast<void**>(static_cast<TShaderReflection**>(&pShaderReflection)));
- CHECK_D3D_RESULT_THROW(hr, "Failed to get the shader reflection");
-
D3D_SHADER_DESC shaderDesc = {};
pShaderReflection->GetDesc(&shaderDesc);
diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp
index e7b61f59..5dac32d4 100644
--- a/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp
+++ b/Graphics/GraphicsEngineD3DBase/include/ShaderD3DBase.hpp
@@ -41,10 +41,11 @@ namespace Diligent
class ShaderD3DBase
{
public:
- ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const char* ShaderModel);
+ ShaderD3DBase(const ShaderCreateInfo& ShaderCI, Uint8 ShaderModel);
protected:
CComPtr<ID3DBlob> m_pShaderByteCode;
+ bool m_isDXIL;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp
index 5765e20a..49976ba8 100644
--- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp
+++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp
@@ -395,7 +395,7 @@ protected:
typename D3D_SHADER_INPUT_BIND_DESC,
typename TShaderReflection,
typename TNewResourceHandler>
- void Initialize(ID3DBlob* pShaderByteCode,
+ void Initialize(TShaderReflection* pShaderReflection,
TNewResourceHandler NewResHandler,
const Char* ShaderName,
const Char* SamplerSuffix);
@@ -460,14 +460,14 @@ template <typename D3D_SHADER_DESC,
typename D3D_SHADER_INPUT_BIND_DESC,
typename TShaderReflection,
typename TNewResourceHandler>
-void ShaderResources::Initialize(ID3DBlob* pShaderByteCode,
+void ShaderResources::Initialize(TShaderReflection* pShaderReflection,
TNewResourceHandler NewResHandler,
const Char* ShaderName,
const Char* CombinedSamplerSuffix)
{
Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0;
- LoadD3DShaderResources<D3D_SHADER_DESC, D3D_SHADER_INPUT_BIND_DESC, TShaderReflection>(
- pShaderByteCode,
+ LoadD3DShaderResources<D3D_SHADER_DESC, D3D_SHADER_INPUT_BIND_DESC>(
+ pShaderReflection,
[&](const D3D_SHADER_DESC& d3dShaderDesc) //
{
diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp
index 3962a8e4..d9a8fdc0 100644
--- a/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp
+++ b/Graphics/GraphicsEngineD3DBase/src/ShaderD3DBase.cpp
@@ -33,6 +33,12 @@
#include "RefCntAutoPtr.hpp"
#include <atlcomcli.h>
#include "ShaderD3DBase.hpp"
+#include <locale>
+#include <cwchar>
+
+#ifdef HAS_DXIL_COMPILER
+#include "dxcapi.h"
+#endif
namespace Diligent
{
@@ -42,6 +48,220 @@ static const Char* g_HLSLDefinitions =
#include "HLSLDefinitions_inc.fxh"
};
+
+#ifdef HAS_DXIL_COMPILER
+class DxcIncludeHandlerImpl final : public IDxcIncludeHandler
+{
+public:
+ explicit DxcIncludeHandlerImpl(IShaderSourceInputStreamFactory* pStreamFactory, CComPtr<IDxcLibrary> pLibrary) :
+ m_pLibrary{pLibrary},
+ m_pStreamFactory{pStreamFactory},
+ m_RefCount{1}
+ {
+ }
+
+ HRESULT STDMETHODCALLTYPE LoadSource(_In_ LPCWSTR pFilename, _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource) override
+ {
+ String fileName = std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>, wchar_t>{}.to_bytes(pFilename);
+ if (fileName.empty())
+ {
+ LOG_ERROR("Failed to convert shader include file name ", fileName, ". File name must be ANSI string");
+ return E_FAIL;
+ }
+
+ RefCntAutoPtr<IFileStream> pSourceStream;
+ m_pStreamFactory->CreateInputStream(fileName.c_str(), &pSourceStream);
+ if (pSourceStream == nullptr)
+ {
+ LOG_ERROR("Failed to open shader include file ", fileName, ". Check that the file exists");
+ return E_FAIL;
+ }
+
+ RefCntAutoPtr<IDataBlob> pFileData(MakeNewRCObj<DataBlobImpl>()(0));
+ pSourceStream->ReadBlob(pFileData);
+
+ CComPtr<IDxcBlobEncoding> sourceBlob;
+ HRESULT hr = m_pLibrary->CreateBlobWithEncodingFromPinned(pFileData->GetDataPtr(), UINT32(pFileData->GetSize()), CP_UTF8, &sourceBlob);
+ if (FAILED(hr))
+ {
+ LOG_ERROR("Failed to allocate space for shader include file ", fileName, ".");
+ return E_FAIL;
+ }
+
+ m_FileDataCache.push_back(pFileData);
+
+ sourceBlob->QueryInterface(__uuidof(*ppIncludeSource), reinterpret_cast<void**>(ppIncludeSource));
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) override
+ {
+ return E_FAIL;
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef(void) override
+ {
+ return m_RefCount++;
+ }
+
+ ULONG STDMETHODCALLTYPE Release(void) override
+ {
+ --m_RefCount;
+ VERIFY(m_RefCount > 0, "Inconsistent call to Release()");
+ return m_RefCount;
+ }
+
+private:
+ CComPtr<IDxcLibrary> m_pLibrary;
+ IShaderSourceInputStreamFactory* m_pStreamFactory;
+ ULONG m_RefCount;
+ std::vector<RefCntAutoPtr<IDataBlob>> m_FileDataCache;
+};
+#endif
+
+static HRESULT CompileDxilShader(const char* Source,
+ const ShaderCreateInfo& ShaderCI,
+ LPCSTR profile,
+ ID3DBlob** ppBlobOut,
+ ID3DBlob** ppCompilerOutput)
+{
+#ifdef HAS_DXIL_COMPILER
+ std::vector<WCHAR> unicodeBuffer; unicodeBuffer.resize(1u << 15);
+ size_t unicodeBufferOffset = 0;
+
+ const auto ToUnicode = [&unicodeBuffer, &unicodeBufferOffset](const char* str) {
+ auto len = strlen(str) + 1;
+ auto pos = unicodeBufferOffset;
+ unicodeBufferOffset += len;
+ VERIFY(unicodeBufferOffset < unicodeBuffer.size(), "buffer overflow");
+ for (size_t i = 0; i < len; ++i) {
+ unicodeBuffer[pos + i] = str[i];
+ }
+ return &unicodeBuffer[pos];
+ };
+
+ std::vector<DxcDefine> D3DMacros;
+ switch (ShaderCI.Desc.ShaderType)
+ {
+ case SHADER_TYPE_VERTEX:
+ D3DMacros.push_back({L"VERTEX_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_PIXEL:
+ D3DMacros.push_back({L"FRAGMENT_SHADER", L"1"});
+ D3DMacros.push_back({L"PIXEL_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_GEOMETRY:
+ D3DMacros.push_back({L"GEOMETRY_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_HULL:
+ D3DMacros.push_back({L"TESS_CONTROL_SHADER", L"1"});
+ D3DMacros.push_back({L"HULL_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_DOMAIN:
+ D3DMacros.push_back({L"TESS_EVALUATION_SHADER", L"1"});
+ D3DMacros.push_back({L"DOMAIN_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_COMPUTE:
+ D3DMacros.push_back({L"COMPUTE_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_AMPLIFICATION:
+ D3DMacros.push_back({L"TASK_SHADER", L"1"});
+ D3DMacros.push_back({L"AMPLIFICATION_SHADER", L"1"});
+ break;
+
+ case SHADER_TYPE_MESH:
+ D3DMacros.push_back({L"MESH_SHADER", L"1"});
+ break;
+
+ default: UNEXPECTED("Unexpected shader type");
+ }
+
+ if (ShaderCI.Macros)
+ {
+ for (auto* pCurrMacro = ShaderCI.Macros; pCurrMacro->Name && pCurrMacro->Definition; ++pCurrMacro)
+ {
+ D3DMacros.push_back({ToUnicode(pCurrMacro->Name), ToUnicode(pCurrMacro->Definition)});
+ }
+ }
+
+ HRESULT hr;
+
+ CComPtr<IDxcLibrary> library;
+ hr = DxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&library));
+ if (FAILED(hr))
+ return hr;
+
+ CComPtr<IDxcCompiler> compiler;
+ hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler));
+ if (FAILED(hr))
+ return hr;
+
+ CComPtr<IDxcBlobEncoding> sourceBlob;
+ hr = library->CreateBlobWithEncodingFromPinned(Source, UINT32(strlen(Source)), CP_UTF8, &sourceBlob);
+ if (FAILED(hr))
+ return hr;
+
+ const wchar_t* pArgs[] =
+ {
+ L"-Zpc", // Matrices in column-major order
+ L"-WX", // Warnings as errors
+# ifdef DILIGENT_DEBUG
+ L"-Zi", // Debug info
+ //L"-Qembed_debug", // Embed debug info into the shader (some compilers do not recognize this flag)
+ L"-Od", // Disable optimization
+# else
+ L"-O3", // Optimization level 3
+# endif
+ };
+
+ DxcIncludeHandlerImpl IncludeHandler{ShaderCI.pShaderSourceStreamFactory, library};
+
+ CComPtr<IDxcOperationResult> result;
+ hr = compiler->Compile(
+ sourceBlob,
+ L"",
+ ToUnicode(ShaderCI.EntryPoint),
+ ToUnicode(profile),
+ pArgs, UINT32(std::size(pArgs)),
+ D3DMacros.data(), UINT32(D3DMacros.size()),
+ &IncludeHandler,
+ &result);
+
+ if (SUCCEEDED(hr))
+ {
+ HRESULT status;
+ if (SUCCEEDED(result->GetStatus(&status)))
+ hr = status;
+ }
+
+ if (FAILED(hr))
+ {
+ if (result)
+ {
+ CComPtr<IDxcBlobEncoding> errorsBlob;
+ if (SUCCEEDED(result->GetErrorBuffer(&errorsBlob)) && errorsBlob)
+ {
+ errorsBlob->QueryInterface(__uuidof(*ppCompilerOutput), reinterpret_cast<void**>(ppCompilerOutput));
+ }
+ }
+ return hr;
+ }
+
+ hr = result->GetResult(reinterpret_cast<IDxcBlob**>(ppBlobOut));
+ return hr;
+#else
+ UNSUPPORTED("Shader model 6 and above requires DXIL compiler");
+ return E_FAIL;
+#endif
+}
+
+
class D3DIncludeImpl : public ID3DInclude
{
public:
@@ -83,14 +303,55 @@ private:
std::unordered_map<LPCVOID, RefCntAutoPtr<IDataBlob>> m_DataBlobs;
};
-static HRESULT CompileShader(const char* Source,
- LPCSTR strFunctionName,
- const D3D_SHADER_MACRO* pDefines,
- IShaderSourceInputStreamFactory* pIncludeStreamFactory,
- LPCSTR profile,
- ID3DBlob** ppBlobOut,
- ID3DBlob** ppCompilerOutput)
+static HRESULT CompileShader(const char* Source,
+ const ShaderCreateInfo& ShaderCI,
+ LPCSTR profile,
+ ID3DBlob** ppBlobOut,
+ ID3DBlob** ppCompilerOutput)
{
+ std::vector<D3D_SHADER_MACRO> D3DMacros;
+ switch (ShaderCI.Desc.ShaderType)
+ {
+ case SHADER_TYPE_VERTEX:
+ D3DMacros.push_back({"VERTEX_SHADER", "1"});
+ break;
+
+ case SHADER_TYPE_PIXEL:
+ D3DMacros.push_back({"FRAGMENT_SHADER", "1"});
+ D3DMacros.push_back({"PIXEL_SHADER", "1"});
+ break;
+
+ case SHADER_TYPE_GEOMETRY:
+ D3DMacros.push_back({"GEOMETRY_SHADER", "1"});
+ break;
+
+ case SHADER_TYPE_HULL:
+ D3DMacros.push_back({"TESS_CONTROL_SHADER", "1"});
+ D3DMacros.push_back({"HULL_SHADER", "1"});
+ break;
+
+ case SHADER_TYPE_DOMAIN:
+ D3DMacros.push_back({"TESS_EVALUATION_SHADER", "1"});
+ D3DMacros.push_back({"DOMAIN_SHADER", "1"});
+ break;
+
+ case SHADER_TYPE_COMPUTE:
+ D3DMacros.push_back({"COMPUTE_SHADER", "1"});
+ break;
+
+ default: UNEXPECTED("Unexpected shader type");
+ }
+
+ if (ShaderCI.Macros)
+ {
+ for (auto* pCurrMacro = ShaderCI.Macros; pCurrMacro->Name && pCurrMacro->Definition; ++pCurrMacro)
+ {
+ D3DMacros.push_back({pCurrMacro->Name, pCurrMacro->Definition});
+ }
+ }
+
+ D3DMacros.push_back({nullptr, nullptr});
+
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined(DILIGENT_DEBUG)
// Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders.
@@ -103,13 +364,13 @@ static HRESULT CompileShader(const char* Source,
// report strange errors:
// dwShaderFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL3;
#endif
- HRESULT hr;
+
// do
// {
- auto SourceLen = strlen(Source);
- D3DIncludeImpl IncludeImpl(pIncludeStreamFactory);
- hr = D3DCompile(Source, SourceLen, NULL, pDefines, &IncludeImpl, strFunctionName, profile, dwShaderFlags, 0, ppBlobOut, ppCompilerOutput);
+ D3DIncludeImpl IncludeImpl(ShaderCI.pShaderSourceStreamFactory);
+ auto SourceLen = strlen(Source);
+ auto hr = D3DCompile(Source, SourceLen, NULL, D3DMacros.data(), &IncludeImpl, ShaderCI.EntryPoint, profile, dwShaderFlags, 0, ppBlobOut, ppCompilerOutput);
// if( FAILED(hr) || errors )
// {
@@ -126,7 +387,8 @@ static HRESULT CompileShader(const char* Source,
return hr;
}
-ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const char* ShaderModel)
+ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, Uint8 ShaderModel) :
+ m_isDXIL{false}
{
if (ShaderCI.Source || ShaderCI.FilePath)
{
@@ -137,18 +399,24 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const char* Shade
switch (ShaderCI.Desc.ShaderType)
{
// clang-format off
- case SHADER_TYPE_VERTEX: strShaderProfile="vs"; break;
- case SHADER_TYPE_PIXEL: strShaderProfile="ps"; break;
- case SHADER_TYPE_GEOMETRY:strShaderProfile="gs"; break;
- case SHADER_TYPE_HULL: strShaderProfile="hs"; break;
- case SHADER_TYPE_DOMAIN: strShaderProfile="ds"; break;
- case SHADER_TYPE_COMPUTE: strShaderProfile="cs"; break;
+ case SHADER_TYPE_VERTEX: strShaderProfile="vs"; break;
+ case SHADER_TYPE_PIXEL: strShaderProfile="ps"; break;
+ case SHADER_TYPE_GEOMETRY: strShaderProfile="gs"; break;
+ case SHADER_TYPE_HULL: strShaderProfile="hs"; break;
+ case SHADER_TYPE_DOMAIN: strShaderProfile="ds"; break;
+ case SHADER_TYPE_COMPUTE: strShaderProfile="cs"; break;
+ case SHADER_TYPE_AMPLIFICATION: strShaderProfile="as"; break;
+ case SHADER_TYPE_MESH: strShaderProfile="ms"; break;
// clang-format on
default: UNEXPECTED("Unknown shader type");
}
strShaderProfile += "_";
- strShaderProfile += ShaderModel;
+ strShaderProfile += '0' + ((ShaderModel >> 4) & 0xF);
+ strShaderProfile += "_";
+ strShaderProfile += ((ShaderModel & 0xF) == 0xF) ? 'x' : ('0' + (ShaderModel & 0xF));
+
+ m_isDXIL = (ShaderModel >= 0x60);
String ShaderSource(g_HLSLDefinitions);
if (ShaderCI.Source)
@@ -171,56 +439,17 @@ ShaderD3DBase::ShaderD3DBase(const ShaderCreateInfo& ShaderCI, const char* Shade
ShaderSource.append(FileDataPtr, FileDataPtr + Size / sizeof(*FileDataPtr));
}
- const D3D_SHADER_MACRO* pDefines = nullptr;
- std::vector<D3D_SHADER_MACRO> D3DMacros;
- switch (ShaderCI.Desc.ShaderType)
- {
- case SHADER_TYPE_VERTEX:
- D3DMacros.push_back({"VERTEX_SHADER", "1"});
- break;
-
- case SHADER_TYPE_PIXEL:
- D3DMacros.push_back({"FRAGMENT_SHADER", "1"});
- D3DMacros.push_back({"PIXEL_SHADER", "1"});
- break;
-
- case SHADER_TYPE_GEOMETRY:
- D3DMacros.push_back({"GEOMETRY_SHADER", "1"});
- break;
-
- case SHADER_TYPE_HULL:
- D3DMacros.push_back({"TESS_CONTROL_SHADER", "1"});
- D3DMacros.push_back({"HULL_SHADER", "1"});
- break;
-
- case SHADER_TYPE_DOMAIN:
- D3DMacros.push_back({"TESS_EVALUATION_SHADER", "1"});
- D3DMacros.push_back({"DOMAIN_SHADER", "1"});
- break;
-
- case SHADER_TYPE_COMPUTE:
- D3DMacros.push_back({"COMPUTE_SHADER", "1"});
- break;
-
- default: UNEXPECTED("Unexpected shader type");
- }
-
- if (ShaderCI.Macros)
- {
- for (auto* pCurrMacro = ShaderCI.Macros; pCurrMacro->Name && pCurrMacro->Definition; ++pCurrMacro)
- {
- D3DMacros.push_back({pCurrMacro->Name, pCurrMacro->Definition});
- }
- }
-
- D3DMacros.push_back({nullptr, nullptr});
- pDefines = D3DMacros.data();
-
DEV_CHECK_ERR(ShaderCI.EntryPoint != nullptr, "Entry point must not be null");
+
CComPtr<ID3DBlob> errors;
- auto hr = CompileShader(ShaderSource.c_str(), ShaderCI.EntryPoint, pDefines, ShaderCI.pShaderSourceStreamFactory, strShaderProfile.c_str(), &m_pShaderByteCode, &errors);
+ HRESULT hr;
+
+ if (m_isDXIL)
+ hr = CompileDxilShader(ShaderSource.c_str(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors);
+ else
+ hr = CompileShader(ShaderSource.c_str(), ShaderCI, strShaderProfile.c_str(), &m_pShaderByteCode, &errors);
- const char* CompilerMsg = errors ? reinterpret_cast<const char*>(errors->GetBufferPointer()) : nullptr;
+ const char* CompilerMsg = errors ? static_cast<const char*>(errors->GetBufferPointer()) : nullptr;
if (CompilerMsg != nullptr && ShaderCI.ppCompilerOutput != nullptr)
{
auto ErrorMsgLen = strlen(CompilerMsg);
diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
index e80e0d04..54eff631 100644
--- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp
@@ -120,6 +120,10 @@ public:
virtual void DILIGENT_CALL_TYPE DrawIndirect (const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
/// Implementation of IDeviceContext::DrawIndexedIndirect() in OpenGL backend.
virtual void DILIGENT_CALL_TYPE DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
+ /// Implementation of IDeviceContext::DrawMesh() in OpenGL backend.
+ virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final;
+ /// Implementation of IDeviceContext::DrawMeshIndirect() in OpenGL backend.
+ virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
/// Implementation of IDeviceContext::DispatchCompute() in OpenGL backend.
virtual void DILIGENT_CALL_TYPE DispatchCompute (const DispatchComputeAttribs& Attribs) override final;
diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
index f6308229..7728de7b 100644
--- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
@@ -84,7 +84,7 @@ void DeviceContextGLImpl::SetPipelineState(IPipelineState* pPipelineState)
TDeviceContextBase::SetPipelineState(pPipelineStateGLImpl, 0 /*Dummy*/);
const auto& Desc = pPipelineStateGLImpl->GetDesc();
- if (Desc.IsComputePipeline)
+ if (Desc.IsComputePipeline())
{
}
else
@@ -874,6 +874,16 @@ void DeviceContextGLImpl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs&
#endif
}
+void DeviceContextGLImpl::DrawMesh(const DrawMeshAttribs& Attribs)
+{
+ UNSUPPORTED("DrawMesh is not supported in OpenGL");
+}
+
+void DeviceContextGLImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ UNSUPPORTED("DrawMeshIndirect is not supported in OpenGL");
+}
+
void DeviceContextGLImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
{
diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
index 72d504be..bb2201d1 100644
--- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
@@ -52,7 +52,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun
m_StaticResourceLayout{*this}
// clang-format on
{
- if (!m_Desc.IsComputePipeline && m_pPS == nullptr)
+ if (m_Desc.IsAnyGraphicsPipeline() && m_pPS == nullptr)
{
// Some OpenGL implementations fail if fragment shader is not present, so
// create a dummy one.
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
index 83e2c077..4dd6ae1e 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
@@ -142,6 +142,10 @@ public:
virtual void DILIGENT_CALL_TYPE DrawIndirect (const DrawIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
/// Implementation of IDeviceContext::DrawIndexedIndirect() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE DrawIndexedIndirect(const DrawIndexedIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
+ /// Implementation of IDeviceContext::DrawMesh() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE DrawMesh (const DrawMeshAttribs& Attribs) override final;
+ /// Implementation of IDeviceContext::DrawMeshIndirect() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE DrawMeshIndirect (const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer) override final;
/// Implementation of IDeviceContext::DispatchCompute() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE DispatchCompute (const DispatchComputeAttribs& Attribs) override final;
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index aca69cac..01f37a76 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -156,7 +156,7 @@ private:
VulkanUtilities::PipelineWrapper m_Pipeline;
PipelineLayout m_PipelineLayout;
- Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1};
+ std::array<Int8, 8> m_ResourceLayoutIndex;
bool m_HasStaticResources = false;
bool m_HasNonStaticResources = false;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
index 1465024b..5e4f5062 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.hpp
@@ -138,6 +138,32 @@ public:
vkCmdDrawIndexedIndirect(m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride);
}
+ __forceinline void DrawMesh(uint32_t TaskCount, uint32_t FirstTask)
+ {
+#ifdef VK_NV_mesh_shader
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksNV() must be called inside render pass (19.3)");
+ VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound");
+
+ vkCmdDrawMeshTasksNV(m_VkCmdBuffer, TaskCount, FirstTask);
+#else
+ UNSUPPORTED("DrawMesh is not supported in current Vulkan headers");
+#endif
+ }
+
+ __forceinline void DrawMeshIndirect(VkBuffer Buffer, VkDeviceSize Offset, uint32_t DrawCount, uint32_t Stride)
+ {
+#ifdef VK_NV_mesh_shader
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "vkCmdDrawMeshTasksNV() must be called inside render pass (19.3)");
+ VERIFY(m_State.GraphicsPipeline != VK_NULL_HANDLE, "No graphics pipeline bound");
+
+ vkCmdDrawMeshTasksIndirectNV(m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride);
+#else
+ UNSUPPORTED("DrawMeshIndirect is not supported in current Vulkan headers");
+#endif
+ }
+
__forceinline void Dispatch(uint32_t GroupCountX, uint32_t GroupCountY, uint32_t GroupCountZ)
{
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp
index 3fcb736d..0ca092c6 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp
@@ -63,6 +63,7 @@ public:
// clang-format off
bool IsLayerAvailable (const char* LayerName) const;
bool IsExtensionAvailable(const char* ExtensionName)const;
+ bool IsExtensionEnabled (const char* ExtensionName)const;
VkPhysicalDevice SelectPhysicalDevice()const;
@@ -82,6 +83,7 @@ private:
std::vector<VkLayerProperties> m_Layers;
std::vector<VkExtensionProperties> m_Extensions;
+ std::vector<const char*> m_EnabledExtensions;
std::vector<VkPhysicalDevice> m_PhysicalDevices;
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
index 24212950..17bc2e4a 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
@@ -29,7 +29,7 @@
#include <memory>
#include <vector>
-#include "VulkanHeaders.h"
+#include "VulkanInstance.hpp"
namespace VulkanUtilities
{
@@ -37,6 +37,18 @@ namespace VulkanUtilities
class VulkanPhysicalDevice
{
public:
+ struct ExtensionFeatures
+ {
+#ifdef VK_NV_mesh_shader
+ VkPhysicalDeviceMeshShaderFeaturesNV MeshShader;
+#endif
+ };
+
+ struct ExtensionProperties
+ {
+ };
+
+public:
// clang-format off
VulkanPhysicalDevice (const VulkanPhysicalDevice&) = delete;
VulkanPhysicalDevice (VulkanPhysicalDevice&&) = delete;
@@ -44,7 +56,8 @@ public:
VulkanPhysicalDevice& operator = (VulkanPhysicalDevice&&) = delete;
// clang-format on
- static std::unique_ptr<VulkanPhysicalDevice> Create(VkPhysicalDevice vkDevice);
+ static std::unique_ptr<VulkanPhysicalDevice> Create(VkPhysicalDevice vkDevice,
+ std::shared_ptr<VulkanInstance> Instance);
// clang-format off
uint32_t FindQueueFamily (VkQueueFlags QueueFlags) const;
@@ -59,15 +72,20 @@ public:
const VkPhysicalDeviceProperties& GetProperties() const { return m_Properties; }
const VkPhysicalDeviceFeatures& GetFeatures() const { return m_Features; }
+ const ExtensionProperties& GetExtProperties() const { return m_ExtProperties; }
+ const ExtensionFeatures& GetExtFeatures() const { return m_ExtFeatures; }
VkFormatProperties GetPhysicalDeviceFormatProperties(VkFormat imageFormat) const;
private:
- VulkanPhysicalDevice(VkPhysicalDevice vkDevice);
+ VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
+ std::shared_ptr<VulkanInstance> Instance);
const VkPhysicalDevice m_VkDevice;
VkPhysicalDeviceProperties m_Properties = {};
VkPhysicalDeviceFeatures m_Features = {};
VkPhysicalDeviceMemoryProperties m_MemoryProperties = {};
+ ExtensionProperties m_ExtProperties = {};
+ ExtensionFeatures m_ExtFeatures = {};
std::vector<VkQueueFamilyProperties> m_QueueFamilyProperties;
std::vector<VkExtensionProperties> m_SupportedExtensions;
};
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index d61ddc97..a8ec8364 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -256,7 +256,7 @@ void DeviceContextVkImpl::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 was disabled in previous pipeline
CommitScissor = !OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable;
}
@@ -264,7 +264,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
TDeviceContextBase::SetPipelineState(pPipelineStateVk, 0 /*Dummy*/);
EnsureVkCmdBuffer();
- if (PSODesc.IsComputePipeline)
+ if (PSODesc.IsComputePipeline())
{
auto vkPipeline = pPipelineStateVk->GetVkPipeline();
m_CommandBuffer.BindComputePipeline(vkPipeline);
@@ -553,6 +553,31 @@ void DeviceContextVkImpl::DrawIndexedIndirect(const DrawIndexedIndirectAttribs&
++m_State.NumCommands;
}
+void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs)
+{
+ if (!DvpVerifyDrawMeshArguments(Attribs))
+ return;
+
+ PrepareForDraw(Attribs.Flags);
+
+ m_CommandBuffer.DrawMesh(Attribs.ThreadGroupCount, 0);
+ ++m_State.NumCommands;
+}
+
+void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attribs, IBuffer* pAttribsBuffer)
+{
+ if (!DvpVerifyDrawMeshIndirectArguments(Attribs, pAttribsBuffer))
+ return;
+
+ // We must prepare indirect draw attribs buffer first because state transitions must
+ // be performed outside of render pass, and PrepareForDraw commits render pass
+ BufferVkImpl* pIndirectDrawAttribsVk = PrepareIndirectDrawAttribsBuffer(pAttribsBuffer, Attribs.IndirectAttribsBufferStateTransitionMode);
+
+ PrepareForDraw(Attribs.Flags);
+
+ m_CommandBuffer.DrawMeshIndirect(pIndirectDrawAttribsVk->GetVkBuffer(), pIndirectDrawAttribsVk->GetDynamicOffset(m_ContextId, this) + Attribs.IndirectDrawArgsOffset, 1, 0);
+ ++m_State.NumCommands;
+}
void DeviceContextVkImpl::PrepareForDispatchCompute()
{
@@ -1067,7 +1092,7 @@ void DeviceContextVkImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, U
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");
CommitScissorRects();
diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index 8d72a0b5..58aea393 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -144,7 +144,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
reinterpret_cast<VkAllocationCallbacks*>(EngineCI.pVkAllocator));
auto vkDevice = Instance->SelectPhysicalDevice();
- auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice);
+ auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice, Instance);
const auto& PhysicalDeviceFeatures = PhysicalDevice->GetFeatures();
// If an implementation exposes any queue family that supports graphics operations,
@@ -155,7 +155,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
QueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
QueueInfo.flags = 0; // reserved for future use
// All commands that are allowed on a queue that supports transfer operations are also allowed on a
- // queue that supports either graphics or compute operations.Thus, if the capabilities of a queue family
+ // queue that supports either graphics or compute operations. Thus, if the capabilities of a queue family
// include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT
// capability separately for that queue family is optional (4.1).
QueueInfo.queueFamilyIndex = PhysicalDevice->FindQueueFamily(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
@@ -200,6 +200,24 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height
};
+
+ // To enable some device extensions you must enable instance extension VK_KHR_get_physical_device_properties2
+ // and add feature description to DeviceCreateInfo.pNext.
+ bool SupportsFeatures2 = Instance->IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+ void** NextExt = const_cast<void **>(&DeviceCreateInfo.pNext);
+
+ // Enable mesh shader extension.
+#ifdef VK_NV_mesh_shader
+ VkPhysicalDeviceMeshShaderFeaturesNV MeshShaderFeats = PhysicalDevice->GetExtFeatures().MeshShader;
+
+ if (SupportsFeatures2 && PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME))
+ {
+ DeviceExtensions.push_back(VK_NV_MESH_SHADER_EXTENSION_NAME);
+ *NextExt = &MeshShaderFeats;
+ NextExt = &MeshShaderFeats.pNext;
+ }
+#endif
+
DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
index 7742cd63..be1bf51d 100644
--- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
@@ -157,7 +157,7 @@ std::array<RefCntAutoPtr<IPipelineState>, 4> GenerateMipsVkHelper::CreatePSOs(TE
PipelineStateCreateInfo PSOCreateInfo;
PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
- PSODesc.IsComputePipeline = true;
+ PSODesc.PipelineType = COMPUTE_PIPELINE;
PSODesc.Name = name.c_str();
PSODesc.ComputePipeline.pCS = pCS;
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index 32a68780..8fa63070 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -46,12 +46,16 @@ static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE Shader
switch (ShaderType)
{
// clang-format off
- case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
- case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
- case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
- case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
- case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
- case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
+ case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
+ case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
+ case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
+ case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
+#ifdef VK_NV_mesh_shader
+ case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV;
+ case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV;
+#endif
// clang-format on
default:
UNEXPECTED("Unknown shader type");
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 99b27d2c..063978f9 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -173,6 +173,8 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2);
m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders);
m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
+ m_ResourceLayoutIndex.fill(-1);
+
for (Uint32 s = 0; s < m_NumShaders; ++s)
{
new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(LogicalDevice);
@@ -228,12 +230,16 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
switch (ShaderType)
{
// clang-format off
- case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break;
- case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
- case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
- case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break;
- case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break;
- case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break;
+ case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break;
+ case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
+ case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
+ case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break;
+ case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break;
+ case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break;
+#ifdef VK_NV_mesh_shader
+ case SHADER_TYPE_AMPLIFICATION: StageCI.stage = VK_SHADER_STAGE_TASK_BIT_NV; break;
+ case SHADER_TYPE_MESH: StageCI.stage = VK_SHADER_STAGE_MESH_BIT_NV; break;
+#endif
default: UNEXPECTED("Unknown shader type");
// clang-format on
}
@@ -269,7 +275,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
}
// Create pipeline
- if (m_Desc.IsComputePipeline)
+ if (m_Desc.IsComputePipeline())
{
auto& ComputePipeline = m_Desc.ComputePipeline;
@@ -642,7 +648,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
}
// Prepare descriptor sets, and also bind them if there are no dynamic descriptors
VERIFY_EXPR(pDescrSetBindInfo != nullptr);
- m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet);
+ m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline(), ResourceCache, *pDescrSetBindInfo, DynamicDescrSet);
// Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools
// are released at the end of the frame by DeviceContextVkImpl::FinishFrame().
}
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 4e6049b0..66ea8716 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -156,6 +156,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
auto& Features = m_DeviceCaps.Features;
const auto& vkDeviceFeatures = m_PhysicalDevice->GetFeatures();
+ const auto& vkExtFeatures = m_PhysicalDevice->GetExtFeatures();
Features.SeparablePrograms = True;
Features.IndirectRendering = True;
@@ -179,6 +180,9 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
Features.PixelUAVWritesAndAtomics = vkDeviceFeatures.fragmentStoresAndAtomics != VK_FALSE;
Features.TextureUAVExtendedFormats = vkDeviceFeatures.shaderStorageImageExtendedFormats != VK_FALSE;
+ // All devices that supports mesh shader also supports task shader, so it is not necessary to use two separate features.
+ Features.MeshShaders = vkExtFeatures.MeshShader.meshShader != VK_FALSE && vkExtFeatures.MeshShader.taskShader != VK_FALSE;
+
const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits;
auto& TexCaps = m_DeviceCaps.TexCaps;
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
index aa6235f3..603da02a 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
@@ -27,6 +27,7 @@
#include <vector>
#include <cstring>
+#include "VulkanUtilities/VulkanInstance.hpp"
#if DILIGENT_USE_VOLK
# define VOLK_IMPLEMENTATION
@@ -34,7 +35,6 @@
#endif
#include "VulkanErrors.hpp"
-#include "VulkanUtilities/VulkanInstance.hpp"
#include "VulkanUtilities/VulkanDebug.hpp"
#if !DILIGENT_NO_GLSLANG
@@ -64,6 +64,15 @@ bool VulkanInstance::IsExtensionAvailable(const char* ExtensionName) const
return false;
}
+bool VulkanInstance::IsExtensionEnabled(const char* ExtensionName) const
+{
+ for (const auto& Extension : m_EnabledExtensions)
+ if (strcmp(Extension, ExtensionName) == 0)
+ return true;
+
+ return false;
+}
+
std::shared_ptr<VulkanInstance> VulkanInstance::Create(bool EnableValidation,
uint32_t GlobalExtensionCount,
const char* const* ppGlobalExtensionNames,
@@ -138,6 +147,14 @@ VulkanInstance::VulkanInstance(bool EnableValidation,
#endif
};
+ // This extension added to core in 1.1, but current version is 1.0
+#ifdef VK_KHR_get_physical_device_properties2
+ if (IsExtensionAvailable(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
+ {
+ GlobalExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+ }
+#endif
+
if (ppGlobalExtensionNames != nullptr)
{
for (uint32_t ext = 0; ext < GlobalExtensionCount; ++ext)
@@ -213,6 +230,8 @@ VulkanInstance::VulkanInstance(bool EnableValidation,
volkLoadInstance(m_VkInstance);
#endif
+ m_EnabledExtensions = std::move(GlobalExtensions);
+
// If requested, we enable the default validation layers for debugging
if (m_DebugUtilsEnabled)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
index 22eee45e..f18d6872 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
@@ -33,13 +33,15 @@
namespace VulkanUtilities
{
-std::unique_ptr<VulkanPhysicalDevice> VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice)
+std::unique_ptr<VulkanPhysicalDevice> VulkanPhysicalDevice::Create(VkPhysicalDevice vkDevice,
+ std::shared_ptr<VulkanInstance> Instance)
{
- auto* PhysicalDevice = new VulkanPhysicalDevice{vkDevice};
+ auto* PhysicalDevice = new VulkanPhysicalDevice{vkDevice, Instance};
return std::unique_ptr<VulkanPhysicalDevice>{PhysicalDevice};
}
-VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) :
+VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
+ std::shared_ptr<VulkanInstance> Instance) :
m_VkDevice{vkDevice}
{
VERIFY_EXPR(m_VkDevice != VK_NULL_HANDLE);
@@ -65,6 +67,29 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice) :
(void)res;
VERIFY_EXPR(ExtensionCount == m_SupportedExtensions.size());
}
+
+ if (Instance->IsExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
+ {
+ VkPhysicalDeviceFeatures2 Feats2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
+ VkPhysicalDeviceProperties2 Props2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
+ void** NextFeat = &Feats2.pNext;
+ //void** NextProp = &Props2.pNext;
+
+ // Enable mesh shader extension.
+#ifdef VK_NV_mesh_shader
+ if (IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME))
+ {
+ *NextFeat = &m_ExtFeatures.MeshShader;
+ NextFeat = &m_ExtFeatures.MeshShader.pNext;
+ m_ExtFeatures.MeshShader.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV;
+ }
+#endif
+
+ // Initialize device extension features by current physical device features.
+ // Some flags may not be supported by hardware.
+ vkGetPhysicalDeviceFeatures2KHR(m_VkDevice, &Feats2);
+ vkGetPhysicalDeviceProperties2KHR(m_VkDevice, &Props2);
+ }
}
uint32_t VulkanPhysicalDevice::FindQueueFamily(VkQueueFlags QueueFlags) const