From 7f26e40e0898391a32e6a05d91ef1a217d885668 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sun, 25 Oct 2020 15:53:05 +0300 Subject: PSO refactoring for ray tracing --- .../src/GraphicsAccessories.cpp | 79 ++- .../GraphicsEngine/include/PipelineStateBase.hpp | 212 +++++- Graphics/GraphicsEngine/interface/APIInfo.h | 120 ++-- Graphics/GraphicsEngine/interface/Constants.h | 4 +- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 15 +- Graphics/GraphicsEngine/interface/PipelineState.h | 92 +-- Graphics/GraphicsEngine/interface/RenderDevice.h | 42 +- Graphics/GraphicsEngine/interface/Shader.h | 7 +- Graphics/GraphicsEngine/src/APIInfo.cpp | 4 +- Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 58 ++ .../include/PipelineStateD3D11Impl.hpp | 2 +- .../include/RenderDeviceD3D11Impl.hpp | 4 + .../include/ShaderResourceBindingD3D11Impl.hpp | 2 +- .../src/PipelineStateD3D11Impl.cpp | 2 + .../src/RenderDeviceD3D11Impl.cpp | 13 +- .../src/ShaderResourceLayoutD3D11.cpp | 5 + .../src/ShaderResourcesD3D11.cpp | 10 + .../GraphicsEngineD3D12/include/CommandContext.hpp | 5 +- .../include/PipelineStateD3D12Impl.hpp | 36 +- .../include/RenderDeviceD3D12Impl.hpp | 9 +- .../GraphicsEngineD3D12/include/RootSignature.hpp | 11 +- .../include/ShaderD3D12Impl.hpp | 8 +- .../include/ShaderResourceBindingD3D12Impl.hpp | 2 +- .../include/ShaderResourceCacheD3D12.hpp | 3 +- .../include/ShaderResourceLayoutD3D12.hpp | 99 ++- .../include/ShaderVariableD3D12.hpp | 4 +- .../interface/PipelineStateD3D12.h | 6 + .../src/DeviceContextD3D12Impl.cpp | 11 +- .../src/PipelineStateD3D12Impl.cpp | 391 +++++++++-- .../src/RenderDeviceD3D12Impl.cpp | 35 +- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 111 ++- .../GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp | 3 +- .../src/ShaderResourceLayoutD3D12.cpp | 632 ++++++++++------- .../src/ShaderResourcesD3D12.cpp | 13 +- .../src/ShaderVariableD3D12.cpp | 8 +- .../include/D3DShaderResourceLoader.hpp | 26 +- .../include/ShaderResources.hpp | 100 +-- .../include/ShaderVariableD3DBase.hpp | 4 +- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 39 +- .../include/RenderDeviceGLImpl.hpp | 4 + .../src/PipelineStateGLImpl.cpp | 2 + .../src/RenderDeviceGLImpl.cpp | 6 + .../include/PipelineLayout.hpp | 6 +- .../include/PipelineStateVkImpl.hpp | 3 +- .../include/RenderDeviceVkImpl.hpp | 3 + .../include/ShaderResourceBindingVkImpl.hpp | 2 +- .../include/ShaderResourceCacheVk.hpp | 13 +- .../include/ShaderResourceLayoutVk.hpp | 162 +++-- .../include/ShaderVariableVk.hpp | 4 +- .../include/VulkanUtilities/VulkanInstance.hpp | 8 +- .../VulkanUtilities/VulkanLogicalDevice.hpp | 12 +- .../VulkanUtilities/VulkanObjectWrappers.hpp | 5 + .../VulkanUtilities/VulkanPhysicalDevice.hpp | 2 + .../src/DeviceContextVkImpl.cpp | 10 +- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 129 ++-- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 38 +- .../src/PipelineStateVkImpl.cpp | 499 ++++++++++---- .../src/RenderDeviceVkImpl.cpp | 53 +- .../src/ShaderResourceCacheVk.cpp | 48 +- .../src/ShaderResourceLayoutVk.cpp | 758 ++++++++++++++------- .../GraphicsEngineVulkan/src/ShaderVariableVk.cpp | 14 +- Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp | 8 + .../src/VulkanUtilities/VulkanInstance.cpp | 21 +- .../src/VulkanUtilities/VulkanLogicalDevice.cpp | 41 +- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 14 +- Graphics/ShaderTools/include/GLSLUtils.hpp | 2 +- Graphics/ShaderTools/include/GLSLangUtils.hpp | 9 + .../ShaderTools/include/SPIRVShaderResources.hpp | 117 ++-- Graphics/ShaderTools/src/DXCompiler.cpp | 240 ++++++- Graphics/ShaderTools/src/GLSLangUtils.cpp | 36 +- Graphics/ShaderTools/src/HLSLUtils.cpp | 24 +- Graphics/ShaderTools/src/SPIRVShaderResources.cpp | 102 ++- Graphics/ShaderTools/src/ShaderToolsCommon.cpp | 45 +- 73 files changed, 3303 insertions(+), 1364 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 499509fb..b909b016 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -824,20 +824,19 @@ const Char* GetBindFlagString(Uint32 BindFlag) static_assert(BIND_FLAGS_LAST == BIND_RAY_TRACING, "Please handle the new bind flag in the switch below"); switch (BindFlag) { - // clang-format off -#define BIND_FLAG_STR_CASE(Flag) case Flag: return #Flag; +#define BIND_FLAG_STR_CASE(Flag) \ + case Flag: return #Flag; BIND_FLAG_STR_CASE(BIND_VERTEX_BUFFER) - BIND_FLAG_STR_CASE(BIND_INDEX_BUFFER) - BIND_FLAG_STR_CASE(BIND_UNIFORM_BUFFER) - BIND_FLAG_STR_CASE(BIND_SHADER_RESOURCE) - BIND_FLAG_STR_CASE(BIND_STREAM_OUTPUT) - BIND_FLAG_STR_CASE(BIND_RENDER_TARGET) - BIND_FLAG_STR_CASE(BIND_DEPTH_STENCIL) - BIND_FLAG_STR_CASE(BIND_UNORDERED_ACCESS) + BIND_FLAG_STR_CASE(BIND_INDEX_BUFFER) + BIND_FLAG_STR_CASE(BIND_UNIFORM_BUFFER) + BIND_FLAG_STR_CASE(BIND_SHADER_RESOURCE) + BIND_FLAG_STR_CASE(BIND_STREAM_OUTPUT) + BIND_FLAG_STR_CASE(BIND_RENDER_TARGET) + BIND_FLAG_STR_CASE(BIND_DEPTH_STENCIL) + BIND_FLAG_STR_CASE(BIND_UNORDERED_ACCESS) BIND_FLAG_STR_CASE(BIND_INDIRECT_DRAW_ARGS) BIND_FLAG_STR_CASE(BIND_RAY_TRACING) -#undef BIND_FLAG_STR_CASE - // clang-format on +#undef BIND_FLAG_STR_CASE default: UNEXPECTED("Unexpected bind flag ", BindFlag); return ""; } } @@ -1087,6 +1086,7 @@ String GetResourceStateString(RESOURCE_STATE State) const char* GetQueryTypeString(QUERY_TYPE QueryType) { + static_assert(QUERY_TYPE_NUM_TYPES == 6, "Not all QUERY_TYPE enum values are handled"); // clang-format off switch(QueryType) { @@ -1097,8 +1097,6 @@ const char* GetQueryTypeString(QUERY_TYPE QueryType) case QUERY_TYPE_PIPELINE_STATISTICS: return "QUERY_TYPE_PIPELINE_STATISTICS"; case QUERY_TYPE_DURATION: return "QUERY_TYPE_DURATION"; - static_assert(QUERY_TYPE_NUM_TYPES == 6, "Not all QUERY_TYPE enum values are handled"); - default: UNEXPECTED("Unepxected query type"); return "Unknown"; @@ -1134,12 +1132,14 @@ const char* GetSurfaceTransformString(SURFACE_TRANSFORM SrfTransform) const char* GetPipelineTypeString(PIPELINE_TYPE PipelineType) { + static_assert(PIPELINE_TYPE_LAST == PIPELINE_TYPE_RAY_TRACING, "Please update this function to handle the new pipeline type"); // clang-format off switch (PipelineType) { - case PIPELINE_TYPE_COMPUTE: return "compute"; - case PIPELINE_TYPE_GRAPHICS: return "graphics"; - case PIPELINE_TYPE_MESH: return "mesh"; + case PIPELINE_TYPE_COMPUTE: return "compute"; + case PIPELINE_TYPE_GRAPHICS: return "graphics"; + case PIPELINE_TYPE_MESH: return "mesh"; + case PIPELINE_TYPE_RAY_TRACING: return "ray tracing"; default: UNEXPECTED("Unexpected pipeline type"); @@ -1150,17 +1150,20 @@ const char* GetPipelineTypeString(PIPELINE_TYPE PipelineType) const char* GetShaderCompilerTypeString(SHADER_COMPILER Compiler) { + static_assert(SHADER_COMPILER_LAST == SHADER_COMPILER_FXC, "Please update this function to handle the new shader compiler"); + // clang-format off switch (Compiler) { case SHADER_COMPILER_DEFAULT: return "Default"; case SHADER_COMPILER_GLSLANG: return "glslang"; - case SHADER_COMPILER_DXC: return "DXC"; - case SHADER_COMPILER_FXC: return "FXC"; + case SHADER_COMPILER_DXC: return "DXC"; + case SHADER_COMPILER_FXC: return "FXC"; default: UNEXPECTED("Unexpected shader compiler"); return "UNKNOWN"; }; + // clang-format on } Uint32 ComputeMipLevelsCount(Uint32 Width) @@ -1348,29 +1351,28 @@ Int32 GetShaderTypePipelineIndex(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineT case SHADER_TYPE_VERTEX: // Graphics case SHADER_TYPE_AMPLIFICATION: // Mesh case SHADER_TYPE_COMPUTE: // Compute + case SHADER_TYPE_RAY_GEN: // RayTracing return 0; - case SHADER_TYPE_HULL: // Graphics - case SHADER_TYPE_MESH: // Mesh + case SHADER_TYPE_HULL: // Graphics + case SHADER_TYPE_MESH: // Mesh + case SHADER_TYPE_RAY_MISS: // RayTracing return 1; - case SHADER_TYPE_DOMAIN: // Graphics + case SHADER_TYPE_DOMAIN: // Graphics + case SHADER_TYPE_RAY_CLOSEST_HIT: // RayTracing return 2; - case SHADER_TYPE_GEOMETRY: // Graphics + case SHADER_TYPE_GEOMETRY: // Graphics + case SHADER_TYPE_RAY_ANY_HIT: // RayTracing return 3; - case SHADER_TYPE_PIXEL: // Graphics or Mesh + case SHADER_TYPE_PIXEL: // Graphics or Mesh + case SHADER_TYPE_RAY_INTERSECTION: // RayTracing return 4; - case SHADER_TYPE_RAY_GEN: - case SHADER_TYPE_RAY_MISS: - case SHADER_TYPE_RAY_CLOSEST_HIT: - case SHADER_TYPE_RAY_ANY_HIT: - case SHADER_TYPE_RAY_INTERSECTION: - case SHADER_TYPE_CALLABLE: - UNEXPECTED("This function is not currently indended to handle ray-tracing shader types"); - return -1; + case SHADER_TYPE_CALLABLE: // RayTracing + return 5; default: UNEXPECTED("Unexpected shader type (", ShaderType, ")"); @@ -1420,8 +1422,19 @@ SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineTy } case PIPELINE_TYPE_RAY_TRACING: - UNEXPECTED("Ray tracing pipeline is not supported by this function"); - return SHADER_TYPE_UNKNOWN; + switch (Index) + { + case 0: return SHADER_TYPE_RAY_GEN; + case 1: return SHADER_TYPE_RAY_MISS; + case 2: return SHADER_TYPE_RAY_CLOSEST_HIT; + case 3: return SHADER_TYPE_RAY_ANY_HIT; + case 4: return SHADER_TYPE_RAY_INTERSECTION; + case 5: return SHADER_TYPE_CALLABLE; + + default: + UNEXPECTED("Index ", Index, " is not a valid ray tracing pipeline shader index"); + return SHADER_TYPE_UNKNOWN; + } default: UNEXPECTED("Unexpected pipeline type"); diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 1effd32f..42b3e16a 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -39,12 +39,14 @@ #include "EngineMemory.h" #include "GraphicsAccessories.hpp" #include "LinearAllocator.hpp" +#include "HashUtils.hpp" namespace Diligent { void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false); void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); +void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false); void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept; @@ -108,6 +110,20 @@ public: ValidateComputePipelineCreateInfo(ComputePipelineCI); } + /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO + /// \param pDevice - Pointer to the device. + /// \param RayTracingPipelineCI - Ray tracing pipeline create information. + /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and + /// must not keep a strong reference to the device. + PipelineStateBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const RayTracingPipelineStateCreateInfo& RayTracingPipelineCI, + bool bIsDeviceInternal = false) : + PipelineStateBase{pRefCounters, pDevice, RayTracingPipelineCI.PSODesc, bIsDeviceInternal} + { + ValidateRayTracingPipelineCreateInfo(ComputePipelineCI); + } + ~PipelineStateBase() { @@ -130,6 +146,15 @@ public: */ } + void Destruct() + { + if (this->m_Desc.IsRayTracingPipeline() && m_pRayTracingPipelineData) + { + m_pRayTracingPipelineData->~RayTracingPipelineData(); + m_pRayTracingPipelineData = nullptr; + } + } + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase) Uint32 GetBufferStride(Uint32 BufferSlot) const @@ -159,7 +184,58 @@ public: return *m_pGraphicsPipelineDesc; } + virtual const RayTracingPipelineDesc& DILIGENT_CALL_TYPE GetRayTracingPipelineDesc() const override final + { + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + return m_pRayTracingPipelineData->Desc; + } + + virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupCount() const override final + { + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + return static_cast(m_pRayTracingPipelineData->NameToGroupIndex.size()); + } + + static constexpr Uint32 InvalidShaderGroupIndex = ~0u; + + virtual Uint32 DILIGENT_CALL_TYPE GetShaderGroupIndex(const char* Name) const override final + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + + auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); + if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) + return iter->second; + + UNEXPECTED("Can't find shader group with specified name"); + return InvalidShaderGroupIndex; + } + + inline void CopyShaderHandle(const char* Name, void* pData, Uint32 DataSize) const + { + VERIFY_EXPR(Name != nullptr && Name[0] != '\0'); + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + VERIFY_EXPR(m_pRayTracingPipelineData != nullptr); + + const auto ShaderHandleSize = m_pRayTracingPipelineData->ShaderHandleSize; + VERIFY_EXPR(ShaderHandleSize <= DataSize); + + auto iter = m_pRayTracingPipelineData->NameToGroupIndex.find(Name); + if (iter != m_pRayTracingPipelineData->NameToGroupIndex.end()) + { + VERIFY_EXPR(ShaderHandleSize * (iter->second + 1) <= m_pRayTracingPipelineData->ShaderDataSize); + std::memcpy(pData, &m_pRayTracingPipelineData->Shaders[ShaderHandleSize * iter->second], ShaderHandleSize); + return; + } + UNEXPECTED("Can't find shader group with specified name"); + } + protected: + using TNameToGroupIndexMap = std::unordered_map; + Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array& ResourceLayoutIndex) const { if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType)) @@ -237,6 +313,9 @@ protected: } MemPool.AddSpace(m_BufferSlotsUsed); + + static_assert(std::is_trivially_destructiblem_pGraphicsPipelineDesc)>::value, "add destructor for this object"); + static_assert(std::is_trivially_destructible::value, "add destructor for this object"); } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, @@ -245,12 +324,40 @@ protected: ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); } + void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, + Uint32 ShaderHandleSize, + LinearAllocator& MemPool) const noexcept + { + ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + MemPool.AddSpaceForString(CreateInfo.pGeneralShaders[i].Name); + } + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + MemPool.AddSpaceForString(CreateInfo.pTriangleHitShaders[i].Name); + } + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + MemPool.AddSpaceForString(CreateInfo.pProceduralHitShaders[i].Name); + } + + size_t RTDataSize = sizeof(RayTracingPipelineData); + // reserve size for shader handles + RTDataSize += ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); + // 1 byte reserved to avoid compiler errors on zero sized arrays + RTDataSize -= sizeof(RayTracingPipelineData::Shaders); + MemPool.AddSpace(RTDataSize, alignof(RayTracingPipelineData)); + } + template void ExtractShaders(const GraphicsPipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages) { VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline()); ShaderStages.clear(); auto AddShaderStage = [&](IShader* pShader) { @@ -297,6 +404,7 @@ protected: TShaderStages& ShaderStages) { VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + VERIFY_EXPR(this->m_Desc.IsComputePipeline()); ShaderStages.clear(); @@ -310,6 +418,70 @@ protected: VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); } + template + void ExtractShaders(const RayTracingPipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages) + { + VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + VERIFY_EXPR(this->m_Desc.IsRayTracingPipeline()); + + std::unordered_set UniqueShaders; + + auto AddShaderStage = [&ShaderStages, &UniqueShaders](IShader* pShader) { + if (pShader != nullptr && UniqueShaders.insert(pShader).second) + { + auto ShaderType = pShader->GetDesc().ShaderType; + ShaderStages[GetShaderTypePipelineIndex(ShaderType, PIPELINE_TYPE_RAY_TRACING)].Append(ValidatedCast(pShader)); + } + }; + + ShaderStages.clear(); + ShaderStages.resize(6); + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_GEN, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_GEN; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_MISS, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_MISS; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_CLOSEST_HIT, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_CLOSEST_HIT; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_ANY_HIT, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_ANY_HIT; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_INTERSECTION, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_RAY_INTERSECTION; + ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_CALLABLE, PIPELINE_TYPE_RAY_TRACING)].Type = SHADER_TYPE_CALLABLE; + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + AddShaderStage(CreateInfo.pGeneralShaders[i].pShader); + } + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + AddShaderStage(CreateInfo.pTriangleHitShaders[i].pClosestHitShader); + AddShaderStage(CreateInfo.pTriangleHitShaders[i].pAnyHitShader); + } + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + AddShaderStage(CreateInfo.pProceduralHitShaders[i].pIntersectionShader); + AddShaderStage(CreateInfo.pProceduralHitShaders[i].pClosestHitShader); + AddShaderStage(CreateInfo.pProceduralHitShaders[i].pAnyHitShader); + } + + if (ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_GEN, PIPELINE_TYPE_RAY_TRACING)].Count() == 0) + LOG_ERROR_AND_THROW("At least one shader with type SHADER_TYPE_RAY_GEN must be provided"); + + if (ShaderStages[GetShaderTypePipelineIndex(SHADER_TYPE_RAY_MISS, PIPELINE_TYPE_RAY_TRACING)].Count() == 0) + LOG_ERROR_AND_THROW("At least one shader with type SHADER_TYPE_RAY_MISS must be provided"); + + // remove empty stages + for (auto iter = ShaderStages.begin(); iter != ShaderStages.end();) + { + if (iter->Count() == 0) + { + iter = ShaderStages.erase(iter); + continue; + } + + m_ShaderStageTypes[m_NumShaderStages++] = iter->Type; + ++iter; + } + + VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); + } + void InitializePipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool) @@ -447,6 +619,28 @@ protected: CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); } + void InitializePipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, + Uint32 ShaderHandleSize, + TNameToGroupIndexMap&& NameToGroupIndex, + LinearAllocator& MemPool) noexcept + { + CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + + size_t RTDataSize = sizeof(RayTracingPipelineData); + // reserve size for shader handles + const Uint32 ShaderDataSize = ShaderHandleSize * (CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); + RTDataSize += ShaderDataSize; + // 1 byte reserved to avoid compiler errors on zero sized arrays + RTDataSize -= sizeof(RayTracingPipelineData::Shaders); + + this->m_pRayTracingPipelineData = static_cast(MemPool.Allocate(RTDataSize, alignof(RayTracingPipelineData))); + new (this->m_pRayTracingPipelineData) RayTracingPipelineData{}; + this->m_pRayTracingPipelineData->ShaderHandleSize = ShaderHandleSize; + this->m_pRayTracingPipelineData->Desc = CreateInfo.RayTracingPipeline; + this->m_pRayTracingPipelineData->ShaderDataSize = ShaderDataSize; + this->m_pRayTracingPipelineData->NameToGroupIndex = std::move(NameToGroupIndex); + } + private: static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept { @@ -469,6 +663,9 @@ private: MemPool.AddSpaceForString(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName); } } + + static_assert(std::is_trivially_destructible::value, "add destructor for this object"); + static_assert(std::is_trivially_destructible::value, "add destructor for this object"); } static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) @@ -525,7 +722,20 @@ protected: RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object - GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr; + struct RayTracingPipelineData + { + RayTracingPipelineDesc Desc; + TNameToGroupIndexMap NameToGroupIndex; + Uint32 ShaderHandleSize; + Uint32 ShaderDataSize; + Uint8 Shaders[1]; + }; + + union + { + GraphicsPipelineDesc* m_pGraphicsPipelineDesc; + RayTracingPipelineData* m_pRayTracingPipelineData; + }; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 0ecbd92b..9b502659 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -39,65 +39,67 @@ DILIGENT_BEGIN_NAMESPACE(Diligent) /// Diligent API Info. This tructure can be used to verify API compatibility. struct APIInfo { - size_t StructSize DEFAULT_INITIALIZER(0); - int APIVersion DEFAULT_INITIALIZER(0); - size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0); - size_t BlendStateDescSize DEFAULT_INITIALIZER(0); - size_t BufferDescSize DEFAULT_INITIALIZER(0); - size_t BufferDataSize DEFAULT_INITIALIZER(0); - size_t BufferFormatSize DEFAULT_INITIALIZER(0); - size_t BufferViewDescSize DEFAULT_INITIALIZER(0); - size_t StencilOpDescSize DEFAULT_INITIALIZER(0); - size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0); - size_t SamplerCapsSize DEFAULT_INITIALIZER(0); - size_t TextureCapsSize DEFAULT_INITIALIZER(0); - size_t DeviceCapsSize DEFAULT_INITIALIZER(0); - size_t DrawAttribsSize DEFAULT_INITIALIZER(0); - size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0); - size_t ViewportSize DEFAULT_INITIALIZER(0); - size_t RectSize DEFAULT_INITIALIZER(0); - size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0); - size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0); - size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0); - size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0); - size_t SwapChainDescSize DEFAULT_INITIALIZER(0); - size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0); - size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0); - size_t BoxSize DEFAULT_INITIALIZER(0); - size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0); - size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0); - size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0); - size_t StateTransitionDescSize DEFAULT_INITIALIZER(0); - size_t LayoutElementSize DEFAULT_INITIALIZER(0); - size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); - size_t SampleDescSize DEFAULT_INITIALIZER(0); - size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); - size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0); - size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); - size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); - size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); - size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); - size_t PipelineStateDescSize DEFAULT_INITIALIZER(0); - size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0); - size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0); - size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0); - size_t SamplerDescSize DEFAULT_INITIALIZER(0); - size_t ShaderDescSize DEFAULT_INITIALIZER(0); - size_t ShaderMacroSize DEFAULT_INITIALIZER(0); - size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0); - size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0); - size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0); - size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0); - size_t TextureDescSize DEFAULT_INITIALIZER(0); - size_t TextureSubResDataSize DEFAULT_INITIALIZER(0); - size_t TextureDataSize DEFAULT_INITIALIZER(0); - size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0); - size_t TextureViewDescSize DEFAULT_INITIALIZER(0); + size_t StructSize DEFAULT_INITIALIZER(0); + int APIVersion DEFAULT_INITIALIZER(0); + size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0); + size_t BlendStateDescSize DEFAULT_INITIALIZER(0); + size_t BufferDescSize DEFAULT_INITIALIZER(0); + size_t BufferDataSize DEFAULT_INITIALIZER(0); + size_t BufferFormatSize DEFAULT_INITIALIZER(0); + size_t BufferViewDescSize DEFAULT_INITIALIZER(0); + size_t StencilOpDescSize DEFAULT_INITIALIZER(0); + size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0); + size_t SamplerCapsSize DEFAULT_INITIALIZER(0); + size_t TextureCapsSize DEFAULT_INITIALIZER(0); + size_t DeviceCapsSize DEFAULT_INITIALIZER(0); + size_t DrawAttribsSize DEFAULT_INITIALIZER(0); + size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0); + size_t ViewportSize DEFAULT_INITIALIZER(0); + size_t RectSize DEFAULT_INITIALIZER(0); + size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0); + size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0); + size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0); + size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0); + size_t SwapChainDescSize DEFAULT_INITIALIZER(0); + size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0); + size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0); + size_t BoxSize DEFAULT_INITIALIZER(0); + size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0); + size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0); + size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0); + size_t StateTransitionDescSize DEFAULT_INITIALIZER(0); + size_t LayoutElementSize DEFAULT_INITIALIZER(0); + size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); + size_t SampleDescSize DEFAULT_INITIALIZER(0); + size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); + size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0); + size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); + size_t PipelineStateDescSize DEFAULT_INITIALIZER(0); + size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); + size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t RayTracingPipelineDescSize DEFAULT_INITIALIZER(0); + size_t RayTracingPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0); + size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0); + size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0); + size_t SamplerDescSize DEFAULT_INITIALIZER(0); + size_t ShaderDescSize DEFAULT_INITIALIZER(0); + size_t ShaderMacroSize DEFAULT_INITIALIZER(0); + size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0); + size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0); + size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0); + size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0); + size_t TextureDescSize DEFAULT_INITIALIZER(0); + size_t TextureSubResDataSize DEFAULT_INITIALIZER(0); + size_t TextureDataSize DEFAULT_INITIALIZER(0); + size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0); + size_t TextureViewDescSize DEFAULT_INITIALIZER(0); }; typedef struct APIInfo APIInfo; diff --git a/Graphics/GraphicsEngine/interface/Constants.h b/Graphics/GraphicsEngine/interface/Constants.h index 9cd45c4d..b00f2de2 100644 --- a/Graphics/GraphicsEngine/interface/Constants.h +++ b/Graphics/GraphicsEngine/interface/Constants.h @@ -51,8 +51,8 @@ static const Uint32 MAX_RENDER_TARGETS = DILIGENT_MAX_RENDER_TARGETS; static const Uint32 MAX_VIEWPORTS = DILIGENT_MAX_VIEWPORTS; /// Maximum number of shader stages in a pipeline. -/// (Vertex, Hull, Domain, Geometry, Pixel) or (Amplification, Mesh, Pixel), or (Compute) -static const Uint32 MAX_SHADERS_IN_PIPELINE = 5; +/// (Vertex, Hull, Domain, Geometry, Pixel) or (Amplification, Mesh, Pixel), or (Compute) or (RayGen, Miss, ClosestHit, AnyHit, Intersection, Callable) +static const Uint32 MAX_SHADERS_IN_PIPELINE = 6; // clang-format on diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 85dbcff6..10a84f1d 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -2117,6 +2117,7 @@ struct VulkanDescriptorPoolSize Uint32 NumUniformTexelBufferDescriptors DEFAULT_INITIALIZER(0); Uint32 NumStorageTexelBufferDescriptors DEFAULT_INITIALIZER(0); Uint32 NumInputAttachmentDescriptors DEFAULT_INITIALIZER(0); + Uint32 NumAccelStructDescriptors DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE VulkanDescriptorPoolSize()noexcept {} @@ -2130,7 +2131,8 @@ struct VulkanDescriptorPoolSize Uint32 _NumStorageBufferDescriptors, Uint32 _NumUniformTexelBufferDescriptors, Uint32 _NumStorageTexelBufferDescriptors, - Uint32 _NumInputAttachmentDescriptors)noexcept : + Uint32 _NumInputAttachmentDescriptors, + Uint32 _NumAccelStructDescriptors)noexcept : MaxDescriptorSets {_MaxDescriptorSets }, NumSeparateSamplerDescriptors {_NumSeparateSamplerDescriptors }, NumCombinedSamplerDescriptors {_NumCombinedSamplerDescriptors }, @@ -2140,7 +2142,8 @@ struct VulkanDescriptorPoolSize NumStorageBufferDescriptors {_NumStorageBufferDescriptors }, NumUniformTexelBufferDescriptors{_NumUniformTexelBufferDescriptors}, NumStorageTexelBufferDescriptors{_NumStorageTexelBufferDescriptors}, - NumInputAttachmentDescriptors {_NumInputAttachmentDescriptors } + NumInputAttachmentDescriptors {_NumInputAttachmentDescriptors }, + NumAccelStructDescriptors {_NumAccelStructDescriptors } { // On clang aggregate initialization fails to compile if // structure members have default initializers @@ -2178,8 +2181,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo) /// the engine creates another one. VulkanDescriptorPoolSize MainDescriptorPoolSize #if DILIGENT_CPP_INTERFACE - //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt - {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024, 256} + //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt AccelSt + {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024, 256, 256} #endif ; @@ -2190,8 +2193,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo) VulkanDescriptorPoolSize DynamicDescriptorPoolSize #if DILIGENT_CPP_INTERFACE - //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt - {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256, 64} + //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt AccelSt + {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256, 64, 64} #endif ; diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index f953b851..e45dc703 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -215,24 +215,14 @@ struct GraphicsPipelineDesc typedef struct GraphicsPipelineDesc GraphicsPipelineDesc; -/// Compute pipeline state description - -/// This structure describes the compute pipeline state and is part of the PipelineStateDesc structure. -struct ComputePipelineDesc -{ - /// Compute shader to be used with the pipeline - IShader* pCS DEFAULT_INITIALIZER(nullptr); -}; -typedef struct ComputePipelineDesc ComputePipelineDesc; - /// AZ TODO struct RayTracingGeneralShaderGroup { /// AZ TODO - const char* Name DEFAULT_INITIALIZER(nullptr); + const char* Name DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* Shader DEFAULT_INITIALIZER(nullptr); + IShader* pShader DEFAULT_INITIALIZER(nullptr); }; typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; @@ -240,13 +230,13 @@ typedef struct RayTracingGeneralShaderGroup RayTracingGeneralShaderGroup; struct RayTracingTriangleHitShaderGroup { /// AZ TODO - const char* Name DEFAULT_INITIALIZER(nullptr); + const char* Name DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* ClosestHitShader DEFAULT_INITIALIZER(nullptr); + IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* AnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null }; typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup; @@ -254,16 +244,16 @@ typedef struct RayTracingTriangleHitShaderGroup RayTracingTriangleHitShaderGroup struct RayTracingProceduralHitShaderGroup { /// AZ TODO - const char* Name DEFAULT_INITIALIZER(nullptr); + const char* Name DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* IntersectionShader DEFAULT_INITIALIZER(nullptr); + IShader* pIntersectionShader DEFAULT_INITIALIZER(nullptr); /// AZ TODO - IShader* ClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null + IShader* pClosestHitShader DEFAULT_INITIALIZER(nullptr); // can be null /// AZ TODO - IShader* AnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null + IShader* pAnyHitShader DEFAULT_INITIALIZER(nullptr); // can be null }; typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderGroup; @@ -271,25 +261,7 @@ typedef struct RayTracingProceduralHitShaderGroup RayTracingProceduralHitShaderG struct RayTracingPipelineDesc { /// AZ TODO - const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); - - /// AZ TODO - Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); - - /// AZ TODO - Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); - - /// AZ TODO - Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); - - /// AZ TODO - Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) + Uint8 MaxRecursionDepth DEFAULT_INITIALIZER(0); // must be 0..31 (check current device limits) }; typedef struct RayTracingPipelineDesc RayTracingPipelineDesc; @@ -308,6 +280,8 @@ DILIGENT_TYPED_ENUM(PIPELINE_TYPE, Uint8) /// Ray tracing pipeline, which is used by IDeviceContext::TraceRays(). PIPELINE_TYPE_RAY_TRACING, + + PIPELINE_TYPE_LAST = PIPELINE_TYPE_RAY_TRACING }; @@ -332,6 +306,7 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs) #if DILIGENT_CPP_INTERFACE bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; } bool IsComputePipeline() const { return PipelineType == PIPELINE_TYPE_COMPUTE; } + bool IsRayTracingPipeline() const { return PipelineType == PIPELINE_TYPE_RAY_TRACING; } #endif }; typedef struct PipelineStateDesc PipelineStateDesc; @@ -420,6 +395,33 @@ struct ComputePipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; +/// Ray tracing pipeline state description. +struct RayTracingPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) + + /// AZ TODO + RayTracingPipelineDesc RayTracingPipeline; + + /// AZ TODO + const RayTracingGeneralShaderGroup* pGeneralShaders DEFAULT_INITIALIZER(nullptr); + + /// AZ TODO + const RayTracingTriangleHitShaderGroup* pTriangleHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + + /// AZ TODO + const RayTracingProceduralHitShaderGroup* pProceduralHitShaders DEFAULT_INITIALIZER(nullptr); // can be null + + /// AZ TODO + Uint16 GeneralShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint16 TriangleHitShaderCount DEFAULT_INITIALIZER(0); + + /// AZ TODO + Uint16 ProceduralHitShaderCount DEFAULT_INITIALIZER(0); +}; +typedef struct RayTracingPipelineStateCreateInfo RayTracingPipelineStateCreateInfo; + + // {06084AE5-6A71-4FE8-84B9-395DD489A28C} static const struct INTERFACE_ID IID_PipelineState = {0x6084ae5, 0x6a71, 0x4fe8, {0x84, 0xb9, 0x39, 0x5d, 0xd4, 0x89, 0xa2, 0x8c}}; @@ -444,6 +446,10 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) /// Returns the graphics pipeline description used to create the object. /// This method must only be called for a graphics or mesh pipeline. VIRTUAL const GraphicsPipelineDesc REF METHOD(GetGraphicsPipelineDesc)(THIS) CONST PURE; + + /// Returns the ray tracing pipeline description used to create the object. + /// This method must only be called for a ray tracing pipeline. + VIRTUAL const RayTracingPipelineDesc REF METHOD(GetRayTracingPipelineDesc)(THIS) CONST PURE; /// Binds resources for all shaders in the pipeline state @@ -522,6 +528,13 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) /// into account vertex shader input layout, number of outputs, etc. VIRTUAL bool METHOD(IsCompatibleWith)(THIS_ const struct IPipelineState* pPSO) CONST PURE; + + /// AZ TODO + VIRTUAL Uint32 METHOD(GetShaderGroupIndex)(THIS_ + const char* Name) CONST PURE; + + /// AZ TODO + VIRTUAL Uint32 METHOD(GetShaderGroupCount)(THIS) CONST PURE; }; DILIGENT_END_INTERFACE @@ -534,12 +547,15 @@ DILIGENT_END_INTERFACE # define IPipelineState_GetDesc(This) (const struct PipelineStateDesc*)IDeviceObject_GetDesc(This) # define IPipelineState_GetGraphicsPipelineDesc(This) CALL_IFACE_METHOD(PipelineState, GetGraphicsPipelineDesc, This) +# define IPipelineState_GetRayTracingPipelineDesc(This) CALL_IFACE_METHOD(PipelineState, GetRayTracingPipelineDesc, This) # define IPipelineState_BindStaticResources(This, ...) CALL_IFACE_METHOD(PipelineState, BindStaticResources, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableCount(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableCount, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableByName(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByName, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableByIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByIndex, This, __VA_ARGS__) # define IPipelineState_CreateShaderResourceBinding(This, ...) CALL_IFACE_METHOD(PipelineState, CreateShaderResourceBinding, This, __VA_ARGS__) # define IPipelineState_IsCompatibleWith(This, ...) CALL_IFACE_METHOD(PipelineState, IsCompatibleWith, This, __VA_ARGS__) +# define IPipelineState_GetShaderGroupIndex(This, ...) CALL_IFACE_METHOD(PipelineState, GetShaderGroupIndex, This, __VA_ARGS__) +# define IPipelineState_GetShaderGroupCount(This) CALL_IFACE_METHOD(PipelineState, GetShaderGroupCount, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 19d98a94..49ab30e7 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -177,6 +177,17 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) VIRTUAL void METHOD(CreateComputePipelineState)(THIS_ const ComputePipelineStateCreateInfo REF PSOCreateInfo, IPipelineState** ppPipelineState) PURE; + + /// Creates a new ray tracing pipeline state object + + /// \param [in] PSOCreateInfo - Ray tracing pipeline state create info, see Diligent::RayTracingPipelineStateCreateInfo for details. + /// \param [out] ppPipelineState - Address of the memory location where the pointer to the + /// pipeline state interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + VIRTUAL void METHOD(CreateRayTracingPipelineState)(THIS_ + const RayTracingPipelineStateCreateInfo REF PSOCreateInfo, + IPipelineState** ppPipelineState) PURE; /// Creates a new fence object @@ -322,21 +333,22 @@ DILIGENT_END_INTERFACE // clang-format off -# define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__) -# define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__) -# define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__) -# define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__) -# define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__) -# define IRenderDevice_CreateGraphicsPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateGraphicsPipelineState, This, __VA_ARGS__) -# define IRenderDevice_CreateComputePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateComputePipelineState, This, __VA_ARGS__) -# define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__) -# define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__) -# define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This) -# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__) -# define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt, This, __VA_ARGS__) -# define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__) -# define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This) -# define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This) +# define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__) +# define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__) +# define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__) +# define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__) +# define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__) +# define IRenderDevice_CreateGraphicsPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateGraphicsPipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateComputePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateComputePipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateRayTracingPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateRayTracingPipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__) +# define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__) +# define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This) +# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__) +# define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt, This, __VA_ARGS__) +# define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__) +# define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This) +# define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This) // clang-format on diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index 950ecc77..28e0bb17 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -109,6 +109,8 @@ DILIGENT_TYPED_ENUM(SHADER_COMPILER, Uint32) /// Legacy HLSL compiler (FXC) for Direct3D11 and Direct3D12 supporting shader models up to 5.1. SHADER_COMPILER_FXC, + + SHADER_COMPILER_LAST = SHADER_COMPILER_FXC }; @@ -354,7 +356,10 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8) /// Input attachment in a render pass SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT, - SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT + /// AZ TODO + SHADER_RESOURCE_TYPE_ACCEL_STRUCT, + + SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_ACCEL_STRUCT }; // clang-format on diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp index e4111327..4facdec4 100644 --- a/Graphics/GraphicsEngine/src/APIInfo.cpp +++ b/Graphics/GraphicsEngine/src/APIInfo.cpp @@ -89,10 +89,12 @@ static APIInfo InitAPIInfo() INIT_STRUCTURE_SIZE(ShaderResourceVariableDesc); INIT_STRUCTURE_SIZE(ImmutableSamplerDesc); INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc); + INIT_STRUCTURE_SIZE(PipelineStateDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineStateCreateInfo); INIT_STRUCTURE_SIZE(ComputePipelineStateCreateInfo); - INIT_STRUCTURE_SIZE(PipelineStateDesc); + INIT_STRUCTURE_SIZE(RayTracingPipelineDesc); + INIT_STRUCTURE_SIZE(RayTracingPipelineStateCreateInfo); INIT_STRUCTURE_SIZE(RasterizerStateDesc); INIT_STRUCTURE_SIZE(ResourceMappingEntry); INIT_STRUCTURE_SIZE(ResourceMappingDesc); diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp index fedc332d..9bd422db 100644 --- a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -248,6 +248,64 @@ void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& Cre VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); } + +void ValidateRayTracingPipelineCreateInfo(const RayTracingPipelineStateCreateInfo& CreateInfo) noexcept(false) +{ +#ifdef DILIGENT_DEVELOPMENT + const auto& PSODesc = CreateInfo.PSODesc; + if (PSODesc.PipelineType != PIPELINE_TYPE_RAY_TRACING) + LOG_PSO_ERROR_AND_THROW("Pipeline type must be RAY_TRACING"); + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + const auto& Group = CreateInfo.pGeneralShaders[i]; + if (Group.pShader == nullptr) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].pShader must not be null"); + if (Group.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must not be null"); + + switch (Group.pShader->GetDesc().ShaderType) + { + case SHADER_TYPE_RAY_GEN: + case SHADER_TYPE_RAY_MISS: + case SHADER_TYPE_RAY_CLOSEST_HIT: break; + default: + LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Group.pShader->GetDesc().ShaderType), " is not a valid type for ray tracing general shader"); + } + } + + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + const auto& Group = CreateInfo.pTriangleHitShaders[i]; + if (Group.pClosestHitShader == nullptr) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].pClosestHitShader must not be null"); + if (Group.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must not be null"); + + VALIDATE_SHADER_TYPE(Group.pClosestHitShader, SHADER_TYPE_RAY_CLOSEST_HIT, "ray tracing triangle closes hit"); + + if (Group.pAnyHitShader != nullptr) + VALIDATE_SHADER_TYPE(Group.pAnyHitShader, SHADER_TYPE_RAY_ANY_HIT, "ray tracing triangle any hit"); + } + + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + const auto& Group = CreateInfo.pProceduralHitShaders[i]; + if (Group.pIntersectionShader == nullptr) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].pIntersectionShader must not be null"); + if (Group.Name == nullptr) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must not be null"); + + VALIDATE_SHADER_TYPE(Group.pIntersectionShader, SHADER_TYPE_RAY_INTERSECTION, "ray tracing procedural intersection"); + + if (Group.pClosestHitShader != nullptr) + VALIDATE_SHADER_TYPE(Group.pClosestHitShader, SHADER_TYPE_RAY_CLOSEST_HIT, "ray tracing procedural closest hit"); + if (Group.pAnyHitShader != nullptr) + VALIDATE_SHADER_TYPE(Group.pAnyHitShader, SHADER_TYPE_RAY_ANY_HIT, "ray tracing procedural any hit"); + } +#endif // DILIGENT_DEVELOPMENT +} + #undef VALIDATE_SHADER_TYPE #undef LOG_PSO_ERROR_AND_THROW diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 520e9bb0..77b68360 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -166,7 +166,7 @@ private: // Resource layout index in m_pStaticResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; std::array m_ImmutableSamplerOffsets = {}; struct ImmutableSamplerInfo diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp index 8565935d..3e5ef8f1 100644 --- a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp @@ -77,6 +77,10 @@ public: virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateRayTracingPipelineState() in Direct3D11 backend. + virtual void DILIGENT_CALL_TYPE CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateFence() in Direct3D11 backend. virtual void DILIGENT_CALL_TYPE CreateFence(const FenceDesc& Desc, IFence** ppFence) override final; diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp index 21437e0f..1e7fd160 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp @@ -110,7 +110,7 @@ private: // Resource layout index in m_pResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; Uint8 m_NumActiveShaders = 0; diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 108f149c..1c03690e 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -203,6 +203,8 @@ PipelineStateD3D11Impl::~PipelineStateD3D11Impl() void PipelineStateD3D11Impl::Destruct() { + TPipelineStateBase::Destruct(); + if (m_pStaticResourceLayouts != nullptr) { for (Uint32 l = 0; l < GetNumShaderStages(); ++l) diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index 06cda6ad..4453b598 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -101,13 +101,18 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo sizeof(FenceD3D11Impl), sizeof(QueryD3D11Impl), sizeof(RenderPassD3D11Impl), - sizeof(FramebufferD3D11Impl) + sizeof(FramebufferD3D11Impl), + 0, + 0, + 0 } }, m_EngineAttribs{EngineAttribs}, m_pd3d11Device {pd3d11Device } // clang-format on { + static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor"); + m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_D3D11; auto FeatureLevel = m_pd3d11Device->GetFeatureLevel(); switch (FeatureLevel) @@ -409,6 +414,12 @@ void RenderDeviceD3D11Impl::CreateComputePipelineState(const ComputePipelineStat CreatePipelineState(PSOCreateInfo, ppPipelineState); } +void RenderDeviceD3D11Impl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + UNSUPPORTED("CreateRayTracingPipelineState is not supported in DirectX 11"); + *ppPipelineState = nullptr; +} + void RenderDeviceD3D11Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence) { CreateDeviceObject("Fence", Desc, ppFence, diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index f7c1958d..0c4c38c7 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -292,6 +292,11 @@ void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr(bufUav++)) BuffUAVBindInfo(BuffUAV, *this, VarType); NumUAVSlots = std::max(NumUAVSlots, Uint32{BuffUAV.BindPoint} + Uint32{BuffUAV.BindCount}); } + }, + + [&](const D3DShaderResourceAttribs&, Uint32) // + { + UNEXPECTED("acceleration structure is not supported in DirectX 11"); }); // clang-format off diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp index 21a65108..b6430c04 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp @@ -94,6 +94,11 @@ ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Im Resources.m_MaxSRVBindPoint = std::max(Resources.m_MaxSRVBindPoint, static_cast(TexAttribs.BindPoint + TexAttribs.BindCount - 1)); } + void OnNewAccelStruct(const D3DShaderResourceAttribs& ASAttribs) + { + UNEXPECTED("Acceleration structure is not supported in DirectX 11"); + } + ~NewResourceHandler() { } @@ -439,6 +444,11 @@ void ShaderResourcesD3D11::dvpVerifyCommittedResources(ID3D11Buffer* return; } } + }, + + [&](const D3DShaderResourceAttribs&, Uint32) // + { + UNEXPECTED("acceleration structure is not supported in DirectX 11"); } // clang-format off ); // clang-format on } diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp index d6477b79..94f74933 100644 --- a/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp +++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.hpp @@ -183,7 +183,8 @@ public: { if (pPSO != m_pCurPipelineState) { - m_pCommandList->SetPipelineState(m_pCurPipelineState = pPSO); + m_pCommandList->SetPipelineState(pPSO); + m_pCurPipelineState = pPSO; } } @@ -218,7 +219,7 @@ protected: CComPtr m_pCommandList; CComPtr m_pCurrentAllocator; - ID3D12PipelineState* m_pCurPipelineState = nullptr; + void* m_pCurPipelineState = nullptr; ID3D12RootSignature* m_pCurGraphicsRootSignature = nullptr; ID3D12RootSignature* m_pCurComputeRootSignature = nullptr; diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index fa761fc7..4bdeb08c 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -53,6 +53,7 @@ public: PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const GraphicsPipelineStateCreateInfo& CreateInfo); PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const ComputePipelineStateCreateInfo& CreateInfo); + PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const RayTracingPipelineStateCreateInfo& CreateInfo); ~PipelineStateD3D12Impl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; @@ -76,7 +77,10 @@ public: virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final; /// Implementation of IPipelineStateD3D12::GetD3D12PipelineState(). - virtual ID3D12PipelineState* DILIGENT_CALL_TYPE GetD3D12PipelineState() const override final { return m_pd3d12PSO; } + virtual ID3D12PipelineState* DILIGENT_CALL_TYPE GetD3D12PipelineState() const override final { return static_cast(m_pd3d12PSO.p); } + + /// Implementation of IPipelineStateD3D12::GetD3D12StateObject(). + virtual ID3D12StateObject* DILIGENT_CALL_TYPE GetD3D12StateObject() const override final { return static_cast(m_pd3d12PSO.p); } /// Implementation of IPipelineStateD3D12::GetD3D12RootSignature(). virtual ID3D12RootSignature* DILIGENT_CALL_TYPE GetD3D12RootSignature() const override final { return m_RootSig.GetD3D12RootSignature(); } @@ -121,27 +125,27 @@ public: } private: - struct D3D12PipelineShaderStageInfo + struct ShaderStageInfo { - const SHADER_TYPE Type; - ShaderD3D12Impl* const pShader; - D3D12PipelineShaderStageInfo(SHADER_TYPE _Type, - ShaderD3D12Impl* _pShader) : - Type{_Type}, - pShader{_pShader} - {} + ShaderStageInfo() {} + ShaderStageInfo(SHADER_TYPE _Type, ShaderD3D12Impl* _pShader); + + void Append(ShaderD3D12Impl* pShader); + size_t Count() const; + + SHADER_TYPE Type; + std::vector Shaders; }; + using TShaderStages = std::vector; template - void InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& ShaderStages); - - void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, - std::vector& ShaderStages); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo, TShaderStages& ShaderStages); + void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); void Destruct(); - CComPtr m_pd3d12PSO; - RootSignature m_RootSig; + CComPtr m_pd3d12PSO; + RootSignature m_RootSig; // Must be defined before default SRB SRBMemoryAllocator m_SRBMemAllocator; @@ -152,7 +156,7 @@ private: // Resource layout index in m_pShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp index 7bdc7801..2bc13c31 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -68,6 +68,9 @@ public: /// Implementation of IRenderDevice::CreateComputePipelineState() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateRayTracingPipelineState() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateBuffer() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, @@ -169,9 +172,8 @@ public: IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); } -#ifdef D3D12_H_HAS_MESH_SHADER ID3D12Device2* GetD3D12Device2(); -#endif + ID3D12Device5* GetD3D12Device5(); ShaderVersion GetMaxShaderModel() const; D3D_FEATURE_LEVEL GetD3DFeatureLevel() const; @@ -185,9 +187,8 @@ private: CComPtr m_pd3d12Device; -#ifdef D3D12_H_HAS_MESH_SHADER CComPtr m_pd3d12Device2; -#endif + CComPtr m_pd3d12Device5; EngineD3D12CreateInfo m_EngineAttribs; diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp index 232bce65..6deac5f0 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp @@ -36,7 +36,6 @@ namespace Diligent { -SHADER_TYPE ShaderTypeFromShaderVisibility(D3D12_SHADER_VISIBILITY ShaderVisibility); D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType); D3D12_DESCRIPTOR_HEAP_TYPE dbgHeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE RangeType); @@ -514,6 +513,10 @@ private: class CommandContext& Ctx, bool IsCompute, bool ValidateStates) const; + +#ifdef DILIGENT_DEBUG + SHADER_TYPE m_DbgShaderStages = SHADER_TYPE_UNKNOWN; +#endif }; void RootSignature::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, @@ -534,11 +537,7 @@ void RootSignature::CommitRootViews(ShaderResourceCacheD3D12& ResourceCache, SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN; #ifdef DILIGENT_DEBUG - { - auto& Param = static_cast(RootView); - VERIFY_EXPR(Param.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); - dbgShaderType = ShaderTypeFromShaderVisibility(Param.ShaderVisibility); - } + dbgShaderType = m_DbgShaderStages; #endif auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType); diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp index b2143b76..0b9b6fee 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderD3D12Impl.hpp @@ -34,9 +34,8 @@ #include "ShaderD3D12.h" #include "ShaderBase.hpp" #include "ShaderD3DBase.hpp" -#include "ShaderResourceLayoutD3D12.hpp" #include "RenderDeviceD3D12Impl.hpp" -#include "ShaderVariableD3D12.hpp" +#include "ShaderResourcesD3D12.hpp" namespace Diligent { @@ -74,7 +73,8 @@ public: ResourceDesc = m_pShaderResources->GetHLSLShaderResourceDesc(Index); } - ID3DBlob* GetShaderByteCode() { return m_pShaderByteCode; } + ID3DBlob* GetShaderByteCode() { return m_pShaderByteCode; } + const Char* GetEntryPoint() const { return m_EntryPoint.c_str(); } const std::shared_ptr& GetShaderResources() const { return m_pShaderResources; } @@ -82,6 +82,8 @@ private: // ShaderResources class instance must be referenced through the shared pointer, because // it is referenced by ShaderResourceLayoutD3D12 class instances std::shared_ptr m_pShaderResources; + + String m_EntryPoint; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp index 7be3372d..ac16cf9f 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp @@ -85,7 +85,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; bool m_bStaticResourcesInitialized = false; const Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp index 8a8f7b25..cf69793a 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp @@ -97,6 +97,7 @@ enum class CachedResourceType : Int32 TexUAV, BufUAV, Sampler, + AccelStruct, NumTypes }; @@ -166,7 +167,7 @@ public: const SHADER_TYPE dbgRefShaderType) const { VERIFY(m_dbgHeapType == dbgDescriptorHeapType, "Incosistent descriptor heap type"); - VERIFY(m_dbgShaderType == dbgRefShaderType, "Incosistent shader type"); + VERIFY((m_dbgShaderType & dbgRefShaderType) == dbgRefShaderType, "Incosistent shader type"); VERIFY(OffsetFromTableStart < m_NumResources, "Root table is not large enough to store descriptor at offset ", OffsetFromTableStart); return m_pResources[OffsetFromTableStart]; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp index 719345fc..bd581101 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp @@ -103,6 +103,7 @@ #include "ShaderBase.hpp" #include "ShaderResourcesD3D12.hpp" #include "ShaderResourceCacheD3D12.hpp" +#include "ShaderD3D12Impl.hpp" namespace Diligent { @@ -121,15 +122,15 @@ public: // - initialize reference layouts that address all types of resources (static, mutable, dynamic). // Root indices and descriptor table offsets are assigned during the initialization; // no shader resource cache is provided - void Initialize(ID3D12Device* pd3d12Device, - PIPELINE_TYPE PipelineType, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - class RootSignature* pRootSig); + void Initialize(ID3D12Device* pd3d12Device, + PIPELINE_TYPE PipelineType, + const PipelineResourceLayoutDesc& ResourceLayout, + const std::vector& Shaders, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + class RootSignature* pRootSig); // clang-format off ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete; @@ -165,31 +166,43 @@ public: static_assert( static_cast(CachedResourceType::NumTypes) < (1 << ResourceTypeBits), "3 bits is not enough to store CachedResourceType"); /* 0 */ const ShaderResourceLayoutD3D12& ParentResLayout; -/* 8 */ const D3DShaderResourceAttribs& Attribs; /*16 */ const Uint32 OffsetFromTableStart; /*20.0*/ const Uint16 ResourceType : ResourceTypeBits; // | 0 1 2 | /*20.3*/ const Uint16 VariableType : VariableTypeBits; // | 3 4 | /*20.5*/ const Uint16 RootIndex : RootIndexBits; // | 5 6 7 ... 15 | /*22 */ const Uint16 SamplerId; -/*24 */ // End of data +/* */ const char* const Name; +/* */ const Uint16 BindCount; +/* */ const Uint16 BindPoint; +/* */ const Uint8 InputType; +/* */ const Uint8 SRVDimension; +/* */ // End of data // clang-format on D3D12Resource(const ShaderResourceLayoutD3D12& _ParentLayout, - const D3DShaderResourceAttribs& _Attribs, SHADER_RESOURCE_VARIABLE_TYPE _VariableType, CachedResourceType _ResType, Uint32 _RootIndex, Uint32 _OffsetFromTableStart, - Uint32 _SamplerId) noexcept : + Uint32 _SamplerId, + const char* _Name, + Uint32 _BindCount, + Uint32 _BindPoint, + D3D_SHADER_INPUT_TYPE _InputType, + D3D_SRV_DIMENSION _SRVDimension) noexcept : // clang-format off ParentResLayout {_ParentLayout }, - Attribs {_Attribs }, ResourceType {static_cast(_ResType) }, VariableType {static_cast(_VariableType)}, RootIndex {static_cast(_RootIndex) }, SamplerId {static_cast(_SamplerId) }, - OffsetFromTableStart{ _OffsetFromTableStart } + OffsetFromTableStart{ _OffsetFromTableStart }, + Name {_Name}, + BindCount {static_cast(_BindCount) }, + BindPoint {static_cast(_BindPoint) }, + InputType {static_cast(_InputType) }, + SRVDimension {static_cast(_SRVDimension) } // clang-format on { VERIFY(IsValidOffset(), "Offset must be valid"); @@ -198,6 +211,10 @@ public: VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type is out of representable range"); VERIFY(_SamplerId == InvalidSamplerId || _SamplerId <= MaxSamplerId, "Sampler id (", _SamplerId, ") exceeds max allowed value (", MaxSamplerId, ")"); VERIFY(_SamplerId == InvalidSamplerId || GetResType() == CachedResourceType::TexSRV, "A sampler can only be assigned to a Texture SRV"); + VERIFY(_BindCount <= std::numeric_limits::max(), "BindCount (", _BindCount, ") exceeds max representable value ", std::numeric_limits::max()); + VERIFY(_BindPoint <= std::numeric_limits::max(), "BindPoint (", _BindPoint, ") exceeds max representable value ", std::numeric_limits::max()); + VERIFY(_InputType <= std::numeric_limits::max(), "InputType (", _InputType, ") exceeds max representable value ", std::numeric_limits::max()); + VERIFY(_SRVDimension <= std::numeric_limits::max(), "SRVDimension (", _SRVDimension, ") exceeds max representable value ", std::numeric_limits::max()); } bool IsBound(Uint32 ArrayIndex, @@ -215,6 +232,35 @@ public: CachedResourceType GetResType() const { return static_cast(ResourceType); } SHADER_RESOURCE_VARIABLE_TYPE GetVariableType() const { return static_cast(VariableType); } + HLSLShaderResourceDesc GetHLSLResourceDesc() const; + + bool IsValidBindPoint() const + { + return BindPoint != D3DShaderResourceAttribs::InvalidBindPoint; + } + + String GetPrintName(Uint32 ArrayInd) const + { + VERIFY_EXPR(ArrayInd < BindCount); + if (BindCount > 1) + return String(Name) + '[' + std::to_string(ArrayInd) + ']'; + else + return Name; + } + + D3D_SHADER_INPUT_TYPE GetInputType() const + { + return static_cast(InputType); + } + + D3D_SRV_DIMENSION GetSRVDimension() const + { + return static_cast(SRVDimension); + } + + RESOURCE_DIMENSION GetResourceDimension() const; + + bool IsMultisample() const; private: void CacheCB(IDeviceObject* pBuffer, @@ -237,6 +283,11 @@ public: ShaderResourceCacheD3D12::Resource& DstSam, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const; + + void CacheAccelStruct(IDeviceObject* pTLAS, + ShaderResourceCacheD3D12::Resource& DstRes, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const; }; void CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache, @@ -272,11 +323,9 @@ public: return GetResource(GetSamplerOffset(VarType, s)); } - const bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedTextureSamplers(); } - - SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } + const bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; } - const ShaderResourcesD3D12& GetResources() const { return *m_pResources; } + SHADER_TYPE GetShaderType() const { return m_ShaderType; } private: const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv) const; @@ -284,7 +333,7 @@ private: const Char* GetShaderName() const { - return m_pResources->GetShaderName(); + return ""; // AZ TODO } @@ -353,11 +402,11 @@ private: /* 16 */ std::array m_CbvSrvUavOffsets = {}; /* 24 */ std::array m_SamplersOffsets = {}; -/* 32 */ IObject& m_Owner; -/* 48 */ CComPtr m_pd3d12Device; - // We must use shared_ptr to reference ShaderResources instance, because - // there may be multiple objects referencing the same set of resources -/* 48 */ std::shared_ptr m_pResources; +/* 24 */ StringPool m_StringPool; +/* 32 */ IObject& m_Owner; +/* 48 */ CComPtr m_pd3d12Device; +/* */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; +/* */ bool m_IsUsingSeparateSamplers = false; /* 64 */ // End of data // clang-format on diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp index c30d8296..1e60ecd8 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp @@ -186,7 +186,7 @@ public: virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements) override final { - VerifyAndCorrectSetArrayArguments(m_Resource.Attribs.Name, m_Resource.Attribs.BindCount, FirstElement, NumElements); + VerifyAndCorrectSetArrayArguments(m_Resource.Name, m_Resource.BindCount, FirstElement, NumElements); for (Uint32 Elem = 0; Elem < NumElements; ++Elem) m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache); } @@ -198,7 +198,7 @@ public: virtual HLSLShaderResourceDesc DILIGENT_CALL_TYPE GetHLSLResourceDesc() const override final { - return m_Resource.Attribs.GetHLSLResourceDesc(); + return m_Resource.GetHLSLResourceDesc(); } virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final diff --git a/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h b/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h index fd219b95..cd315d3e 100644 --- a/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h +++ b/Graphics/GraphicsEngineD3D12/interface/PipelineStateD3D12.h @@ -54,6 +54,12 @@ DILIGENT_BEGIN_INTERFACE(IPipelineStateD3D12, IPipelineState) /// so Release() must not be called. VIRTUAL ID3D12PipelineState* METHOD(GetD3D12PipelineState)(THIS) CONST PURE; + /// Returns ID3D12StateObject interface of the internal D3D12 state object for ray tracing. + + /// The method does *NOT* call AddRef() on the returned interface, + /// so Release() must not be called. + VIRTUAL ID3D12StateObject* METHOD(GetD3D12StateObject)(THIS) CONST PURE; + /// Returns a pointer to the root signature object associated with this pipeline state. /// The method does *NOT* call AddRef() on the returned interface, diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index b89b226c..6ca74c27 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -219,8 +219,7 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) TDeviceContextBase::SetPipelineState(pPipelineStateD3D12, 0 /*Dummy*/); - auto& CmdCtx = GetCmdContext(); - auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState(); + auto& CmdCtx = GetCmdContext(); switch (PSODesc.PipelineType) { @@ -229,6 +228,7 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) { auto& GraphicsPipeline = pPipelineStateD3D12->GetGraphicsPipelineDesc(); auto& GraphicsCtx = CmdCtx.AsGraphicsContext(); + auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState(); GraphicsCtx.SetPipelineState(pd3d12PSO); if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) @@ -254,13 +254,16 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) } break; } - case PIPELINE_TYPE_COMPUTE: { + auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState(); CmdCtx.AsComputeContext().SetPipelineState(pd3d12PSO); break; } - + case PIPELINE_TYPE_RAY_TRACING: + { + break; + } default: UNEXPECTED("unknown pipeline type"); } diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 2d31e70d..6efa4acc 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -37,6 +37,7 @@ #include "EngineMemory.h" #include "StringTools.hpp" #include "ShaderVariableD3D12.hpp" +#include "DynamicLinearAllocator.hpp" namespace Diligent { @@ -70,7 +71,6 @@ struct alignas(void*) PSS_SubObject # pragma warning(pop) #endif -} // namespace class PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE { @@ -98,9 +98,211 @@ private: std::array m_Map; }; + +template +void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateInfo, + TNameToGroupIndexMap& NameToGroupIndex, + std::vector& Subobjects, + DynamicLinearAllocator& TempPool, + LinearAllocator& MemPool) +{ +#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ray tracing PSO '", CreateInfo.PSODesc.Name, "' is invalid: ", ##__VA_ARGS__) + + Uint32 ShaderIndex = 0; + Uint32 GroupIndex = 0; + std::unordered_map UniqueShaders; + + const auto ShaderIndexToStr = [&TempPool](Uint32 Index) -> LPCWSTR { + const Uint32 Len = sizeof(Index) * 2; + auto* Dst = TempPool.Allocate(Len + 1); + for (Uint32 i = 0; i < Len; ++i) + { + Uint32 c = Index & 0xF; + Dst[i] = static_cast(c < 10 ? '0' + c : 'A' + c - 10); + Index >>= 4; + } + Dst[Len] = 0; + return Dst; + }; + + const auto AddDxilLib = [&](IShader* pShader, const char* Name) -> LPCWSTR { + if (pShader != nullptr) + { + auto Result = UniqueShaders.emplace(pShader, nullptr); + if (Result.second) + { + auto& LibDesc = *TempPool.Allocate(); + auto& ExportDesc = *TempPool.Allocate(); + auto* pShaderD3D12 = ValidatedCast(pShader); + + LibDesc.DXILLibrary.BytecodeLength = pShaderD3D12->GetShaderByteCode()->GetBufferSize(); + LibDesc.DXILLibrary.pShaderBytecode = pShaderD3D12->GetShaderByteCode()->GetBufferPointer(); + LibDesc.NumExports = 1; + LibDesc.pExports = &ExportDesc; + + ExportDesc.Flags = D3D12_EXPORT_FLAG_NONE; + ExportDesc.ExportToRename = TempPool.CopyWString(pShaderD3D12->GetEntryPoint()); + + if (Name != nullptr) + ExportDesc.Name = TempPool.CopyWString(Name); + else + ExportDesc.Name = ShaderIndexToStr(++ShaderIndex); + + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_DXIL_LIBRARY, &LibDesc}); + + Result.first->second = ExportDesc.Name; + return ExportDesc.Name; + } + else + return Result.first->second; + } + return nullptr; + }; + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + AddDxilLib(CreateInfo.pGeneralShaders[i].pShader, CreateInfo.pGeneralShaders[i].Name); + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); + } + + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + auto& HitGroupDesc = *TempPool.Allocate(); + HitGroupDesc.HitGroupExport = TempPool.CopyWString(CreateInfo.pTriangleHitShaders[i].Name); + HitGroupDesc.Type = D3D12_HIT_GROUP_TYPE_TRIANGLES; + HitGroupDesc.ClosestHitShaderImport = AddDxilLib(CreateInfo.pTriangleHitShaders[i].pClosestHitShader, nullptr); + HitGroupDesc.AnyHitShaderImport = AddDxilLib(CreateInfo.pTriangleHitShaders[i].pAnyHitShader, nullptr); + HitGroupDesc.IntersectionShaderImport = nullptr; + + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &HitGroupDesc}); + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); + } + + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + auto& HitGroupDesc = *TempPool.Allocate(); + HitGroupDesc.HitGroupExport = TempPool.CopyWString(CreateInfo.pProceduralHitShaders[i].Name); + HitGroupDesc.Type = D3D12_HIT_GROUP_TYPE_PROCEDURAL_PRIMITIVE; + HitGroupDesc.ClosestHitShaderImport = AddDxilLib(CreateInfo.pProceduralHitShaders[i].pClosestHitShader, nullptr); + HitGroupDesc.AnyHitShaderImport = AddDxilLib(CreateInfo.pProceduralHitShaders[i].pAnyHitShader, nullptr); + HitGroupDesc.IntersectionShaderImport = AddDxilLib(CreateInfo.pProceduralHitShaders[i].pIntersectionShader, nullptr); + + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_HIT_GROUP, &HitGroupDesc}); + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); + } + + VERIFY_EXPR(Uint32(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount) == GroupIndex); + + if (CreateInfo.RayTracingPipeline.MaxRecursionDepth > D3D12_RAYTRACING_MAX_DECLARABLE_TRACE_RECURSION_DEPTH) + LOG_PSO_ERROR_AND_THROW("MaxRecursionDepth must be less than equal to ", D3D12_RAYTRACING_MAX_DECLARABLE_TRACE_RECURSION_DEPTH); + + auto& PipelineConfig = *TempPool.Allocate(); + // for compatibility with Vulkan set minimal recursion depth to 1 + PipelineConfig.MaxTraceRecursionDepth = std::max(1, CreateInfo.RayTracingPipeline.MaxRecursionDepth); + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_PIPELINE_CONFIG, &PipelineConfig}); + + auto& ShaderConfig = *TempPool.Allocate(); + ShaderConfig.MaxAttributeSizeInBytes = D3D12_RAYTRACING_MAX_ATTRIBUTE_SIZE_IN_BYTES; + ShaderConfig.MaxPayloadSizeInBytes = 32; // AZ TODO + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_RAYTRACING_SHADER_CONFIG, &ShaderConfig}); +#undef LOG_PSO_ERROR_AND_THROW +} + +template +void GetShaderIdentifiers(ID3D12StateObject* pSO, + const RayTracingPipelineStateCreateInfo& CreateInfo, + const TNameToGroupIndexMap& NameToGroupIndex, + Uint8* ShaderData) +{ + const Uint32 ShaderIdentifierSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; + + WCHAR TempName[256] = {}; + auto ConvertWStr = [&TempName](const char* Src) { + Uint32 i = 0; + for (; i < _countof(TempName) && Src[i] != 0; ++i) + TempName[i] = static_cast(Src[i]); + TempName[i] = 0; + return TempName; + }; + + CComPtr pStateObjectProperties; + auto hr = pSO->QueryInterface(IID_PPV_ARGS(&pStateObjectProperties)); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to get state object properties"); + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + auto iter = NameToGroupIndex.find(CreateInfo.pGeneralShaders[i].Name); + if (iter == NameToGroupIndex.end()) + LOG_ERROR_AND_THROW("Failed to get shader group index by name"); + + WCHAR* ShaderName = ConvertWStr(CreateInfo.pGeneralShaders[i].Name); + const void* ShaderID = pStateObjectProperties->GetShaderIdentifier(ShaderName); + if (ShaderID == nullptr) + LOG_ERROR_AND_THROW("Failed to get shader identifier"); + + std::memcpy(&ShaderData[ShaderIdentifierSize * iter->second], ShaderID, ShaderIdentifierSize); + } + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + auto iter = NameToGroupIndex.find(CreateInfo.pTriangleHitShaders[i].Name); + if (iter == NameToGroupIndex.end()) + LOG_ERROR_AND_THROW("Failed to get shader group index by name"); + + WCHAR* ShaderName = ConvertWStr(CreateInfo.pTriangleHitShaders[i].Name); + const void* ShaderID = pStateObjectProperties->GetShaderIdentifier(ShaderName); + if (ShaderID == nullptr) + LOG_ERROR_AND_THROW("Failed to get shader identifier"); + + std::memcpy(&ShaderData[ShaderIdentifierSize * iter->second], ShaderID, ShaderIdentifierSize); + } + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + auto iter = NameToGroupIndex.find(CreateInfo.pProceduralHitShaders[i].Name); + if (iter == NameToGroupIndex.end()) + LOG_ERROR_AND_THROW("Failed to get shader group index by name"); + + WCHAR* ShaderName = ConvertWStr(CreateInfo.pProceduralHitShaders[i].Name); + const void* ShaderID = pStateObjectProperties->GetShaderIdentifier(ShaderName); + if (ShaderID == nullptr) + LOG_ERROR_AND_THROW("Failed to get shader identifier"); + + std::memcpy(&ShaderData[ShaderIdentifierSize * iter->second], ShaderID, ShaderIdentifierSize); + } +} + +} // namespace + + +PipelineStateD3D12Impl::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type, ShaderD3D12Impl* _pShader) : + Type{_Type} +{ + Shaders.push_back(_pShader); +} + +void PipelineStateD3D12Impl::ShaderStageInfo::Append(ShaderD3D12Impl* pShader) +{ + Shaders.push_back(pShader); +} + +size_t PipelineStateD3D12Impl::ShaderStageInfo::Count() const +{ + return Shaders.size(); +} + + template -void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& ShaderStages) +void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + TShaderStages& ShaderStages) { m_ResourceLayoutIndex.fill(-1); @@ -151,8 +353,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* { try { - std::vector ShaderStages; - + TShaderStages ShaderStages; InitInternalObjects(CreateInfo, ShaderStages); auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); @@ -164,19 +365,20 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* for (const auto& Stage : ShaderStages) { - auto* pShaderD3D12 = Stage.pShader; + VERIFY_EXPR(Stage.Shaders.size() == 1); + auto* pShaderD3D12 = Stage.Shaders[0]; auto ShaderType = pShaderD3D12->GetDesc().ShaderType; VERIFY_EXPR(ShaderType == Stage.Type); 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 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"); } @@ -237,9 +439,12 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* // 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(static_cast(&m_pd3d12PSO))); + CComPtr pPSO; + HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, IID_PPV_ARGS(&pPSO)); if (FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create pipeline state"); + + m_pd3d12PSO = pPSO; } #ifdef D3D12_H_HAS_MESH_SHADER @@ -268,17 +473,18 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* for (const auto& Stage : ShaderStages) { - auto* pShaderD3D12 = Stage.pShader; + VERIFY_EXPR(Stage.Shaders.size() == 1); + auto* pShaderD3D12 = Stage.Shaders[0]; auto ShaderType = pShaderD3D12->GetDesc().ShaderType; VERIFY_EXPR(ShaderType == Stage.Type); 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 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"); } @@ -321,9 +527,13 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* streamDesc.SizeInBytes = sizeof(d3d12PSODesc); streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; - auto* device2 = pDeviceD3D12->GetD3D12Device2(); + auto* device2 = pDeviceD3D12->GetD3D12Device2(); + CComPtr pPSO; + HRESULT hr = device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&pPSO)); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); - CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); + m_pd3d12PSO = pPSO; } #endif // D3D12_H_HAS_MESH_SHADER else @@ -355,8 +565,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* { try { - std::vector ShaderStages; - + TShaderStages ShaderStages; InitInternalObjects(CreateInfo, ShaderStages); auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); @@ -364,7 +573,8 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); - auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); + VERIFY_EXPR(ShaderStages[0].Shaders.size() == 1); + auto* pByteCode = ShaderStages[0].Shaders[0]->GetShaderByteCode(); d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); @@ -381,10 +591,101 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + CComPtr pPSO; + HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, IID_PPV_ARGS(&pPSO)); if (FAILED(hr)) LOG_ERROR_AND_THROW("Failed to create pipeline state"); + m_pd3d12PSO = pPSO; + + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + } + catch (...) + { + Destruct(); + throw; + } +} + +PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDeviceD3D12, + const RayTracingPipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + try + { + m_ResourceLayoutIndex.fill(-1); + + TShaderStages ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + TNameToGroupIndexMap NameToGroupIndex; + std::vector Subobjects; + const Uint32 ShaderIdentifierSize = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; + DynamicLinearAllocator TempPool{GetRawAllocator(), 4 << 10}; + LinearAllocator MemPool{GetRawAllocator()}; + + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); + + ReserveSpaceForPipelineDesc(CreateInfo, ShaderIdentifierSize, MemPool); + + MemPool.Reserve(); + + m_pStaticResourceCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateD3D12Impl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_pStaticResourceCaches); + (void)Ptr; + + m_pShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, std::ref(*this)); + + m_pStaticVarManagers = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_pStaticVarManagers + s) ShaderVariableManagerD3D12{*this, GetStaticShaderResCache(s)}; + + BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, Subobjects, TempPool, MemPool); + InitializePipelineDesc(CreateInfo, ShaderIdentifierSize, std::move(NameToGroupIndex), MemPool); + + m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(CreateInfo, ShaderStages); + + D3D12_GLOBAL_ROOT_SIGNATURE GlobalRoot; + GlobalRoot.pGlobalRootSignature = m_RootSig.GetD3D12RootSignature(); + Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &GlobalRoot}); + + D3D12_STATE_OBJECT_DESC RTPipelineDesc; + RTPipelineDesc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE; + RTPipelineDesc.NumSubobjects = static_cast(Subobjects.size()); + RTPipelineDesc.pSubobjects = Subobjects.data(); + + auto pd3d12Device = pDeviceD3D12->GetD3D12Device5(); + CComPtr pSO; + HRESULT hr = pd3d12Device->CreateStateObject(&RTPipelineDesc, IID_PPV_ARGS(&pSO)); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create ray tracing state object"); + + m_pd3d12PSO = pSO; + + GetShaderIdentifiers(pSO, CreateInfo, m_pRayTracingPipelineData->NameToGroupIndex, m_pRayTracingPipelineData->Shaders); + if (*m_Desc.Name != 0) { m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); @@ -408,6 +709,8 @@ PipelineStateD3D12Impl::~PipelineStateD3D12Impl() void PipelineStateD3D12Impl::Destruct() { + TPipelineStateBase::Destruct(); + auto& ShaderResLayoutAllocator = GetRawAllocator(); for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { @@ -444,18 +747,19 @@ void PipelineStateD3D12Impl::Destruct() IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase) -void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, - std::vector& ShaderStages) +void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages) { auto pd3d12Device = GetDevice()->GetD3D12Device(); const auto& ResourceLayout = m_Desc.ResourceLayout; -#ifdef DILIGENT_DEVELOPMENT + // AZ TODO +#if 0 //def DILIGENT_DEVELOPMENT { const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; for (size_t s = 0; s < ShaderStages.size(); ++s) { - const auto* pShader = ShaderStages[s].pShader; + const auto* pShader = ShaderStages[s].Shaders[0]; pResources[s] = &(*pShader->GetShaderResources()); } ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), @@ -466,9 +770,9 @@ void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto* pShaderD3D12 = ShaderStages[s].pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); + auto Shaders = ShaderStages[s].Shaders; + auto ShaderType = ShaderStages[s].Type; + auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); m_ResourceLayoutIndex[ShaderInd] = static_cast(s); @@ -476,7 +780,7 @@ void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& pd3d12Device, m_Desc.PipelineType, ResourceLayout, - pShaderD3D12->GetShaderResources(), + Shaders, GetRawAllocator(), nullptr, 0, @@ -489,7 +793,7 @@ void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& pd3d12Device, m_Desc.PipelineType, ResourceLayout, - pShaderD3D12->GetShaderResources(), + Shaders, GetRawAllocator(), StaticVarType, _countof(StaticVarType), @@ -550,7 +854,8 @@ bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const auto IsSameRootSignature = m_RootSig.IsSameAs(pPSOD3D12->m_RootSig); -#ifdef DILIGENT_DEBUG + // AZ TODO +#if 0 //def DILIGENT_DEBUG { bool IsCompatibleShaders = true; if (GetNumShaderStages() != pPSOD3D12->GetNumShaderStages()) @@ -601,10 +906,10 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou { if (Attrib.CommitResources) { - if (m_Desc.IsComputePipeline()) - CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); - else + if (m_Desc.IsAnyGraphicsPipeline()) CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature()); + else + CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); } return nullptr; } @@ -630,18 +935,18 @@ ShaderResourceCacheD3D12* PipelineStateD3D12Impl::CommitAndTransitionShaderResou auto& ResourceCache = pResBindingD3D12Impl->GetResourceCache(); if (Attrib.CommitResources) { - if (m_Desc.IsComputePipeline()) - CmdCtx.AsComputeContext().SetRootSignature(GetD3D12RootSignature()); - else + if (m_Desc.IsAnyGraphicsPipeline()) CmdCtx.AsGraphicsContext().SetRootSignature(GetD3D12RootSignature()); + else + CmdCtx.AsComputeContext().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.IsAnyGraphicsPipeline(), 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.IsAnyGraphicsPipeline(), Attrib.ValidateStates); } } else @@ -653,7 +958,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.IsAnyGraphicsPipeline(), Attrib.CtxId, pDeviceCtx, Attrib.CommitResources, // CommitViews diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 61ad5871..eee2e1fa 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -89,7 +89,6 @@ D3D_FEATURE_LEVEL RenderDeviceD3D12Impl::GetD3DFeatureLevel() const return FeatureLevelsData.MaxSupportedFeatureLevel; } -#ifdef D3D12_H_HAS_MESH_SHADER ID3D12Device2* RenderDeviceD3D12Impl::GetD3D12Device2() { if (!m_pd3d12Device2) @@ -98,7 +97,15 @@ ID3D12Device2* RenderDeviceD3D12Impl::GetD3D12Device2() } return m_pd3d12Device2; } -#endif + +ID3D12Device5* RenderDeviceD3D12Impl::GetD3D12Device5() +{ + if (!m_pd3d12Device5) + { + CHECK_D3D_RESULT_THROW(m_pd3d12Device->QueryInterface(IID_PPV_ARGS(&m_pd3d12Device5)), "Failed to get ID3D12Device5"); + } + return m_pd3d12Device5; +} RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator, @@ -154,6 +161,8 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo m_pDxCompiler {CreateDXCompiler(DXCompilerTarget::Direct3D12, EngineCI.pDxCompilerPath)} // clang-format on { + static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor"); + try { m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_D3D12; @@ -203,9 +212,9 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo // Header may not have constants for D3D_SHADER_MODEL_6_1 and above. const D3D_SHADER_MODEL Models[] = // { - static_cast(0x65), // minimum required for mesh shader + static_cast(0x65), // minimum required for mesh shader and DXR 1.1 static_cast(0x64), - static_cast(0x63), + static_cast(0x63), // minimum required for DXR 1.0 static_cast(0x62), static_cast(0x61), D3D_SHADER_MODEL_6_0 // @@ -251,7 +260,16 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo m_DeviceCaps.Features.MeshShaders = MeshShadersSupported ? DEVICE_FEATURE_STATE_ENABLED : DEVICE_FEATURE_STATE_DISABLED; - // AZ TODO: ray tracing + { + D3D12_FEATURE_DATA_D3D12_OPTIONS5 d3d12Features = {}; + if (SUCCEEDED(m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &d3d12Features, sizeof(d3d12Features)))) + { + if (d3d12Features.RaytracingTier >= D3D12_RAYTRACING_TIER_1_0) + { + m_DeviceCaps.Features.RayTracing = DEVICE_FEATURE_STATE_ENABLED; + } + } + } { D3D12_FEATURE_DATA_D3D12_OPTIONS d3d12Features = {}; @@ -294,6 +312,8 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo CHECK_REQUIRED_FEATURE(ShaderInt8, "8-bit shader operations are"); CHECK_REQUIRED_FEATURE(ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); CHECK_REQUIRED_FEATURE(UniformBuffer8BitAccess, "8-bit uniform buffer access is"); + + CHECK_REQUIRED_FEATURE(RayTracing, "ray tracing is"); // clang-format on #undef CHECK_REQUIRED_FEATURE @@ -558,6 +578,11 @@ void RenderDeviceD3D12Impl::CreateComputePipelineState(const ComputePipelineStat CreatePipelineState(PSOCreateInfo, ppPipelineState); } +void RenderDeviceD3D12Impl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState); +} + void RenderDeviceD3D12Impl::CreateBufferFromD3DResource(ID3D12Resource* pd3d12Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) { CreateDeviceObject("buffer", BuffDesc, ppBuffer, diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 2afb9eb1..718f4b17 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -183,8 +183,17 @@ static constexpr D3D12_SHADER_VISIBILITY ShaderTypeInd2ShaderVisibilityMap[] D3D12_SHADER_VISIBILITY_ALL, // 5 #ifdef D3D12_H_HAS_MESH_SHADER D3D12_SHADER_VISIBILITY_AMPLIFICATION, // 6 - D3D12_SHADER_VISIBILITY_MESH // 7 + D3D12_SHADER_VISIBILITY_MESH, // 7 +#else + D3D12_SHADER_VISIBILITY(6), + D3D12_SHADER_VISIBILITY(7), #endif + D3D12_SHADER_VISIBILITY_ALL, // 8 + D3D12_SHADER_VISIBILITY_ALL, // 9 + D3D12_SHADER_VISIBILITY_ALL, // 10 + D3D12_SHADER_VISIBILITY_ALL, // 11 + D3D12_SHADER_VISIBILITY_ALL, // 12 + D3D12_SHADER_VISIBILITY_ALL, // 13 }; // clang-format on D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType) @@ -192,19 +201,26 @@ D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType) auto ShaderInd = GetShaderTypeIndex(ShaderType); auto ShaderVisibility = ShaderTypeInd2ShaderVisibilityMap[ShaderInd]; #ifdef DILIGENT_DEBUG + static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type"); 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 D3D12_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; + 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 + case SHADER_TYPE_RAY_GEN: + case SHADER_TYPE_RAY_MISS: + case SHADER_TYPE_RAY_CLOSEST_HIT: + case SHADER_TYPE_RAY_ANY_HIT: + case SHADER_TYPE_RAY_INTERSECTION: + case SHADER_TYPE_CALLABLE: VERIFY_EXPR(ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL); break; // clang-format on default: LOG_ERROR("Unknown shader type (", ShaderType, ")"); break; } @@ -212,46 +228,6 @@ D3D12_SHADER_VISIBILITY GetShaderVisibility(SHADER_TYPE ShaderType) return ShaderVisibility; } -// 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_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(uint32_t(ShaderVisibility) < _countof(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; -# ifdef D3D12_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; - } -#endif - return ShaderType; -} - - // clang-format off static D3D12_DESCRIPTOR_HEAP_TYPE RangeType2HeapTypeMap[] { @@ -287,6 +263,10 @@ void RootSignature::InitImmutableSampler(SHADER_TYPE ShaderT const char* SamplerSuffix, const D3DShaderResourceAttribs& SamplerAttribs) { +#ifdef DILIGENT_DEBUG + m_DbgShaderStages |= ShaderType; +#endif + auto ShaderVisibility = GetShaderVisibility(ShaderType); auto SamplerFound = false; for (auto& ImtblSmplr : m_ImmutableSamplers) @@ -319,6 +299,10 @@ void RootSignature::AllocateResourceSlot(SHADER_TYPE ShaderT Uint32& OffsetFromTableStart // Output parameter ) { +#ifdef DILIGENT_DEBUG + m_DbgShaderStages |= ShaderType; +#endif + const auto ShaderVisibility = GetShaderVisibility(ShaderType); if (RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV && ShaderResAttribs.BindCount == 1) { @@ -564,7 +548,9 @@ void RootSignature::Finalize(ID3D12Device* pd3d12Device) CComPtr signature; CComPtr error; HRESULT hr = D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error); - hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), __uuidof(m_pd3d12RootSignature), reinterpret_cast(static_cast(&m_pd3d12RootSignature))); + CHECK_D3D_RESULT_THROW(hr, "Failed to serialize root signature"); + + hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), __uuidof(m_pd3d12RootSignature), reinterpret_cast(static_cast(&m_pd3d12RootSignature))); CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature"); bool bHasDynamicDescriptors = m_TotalSrvCbvUavSlots[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] != 0 || m_TotalSamplerSlots[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] != 0; @@ -658,10 +644,6 @@ void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl const auto& D3D12RootParam = static_cast(RootParam); auto& RootTableCache = ResourceCache.GetRootTable(RootParam.GetRootIndex()); - SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN; -#ifdef DILIGENT_DEBUG - dbgShaderType = ShaderTypeFromShaderVisibility(D3D12RootParam.ShaderVisibility); -#endif VERIFY_EXPR(D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE); auto TableSize = RootParam.GetDescriptorTableSize(); @@ -670,7 +652,7 @@ void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl auto HeapType = HeapTypeFromRangeType(D3D12RootParam.DescriptorTable.pDescriptorRanges[0].RangeType); #ifdef DILIGENT_DEBUG - RootTableCache.SetDebugAttribs(TableSize, HeapType, dbgShaderType); + RootTableCache.SetDebugAttribs(TableSize, HeapType, m_DbgShaderStages); #endif // Space for dynamic variables is allocated at every draw call @@ -702,9 +684,8 @@ void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl // Root views are not assigned valid table start offset VERIFY_EXPR(RootTableCache.m_TableStartOffset == ShaderResourceCacheD3D12::InvalidDescriptorOffset); - SHADER_TYPE dbgShaderType = ShaderTypeFromShaderVisibility(D3D12RootParam.ShaderVisibility); VERIFY_EXPR(D3D12RootParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV); - RootTableCache.SetDebugAttribs(1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType); + RootTableCache.SetDebugAttribs(1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_DbgShaderStages); } #endif @@ -718,6 +699,7 @@ __forceinline void TransitionResource(CommandContext& Ctx, ShaderResourceCacheD3D12::Resource& Res, D3D12_DESCRIPTOR_RANGE_TYPE RangeType) { + static_assert(static_cast(CachedResourceType::NumTypes) == 7, "Please update this function to handle the new resource type"); switch (Res.Type) { case CachedResourceType::CBV: @@ -782,6 +764,11 @@ __forceinline void TransitionResource(CommandContext& Ctx, VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type"); break; + case CachedResourceType::AccelStruct: + { + } + break; + default: // Resource not bound VERIFY(Res.Type == CachedResourceType::Unknown, "Unexpected resource type"); @@ -794,6 +781,7 @@ __forceinline void TransitionResource(CommandContext& Ctx, void RootSignature::DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resource& Res, D3D12_DESCRIPTOR_RANGE_TYPE RangeType) { + static_assert(static_cast(CachedResourceType::NumTypes) == 7, "Please update this function to handle the new resource type"); switch (Res.Type) { case CachedResourceType::CBV: @@ -880,6 +868,11 @@ void RootSignature::DvpVerifyResourceState(const ShaderResourceCacheD3D12::Resou VERIFY(RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, "Unexpected descriptor range type"); break; + case CachedResourceType::AccelStruct: + { + } + break; + default: // Resource not bound VERIFY(Res.Type == CachedResourceType::Unknown, "Unexpected resource type"); @@ -922,13 +915,11 @@ __forceinline void ProcessCachedTableResources(Uint32 RootI const auto& range = D3D12Param.DescriptorTable.pDescriptorRanges[r]; for (UINT d = 0; d < range.NumDescriptors; ++d) { - SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN; #ifdef DILIGENT_DEBUG - dbgShaderType = ShaderTypeFromShaderVisibility(D3D12Param.ShaderVisibility); VERIFY(dbgHeapType == HeapTypeFromRangeType(range.RangeType), "Mistmatch between descriptor heap type and descriptor range type"); #endif auto OffsetFromTableStart = range.OffsetInDescriptorsFromTableStart + d; - auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(OffsetFromTableStart, dbgHeapType, dbgShaderType); + auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(OffsetFromTableStart, dbgHeapType, SHADER_TYPE_UNKNOWN); Operation(OffsetFromTableStart, range, Res); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp index 36a14167..a356d73a 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp @@ -94,7 +94,8 @@ ShaderD3D12Impl::ShaderD3D12Impl(IReferenceCounters* pRefCounters, pRenderDeviceD3D12, ShaderCI.Desc }, - ShaderD3DBase{ShaderCI, GetD3D12ShaderModel(pRenderDeviceD3D12, ShaderCI.HLSLVersion, ShaderCI.ShaderCompiler), pRenderDeviceD3D12->GetDxCompiler()} + ShaderD3DBase{ShaderCI, GetD3D12ShaderModel(pRenderDeviceD3D12, ShaderCI.HLSLVersion, ShaderCI.ShaderCompiler), pRenderDeviceD3D12->GetDxCompiler()}, + m_EntryPoint{ShaderCI.EntryPoint} // clang-format on { // Load shader resources diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index c0428e7e..157e42f7 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -57,12 +57,13 @@ D3D12_DESCRIPTOR_RANGE_TYPE GetDescriptorRangeType(CachedResourceType ResType) ResTypeToD3D12DescrRangeType() { // clang-format off - m_Map[(size_t)CachedResourceType::CBV] = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; - m_Map[(size_t)CachedResourceType::TexSRV] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - m_Map[(size_t)CachedResourceType::BufSRV] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - m_Map[(size_t)CachedResourceType::TexUAV] = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - m_Map[(size_t)CachedResourceType::BufUAV] = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - m_Map[(size_t)CachedResourceType::Sampler] = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + m_Map[(size_t)CachedResourceType::CBV] = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + m_Map[(size_t)CachedResourceType::TexSRV] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + m_Map[(size_t)CachedResourceType::BufSRV] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + m_Map[(size_t)CachedResourceType::TexUAV] = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + m_Map[(size_t)CachedResourceType::BufUAV] = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + m_Map[(size_t)CachedResourceType::Sampler] = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + m_Map[(size_t)CachedResourceType::AccelStruct] = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; // clang-format on } @@ -113,240 +114,281 @@ void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator& // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Resource-Layouts-in-a-Pipeline-State -void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, - PIPELINE_TYPE PipelineType, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - RootSignature* pRootSig) +void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, + PIPELINE_TYPE PipelineType, + const PipelineResourceLayoutDesc& ResourceLayout, + const std::vector& Shaders, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + RootSignature* pRootSig) { m_pd3d12Device = pd3d12Device; - m_pResources = std::move(pSrcResources); VERIFY_EXPR((pResourceCache != nullptr) ^ (pRootSig != nullptr)); + VERIFY_EXPR(Shaders.size() > 0); const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); std::array CbvSrvUavCount = {}; std::array SamplerCount = {}; + std::unordered_map ResourceNameToIndex; + // Count number of resources to allocate all needed memory - m_pResources->ProcessResources( - [&](const D3DShaderResourceAttribs& CB, Uint32) // - { - auto VarType = m_pResources->FindVariableType(CB, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - ++CbvSrvUavCount[VarType]; - }, - [&](const D3DShaderResourceAttribs& Sam, Uint32) // - { - auto VarType = m_pResources->FindVariableType(Sam, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - constexpr bool LogImtblSamplerArrayError = true; + m_IsUsingSeparateSamplers = !Shaders[0]->GetShaderResources()->IsUsingCombinedTextureSamplers(); + m_ShaderType = Shaders[0]->GetDesc().ShaderType; + size_t StringPoolSize = 0; - auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError); - // Skip immutable samplers - if (ImtblSamplerInd < 0) - ++SamplerCount[VarType]; - } - }, - [&](const D3DShaderResourceAttribs& TexSRV, Uint32) // + for (auto* pShader : Shaders) + { + auto pResources = pShader->GetShaderResources(); + VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); + const auto HandleResType = [&](const auto& Res, Uint32) // { - auto VarType = m_pResources->FindVariableType(TexSRV, ResourceLayout); + auto VarType = pResources->FindVariableType(Res, ResourceLayout); if (IsAllowedType(VarType, AllowedTypeBits)) { - ++CbvSrvUavCount[VarType]; - if (TexSRV.IsCombinedWithSampler()) + bool IsUniqueName = ResourceNameToIndex.emplace(HashMapStringKey{Res.Name}, ~0u).second; + if (IsUniqueName) { - const auto& SamplerAttribs = m_pResources->GetCombinedSampler(TexSRV); - auto SamplerVarType = m_pResources->FindVariableType(SamplerAttribs, ResourceLayout); - DEV_CHECK_ERR(SamplerVarType == VarType, - "The type (", GetShaderVariableTypeLiteralName(VarType), ") of texture SRV variable '", TexSRV.Name, - "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SamplerVarType), - ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); - (void)SamplerVarType; + StringPoolSize += strlen(Res.Name) + 1; + ++CbvSrvUavCount[VarType]; } } - }, - [&](const D3DShaderResourceAttribs& TexUAV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(TexUAV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - ++CbvSrvUavCount[VarType]; - }, - [&](const D3DShaderResourceAttribs& BufSRV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(BufSRV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - ++CbvSrvUavCount[VarType]; - }, - [&](const D3DShaderResourceAttribs& BufUAV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(BufUAV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - ++CbvSrvUavCount[VarType]; - } // - ); + }; + pResources->ProcessResources( + HandleResType, + [&](const D3DShaderResourceAttribs& Sam, Uint32) // + { + auto VarType = pResources->FindVariableType(Sam, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + constexpr bool LogImtblSamplerArrayError = true; + + auto ImtblSamplerInd = pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError); + // Skip immutable samplers + if (ImtblSamplerInd < 0) + { + bool IsUniqueName = ResourceNameToIndex.emplace(HashMapStringKey{Sam.Name}, ~0u).second; + if (IsUniqueName) + { + StringPoolSize += strlen(Sam.Name) + 1; + ++SamplerCount[VarType]; + } + } + } + }, + [&](const D3DShaderResourceAttribs& TexSRV, Uint32) // + { + auto VarType = pResources->FindVariableType(TexSRV, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + bool IsUniqueName = ResourceNameToIndex.emplace(HashMapStringKey{TexSRV.Name}, ~0u).second; + if (IsUniqueName) + { + StringPoolSize += strlen(TexSRV.Name) + 1; + ++CbvSrvUavCount[VarType]; + if (TexSRV.IsCombinedWithSampler()) + { + const auto& SamplerAttribs = pResources->GetCombinedSampler(TexSRV); + auto SamplerVarType = pResources->FindVariableType(SamplerAttribs, ResourceLayout); + DEV_CHECK_ERR(SamplerVarType == VarType, + "The type (", GetShaderVariableTypeLiteralName(VarType), ") of texture SRV variable '", TexSRV.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SamplerVarType), + ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); + (void)SamplerVarType; + } + } + } + }, + HandleResType, + HandleResType, + HandleResType, + HandleResType); + } AllocateMemory(LayoutDataAllocator, CbvSrvUavCount, SamplerCount); - std::array CurrCbvSrvUav = {}; - std::array CurrSampler = {}; + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - Uint32 StaticResCacheTblSizes[4] = {0, 0, 0, 0}; + std::array CurrCbvSrvUav = {}; + std::array CurrSampler = {}; + std::array StaticResCacheTblSizes = {}; auto AddResource = [&](const D3DShaderResourceAttribs& Attribs, CachedResourceType ResType, SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 SamplerId = D3D12Resource::InvalidSamplerId) // { - Uint32 RootIndex = D3D12Resource::InvalidRootIndex; - Uint32 Offset = D3D12Resource::InvalidOffset; - - D3D12_DESCRIPTOR_RANGE_TYPE DescriptorRangeType = GetDescriptorRangeType(ResType); + auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); + VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - if (pRootSig) - { - pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), PipelineType, Attribs, VarType, DescriptorRangeType, RootIndex, Offset); - VERIFY(RootIndex <= D3D12Resource::MaxRootIndex, "Root index excceeds allowed limit"); - } - else + if (ResIter->second == ~0u) { - // If root signature is not provided - use artifial root signature to store - // static shader resources: - // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV (0) - // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV (1) - // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV (2) - // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER (3) + Uint32 RootIndex = D3D12Resource::InvalidRootIndex; + Uint32 Offset = D3D12Resource::InvalidOffset; - // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Special-Resource-Layout-for-Managing-Static-Shader-Resources + D3D12_DESCRIPTOR_RANGE_TYPE DescriptorRangeType = GetDescriptorRangeType(ResType); - VERIFY_EXPR(pResourceCache != nullptr); + if (pRootSig) + { + pRootSig->AllocateResourceSlot(GetShaderType(), PipelineType, Attribs, VarType, DescriptorRangeType, RootIndex, Offset); + VERIFY(RootIndex <= D3D12Resource::MaxRootIndex, "Root index excceeds allowed limit"); + } + else + { + // If root signature is not provided - use artifial root signature to store + // static shader resources: + // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV (0) + // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV (1) + // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV (2) + // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER (3) - RootIndex = DescriptorRangeType; - Offset = Attribs.BindPoint; - // Resources in the static resource cache are indexed by the bind point - StaticResCacheTblSizes[RootIndex] = std::max(StaticResCacheTblSizes[RootIndex], Offset + Attribs.BindCount); - } - VERIFY(RootIndex != D3D12Resource::InvalidRootIndex, "Root index must be valid"); - VERIFY(Offset != D3D12Resource::InvalidOffset, "Offset must be valid"); - - // Immutable samplers are never copied, and SamplerId == InvalidSamplerId - auto& NewResource = (ResType == CachedResourceType::Sampler) ? - GetSampler(VarType, CurrSampler[VarType]++) : - GetSrvCbvUav(VarType, CurrCbvSrvUav[VarType]++); - ::new (&NewResource) D3D12Resource(*this, Attribs, VarType, ResType, RootIndex, Offset, SamplerId); - }; + // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Special-Resource-Layout-for-Managing-Static-Shader-Resources + VERIFY_EXPR(pResourceCache != nullptr); - m_pResources->ProcessResources( - [&](const D3DShaderResourceAttribs& CB, Uint32) // - { - auto VarType = m_pResources->FindVariableType(CB, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - AddResource(CB, CachedResourceType::CBV, VarType); - }, - [&](const D3DShaderResourceAttribs& Sam, Uint32) // - { - auto VarType = m_pResources->FindVariableType(Sam, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - // The error (if any) have already been logged when counting the resources - constexpr bool LogImtblSamplerArrayError = false; - - auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError); - if (ImtblSamplerInd >= 0) - { - if (pRootSig != nullptr) - pRootSig->InitImmutableSampler(m_pResources->GetShaderType(), Sam.Name, m_pResources->GetCombinedSamplerSuffix(), Sam); - } - else - { - AddResource(Sam, CachedResourceType::Sampler, VarType); - } + RootIndex = DescriptorRangeType; + Offset = Attribs.BindPoint; + // Resources in the static resource cache are indexed by the bind point + StaticResCacheTblSizes[RootIndex] = std::max(StaticResCacheTblSizes[RootIndex], Offset + Attribs.BindCount); } - }, - [&](const D3DShaderResourceAttribs& TexSRV, Uint32) // + VERIFY(RootIndex != D3D12Resource::InvalidRootIndex, "Root index must be valid"); + VERIFY(Offset != D3D12Resource::InvalidOffset, "Offset must be valid"); + + // Static samplers are never copied, and SamplerId == InvalidSamplerId + Uint32 ResOffset = (ResType == CachedResourceType::Sampler) ? + GetSamplerOffset(VarType, CurrSampler[VarType]++) : + GetSrvCbvUavOffset(VarType, CurrCbvSrvUav[VarType]++); + ResIter->second = ResOffset; + auto& NewResource = GetResource(ResOffset); + ::new (&NewResource) D3D12Resource{*this, VarType, ResType, RootIndex, Offset, SamplerId, m_StringPool.CopyString(Attribs.Name), Attribs.BindCount, Attribs.BindPoint, + Attribs.GetInputType(), Attribs.GetSRVDimension()}; + } + else { - auto VarType = m_pResources->FindVariableType(TexSRV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - static_assert(SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES == 3, "Unexpected number of shader variable types"); - VERIFY(CurrSampler[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] + CurrSampler[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] + CurrSampler[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] == GetTotalSamplerCount(), "All samplers must be initialized before texture SRVs"); + // merge with existing + auto& ExistingRes = GetResource(ResIter->second); + VERIFY_EXPR(ExistingRes.VariableType == VarType); + VERIFY_EXPR(ExistingRes.GetInputType() == Attribs.GetInputType()); + VERIFY_EXPR(ExistingRes.BindCount == Attribs.BindCount); + } + }; - Uint32 SamplerId = D3D12Resource::InvalidSamplerId; - if (TexSRV.IsCombinedWithSampler()) + for (auto* pShader : Shaders) + { + auto pResources = pShader->GetShaderResources(); + pResources->ProcessResources( + [&](const D3DShaderResourceAttribs& CB, Uint32) // + { + auto VarType = pResources->FindVariableType(CB, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + AddResource(CB, CachedResourceType::CBV, VarType); + }, + [&](const D3DShaderResourceAttribs& Sam, Uint32) // + { + auto VarType = pResources->FindVariableType(Sam, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) { - const auto& SamplerAttribs = m_pResources->GetCombinedSampler(TexSRV); - auto SamplerVarType = m_pResources->FindVariableType(SamplerAttribs, ResourceLayout); - DEV_CHECK_ERR(SamplerVarType == VarType, - "The type (", GetShaderVariableTypeLiteralName(VarType), ") of texture SRV variable '", TexSRV.Name, - "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SamplerVarType), - ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); - // The error (if any) have already been logged when counting the resources - constexpr bool LogImtblSamplerArrayError = false; - - auto ImtblSamplerInd = m_pResources->FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); - if (ImtblSamplerInd >= 0) + constexpr bool LogStaticSamplerArrayError = false; + auto StaticSamplerInd = pResources->FindImmutableSampler(Sam, ResourceLayout, LogStaticSamplerArrayError); + if (StaticSamplerInd >= 0) { - // Immutable samplers are never copied, and SamplerId == InvalidSamplerId -#ifdef DILIGENT_DEBUG - auto SamplerCount = GetTotalSamplerCount(); - for (Uint32 s = 0; s < SamplerCount; ++s) - { - const auto& Sampler = GetSampler(s); - if (strcmp(Sampler.Attribs.Name, SamplerAttribs.Name) == 0) - LOG_ERROR("Immutable sampler '", Sampler.Attribs.Name, "' was found among resources. This seems to be a bug"); - } -#endif + if (pRootSig != nullptr) + pRootSig->InitImmutableSampler(pResources->GetShaderType(), Sam.Name, pResources->GetCombinedSamplerSuffix(), Sam); } else { - auto SamplerCount = GetTotalSamplerCount(); - bool SamplerFound = false; - for (SamplerId = 0; SamplerId < SamplerCount; ++SamplerId) + AddResource(Sam, CachedResourceType::Sampler, VarType); + } + } + }, + [&](const D3DShaderResourceAttribs& TexSRV, Uint32) // + { + auto VarType = pResources->FindVariableType(TexSRV, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + static_assert(SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES == 3, "Unexpected number of shader variable types"); + VERIFY(CurrSampler[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] + CurrSampler[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] + CurrSampler[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] == GetTotalSamplerCount(), "All samplers must be initialized before texture SRVs"); + + Uint32 SamplerId = D3D12Resource::InvalidSamplerId; + if (TexSRV.IsCombinedWithSampler()) + { + const auto& SamplerAttribs = pResources->GetCombinedSampler(TexSRV); + auto SamplerVarType = pResources->FindVariableType(SamplerAttribs, ResourceLayout); + DEV_CHECK_ERR(SamplerVarType == VarType, + "The type (", GetShaderVariableTypeLiteralName(VarType), ") of texture SRV variable '", TexSRV.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SamplerVarType), + ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); + + // The error (if any) have already been logged when counting the resources + constexpr bool LogStaticSamplerArrayError = false; + auto StaticSamplerInd = pResources->FindImmutableSampler(SamplerAttribs, ResourceLayout, LogStaticSamplerArrayError); + if (StaticSamplerInd >= 0) { - const auto& Sampler = GetSampler(SamplerId); - SamplerFound = strcmp(Sampler.Attribs.Name, SamplerAttribs.Name) == 0; - if (SamplerFound) - break; + // Static samplers are never copied, and SamplerId == InvalidSamplerId +#ifdef DILIGENT_DEBUG + auto SamplerCount = GetTotalSamplerCount(); + for (Uint32 s = 0; s < SamplerCount; ++s) + { + const auto& Sampler = GetSampler(s); + if (strcmp(Sampler.Name, SamplerAttribs.Name) == 0) + LOG_ERROR("Static sampler '", Sampler.Name, "' was found among resources. This seems to be a bug"); + } +#endif } - - if (!SamplerFound) + else { - LOG_ERROR("Unable to find sampler '", SamplerAttribs.Name, "' assigned to texture SRV '", TexSRV.Name, "' in the list of already created resources. This seems to be a bug."); - SamplerId = D3D12Resource::InvalidSamplerId; + auto SamplerCount = GetTotalSamplerCount(); + bool SamplerFound = false; + for (SamplerId = 0; SamplerId < SamplerCount; ++SamplerId) + { + const auto& Sampler = GetSampler(SamplerId); + SamplerFound = strcmp(Sampler.Name, SamplerAttribs.Name) == 0; + if (SamplerFound) + break; + } + + if (!SamplerFound) + { + LOG_ERROR("Unable to find sampler '", SamplerAttribs.Name, "' assigned to texture SRV '", TexSRV.Name, "' in the list of already created resources. This seems to be a bug."); + SamplerId = D3D12Resource::InvalidSamplerId; + } + VERIFY(SamplerId <= D3D12Resource::MaxSamplerId, "Sampler index excceeds allowed limit"); } - VERIFY(SamplerId <= D3D12Resource::MaxSamplerId, "Sampler index excceeds allowed limit"); } + AddResource(TexSRV, CachedResourceType::TexSRV, VarType, SamplerId); } - AddResource(TexSRV, CachedResourceType::TexSRV, VarType, SamplerId); - } - }, - [&](const D3DShaderResourceAttribs& TexUAV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(TexUAV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - AddResource(TexUAV, CachedResourceType::TexUAV, VarType); - }, - [&](const D3DShaderResourceAttribs& BufSRV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(BufSRV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - AddResource(BufSRV, CachedResourceType::BufSRV, VarType); - }, - [&](const D3DShaderResourceAttribs& BufUAV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(BufUAV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - AddResource(BufUAV, CachedResourceType::BufUAV, VarType); - } // - ); + }, + [&](const D3DShaderResourceAttribs& TexUAV, Uint32) // + { + auto VarType = pResources->FindVariableType(TexUAV, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + AddResource(TexUAV, CachedResourceType::TexUAV, VarType); + }, + [&](const D3DShaderResourceAttribs& BufSRV, Uint32) // + { + auto VarType = pResources->FindVariableType(BufSRV, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + AddResource(BufSRV, CachedResourceType::BufSRV, VarType); + }, + [&](const D3DShaderResourceAttribs& BufUAV, Uint32) // + { + auto VarType = pResources->FindVariableType(BufUAV, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + AddResource(BufUAV, CachedResourceType::BufUAV, VarType); + }, + [&](const D3DShaderResourceAttribs& AccelStruct, Uint32) // + { + auto VarType = pResources->FindVariableType(AccelStruct, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + AddResource(AccelStruct, CachedResourceType::AccelStruct, VarType); + } // + ); + } #ifdef DILIGENT_DEBUG for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) @@ -362,12 +404,12 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-the-Cache-for-Static-Shader-Resources // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Objects VERIFY_EXPR(pRootSig == nullptr); - pResourceCache->Initialize(GetRawAllocator(), _countof(StaticResCacheTblSizes), StaticResCacheTblSizes); + pResourceCache->Initialize(GetRawAllocator(), static_cast(StaticResCacheTblSizes.size()), StaticResCacheTblSizes.data()); #ifdef DILIGENT_DEBUG - pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SRV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_UAV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_UAV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_CBV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_CBV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SRV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SRV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_UAV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_UAV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_CBV).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_CBV], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GetShaderType()); + pResourceCache->GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).SetDebugAttribs(StaticResCacheTblSizes[D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GetShaderType()); #endif } } @@ -385,7 +427,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheCB(IDeviceObject* // resource mapping can be of wrong type RefCntAutoPtr pBuffD3D12(pBuffer, IID_BufferD3D12); #ifdef DILIGENT_DEVELOPMENT - VerifyConstantBufferBinding(Attribs, GetVariableType(), ArrayInd, pBuffer, pBuffD3D12.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBuffD3D12.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); #endif if (pBuffD3D12) { @@ -421,6 +463,39 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheCB(IDeviceObject* } } +RESOURCE_DIMENSION ShaderResourceLayoutD3D12::D3D12Resource::GetResourceDimension() const +{ + switch (GetSRVDimension()) + { + // clang-format off + case D3D_SRV_DIMENSION_BUFFER: return RESOURCE_DIM_BUFFER; + case D3D_SRV_DIMENSION_TEXTURE1D: return RESOURCE_DIM_TEX_1D; + case D3D_SRV_DIMENSION_TEXTURE1DARRAY: return RESOURCE_DIM_TEX_1D_ARRAY; + case D3D_SRV_DIMENSION_TEXTURE2D: return RESOURCE_DIM_TEX_2D; + case D3D_SRV_DIMENSION_TEXTURE2DARRAY: return RESOURCE_DIM_TEX_2D_ARRAY; + case D3D_SRV_DIMENSION_TEXTURE2DMS: return RESOURCE_DIM_TEX_2D; + case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: return RESOURCE_DIM_TEX_2D_ARRAY; + case D3D_SRV_DIMENSION_TEXTURE3D: return RESOURCE_DIM_TEX_3D; + case D3D_SRV_DIMENSION_TEXTURECUBE: return RESOURCE_DIM_TEX_CUBE; + case D3D_SRV_DIMENSION_TEXTURECUBEARRAY: return RESOURCE_DIM_TEX_CUBE_ARRAY; + // clang-format on + default: + return RESOURCE_DIM_BUFFER; + } +} + +bool ShaderResourceLayoutD3D12::D3D12Resource::IsMultisample() const +{ + switch (GetSRVDimension()) + { + case D3D_SRV_DIMENSION_TEXTURE2DMS: + case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: + return true; + default: + return false; + } +} + template struct ResourceViewTraits @@ -431,7 +506,7 @@ struct ResourceViewTraits { static const INTERFACE_ID& IID; - static bool VerifyView(ITextureViewD3D12* pViewD3D12, const D3DShaderResourceAttribs& Attribs, const char* ShaderName) + static bool VerifyView(ITextureViewD3D12* pViewD3D12, const ShaderResourceLayoutD3D12::D3D12Resource& Attribs, const char* ShaderName) { return true; } @@ -443,7 +518,7 @@ struct ResourceViewTraits { static const INTERFACE_ID& IID; - static bool VerifyView(IBufferViewD3D12* pViewD3D12, const D3DShaderResourceAttribs& Attribs, const char* ShaderName) + static bool VerifyView(IBufferViewD3D12* pViewD3D12, const ShaderResourceLayoutD3D12::D3D12Resource& Attribs, const char* ShaderName) { return VerifyBufferViewModeD3D(pViewD3D12, Attribs, ShaderName); } @@ -464,8 +539,8 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* // resource mapping can be of wrong type RefCntAutoPtr pViewD3D12{pView, ResourceViewTraits::IID}; #ifdef DILIGENT_DEVELOPMENT - VerifyResourceViewBinding(Attribs, GetVariableType(), ArrayIndex, pView, pViewD3D12.RawPtr(), {dbgExpectedViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); - ResourceViewTraits::VerifyView(pViewD3D12, Attribs, ParentResLayout.GetShaderName()); + VerifyResourceViewBinding(*this, GetVariableType(), ArrayIndex, pView, pViewD3D12.RawPtr(), {dbgExpectedViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + ResourceViewTraits::VerifyView(pViewD3D12, *this, ParentResLayout.GetShaderName()); #endif if (pViewD3D12) { @@ -501,8 +576,8 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheSampler(IDeviceObject* Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const { - VERIFY(Attribs.IsValidBindPoint(), "Invalid bind point"); - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + VERIFY(IsValidBindPoint(), "Invalid bind point"); + VERIFY_EXPR(ArrayIndex < BindCount); RefCntAutoPtr pSamplerD3D12(pSampler, IID_SamplerD3D12); if (pSamplerD3D12) @@ -512,7 +587,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheSampler(IDeviceObject* if (DstSam.pObject != pSampler) { auto VarTypeStr = GetShaderVariableTypeLiteralName(GetVariableType()); - LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", Attribs.GetPrintName(ArrayIndex), + LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetPrintName(ArrayIndex), "' in shader '", ParentResLayout.GetShaderName(), "'. Attempting to bind another sampler is an error and will " "be ignored. Use another shader resource binding instance or label the variable as dynamic."); } @@ -541,18 +616,25 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheSampler(IDeviceObject* } else { - LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", Attribs.GetPrintName(ArrayIndex), + LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", GetPrintName(ArrayIndex), "' in shader '", ParentResLayout.GetShaderName(), "'. Incorect object type: sampler is expected."); } } +void ShaderResourceLayoutD3D12::D3D12Resource::CacheAccelStruct(IDeviceObject* pTLAS, + ShaderResourceCacheD3D12::Resource& DstRes, + Uint32 ArrayIndex, + D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle) const +{ +} + const ShaderResourceLayoutD3D12::D3D12Resource& ShaderResourceLayoutD3D12::GetAssignedSampler(const D3D12Resource& TexSrv) const { VERIFY(TexSrv.GetResType() == CachedResourceType::TexSRV, "Unexpected resource type: texture SRV is expected"); VERIFY(TexSrv.ValidSamplerAssigned(), "Texture SRV has no associated sampler"); const auto& SamInfo = GetSampler(TexSrv.SamplerId); VERIFY(SamInfo.GetVariableType() == TexSrv.GetVariableType(), "Inconsistent texture and sampler variable types"); - VERIFY(StreqSuff(SamInfo.Attribs.Name, TexSrv.Attribs.Name, m_pResources->GetCombinedSamplerSuffix()), "Sampler name '", SamInfo.Attribs.Name, "' does not match texture name '", TexSrv.Attribs.Name, '\''); + //VERIFY(StreqSuff(SamInfo.Name, TexSrv.Name, GetCombinedSamplerSuffix()), "Sampler name '", SamInfo.Name, "' does not match texture name '", TexSrv.Name, '\''); return SamInfo; } @@ -566,11 +648,11 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* Uint32 ArrayIndex, ShaderResourceCacheD3D12& ResourceCache) const { - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + VERIFY_EXPR(ArrayIndex < BindCount); const bool IsSampler = GetResType() == CachedResourceType::Sampler; auto DescriptorHeapType = IsSampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - auto& DstRes = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, DescriptorHeapType, ParentResLayout.m_pResources->GetShaderType()); + auto& DstRes = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, DescriptorHeapType, ParentResLayout.GetShaderType()); auto ShdrVisibleHeapCPUDescriptorHandle = IsSampler ? ResourceCache.GetShaderVisibleTableCPUDescriptorHandle(RootIndex, OffsetFromTableStart + ArrayIndex) : @@ -584,7 +666,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* } else if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) { - if (GetResType() == CachedResourceType::CBV && Attribs.BindCount == 1) + if (GetResType() == CachedResourceType::CBV && BindCount == 1) { VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Non-array constant buffers are bound as root views and should not be assigned shader visible descriptor space"); } @@ -605,6 +687,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* if (pObj) { + static_assert(static_cast(CachedResourceType::NumTypes) == 7, "Please update this function to handle the new resource type"); switch (GetResType()) { case CachedResourceType::CBV: @@ -619,13 +702,13 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* if (ValidSamplerAssigned()) { auto& Sam = ParentResLayout.GetAssignedSampler(*this); - //VERIFY( !Sam.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" ); - VERIFY_EXPR(Attribs.BindCount == Sam.Attribs.BindCount || Sam.Attribs.BindCount == 1); - auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0; + //VERIFY( !Sam.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" ); + VERIFY_EXPR(BindCount == Sam.BindCount || Sam.BindCount == 1); + auto SamplerArrInd = Sam.BindCount > 1 ? ArrayIndex : 0; auto ShdrVisibleSamplerHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle(Sam.RootIndex, Sam.OffsetFromTableStart + SamplerArrInd); - auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.m_pResources->GetShaderType()); + auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.GetShaderType()); #ifdef DILIGENT_DEBUG { if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) @@ -652,7 +735,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* } else { - LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", Sam.Attribs.Name, ". Sampler is not set in the texture view '", pTexView->GetDesc().Name, '\''); + LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", Sam.Name, ". Sampler is not set in the texture view '", pTexView->GetDesc().Name, '\''); } } }); @@ -675,23 +758,27 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* CacheSampler(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle); break; + case CachedResourceType::AccelStruct: + CacheAccelStruct(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle); + break; + default: UNEXPECTED("Unknown resource type ", static_cast(GetResType())); } } else { if (DstRes.pObject != nullptr && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) - LOG_ERROR_MESSAGE("Shader variable '", Attribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic if you need to bind another resource."); + LOG_ERROR_MESSAGE("Shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic if you need to bind another resource."); DstRes = ShaderResourceCacheD3D12::Resource{}; if (ValidSamplerAssigned()) { auto& Sam = ParentResLayout.GetAssignedSampler(*this); D3D12_CPU_DESCRIPTOR_HANDLE NullHandle = {0}; - auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0; - auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.m_pResources->GetShaderType()); + auto SamplerArrInd = Sam.BindCount > 1 ? ArrayIndex : 0; + auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.GetShaderType()); if (DstSam.pObject != nullptr && Sam.GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) - LOG_ERROR_MESSAGE("Sampler variable '", Sam.Attribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic if you need to bind another sampler."); + LOG_ERROR_MESSAGE("Sampler variable '", Sam.Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic if you need to bind another sampler."); DstSam = ShaderResourceCacheD3D12::Resource{}; } } @@ -699,7 +786,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* bool ShaderResourceLayoutD3D12::D3D12Resource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheD3D12& ResourceCache) const { - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + VERIFY_EXPR(ArrayIndex < BindCount); if (RootIndex < ResourceCache.GetNumRootTables()) { @@ -709,7 +796,7 @@ bool ShaderResourceLayoutD3D12::D3D12Resource::IsBound(Uint32 ArrayIndex, const const auto& CachedRes = RootTable.GetResource(OffsetFromTableStart + ArrayIndex, GetResType() == CachedResourceType::Sampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - ParentResLayout.m_pResources->GetShaderType()); + ParentResLayout.GetShaderType()); if (CachedRes.pObject != nullptr) { VERIFY(CachedRes.CPUDescriptorHandle.ptr != 0 || CachedRes.pObject.RawPtr()->GetDesc().Usage == USAGE_DYNAMIC, "No relevant descriptor handle"); @@ -721,6 +808,55 @@ bool ShaderResourceLayoutD3D12::D3D12Resource::IsBound(Uint32 ArrayIndex, const return false; } +HLSLShaderResourceDesc ShaderResourceLayoutD3D12::D3D12Resource::GetHLSLResourceDesc() const +{ + HLSLShaderResourceDesc ResourceDesc; + ResourceDesc.Name = Name; + ResourceDesc.ArraySize = BindCount; + ResourceDesc.ShaderRegister = BindPoint; + switch (GetInputType()) + { + case D3D_SIT_CBUFFER: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; + break; + + case D3D_SIT_TBUFFER: + UNSUPPORTED("TBuffers are not supported"); + ResourceDesc.Type = SHADER_RESOURCE_TYPE_UNKNOWN; + break; + + case D3D_SIT_TEXTURE: + ResourceDesc.Type = (GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER ? SHADER_RESOURCE_TYPE_BUFFER_SRV : SHADER_RESOURCE_TYPE_TEXTURE_SRV); + break; + + case D3D_SIT_SAMPLER: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER; + break; + + case D3D_SIT_UAV_RWTYPED: + ResourceDesc.Type = (GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER ? SHADER_RESOURCE_TYPE_BUFFER_UAV : SHADER_RESOURCE_TYPE_TEXTURE_UAV); + break; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_BYTEADDRESS: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; + break; + + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_RWBYTEADDRESS: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + default: + UNEXPECTED("Unknown input type"); + } + + return ResourceDesc; +} + void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderResourceCacheD3D12& SrcCache, const ShaderResourceLayoutD3D12& DstLayout, ShaderResourceCacheD3D12& DstCache) const { @@ -739,18 +875,18 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR // Get resource attributes const auto& res = DstLayout.GetSrvCbvUav(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); auto RangeType = GetDescriptorRangeType(res.GetResType()); - for (Uint32 ArrInd = 0; ArrInd < res.Attribs.BindCount; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < res.BindCount; ++ArrInd) { - auto BindPoint = res.Attribs.BindPoint + ArrInd; + auto BindPoint = res.BindPoint + ArrInd; // Source resource in the static resource cache is in the root table at index RangeType, at offset BindPoint // D3D12_DESCRIPTOR_RANGE_TYPE_SRV = 0, // D3D12_DESCRIPTOR_RANGE_TYPE_UAV = 1 // D3D12_DESCRIPTOR_RANGE_TYPE_CBV = 2 - const auto& SrcRes = SrcCache.GetRootTable(RangeType).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + const auto& SrcRes = SrcCache.GetRootTable(RangeType).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GetShaderType()); if (!SrcRes.pObject) - LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", res.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", res.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); // Destination resource is at the root index and offset defined by the resource layout - auto& DstRes = DstCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + auto& DstRes = DstCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GetShaderType()); if (DstRes.pObject != SrcRes.pObject) { @@ -793,10 +929,10 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR { const auto& SamInfo = DstLayout.GetAssignedSampler(res); - //VERIFY(!SamInfo.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache"); + //VERIFY(!SamInfo.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache"); - VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid"); - VERIFY_EXPR(SamInfo.Attribs.BindCount == res.Attribs.BindCount || SamInfo.Attribs.BindCount == 1); + VERIFY(SamInfo.IsValidBindPoint(), "Sampler bind point must be valid"); + VERIFY_EXPR(SamInfo.BindCount == res.BindCount || SamInfo.BindCount == 1); } } @@ -805,15 +941,15 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR for (Uint32 s = 0; s < SamplerCount; ++s) { const auto& SamInfo = DstLayout.GetSampler(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, s); - for (Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < SamInfo.BindCount; ++ArrInd) { - auto BindPoint = SamInfo.Attribs.BindPoint + ArrInd; + auto BindPoint = SamInfo.BindPoint + ArrInd; // Source sampler in the static resource cache is in the root table at index 3 // (D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = 3), at offset BindPoint - const auto& SrcSampler = SrcCache.GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + const auto& SrcSampler = SrcCache.GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GetShaderType()); if (!SrcSampler.pObject) - LOG_ERROR_MESSAGE("No sampler assigned to static shader variable '", SamInfo.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); - auto& DstSampler = DstCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + LOG_ERROR_MESSAGE("No sampler assigned to static shader variable '", SamInfo.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); + auto& DstSampler = DstCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GetShaderType()); if (DstSampler.pObject != SrcSampler.pObject) { @@ -852,9 +988,9 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12 const auto& res = GetSrvCbvUav(VarType, r); VERIFY(res.GetVariableType() == VarType, "Unexpected variable type"); - for (Uint32 ArrInd = 0; ArrInd < res.Attribs.BindCount; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < res.BindCount; ++ArrInd) { - const auto& CachedRes = ResourceCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); + const auto& CachedRes = ResourceCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, GetShaderType()); if (CachedRes.pObject) VERIFY(CachedRes.Type == res.GetResType(), "Inconsistent cached resource types"); else @@ -864,24 +1000,24 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12 // Dynamic buffers do not have CPU descriptor handle as they do not keep D3D12 buffer, and space is allocated from the GPU ring buffer CachedRes.CPUDescriptorHandle.ptr == 0 && !(CachedRes.Type == CachedResourceType::CBV && CachedRes.pObject.RawPtr()->GetDesc().Usage == USAGE_DYNAMIC)) { - LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(res.GetVariableType()), " variable '", res.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); + LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(res.GetVariableType()), " variable '", res.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); BindingsOK = false; } - if (res.Attribs.BindCount > 1 && res.ValidSamplerAssigned()) + if (res.BindCount > 1 && res.ValidSamplerAssigned()) { // Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent const auto& SamInfo = GetAssignedSampler(res); - if (SamInfo.Attribs.BindCount == 1) + if (SamInfo.BindCount == 1) { - const auto& CachedSampler = ResourceCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + const auto& CachedSampler = ResourceCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GetShaderType()); // Conversion must always succeed as the type is verified when resource is bound to the variable if (const auto* pTexView = CachedRes.pObject.RawPtr()) { const auto* pSampler = pTexView->GetSampler(); if (pSampler != nullptr && CachedSampler.pObject != nullptr && CachedSampler.pObject != pSampler) { - LOG_ERROR_MESSAGE("All elements of texture array '", res.Attribs.Name, "' in shader '", GetShaderName(), "' share the same sampler. However, the sampler set in view for element ", ArrInd, " does not match bound sampler. This may cause incorrect behavior on GL platform."); + LOG_ERROR_MESSAGE("All elements of texture array '", res.Name, "' in shader '", GetShaderName(), "' share the same sampler. However, the sampler set in view for element ", ArrInd, " does not match bound sampler. This may cause incorrect behavior on GL platform."); } } } @@ -896,7 +1032,7 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12 } else if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources) { - if (res.GetResType() == CachedResourceType::CBV && res.Attribs.BindCount == 1) + if (res.GetResType() == CachedResourceType::CBV && res.BindCount == 1) { VERIFY(ShdrVisibleHeapCPUDescriptorHandle.ptr == 0, "Non-array constant buffers are bound as root views and should not be assigned shader visible descriptor space"); } @@ -920,19 +1056,19 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12 { VERIFY(res.GetResType() == CachedResourceType::TexSRV, "Sampler can only be assigned to a texture SRV"); const auto& SamInfo = GetAssignedSampler(res); - //VERIFY(!SamInfo.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" ); - VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid"); + //VERIFY(!SamInfo.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" ); + VERIFY(SamInfo.IsValidBindPoint(), "Sampler bind point must be valid"); - for (Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < SamInfo.BindCount; ++ArrInd) { - const auto& CachedSampler = ResourceCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + const auto& CachedSampler = ResourceCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GetShaderType()); if (CachedSampler.pObject) VERIFY(CachedSampler.Type == CachedResourceType::Sampler, "Incorrect cached sampler type"); else VERIFY(CachedSampler.Type == CachedResourceType::Unknown, "Unexpected cached sampler type"); if (!CachedSampler.pObject || CachedSampler.CPUDescriptorHandle.ptr == 0) { - LOG_ERROR_MESSAGE("No sampler is assigned to texture variable '", res.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); + LOG_ERROR_MESSAGE("No sampler is assigned to texture variable '", res.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); BindingsOK = false; } @@ -965,16 +1101,16 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12 const auto& sam = GetSampler(VarType, s); VERIFY(sam.GetVariableType() == VarType, "Unexpected sampler variable type"); - for (Uint32 ArrInd = 0; ArrInd < sam.Attribs.BindCount; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < sam.BindCount; ++ArrInd) { - const auto& CachedSampler = ResourceCache.GetRootTable(sam.RootIndex).GetResource(sam.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + const auto& CachedSampler = ResourceCache.GetRootTable(sam.RootIndex).GetResource(sam.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, GetShaderType()); if (CachedSampler.pObject) VERIFY(CachedSampler.Type == CachedResourceType::Sampler, "Incorrect cached sampler type"); else VERIFY(CachedSampler.Type == CachedResourceType::Unknown, "Unexpected cached sampler type"); if (!CachedSampler.pObject || CachedSampler.CPUDescriptorHandle.ptr == 0) { - LOG_ERROR_MESSAGE("No sampler is bound to sampler variable '", sam.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); + LOG_ERROR_MESSAGE("No sampler is bound to sampler variable '", sam.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); BindingsOK = false; } } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp index 26f889e5..093a5480 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourcesD3D12.cpp @@ -106,12 +106,13 @@ ShaderResourcesD3D12::ShaderResourcesD3D12(ID3DBlob* pShaderBytecode, { public: // clang-format off - void OnNewCB (const D3DShaderResourceAttribs& CBAttribs) {} - void OnNewTexUAV (const D3DShaderResourceAttribs& TexUAV) {} - void OnNewBuffUAV(const D3DShaderResourceAttribs& BuffUAV) {} - void OnNewBuffSRV(const D3DShaderResourceAttribs& BuffSRV) {} - void OnNewSampler(const D3DShaderResourceAttribs& SamplerAttribs){} - void OnNewTexSRV (const D3DShaderResourceAttribs& TexAttribs) {} + void OnNewCB (const D3DShaderResourceAttribs& CBAttribs) {} + void OnNewTexUAV (const D3DShaderResourceAttribs& TexUAV) {} + void OnNewBuffUAV (const D3DShaderResourceAttribs& BuffUAV) {} + void OnNewBuffSRV (const D3DShaderResourceAttribs& BuffSRV) {} + void OnNewSampler (const D3DShaderResourceAttribs& SamplerAttribs){} + void OnNewTexSRV (const D3DShaderResourceAttribs& TexAttribs) {} + void OnNewAccelStruct(const D3DShaderResourceAttribs& ASAttribs) {} // clang-format on }; diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp index fd58eacf..1c3afa53 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp @@ -125,7 +125,7 @@ ShaderVariableD3D12Impl* ShaderVariableManagerD3D12::GetVariable(const Char* Nam for (Uint32 v = 0; v < m_NumVariables; ++v) { auto& Var = m_pVariables[v]; - if (strcmp(Var.m_Resource.Attribs.Name, Name) == 0) + if (strcmp(Var.m_Resource.Name, Name) == 0) { pVar = &Var; break; @@ -181,14 +181,14 @@ void ShaderVariableManagerD3D12::BindResources(IResourceMapping* pResourceMappin if ((Flags & (1 << Res.GetVariableType())) == 0) continue; - for (Uint32 ArrInd = 0; ArrInd < Res.Attribs.BindCount; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < Res.BindCount; ++ArrInd) { if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache)) continue; RefCntAutoPtr pObj; VERIFY_EXPR(pResourceMapping != nullptr); - pResourceMapping->GetResource(Res.Attribs.Name, &pObj, ArrInd); + pResourceMapping->GetResource(Res.Name, &pObj, ArrInd); if (pObj) { // Call non-virtual function @@ -197,7 +197,7 @@ void ShaderVariableManagerD3D12::BindResources(IResourceMapping* pResourceMappin else { if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache)) - LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.Attribs.GetPrintName(ArrInd), "': resource is not found in the resource mapping"); + LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.GetPrintName(ArrInd), "': resource is not found in the resource mapping"); } } } diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp index f63aa8ad..b12ef6ae 100644 --- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.hpp @@ -42,12 +42,13 @@ namespace Diligent struct D3DShaderResourceCounters { - Uint32 NumCBs = 0; - Uint32 NumTexSRVs = 0; - Uint32 NumTexUAVs = 0; - Uint32 NumBufSRVs = 0; - Uint32 NumBufUAVs = 0; - Uint32 NumSamplers = 0; + Uint32 NumCBs = 0; + Uint32 NumTexSRVs = 0; + Uint32 NumTexUAVs = 0; + Uint32 NumBufSRVs = 0; + Uint32 NumBufUAVs = 0; + Uint32 NumSamplers = 0; + Uint32 NumAccelStructs = 0; }; template + typename TOnNewTexSRV, + typename TOnNewAccelStruct> void LoadD3DShaderResources(TShaderReflection* pShaderReflection, THandleShaderDesc HandleShaderDesc, TOnResourcesCounted OnResourcesCounted, @@ -70,7 +72,8 @@ void LoadD3DShaderResources(TShaderReflection* pShaderReflection, TOnNewBuffUAV OnNewBuffUAV, TOnNewBuffSRV OnNewBuffSRV, TOnNewSampler OnNewSampler, - TOnNewTexSRV OnNewTexSRV) + TOnNewTexSRV OnNewTexSRV, + TOnNewAccelStruct OnNewAccelStruct) { D3D_SHADER_DESC shaderDesc = {}; pShaderReflection->GetDesc(&shaderDesc); @@ -173,6 +176,7 @@ void LoadD3DShaderResources(TShaderReflection* pShaderReflection, case D3D_SIT_UAV_APPEND_STRUCTURED: UNSUPPORTED( "Append structured buffers are not supported" ); break; case D3D_SIT_UAV_CONSUME_STRUCTURED: UNSUPPORTED( "Consume structured buffers are not supported" ); break; case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: UNSUPPORTED( "RW structured buffers with counter are not supported" ); break; + case D3D_SIT_RTACCELERATIONSTRUCTURE: ++RC.NumAccelStructs; break; // clang-format on default: UNEXPECTED("Unexpected resource type"); } @@ -284,6 +288,12 @@ void LoadD3DShaderResources(TShaderReflection* pShaderReflection, break; } + case D3D_SIT_RTACCELERATIONSTRUCTURE: + { + OnNewAccelStruct(Res); + break; + } + default: { UNEXPECTED("Unexpected resource input type"); diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp index efbff703..cc24414e 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -280,20 +280,22 @@ public: ~ShaderResources(); // clang-format off - Uint32 GetNumCBs() const noexcept { return (m_TexSRVOffset - 0); } - Uint32 GetNumTexSRV() const noexcept { return (m_TexUAVOffset - m_TexSRVOffset); } - Uint32 GetNumTexUAV() const noexcept { return (m_BufSRVOffset - m_TexUAVOffset); } - Uint32 GetNumBufSRV() const noexcept { return (m_BufUAVOffset - m_BufSRVOffset); } - Uint32 GetNumBufUAV() const noexcept { return (m_SamplersOffset - m_BufUAVOffset); } - Uint32 GetNumSamplers() const noexcept { return (m_TotalResources - m_SamplersOffset); } - Uint32 GetTotalResources()const noexcept { return m_TotalResources; } - - const D3DShaderResourceAttribs& GetCB (Uint32 n)const noexcept { return GetResAttribs(n, GetNumCBs(), 0); } - const D3DShaderResourceAttribs& GetTexSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } - const D3DShaderResourceAttribs& GetTexUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } - const D3DShaderResourceAttribs& GetBufSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } - const D3DShaderResourceAttribs& GetBufUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } - const D3DShaderResourceAttribs& GetSampler(Uint32 n)const noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } + Uint32 GetNumCBs() const noexcept { return (m_TexSRVOffset - 0); } + Uint32 GetNumTexSRV() const noexcept { return (m_TexUAVOffset - m_TexSRVOffset); } + Uint32 GetNumTexUAV() const noexcept { return (m_BufSRVOffset - m_TexUAVOffset); } + Uint32 GetNumBufSRV() const noexcept { return (m_BufUAVOffset - m_BufSRVOffset); } + Uint32 GetNumBufUAV() const noexcept { return (m_SamplersOffset - m_BufUAVOffset); } + Uint32 GetNumSamplers() const noexcept { return (m_AccelStructsOffset - m_SamplersOffset); } + Uint32 GetNumAccelStructs()const noexcept { return (m_TotalResources - m_AccelStructsOffset); } + Uint32 GetTotalResources() const noexcept { return m_TotalResources; } + + const D3DShaderResourceAttribs& GetCB (Uint32 n)const noexcept { return GetResAttribs(n, GetNumCBs(), 0); } + const D3DShaderResourceAttribs& GetTexSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } + const D3DShaderResourceAttribs& GetTexUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } + const D3DShaderResourceAttribs& GetBufSRV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } + const D3DShaderResourceAttribs& GetBufUAV (Uint32 n)const noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } + const D3DShaderResourceAttribs& GetSampler (Uint32 n)const noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } + const D3DShaderResourceAttribs& GetAccelStruct(Uint32 n)const noexcept { return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructsOffset); } // clang-format on const D3DShaderResourceAttribs& GetCombinedSampler(const D3DShaderResourceAttribs& TexSRV) const noexcept @@ -317,13 +319,15 @@ public: typename THandleTexSRV, typename THandleTexUAV, typename THandleBufSRV, - typename THandleBufUAV> - void ProcessResources(THandleCB HandleCB, - THandleSampler HandleSampler, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV) const + typename THandleBufUAV, + typename THandleAccelStruct> + void ProcessResources(THandleCB HandleCB, + THandleSampler HandleSampler, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV, + THandleAccelStruct HandleAccelStruct) const { for (Uint32 n = 0; n < GetNumCBs(); ++n) { @@ -360,6 +364,12 @@ public: const auto& BufUAV = GetBufUAV(n); HandleBufUAV(BufUAV, n); } + + for (Uint32 n = 0; n < GetNumAccelStructs(); ++n) + { + const auto& AS = GetAccelStruct(n); + HandleAccelStruct(AS, n); + } } bool IsCompatibleWith(const ShaderResources& Resources) const; @@ -420,12 +430,13 @@ protected: } // clang-format off - D3DShaderResourceAttribs& GetCB(Uint32 n) noexcept { return GetResAttribs(n, GetNumCBs(), 0); } - D3DShaderResourceAttribs& GetTexSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } - D3DShaderResourceAttribs& GetTexUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } - D3DShaderResourceAttribs& GetBufSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } - D3DShaderResourceAttribs& GetBufUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } - D3DShaderResourceAttribs& GetSampler(Uint32 n) noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } + D3DShaderResourceAttribs& GetCB(Uint32 n) noexcept { return GetResAttribs(n, GetNumCBs(), 0); } + D3DShaderResourceAttribs& GetTexSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexSRV(), m_TexSRVOffset); } + D3DShaderResourceAttribs& GetTexUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumTexUAV(), m_TexUAVOffset); } + D3DShaderResourceAttribs& GetBufSRV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufSRV(), m_BufSRVOffset); } + D3DShaderResourceAttribs& GetBufUAV(Uint32 n) noexcept { return GetResAttribs(n, GetNumBufUAV(), m_BufUAVOffset); } + D3DShaderResourceAttribs& GetSampler(Uint32 n) noexcept { return GetResAttribs(n, GetNumSamplers(), m_SamplersOffset); } + D3DShaderResourceAttribs& GetAccelStruct(Uint32 n)noexcept { return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructsOffset); } // clang-format on private: @@ -447,12 +458,13 @@ private: // Offsets in elements of D3DShaderResourceAttribs typedef Uint16 OffsetType; - OffsetType m_TexSRVOffset = 0; - OffsetType m_TexUAVOffset = 0; - OffsetType m_BufSRVOffset = 0; - OffsetType m_BufUAVOffset = 0; - OffsetType m_SamplersOffset = 0; - OffsetType m_TotalResources = 0; + OffsetType m_TexSRVOffset = 0; + OffsetType m_TexUAVOffset = 0; + OffsetType m_BufSRVOffset = 0; + OffsetType m_BufUAVOffset = 0; + OffsetType m_SamplersOffset = 0; + OffsetType m_AccelStructsOffset = 0; + OffsetType m_TotalResources = 0; const SHADER_TYPE m_ShaderType; @@ -469,7 +481,7 @@ void ShaderResources::Initialize(TShaderReflection* pShaderReflection, const Char* ShaderName, const Char* CombinedSamplerSuffix) { - Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0; + Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0, CurrAS = 0; // Resource names pool is only needed to facilitate string allocation. StringPool ResourceNamesPool; @@ -541,6 +553,13 @@ void ShaderResources::Initialize(TShaderReflection* pShaderReflection, } ++CurrTexSRV; NewResHandler.OnNewTexSRV(*pNewTexSRV); + }, + + [&](const D3DShaderResourceAttribs& AccelStructAttribs) // + { + VERIFY_EXPR(AccelStructAttribs.GetInputType() == D3D_SIT_RTACCELERATIONSTRUCTURE); + auto* pNewAccelStruct = new (&GetAccelStruct(CurrAS++)) D3DShaderResourceAttribs{ResourceNamesPool, AccelStructAttribs}; + NewResHandler.OnNewAccelStruct(*pNewAccelStruct); } // ); @@ -562,12 +581,13 @@ void ShaderResources::Initialize(TShaderReflection* pShaderReflection, VERIFY_EXPR(ResourceNamesPool.GetRemainingSize() == 0); // clang-format off - VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called"); - VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); - VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called"); + VERIFY(CurrTexSRV == GetNumTexSRV(), "Not all Tex SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrTexUAV == GetNumTexUAV(), "Not all Tex UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrBufSRV == GetNumBufSRV(), "Not all Buf SRVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrBufUAV == GetNumBufUAV(), "Not all Buf UAVs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrSampler == GetNumSamplers(), "Not all Samplers are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); + VERIFY(CurrAS == GetNumAccelStructs(), "Not all Accel Structs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called" ); // clang-format on } diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp index 2497b17d..78525f30 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp @@ -87,8 +87,8 @@ protected: }; -template -bool VerifyBufferViewModeD3D(BufferViewImplType* pViewD3D11, const D3DShaderResourceAttribs& Attribs, const char* ShaderName) +template +bool VerifyBufferViewModeD3D(BufferViewImplType* pViewD3D11, const AttribsType& Attribs, const char* ShaderName) { if (pViewD3D11 == nullptr) return true; diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index b975b506..79d2cb22 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -74,23 +74,25 @@ void ShaderResources::AllocateMemory(IMemoryAllocator& Allocator, }; // clang-format off - auto CBOffset = AdvanceOffset(ResCounters.NumCBs); (void)CBOffset; // To suppress warning - m_TexSRVOffset = AdvanceOffset(ResCounters.NumTexSRVs); - m_TexUAVOffset = AdvanceOffset(ResCounters.NumTexUAVs); - m_BufSRVOffset = AdvanceOffset(ResCounters.NumBufSRVs); - m_BufUAVOffset = AdvanceOffset(ResCounters.NumBufUAVs); - m_SamplersOffset = AdvanceOffset(ResCounters.NumSamplers); - m_TotalResources = AdvanceOffset(0); + auto CBOffset = AdvanceOffset(ResCounters.NumCBs); (void)CBOffset; // To suppress warning + m_TexSRVOffset = AdvanceOffset(ResCounters.NumTexSRVs); + m_TexUAVOffset = AdvanceOffset(ResCounters.NumTexUAVs); + m_BufSRVOffset = AdvanceOffset(ResCounters.NumBufSRVs); + m_BufUAVOffset = AdvanceOffset(ResCounters.NumBufUAVs); + m_SamplersOffset = AdvanceOffset(ResCounters.NumSamplers); + m_AccelStructsOffset = AdvanceOffset(ResCounters.NumAccelStructs); + m_TotalResources = AdvanceOffset(0); auto AlignedResourceNamesPoolSize = Align(ResourceNamesPoolSize, sizeof(void*)); auto MemorySize = m_TotalResources * sizeof(D3DShaderResourceAttribs) + AlignedResourceNamesPoolSize * sizeof(char); - VERIFY_EXPR(GetNumCBs() == ResCounters.NumCBs); - VERIFY_EXPR(GetNumTexSRV() == ResCounters.NumTexSRVs); - VERIFY_EXPR(GetNumTexUAV() == ResCounters.NumTexUAVs); - VERIFY_EXPR(GetNumBufSRV() == ResCounters.NumBufSRVs); - VERIFY_EXPR(GetNumBufUAV() == ResCounters.NumBufUAVs); - VERIFY_EXPR(GetNumSamplers()== ResCounters.NumSamplers); + VERIFY_EXPR(GetNumCBs() == ResCounters.NumCBs); + VERIFY_EXPR(GetNumTexSRV() == ResCounters.NumTexSRVs); + VERIFY_EXPR(GetNumTexUAV() == ResCounters.NumTexUAVs); + VERIFY_EXPR(GetNumBufSRV() == ResCounters.NumBufSRVs); + VERIFY_EXPR(GetNumBufUAV() == ResCounters.NumBufUAVs); + VERIFY_EXPR(GetNumSamplers() == ResCounters.NumSamplers); + VERIFY_EXPR(GetNumAccelStructs()== ResCounters.NumAccelStructs); // clang-format on if (MemorySize) @@ -208,6 +210,12 @@ D3DShaderResourceCounters ShaderResources::CountResources(const PipelineResource auto VarType = FindVariableType(BufUAV, ResourceLayout); if (IsAllowedType(VarType, AllowedTypeBits)) ++Counters.NumBufUAVs; + }, + [&](const D3DShaderResourceAttribs& AccelStruct, Uint32) // + { + auto VarType = FindVariableType(AccelStruct, ResourceLayout); + if (IsAllowedType(VarType, AllowedTypeBits)) + ++Counters.NumAccelStructs; } // ); @@ -400,6 +408,11 @@ bool ShaderResources::IsCompatibleWith(const ShaderResources& Res) const { if (!BufUAV.IsCompatibleWith(Res.GetBufUAV(n))) IsCompatible = false; + }, + [&](const D3DShaderResourceAttribs& AccelStruct, Uint32 n) // + { + if (!AccelStruct.IsCompatibleWith(Res.GetAccelStruct(n))) + IsCompatible = false; } // ); return IsCompatible; diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp index 3c34b483..23c0fc9c 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp @@ -94,6 +94,10 @@ public: virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateRayTracingPipelineState() in OpenGL backend. + virtual void DILIGENT_CALL_TYPE CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; + void CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 8b429094..b911cdde 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -154,6 +154,8 @@ PipelineStateGLImpl::~PipelineStateGLImpl() void PipelineStateGLImpl::Destruct() { + TPipelineStateBase::Destruct(); + auto& RawAllocator = GetRawAllocator(); m_StaticResourceCache.Destroy(RawAllocator); GetDevice()->OnDestroyPSO(this); diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index ca75a9ca..7707f979 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -736,6 +736,12 @@ void RenderDeviceGLImpl::CreateComputePipelineState(const ComputePipelineStateCr return CreateComputePipelineState(PSOCreateInfo, ppPipelineState, false); } +void RenderDeviceGLImpl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + UNSUPPORTED("CreateRayTracingPipelineState is not supported in OpenGL"); + *ppPipelineState = nullptr; +} + void RenderDeviceGLImpl::CreateFence(const FenceDesc& Desc, IFence** ppFence) { CreateDeviceObject( diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp index 73fced1f..8a0fab15 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp @@ -48,7 +48,7 @@ class ShaderResourceCacheVk; class PipelineLayout { public: - static VkDescriptorType GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res); + static VkDescriptorType GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type); PipelineLayout(); void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask); @@ -69,8 +69,7 @@ public: SHADER_TYPE ShaderType, Uint32& DescriptorSet, Uint32& Binding, - Uint32& OffsetInCache, - std::vector& SPIRV); + Uint32& OffsetInCache); Uint32 GetTotalDescriptors(SHADER_RESOURCE_VARIABLE_TYPE VarType) const { @@ -137,7 +136,6 @@ public: // set by the same Vulkan command. If there are no dynamic descriptors, this // function also binds descriptor sets rightaway. void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, - bool IsCompute, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index d4f2fc36..a02c8d74 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -59,6 +59,7 @@ public: PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo); PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const ComputePipelineStateCreateInfo& CreateInfo); + PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const RayTracingPipelineStateCreateInfo& CreateInfo); ~PipelineStateVkImpl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; @@ -168,7 +169,7 @@ private: // Resource layout index in m_ShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index d85e9ff3..9ceed3e4 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -78,6 +78,9 @@ public: /// Implementation of IRenderDevice::CreateComputePipelineState() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateRayTracingPipelineState() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateBuffer() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 00f2c33a..68401f52 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -83,7 +83,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; bool m_bStaticResourcesInitialized = false; Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp index 7d77ff48..0bcf79a0 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp @@ -112,12 +112,13 @@ public: /*1-7*/ // Unused /* 8 */ RefCntAutoPtr pObject; - VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const; - VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const; - VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler)const; - VkBufferView GetBufferViewWriteInfo () const; - VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const; - VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const; + VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const; + VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const; + VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler) const; + VkBufferView GetBufferViewWriteInfo () const; + VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const; + VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const; + VkWriteDescriptorSetAccelerationStructureKHR GetAccelerationStructureWriteInfo() const; // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 9452a390..e5cddb0c 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -113,18 +113,21 @@ namespace Diligent class ShaderVkImpl; /// Diligent::ShaderResourceLayoutVk class -// sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64) +// sizeof(ShaderResourceLayoutVk)==72 (MS compiler, x64) class ShaderResourceLayoutVk { public: struct ShaderStageInfo { - ShaderStageInfo(SHADER_TYPE _Type, - const ShaderVkImpl* _pShader); + ShaderStageInfo() {} + ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader); - const SHADER_TYPE Type; - const ShaderVkImpl* const pShader; - std::vector SPIRV; + void Append(const ShaderVkImpl* pShader); + size_t Count() const; + + SHADER_TYPE Type = SHADER_TYPE_UNKNOWN; + std::vector Shaders; + std::vector> SPIRVs; }; using TShaderStages = std::vector; @@ -144,10 +147,10 @@ public: // This method is called by PipelineStateVkImpl class instance to initialize static // shader resource layout and the cache - void InitializeStaticResourceLayout(const ShaderVkImpl* pShader, - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderResourceCacheVk& StaticResourceCache); + void InitializeStaticResourceLayout(const std::vector& Shaders, + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderResourceCacheVk& StaticResourceCache); // This method is called by PipelineStateVkImpl class instance to initialize resource // layouts for all shader stages in the pipeline. @@ -160,7 +163,7 @@ public: bool VerifyVariables, bool VerifyImmutableSamplers); - // sizeof(VkResource) == 24 (x64) + // sizeof(VkResource) == 32 (x64) struct VkResource { // clang-format off @@ -178,40 +181,56 @@ public: static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1; + using ResourceType = SPIRVShaderResourceAttribs::ResourceType; + /* 0 */ const Uint16 Binding; -/* 2 */ const Uint16 DescriptorSet; +/* 2 */ const Uint16 ArraySize; /* 4.0 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set /* 6.5 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler // assigned to separate image /* 7.5 */ const Uint32 VariableType : VariableTypeBits; /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits; +/* 8 */ const Uint8 DescriptorSet; + +/* 9 */ const ResourceType Type; +/* 10.0*/ const Uint8 ResourceDim : 7; +/* 10.7*/ const Uint8 IsMS : 1; +/* 16 */ const char* const Name; +/* 24 */ const ShaderResourceLayoutVk& ParentResLayout; + // clang-format on -/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs; -/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; - - VkResource(const ShaderResourceLayoutVk& _ParentLayout, - const SPIRVShaderResourceAttribs& _SpirvAttribs, - SHADER_RESOURCE_VARIABLE_TYPE _VariableType, - uint32_t _Binding, - uint32_t _DescriptorSet, - Uint32 _CacheOffset, - Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned = false)noexcept : + VkResource(const ShaderResourceLayoutVk& _ParentLayout, + const char* _Name, + Uint16 _ArraySize, + ResourceType _Type, + Uint8 _ResourceDim, + Uint8 _IsMS, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, + uint32_t _Binding, + uint32_t _DescriptorSet, + Uint32 _CacheOffset, + Uint32 _SamplerInd, + bool _ImmutableSamplerAssigned = false) noexcept : + // clang-format off Binding {static_cast(_Binding) }, DescriptorSet {static_cast(_DescriptorSet)}, CacheOffset {_CacheOffset }, SamplerInd {_SamplerInd }, VariableType {_VariableType }, ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, - SpirvAttribs {_SpirvAttribs }, + Name {_Name }, + ArraySize {_ArraySize }, + Type {_Type }, + ResourceDim {_ResourceDim }, + IsMS {_IsMS }, ParentResLayout {_ParentLayout } + // clang-format on { - VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); - VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); - VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max() ); + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits)); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits)); + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max()); VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); } - // clang-format on // Checks if a resource is bound in ResourceCache at the given ArrayIndex bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const; @@ -220,17 +239,18 @@ public: void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const; // Updates resource descriptor in the descriptor set - inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, - uint32_t ArrayElement, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) const; + inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, + uint32_t ArrayElement, + const VkDescriptorImageInfo* pImageInfo, + const VkDescriptorBufferInfo* pBufferInfo, + const VkBufferView* pTexelBufferView, + const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const; bool IsImmutableSamplerAssigned() const { VERIFY(ImmutableSamplerAssigned == 0 || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, + Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Immutable sampler can only be assigned to a sampled image or separate sampler"); return ImmutableSamplerAssigned != 0; } @@ -240,6 +260,31 @@ public: return static_cast(VariableType); } + String GetPrintName(Uint32 ArrayInd) const + { + VERIFY_EXPR(ArrayInd < ArraySize); + if (ArraySize > 1) + { + std::stringstream ss; + ss << Name << '[' << ArrayInd << ']'; + return ss.str(); + } + else + return Name; + } + + ShaderResourceDesc GetResourceDesc() const; + + RESOURCE_DIMENSION GetResourceDimension() const + { + return static_cast(ResourceDim); + } + + bool IsMultisample() const + { + return IsMS != 0; + } + private: void CacheUniformBuffer(IDeviceObject* pBuffer, ShaderResourceCacheVk::Resource& DstRes, @@ -276,6 +321,11 @@ public: VkDescriptorSet vkDescrSet, Uint32 ArrayInd) const; + void CacheAccelerationStructure(IDeviceObject* pTLAS, + ShaderResourceCacheVk::Resource& DstRes, + VkDescriptorSet vkDescrSet, + Uint32 ArrayInd) const; + template bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes, RefCntAutoPtr&& pObject, @@ -310,15 +360,10 @@ public: const Char* GetShaderName() const { - return m_pResources->GetShaderName(); + return ""; // AZ TODO } - SHADER_TYPE GetShaderType() const - { - return m_pResources->GetShaderType(); - } - - const SPIRVShaderResources& GetResources() const { return *m_pResources; } + SHADER_TYPE GetShaderType() const { return m_ShaderType; } const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const { @@ -327,7 +372,7 @@ public: return Resources[GetResourceOffset(VarType, r)]; } - bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedSamplers(); } + bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; } private: Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const @@ -358,12 +403,14 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } - void AllocateMemory(const ShaderVkImpl* pShader, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool AllocateImmutableSamplers); + using ResourceNameToIndex_t = std::unordered_map; + void AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers); using ImmutableSamplerPtrType = RefCntAutoPtr; ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept @@ -374,16 +421,17 @@ private: } // clang-format off -/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; -/* 8 */ std::unique_ptr > m_ResourceBuffer; +/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; +/* 8 */ std::unique_ptr > m_ResourceBuffer; // AZ TODO: use linear allocator +/*24 */ StringPool m_StringPool; + +/*48 */ std::array m_NumResources = {}; - // We must use shared_ptr to reference ShaderResources instance, because - // there may be multiple objects referencing the same set of resources -/*24 */ std::shared_ptr m_pResources; +/*56 */ Uint32 m_NumImmutableSamplers = 0; +/*60 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; +/*64 */ bool m_IsUsingSeparateSamplers = false; -/*40 */ std::array m_NumResources = {}; -/*48 */ Uint32 m_NumImmutableSamplers = 0; -/*56*/ // End of class +/*72 */ // End of class // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp index 27689c1e..6c88bf56 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp @@ -183,14 +183,14 @@ public: Uint32 FirstElement, Uint32 NumElements) override final { - VerifyAndCorrectSetArrayArguments(m_Resource.SpirvAttribs.Name, m_Resource.SpirvAttribs.ArraySize, FirstElement, NumElements); + VerifyAndCorrectSetArrayArguments(m_Resource.Name, m_Resource.ArraySize, FirstElement, NumElements); for (Uint32 Elem = 0; Elem < NumElements; ++Elem) m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache); } virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final { - ResourceDesc = m_Resource.SpirvAttribs.GetResourceDesc(); + ResourceDesc = m_Resource.GetResourceDesc(); } virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp index f5b921a6..c28be56c 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp @@ -44,7 +44,8 @@ public: VulkanInstance& operator = ( VulkanInstance&&) = delete; // clang-format on - static std::shared_ptr Create(bool EnableValidation, + static std::shared_ptr Create(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator); @@ -69,10 +70,12 @@ public: VkAllocationCallbacks* GetVkAllocator()const{return m_pVkAllocator;} VkInstance GetVkInstance() const{return m_VkInstance; } + uint32_t GetVkVersion() const{return m_VkVersion; } // clang-format on private: - VulkanInstance(bool EnableValidation, + VulkanInstance(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator); @@ -80,6 +83,7 @@ private: bool m_DebugUtilsEnabled = false; VkAllocationCallbacks* const m_pVkAllocator; VkInstance m_VkInstance = VK_NULL_HANDLE; + uint32_t m_VkVersion = VK_API_VERSION_1_0; std::vector m_Layers; std::vector m_Extensions; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp index a8366551..5e60a343 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp @@ -88,8 +88,11 @@ using AccelStructWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(AccelerationStru class VulkanLogicalDevice : public std::enable_shared_from_this { public: + using ExtensionFeatures = VulkanPhysicalDevice::ExtensionFeatures; + static std::shared_ptr Create(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator); // clang-format off @@ -131,8 +134,9 @@ public: RenderPassWrapper CreateRenderPass (const VkRenderPassCreateInfo& RenderPassCI,const char* DebugName = "") const; DeviceMemoryWrapper AllocateDeviceMemory(const VkMemoryAllocateInfo & AllocInfo, const char* DebugName = "") const; - PipelineWrapper CreateComputePipeline (const VkComputePipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; - PipelineWrapper CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; + PipelineWrapper CreateComputePipeline (const VkComputePipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; + PipelineWrapper CreateGraphicsPipeline (const VkGraphicsPipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; + PipelineWrapper CreateRayTracingPipeline(const VkRayTracingPipelineCreateInfoKHR& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const; ShaderModuleWrapper CreateShaderModule (const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName = "") const; PipelineLayoutWrapper CreatePipelineLayout (const VkPipelineLayoutCreateInfo& LayoutCI, const char* DebugName = "") const; @@ -216,12 +220,15 @@ public: } VkPipelineStageFlags GetEnabledGraphicsShaderStages() const { return m_EnabledGraphicsShaderStages; } + VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const; const VkPhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; } + const ExtensionFeatures& GetEnabledExtFeatures() const { return m_EnabledExtFeatures; } private: VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator); template GetPhysicalDevice(); - const auto& MeshShaderFeats = PhysicalDevice.GetExtFeatures().MeshShader; + const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); + const auto& MeshShaderFeats = LogicalDevice.GetEnabledExtFeatures().MeshShader; VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount); } @@ -612,7 +618,7 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib #ifdef DILIGENT_DEBUG { - const auto& MeshShaderFeats = m_pDevice->GetPhysicalDevice().GetExtFeatures().MeshShader; + const auto& MeshShaderFeats = m_pDevice->GetLogicalDevice().GetEnabledExtFeatures().MeshShader; VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index d37655a5..fcb64973 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -138,6 +138,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E try { auto Instance = VulkanUtilities::VulkanInstance::Create( + VK_API_VERSION_1_2, // AZ TODO: use 1.2 only for ray tracing, wave ops extensions EngineCI.EnableValidation, EngineCI.GlobalExtensionCount, EngineCI.ppGlobalExtensionNames, @@ -238,7 +239,11 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height }; - const auto& DeviceExtFeatures = PhysicalDevice->GetExtFeatures(); + const VulkanUtilities::VulkanPhysicalDevice::ExtensionFeatures& DeviceExtFeatures = PhysicalDevice->GetExtFeatures(); + VulkanUtilities::VulkanPhysicalDevice::ExtensionFeatures EnabledExtFeats = {}; + + // SPIRV 1.5 is in Vulkan 1.2 core + EnabledExtFeats.Spirv15 = DeviceExtFeatures.Spirv15; #define ENABLE_FEATURE(IsFeatureSupported, Feature, FeatureName) \ do \ @@ -247,33 +252,25 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E GetFeatureState(EngineCI.Features.Feature, IsFeatureSupported, FeatureName); \ } while (false) + ENABLE_FEATURE(DeviceExtFeatures.MeshShader.taskShader != VK_FALSE && DeviceExtFeatures.MeshShader.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); - auto MeshShaderFeats = DeviceExtFeatures.MeshShader; - ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); - - auto ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; // clang-format off - ENABLE_FEATURE(ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); - ENABLE_FEATURE(ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); + ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); + ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); // clang-format on - auto Storage16BitFeats = DeviceExtFeatures.Storage16Bit; // clang-format off - ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); - ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); - ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); + ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); // clang-format on - auto Storage8BitFeats = DeviceExtFeatures.Storage8Bit; // clang-format off - ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); - ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); + ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); // clang-format on - auto RayTracingFeats = DeviceExtFeatures.RayTracing; - auto BufferDeviceAddressFeats = DeviceExtFeatures.BufferDeviceAddress; - auto DescriptorIndexingFeats = DeviceExtFeatures.DescriptorIndexing; - ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); + ENABLE_FEATURE((DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE && DeviceExtFeatures.Spirv14) || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); #undef FeatureSupport @@ -289,31 +286,33 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // Mesh shader if (EngineCI.Features.MeshShaders != DEVICE_FEATURE_STATE_DISABLED) { - VERIFY_EXPR(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE); + EnabledExtFeats.MeshShader = DeviceExtFeatures.MeshShader; + VERIFY_EXPR(EnabledExtFeats.MeshShader.taskShader != VK_FALSE && EnabledExtFeats.MeshShader.meshShader != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME), "VK_NV_mesh_shader extension must be supported as it has already been checked by VulkanPhysicalDevice and " "both taskShader and meshShader features are TRUE"); DeviceExtensions.push_back(VK_NV_MESH_SHADER_EXTENSION_NAME); - *NextExt = &MeshShaderFeats; - NextExt = &MeshShaderFeats.pNext; + *NextExt = &EnabledExtFeats.MeshShader; + NextExt = &EnabledExtFeats.MeshShader.pNext; } if (EngineCI.Features.ShaderFloat16 != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.ShaderInt8 != DEVICE_FEATURE_STATE_DISABLED) { - VERIFY_EXPR(ShaderFloat16Int8.shaderFloat16 != VK_FALSE || ShaderFloat16Int8.shaderInt8 != VK_FALSE); + EnabledExtFeats.ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; + VERIFY_EXPR(EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 != VK_FALSE || EnabledExtFeats.ShaderFloat16Int8.shaderInt8 != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME), "VK_KHR_shader_float16_int8 extension must be supported as it has already been checked by VulkanPhysicalDevice " "and at least one of shaderFloat16 or shaderInt8 features is TRUE"); DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); if (EngineCI.Features.ShaderFloat16 == DEVICE_FEATURE_STATE_DISABLED) - ShaderFloat16Int8.shaderFloat16 = VK_FALSE; + EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 = VK_FALSE; if (EngineCI.Features.ShaderInt8 == DEVICE_FEATURE_STATE_DISABLED) - ShaderFloat16Int8.shaderInt8 = VK_FALSE; + EnabledExtFeats.ShaderFloat16Int8.shaderInt8 = VK_FALSE; - *NextExt = &ShaderFloat16Int8; - NextExt = &ShaderFloat16Int8.pNext; + *NextExt = &EnabledExtFeats.ShaderFloat16Int8; + NextExt = &EnabledExtFeats.ShaderFloat16Int8.pNext; } bool StorageBufferStorageClassExtensionRequired = false; @@ -325,9 +324,10 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE); - VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE); - VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.storageInputOutput16 != VK_FALSE); + EnabledExtFeats.Storage16Bit = DeviceExtFeatures.Storage16Bit; + VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess != VK_FALSE); + VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE); + VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageInputOutput16 != VK_FALSE); // clang-format on VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_16BIT_STORAGE_EXTENSION_NAME), @@ -344,14 +344,14 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E StorageBufferStorageClassExtensionRequired = true; if (EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage16BitFeats.storageBuffer16BitAccess = VK_FALSE; + EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess = VK_FALSE; if (EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage16BitFeats.uniformAndStorageBuffer16BitAccess = VK_FALSE; + EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess = VK_FALSE; if (EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED) - Storage16BitFeats.storageInputOutput16 = VK_FALSE; + EnabledExtFeats.Storage16Bit.storageInputOutput16 = VK_FALSE; - *NextExt = &Storage16BitFeats; - NextExt = &Storage16BitFeats.pNext; + *NextExt = &EnabledExtFeats.Storage16Bit; + NextExt = &EnabledExtFeats.Storage16Bit.pNext; } // clang-format off @@ -360,8 +360,9 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE); - VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE); + EnabledExtFeats.Storage8Bit = DeviceExtFeatures.Storage8Bit; + VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess != VK_FALSE); + VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE); // clang-format on VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_8BIT_STORAGE_EXTENSION_NAME), @@ -378,12 +379,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E StorageBufferStorageClassExtensionRequired = true; if (EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage8BitFeats.storageBuffer8BitAccess = VK_FALSE; + EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess = VK_FALSE; if (EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED) - Storage8BitFeats.uniformAndStorageBuffer8BitAccess = VK_FALSE; + EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess = VK_FALSE; - *NextExt = &Storage8BitFeats; - NextExt = &Storage8BitFeats.pNext; + *NextExt = &EnabledExtFeats.Storage8Bit; + NextExt = &EnabledExtFeats.Storage8Bit.pNext; } if (StorageBufferStorageClassExtensionRequired) @@ -398,29 +399,37 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E { if (DeviceExtFeatures.RayTracingNV) { + EnabledExtFeats.RayTracingNV = DeviceExtFeatures.RayTracingNV; DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME); } - else if (RayTracingFeats.rayTracing != VK_FALSE) - { - // required extensions - DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); - DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); - DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); - - *NextExt = &RayTracingFeats; - NextExt = &RayTracingFeats.pNext; - *NextExt = &DescriptorIndexingFeats; - NextExt = &DescriptorIndexingFeats.pNext; - *NextExt = &BufferDeviceAddressFeats; - NextExt = &BufferDeviceAddressFeats.pNext; - } - else + else if (DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE) { - UNEXPECTED("Either KHR or NV extension must be enabled"); + DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing + DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); // required for VK_KHR_ray_tracing + DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); // required for VK_KHR_ray_tracing + + EnabledExtFeats.RayTracing = DeviceExtFeatures.RayTracing; + EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress; + EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing; + + if (!DeviceExtFeatures.Spirv15) + { + DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4 + DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for ray tracing shaders + EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14; + } + + *NextExt = &EnabledExtFeats.RayTracing; + NextExt = &EnabledExtFeats.RayTracing.pNext; + *NextExt = &EnabledExtFeats.DescriptorIndexing; + NextExt = &EnabledExtFeats.DescriptorIndexing.pNext; + *NextExt = &EnabledExtFeats.BufferDeviceAddress; + NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext; } } @@ -436,7 +445,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E DeviceCreateInfo.enabledExtensionCount = static_cast(DeviceExtensions.size()); auto vkAllocator = Instance->GetVkAllocator(); - auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, vkAllocator); + auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, EnabledExtFeats, vkAllocator); auto& RawMemAllocator = GetRawAllocator(); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index b221659a..d0e37670 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -45,18 +45,19 @@ class ResourceTypeToVkDescriptorType public: ResourceTypeToVkDescriptorType() { - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please add the corresponding decriptor type"); - m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; - m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER; - m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please add the corresponding decriptor type"); + m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; + m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; + m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_MAX_ENUM; // atomic counter doesn't exist in Vulkan + m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + m_Map[SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure] = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; } VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType) const @@ -68,10 +69,10 @@ private: std::array m_Map = {}; }; -VkDescriptorType PipelineLayout::GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res) +VkDescriptorType PipelineLayout::GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type) { static const ResourceTypeToVkDescriptorType ResTypeToVkDescrType; - return ResTypeToVkDescrType[Res.Type]; + return ResTypeToVkDescrType[Type]; } PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayoutManager(IMemoryAllocator& MemAllocator) : @@ -331,7 +332,7 @@ void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIR Binding = DescrSet.NumLayoutBindings; VkBinding.binding = Binding; - VkBinding.descriptorType = GetVkDescriptorType(ResAttribs); + VkBinding.descriptorType = GetVkDescriptorType(ResAttribs.Type); VkBinding.descriptorCount = ResAttribs.ArraySize; // There are no limitations on what combinations of stages can use a descriptor binding (13.2.1) VkBinding.stageFlags = ShaderTypeToVkShaderStageFlagBit(ShaderType); @@ -369,16 +370,13 @@ void PipelineLayout::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResA SHADER_TYPE ShaderType, Uint32& DescriptorSet, // Output parameter Uint32& Binding, // Output parameter - Uint32& OffsetInCache, - std::vector& SPIRV) + Uint32& OffsetInCache) { VERIFY((ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) || vkImmutableSampler == VK_NULL_HANDLE, "Immutable sampler should only be specified for combined image samplers or separate samplers"); m_LayoutMgr.AllocateResourceSlot(ResAttribs, VariableType, vkImmutableSampler, ShaderType, DescriptorSet, Binding, OffsetInCache); - SPIRV[ResAttribs.BindingDecorationOffset] = Binding; - SPIRV[ResAttribs.DescriptorSetDecorationOffset] = DescriptorSet; } void PipelineLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) @@ -435,7 +433,6 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, } void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, - bool IsCompute, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const @@ -481,7 +478,6 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkIm BindInfo.DynamicOffsetCount = TotalDynamicDescriptors; if (TotalDynamicDescriptors > BindInfo.DynamicOffsets.size()) BindInfo.DynamicOffsets.resize(TotalDynamicDescriptors); - BindInfo.BindPoint = IsCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS; BindInfo.pResourceCache = &ResourceCache; #ifdef DILIGENT_DEBUG BindInfo.pDbgPipelineLayout = this; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 83512870..c7b9e05f 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -44,98 +44,24 @@ namespace Diligent { - -RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc( - Uint32 NumRenderTargets, - const TEXTURE_FORMAT RTVFormats[], - TEXTURE_FORMAT DSVFormat, - Uint8 SampleCount, - std::array& Attachments, - std::array& AttachmentReferences, - SubpassDesc& SubpassDesc) +namespace { - VERIFY_EXPR(NumRenderTargets <= MAX_RENDER_TARGETS); - - RenderPassDesc RPDesc; - - RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets; - uint32_t AttachmentInd = 0; - AttachmentReference* pDepthAttachmentReference = nullptr; - if (DSVFormat != TEX_FORMAT_UNKNOWN) - { - auto& DepthAttachment = Attachments[AttachmentInd]; - - DepthAttachment.Format = DSVFormat; - DepthAttachment.SampleCount = SampleCount; - DepthAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area - // will be preserved. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT. - DepthAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render - // area are written to memory. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. - DepthAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_LOAD; - DepthAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_STORE; - DepthAttachment.InitialState = RESOURCE_STATE_DEPTH_WRITE; - DepthAttachment.FinalState = RESOURCE_STATE_DEPTH_WRITE; - - pDepthAttachmentReference = &AttachmentReferences[AttachmentInd]; - pDepthAttachmentReference->AttachmentIndex = AttachmentInd; - pDepthAttachmentReference->State = RESOURCE_STATE_DEPTH_WRITE; - - ++AttachmentInd; - } - - AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr; - for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd) - { - auto& ColorAttachment = Attachments[AttachmentInd]; - - ColorAttachment.Format = RTVFormats[rt]; - ColorAttachment.SampleCount = SampleCount; - ColorAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area - // will be preserved. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. - ColorAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render - // area are written to memory. For attachments with a color format, - // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. - ColorAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_DISCARD; - ColorAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_DISCARD; - ColorAttachment.InitialState = RESOURCE_STATE_RENDER_TARGET; - ColorAttachment.FinalState = RESOURCE_STATE_RENDER_TARGET; - - auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd]; - ColorAttachmentRef.AttachmentIndex = AttachmentInd; - ColorAttachmentRef.State = RESOURCE_STATE_RENDER_TARGET; - } - - RPDesc.pAttachments = Attachments.data(); - RPDesc.SubpassCount = 1; - RPDesc.pSubpasses = &SubpassDesc; - RPDesc.DependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies. - RPDesc.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing - // dependencies between pairs of subpasses, or NULL if dependencyCount is zero. - - - SubpassDesc.InputAttachmentCount = 0; - SubpassDesc.pInputAttachments = nullptr; - SubpassDesc.RenderTargetAttachmentCount = NumRenderTargets; - SubpassDesc.pRenderTargetAttachments = pColorAttachmentsReference; - SubpassDesc.pResolveAttachments = nullptr; - SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference; - SubpassDesc.PreserveAttachmentCount = 0; - SubpassDesc.pPreserveAttachments = nullptr; - - return RPDesc; -} - -static bool StripReflection(std::vector& SPIRV) +bool StripReflection(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, std::vector& SPIRV) { #if DILIGENT_NO_HLSL - return false; + return true; #else std::vector StrippedSPIRV; - spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0); + spv_target_env Target = SPV_ENV_VULKAN_1_0; + const auto& ExtFeats = LogicalDevice.GetEnabledExtFeatures(); + + if (ExtFeats.Spirv15) + Target = SPV_ENV_VULKAN_1_2; + else if (ExtFeats.Spirv14) + Target = SPV_ENV_VULKAN_1_1_SPIRV_1_4; + + spvtools::Optimizer SpirvOptimizer(Target); // Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions // removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation. SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass()); @@ -149,21 +75,25 @@ static bool StripReflection(std::vector& SPIRV) #endif } -static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, - ShaderResourceLayoutVk::TShaderStages& ShaderStages, - std::vector& vkShaderModules, - std::vector& vkPipelineShaderStages) +void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, + ShaderResourceLayoutVk::TShaderStages& ShaderStages, + std::vector& ShaderModules, + std::vector& Stages) { for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& StageInfo = ShaderStages[s]; + const auto& Shaders = ShaderStages[s].Shaders; + auto& SPIRVs = ShaderStages[s].SPIRVs; + const auto ShaderType = ShaderStages[s].Type; + + VERIFY_EXPR(Shaders.size() == SPIRVs.size()); VkPipelineShaderStageCreateInfo StageCI = {}; StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; StageCI.pNext = nullptr; StageCI.flags = 0; // reserved for future use - StageCI.stage = ShaderTypeToVkShaderStageFlagBit(StageInfo.Type); + StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType); VkShaderModuleCreateInfo ShaderModuleCI = {}; @@ -171,33 +101,39 @@ static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& ShaderModuleCI.pNext = nullptr; ShaderModuleCI.flags = 0; - // We have to strip reflection instructions to fix the follownig validation error: - // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string - // Optimizer also performs validation and may catch problems with the byte code. - if (!StripReflection(StageInfo.SPIRV)) - LOG_ERROR("Failed to strip reflection information from shader '", StageInfo.pShader->GetDesc().Name, "'. This may indicate a problem with the byte code."); + for (size_t i = 0; i < Shaders.size(); ++i) + { + auto* pShader = Shaders[i]; + auto& SPIRV = SPIRVs[i]; + + // We have to strip reflection instructions to fix the follownig validation error: + // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string + // Optimizer also performs validation and may catch problems with the byte code. + if (!StripReflection(LogicalDevice, SPIRV)) + LOG_ERROR("Failed to strip reflection information from shader '", pShader->GetDesc().Name, "'. This may indicate a problem with the byte code."); - ShaderModuleCI.codeSize = StageInfo.SPIRV.size() * sizeof(uint32_t); - ShaderModuleCI.pCode = StageInfo.SPIRV.data(); + ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t); + ShaderModuleCI.pCode = SPIRV.data(); - vkShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, StageInfo.pShader->GetDesc().Name)); + ShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, pShader->GetDesc().Name)); - StageCI.module = vkShaderModules.back(); - StageCI.pName = StageInfo.pShader->GetEntryPoint(); - StageCI.pSpecializationInfo = nullptr; + StageCI.module = ShaderModules.back(); + StageCI.pName = pShader->GetEntryPoint(); + StageCI.pSpecializationInfo = nullptr; - vkPipelineShaderStages.push_back(StageCI); + Stages.push_back(StageCI); + } } - VERIFY_EXPR(vkShaderModules.size() == vkPipelineShaderStages.size()); + VERIFY_EXPR(ShaderModules.size() == Stages.size()); } -static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - VulkanUtilities::PipelineWrapper& Pipeline) +void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); @@ -218,13 +154,13 @@ static void CreateComputePipeline(RenderDeviceVkImpl* } -static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - const GraphicsPipelineDesc& GraphicsPipeline, - VulkanUtilities::PipelineWrapper& Pipeline, - RefCntAutoPtr& pRenderPass) +void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const GraphicsPipelineDesc& GraphicsPipeline, + VulkanUtilities::PipelineWrapper& Pipeline, + RefCntAutoPtr& pRenderPass) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); @@ -401,6 +337,240 @@ static void CreateGraphicsPipeline(RenderDeviceVkImpl* Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); } + +void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const std::vector& ShaderGroups, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const RayTracingPipelineDesc& RayTracingPipeline, + VulkanUtilities::PipelineWrapper& Pipeline) +{ + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); + const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing; + + DEV_CHECK_ERR(RayTracingPipeline.MaxRecursionDepth <= RTLimits.maxRecursionDepth, + "RayTracingPipeline.MaxRecursionDepth must not exceed ", RTLimits.maxRecursionDepth); + + VkRayTracingPipelineCreateInfoKHR PipelineCI = {}; + + PipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; + PipelineCI.pNext = nullptr; +#ifdef DILIGENT_DEBUG + PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; +#endif + + PipelineCI.stageCount = static_cast(Stages.size()); + PipelineCI.pStages = Stages.data(); + PipelineCI.layout = Layout.GetVkPipelineLayout(); + + PipelineCI.groupCount = static_cast(ShaderGroups.size()); + PipelineCI.pGroups = ShaderGroups.data(); + PipelineCI.maxRecursionDepth = RayTracingPipeline.MaxRecursionDepth; + PipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; + PipelineCI.libraries.pNext = nullptr; + PipelineCI.libraries.libraryCount = 0; + PipelineCI.libraries.pLibraries = nullptr; + PipelineCI.pLibraryInterface = nullptr; + PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from + PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from + + Pipeline = LogicalDevice.CreateRayTracingPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); +} + + +template +void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateInfo, + TNameToGroupIndexMap& NameToGroupIndex, + std::vector& ShaderGroups, + const ShaderResourceLayoutVk::TShaderStages& ShaderStages, + LinearAllocator& MemPool) +{ +#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ray tracing PSO '", CreateInfo.PSODesc.Name, "' is invalid: ", ##__VA_ARGS__) + ShaderGroups.reserve(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount); + + Uint32 GroupIndex = 0; + Uint32 ShaderIndex = 0; + + std::unordered_map UniqueShaders; + + const auto ShaderToIndex = [&ShaderIndex, &UniqueShaders](const IShader* pShader) -> Uint32 { + if (pShader != nullptr) + { + auto Result = UniqueShaders.emplace(pShader, ShaderIndex); + if (Result.second) + { + ++ShaderIndex; + } + return Result.first->second; + } + return VK_SHADER_UNUSED_KHR; + }; + + for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) + { + VkRayTracingShaderGroupCreateInfoKHR Group = {}; + + Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + Group.generalShader = ShaderToIndex(CreateInfo.pGeneralShaders[i].pShader); + Group.closestHitShader = VK_SHADER_UNUSED_KHR; + Group.anyHitShader = VK_SHADER_UNUSED_KHR; + Group.intersectionShader = VK_SHADER_UNUSED_KHR; + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); + + ShaderGroups.push_back(Group); + } + + for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) + { + VkRayTracingShaderGroupCreateInfoKHR Group = {}; + + Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + Group.generalShader = VK_SHADER_UNUSED_KHR; + Group.closestHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pClosestHitShader); + Group.anyHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pAnyHitShader); + Group.intersectionShader = VK_SHADER_UNUSED_KHR; + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); + + ShaderGroups.push_back(Group); + } + + for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) + { + VkRayTracingShaderGroupCreateInfoKHR Group = {}; + + Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; + Group.generalShader = VK_SHADER_UNUSED_KHR; + Group.intersectionShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pIntersectionShader); + Group.closestHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pClosestHitShader); + Group.anyHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pAnyHitShader); + + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second; + if (!IsUniqueName) + LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); + + ShaderGroups.push_back(Group); + } + + VERIFY_EXPR(Uint32(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount) == GroupIndex); + +#ifdef DILIGENT_DEVELOPMENT + Uint32 ShaderIndex2 = 0; + for (auto& Stage : ShaderStages) + { + for (auto* pShader : Stage.Shaders) + { + auto iter = UniqueShaders.find(static_cast(pShader)); + if (iter != UniqueShaders.end()) + VERIFY_EXPR(iter->second == ShaderIndex2); + else + UNEXPECTED("shader is not used in ray tracing shader groups"); + + ++ShaderIndex2; + } + } + VERIFY_EXPR(ShaderIndex == ShaderIndex2); +#endif +#undef LOG_PSO_ERROR_AND_THROW +} + +} // namespace + + +RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc( + Uint32 NumRenderTargets, + const TEXTURE_FORMAT RTVFormats[], + TEXTURE_FORMAT DSVFormat, + Uint8 SampleCount, + std::array& Attachments, + std::array& AttachmentReferences, + SubpassDesc& SubpassDesc) +{ + VERIFY_EXPR(NumRenderTargets <= MAX_RENDER_TARGETS); + + RenderPassDesc RPDesc; + + RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets; + + uint32_t AttachmentInd = 0; + AttachmentReference* pDepthAttachmentReference = nullptr; + if (DSVFormat != TEX_FORMAT_UNKNOWN) + { + auto& DepthAttachment = Attachments[AttachmentInd]; + + DepthAttachment.Format = DSVFormat; + DepthAttachment.SampleCount = SampleCount; + DepthAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area + // will be preserved. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT. + DepthAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render + // area are written to memory. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. + DepthAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_LOAD; + DepthAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_STORE; + DepthAttachment.InitialState = RESOURCE_STATE_DEPTH_WRITE; + DepthAttachment.FinalState = RESOURCE_STATE_DEPTH_WRITE; + + pDepthAttachmentReference = &AttachmentReferences[AttachmentInd]; + pDepthAttachmentReference->AttachmentIndex = AttachmentInd; + pDepthAttachmentReference->State = RESOURCE_STATE_DEPTH_WRITE; + + ++AttachmentInd; + } + + AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr; + for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd) + { + auto& ColorAttachment = Attachments[AttachmentInd]; + + ColorAttachment.Format = RTVFormats[rt]; + ColorAttachment.SampleCount = SampleCount; + ColorAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area + // will be preserved. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. + ColorAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render + // area are written to memory. For attachments with a color format, + // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. + ColorAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_DISCARD; + ColorAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_DISCARD; + ColorAttachment.InitialState = RESOURCE_STATE_RENDER_TARGET; + ColorAttachment.FinalState = RESOURCE_STATE_RENDER_TARGET; + + auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd]; + ColorAttachmentRef.AttachmentIndex = AttachmentInd; + ColorAttachmentRef.State = RESOURCE_STATE_RENDER_TARGET; + } + + RPDesc.pAttachments = Attachments.data(); + RPDesc.SubpassCount = 1; + RPDesc.pSubpasses = &SubpassDesc; + RPDesc.DependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies. + RPDesc.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing + // dependencies between pairs of subpasses, or NULL if dependencyCount is zero. + + + SubpassDesc.InputAttachmentCount = 0; + SubpassDesc.pInputAttachments = nullptr; + SubpassDesc.RenderTargetAttachmentCount = NumRenderTargets; + SubpassDesc.pRenderTargetAttachments = pColorAttachmentsReference; + SubpassDesc.pResolveAttachments = nullptr; + SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference; + SubpassDesc.PreserveAttachmentCount = 0; + SubpassDesc.pPreserveAttachments = nullptr; + + return RPDesc; +} + void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages) { @@ -416,7 +586,7 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s]; - StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); + StaticResLayout.InitializeStaticResourceLayout(StageInfo.Shaders, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0); } @@ -509,6 +679,7 @@ void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); } + PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo) : @@ -554,6 +725,75 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p } } +PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVk, + const RayTracingPipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + try + { + m_ResourceLayoutIndex.fill(-1); + + TShaderStages ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + const auto ShaderGroupHandleSize = pDeviceVk->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; + TNameToGroupIndexMap NameToGroupIndex; + LinearAllocator MemPool{GetRawAllocator()}; + + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); + + ReserveSpaceForPipelineDesc(CreateInfo, ShaderGroupHandleSize, MemPool); + + MemPool.Reserve(); + + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + + m_StaticResCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_StaticResCaches); + (void)Ptr; + + m_ShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, LogicalDevice); + + m_StaticVarsMgrs = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; + + std::vector ShaderGroups; + BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, ShaderGroupHandleSize, std::move(NameToGroupIndex), MemPool); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(CreateInfo, ShaderStages); + + // Create shader modules and initialize shader stages + std::vector vkShaderStages; + std::vector ShaderModules; + InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); + + CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline); + + auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]); + VERIFY(err == VK_SUCCESS, "Failed to get shader group handles"); + (void)err; + } + catch (...) + { + Destruct(); + throw; + } +} PipelineStateVkImpl::~PipelineStateVkImpl() { @@ -562,6 +802,8 @@ PipelineStateVkImpl::~PipelineStateVkImpl() void PipelineStateVkImpl::Destruct() { + TPipelineStateBase::Destruct(); + m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask); m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask); @@ -617,8 +859,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const return false; auto IsSamePipelineLayout = m_PipelineLayout.IsSameAs(pPSOVk->m_PipelineLayout); - -#ifdef DILIGENT_DEBUG +#if 0 //def DILIGENT_DEBUG // AZ TODO { bool IsCompatibleShaders = true; if (GetNumShaderStages() != pPSOVk->GetNumShaderStages()) @@ -736,9 +977,21 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind Layout.CommitDynamicResources(ResourceCache, DynamicDescrSet); } } - // 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); + switch (m_Desc.PipelineType) + { + // clang-format off + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break; + case PIPELINE_TYPE_COMPUTE: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break; + case PIPELINE_TYPE_RAY_TRACING: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break; + default: UNEXPECTED("unknown pipeline type"); + // clang-format on + } + + // Prepare descriptor sets, and also bind them if there are no dynamic descriptors + m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, 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(). } @@ -783,7 +1036,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY if (LayoutInd < 0) return nullptr; - const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); return StaticVarMgr.GetVariable(Index); } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index cdcac036..3199a014 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -96,17 +96,18 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* "Main descriptor pool", std::vector { - {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, EngineCI.MainDescriptorPoolSize.NumAccelStructDescriptors} }, EngineCI.MainDescriptorPoolSize.MaxDescriptorSets, true @@ -117,17 +118,18 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* "Dynamic descriptor pool", std::vector { - {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, + {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, EngineCI.MainDescriptorPoolSize.NumAccelStructDescriptors} }, EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets, false // Pools can only be reset @@ -160,6 +162,9 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, EngineCI.pDxCompilerPath)} // clang-format on { + static_assert(sizeof(VulkanDescriptorPoolSize) == sizeof(Uint32) * 11, "Please add new descriptors to m_DescriptorSetAllocator and m_DynamicDescriptorPool constructors"); + static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor"); + m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_VULKAN; m_DeviceCaps.MajorVersion = 1; m_DeviceCaps.MinorVersion = 0; @@ -573,6 +578,10 @@ void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCr CreatePipelineState(PSOCreateInfo, ppPipelineState); } +void RenderDeviceVkImpl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState); +} void RenderDeviceVkImpl::CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) { diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index caf8ffd2..8a9da14e 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -155,7 +155,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) for (Uint32 res = 0; res < m_TotalResources; ++res) { auto& Res = pResources[res]; - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below"); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); switch (Res.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: @@ -321,6 +321,36 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl) } break; + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + { + //auto* pTLASVk = Res.pObject.RawPtr(); + //if (pTLASVk != nullptr && pTLASVk->IsInKnownState()) + //{ + // constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING; + // const bool IsInRequiredState = pTLASVk->CheckState(RequiredState); + // if (VerifyOnly) + // { + // if (!IsInRequiredState) + // { + // LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ", + // GetResourceStateString(RequiredState), ". Actual state: ", + // GetResourceStateString(pTLASVk->GetState()), + // ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION " + // "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state " + // "with IDeviceContext::TransitionResourceStates()."); + // } + // } + // else + // { + // if (!IsInRequiredState) + // { + // pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true); + // } + // } + //} + } + break; + default: UNEXPECTED("Unexpected resource type"); } } @@ -497,4 +527,20 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetInputAttachmentDescrip return DescrImgInfo; } +VkWriteDescriptorSetAccelerationStructureKHR ShaderResourceCacheVk::Resource::GetAccelerationStructureWriteInfo() const +{ + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration structure resource is expected"); + DEV_CHECK_ERR(pObject != nullptr, "Unable to get acceleration structure write info: cached object is null"); + + //auto* pTLASVk = pObject.RawPtr(); + + VkWriteDescriptorSetAccelerationStructureKHR DescrAS = {}; + //DescrAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + //DescrAS.pNext = nullptr; + //DescrAS.accelerationStructureCount = 1; + //DescrAS.pAccelerationStructures = pTLASVk->GetVkTLASPtr(); + + return DescrAS; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index e73ee9aa..16b6bee3 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -93,12 +93,24 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE } } -ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type, - const ShaderVkImpl* _pShader) : - Type{_Type}, - pShader{_pShader}, - SPIRV{pShader->GetSPIRV()} + +ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) : + Type{Stage} +{ + Shaders.push_back(pShader); + SPIRVs.push_back(pShader->GetSPIRV()); +} + +void ShaderResourceLayoutVk::ShaderStageInfo::Append(const ShaderVkImpl* pShader) { + Shaders.push_back(pShader); + SPIRVs.push_back(pShader->GetSPIRV()); +} + +size_t ShaderResourceLayoutVk::ShaderStageInfo::Count() const +{ + VERIFY_EXPR(Shaders.size() == SPIRVs.size()); + return Shaders.size(); } @@ -111,38 +123,53 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk() GetImmutableSampler(s).~ImmutableSamplerPtrType(); } -void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* pShader, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool AllocateImmutableSamplers) +void ShaderResourceLayoutVk::AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); - VERIFY_EXPR(!m_pResources); - m_pResources = pShader->GetShaderResources(); + VERIFY_EXPR(Shaders.size() > 0); + VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN); + + size_t StringPoolSize = 0; + m_ShaderType = Shaders[0]->GetDesc().ShaderType; + m_IsUsingSeparateSamplers = !Shaders[0]->GetShaderResources()->IsUsingCombinedSamplers(); + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - const auto ShaderType = pShader->GetDesc().ShaderType; - VERIFY_EXPR(m_pResources->GetShaderType() == ShaderType); // Count the number of resources to allocate all needed memory + for (size_t s = 0; s < Shaders.size(); ++s) { - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); - m_pResources->ProcessResources( + auto pResources = Shaders[s]->GetShaderResources(); + const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); + VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); + pResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { - auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); + auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); if (IsAllowedType(VarType, AllowedTypeBits)) { - // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app + bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, ~0u).second; + if (IsUniqueName) + { + StringPoolSize += strlen(ResAttribs.Name) + 1; + + // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app - VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits::max()}, "Number of resources exceeds Uint16 maximum representable value"); - ++m_NumResources[VarType]; + VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits::max()}, "Number of resources exceeds Uint16 maximum representable value"); + ++m_NumResources[VarType]; + } } } // ); + VERIFY_EXPR(m_IsUsingSeparateSamplers == !pResources->IsUsingCombinedSamplers()); } + m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); + Uint32 TotalResources = 0; for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) { @@ -157,7 +184,7 @@ void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s) { const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[s]; - if ((ImtblSamDesc.ShaderStages & ShaderType) != 0) + if ((ImtblSamDesc.ShaderStages & m_ShaderType) != 0) ++m_NumImmutableSamplers; } } @@ -194,8 +221,8 @@ static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd) { const auto& Res = Layout.GetResource(ImgVarType, SamplerInd); - if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && - strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0) + if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + strcmp(Res.Name, SepSampler.Name) == 0) { VERIFY(ImgVarType == Res.GetVariableType(), "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name, @@ -217,62 +244,88 @@ static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, } -void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const ShaderVkImpl* pShader, - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderResourceCacheVk& StaticResourceCache) +void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector& Shaders, + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderResourceCacheVk& StaticResourceCache) { const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; // We do not need immutable samplers in static shader resource layout as they // are relevant only when the main layout is initialized - constexpr bool AllocateImmutableSamplers = false; - AllocateMemory(pShader, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers); + ResourceNameToIndex_t ResourceNameToIndex; + constexpr bool AllocateImmutableSamplers = false; + AllocateMemory(Shaders, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, ResourceNameToIndex, AllocateImmutableSamplers); std::array CurrResInd = {}; - Uint32 StaticResCacheSize = 0; + Uint32 StaticResCacheSize = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); - const auto ShaderType = pShader->GetDesc().ShaderType; + for (auto* pShader : Shaders) + { + auto pResources = pShader->GetShaderResources(); + const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); + pResources->ProcessResources( + [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // + { + auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (!IsAllowedType(VarType, AllowedTypeBits)) + return; - m_pResources->ProcessResources( - [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // - { - auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); - if (!IsAllowedType(VarType, AllowedTypeBits)) - return; + auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); + VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - Int32 SrcImmutableSamplerInd = -1; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) - { - // Only search for the immutable sampler for combined image samplers and separate samplers - SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); - // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app - } + if (ResIter->second == ~0u) + { + Int32 SrcImmutableSamplerInd = -1; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + SrcImmutableSamplerInd = FindImmutableSampler(m_ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); + // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app + } - Uint32 Binding = Attribs.Type; - Uint32 DescriptorSet = 0; - Uint32 CacheOffset = StaticResCacheSize; - StaticResCacheSize += Attribs.ArraySize; + Uint32 Binding = Attribs.Type; + Uint32 DescriptorSet = 0; + Uint32 CacheOffset = StaticResCacheSize; + StaticResCacheSize += Attribs.ArraySize; - Uint32 SamplerInd = VkResource::InvalidSamplerInd; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) - { - // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must have already been created. - SamplerInd = FindAssignedSampler(*this, *m_pResources, Attribs, CurrResInd[VarType], VarType); - } - ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); - } // - ); + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + { + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(*this, *pResources, Attribs, CurrResInd[VarType], VarType); + } + + // add new resource + ResIter->second = CurrResInd[VarType]; + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, + Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, + Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); + } + else + { + // merge with existing + auto& ExistingRes = GetResource(VarType, ResIter->second); + VERIFY_EXPR(ExistingRes.VariableType == VarType); + VERIFY_EXPR(ExistingRes.Type == Attribs.Type); + VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim); + VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS); + VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize); + } + } // + ); + } #ifdef DILIGENT_DEBUG for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) { VERIFY(CurrResInd[VarType] == m_NumResources[VarType], "Not all resources have been initialized, which will cause a crash when dtor is called"); } + + VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); #endif StaticResourceCache.InitializeSets(GetRawAllocator(), 1, &StaticResCacheSize); @@ -296,14 +349,15 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& const auto ShaderType = Stages & static_cast(~(static_cast(Stages) - 1)); const char* ShaderName = nullptr; - for (const auto& StageInfo : ShaderStages) + // AZ TODO + /*for (const auto& StageInfo : ShaderStages) { if ((Stages & StageInfo.Type) != 0) { ShaderName = StageInfo.pShader->GetDesc().Name; break; } - } + }*/ if (!ShadersStr.empty()) ShadersStr.append(", "); @@ -340,13 +394,17 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& bool VariableFound = false; for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s) { - const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) + auto& Shaders = ShaderStages[s].Shaders; + for (size_t i = 0; i < Shaders.size() && !VariableFound; ++i) { - for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) + const auto& Resources = *Shaders[i]->GetShaderResources(); + if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) { - const auto& ResAttribs = Resources.GetResource(res); - VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); + for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) + { + const auto& ResAttribs = Resources.GetResource(res); + VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); + } } } } @@ -373,28 +431,32 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& bool SamplerFound = false; for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { - const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) - continue; - - // Irrespective of whether HLSL-style combined image samplers are used, - // an immutable sampler can be assigned to a GLSL sampled image (i.e. sampler2D g_tex) - for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) + auto& Shaders = ShaderStages[s].Shaders; + for (size_t j = 0; j < Shaders.size() && !SamplerFound; ++j) { - const auto& SmplImg = Resources.GetSmpldImg(i); - SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0); - } + const auto& Resources = *Shaders[j]->GetShaderResources(); + if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) + continue; - if (!SamplerFound) - { - // Check if an immutable sampler is assigned to a separate sampler. - // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". - // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". - const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); - for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i) + // Irrespective of whether HLSL-style combined image samplers are used, + // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) + for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) + { + const auto& SmplImg = Resources.GetSmpldImg(i); + SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0); + } + + if (!SamplerFound) { - const auto& SepSmpl = Resources.GetSepSmplr(i); - SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); + // Check if static sampler is assigned to a separate sampler. + // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". + // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". + const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); + for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i) + { + const auto& SepSmpl = Resources.GetSepSmplr(i); + SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); + } } } } @@ -423,15 +485,16 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyImmutableSamplers); #endif - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; - const Uint32 NumAllowedTypes = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - constexpr bool AllocateImmutableSamplers = true; + std::array ResourceNameToIndexArray; + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; + const Uint32 NumAllowedTypes = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + constexpr bool AllocateImmutableSamplers = true; for (size_t s = 0; s < ShaderStages.size(); ++s) { - Layouts[s].AllocateMemory(ShaderStages[s].pShader, LayoutDataAllocator, ResourceLayoutDesc, - AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); + Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc, + AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], AllocateImmutableSamplers); } //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); @@ -444,74 +507,107 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende auto AddResource = [&](Uint32 ShaderInd, ShaderResourceLayoutVk& ResLayout, const SPIRVShaderResources& Resources, - const SPIRVShaderResourceAttribs& Attribs) // + const SPIRVShaderResourceAttribs& Attribs, + ResourceNameToIndex_t& ResourceNameToIndex, + std::vector& SPIRV) // { const auto ShaderType = Resources.GetShaderType(); const SHADER_RESOURCE_VARIABLE_TYPE VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, Resources.GetCombinedSamplerSuffix()); if (!IsAllowedType(VarType, AllowedTypeBits)) return; - Uint32 Binding = 0; - Uint32 DescriptorSet = 0; - Uint32 CacheOffset = 0; - Uint32 SamplerInd = VkResource::InvalidSamplerInd; + auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); + VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + if (ResIter->second == ~0u) { - // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must have already been created. - SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType); - } + // add new resource + Uint32 Binding = 0; + Uint32 DescriptorSet = 0; + Uint32 CacheOffset = 0; + Uint32 SamplerInd = VkResource::InvalidSamplerInd; - VkSampler vkImmutableSampler = VK_NULL_HANDLE; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) - { - // Only search for the immutable sampler for combined image samplers and separate samplers - Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix()); - if (SrcImmutableSamplerInd >= 0) + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) { - auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++); - VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!"); - const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc; - pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler); - vkImmutableSampler = ImmutableSampler.RawPtr()->GetVkSampler(); + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType); } - } - auto& ShaderSPIRV = ShaderStages[ShaderInd].SPIRV; - PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV); - VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); - VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); + VkSampler vkImmutableSampler = VK_NULL_HANDLE; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix()); + if (SrcImmutableSamplerInd >= 0) + { + auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++); + VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!"); + const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc; + pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler); + vkImmutableSampler = ImmutableSampler.RawPtr()->GetVkSampler(); + } + } + + PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset); + VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); + VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); + + SPIRV[Attribs.BindingDecorationOffset] = Binding; + SPIRV[Attribs.DescriptorSetDecorationOffset] = DescriptorSet; #ifdef DILIGENT_DEBUG - // Verify that bindings and cache offsets monotonically increase in every descriptor set - auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet); - if (Binding_OffsetIt != dbgBindings_CacheOffsets.end()) - { - VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic"); - VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic"); - } - dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset); + // Verify that bindings and cache offsets monotonically increase in every descriptor set + auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet); + if (Binding_OffsetIt != dbgBindings_CacheOffsets.end()) + { + VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic"); + VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic"); + } + dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset); #endif - auto& ResInd = CurrResInd[ShaderInd][VarType]; - ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); + auto& ResInd = CurrResInd[ShaderInd][VarType]; + ResIter->second = ResInd; + ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, ResLayout.m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, + Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, + Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); + } + else + { + // merge with existing + auto& ExistingRes = ResLayout.GetResource(VarType, ResIter->second); + + VERIFY_EXPR(ExistingRes.VariableType == VarType); + VERIFY_EXPR(ExistingRes.Type == Attribs.Type); + VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim); + VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS); + VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize); + + SPIRV[Attribs.BindingDecorationOffset] = ExistingRes.Binding; + SPIRV[Attribs.DescriptorSetDecorationOffset] = ExistingRes.DescriptorSet; + } }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set for (size_t s = 0; s < ShaderStages.size(); ++s) { + auto& Shaders = ShaderStages[s].Shaders; auto& Layout = Layouts[s]; - auto* pShaderVk = ShaderStages[s].pShader; - auto& Resources = *pShaderVk->GetShaderResources(); - for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) + auto& NameToIdx = ResourceNameToIndexArray[s]; + for (size_t i = 0; i < Shaders.size(); ++i) { - const auto& UB = Resources.GetUB(n); - auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc); - if (IsAllowedType(VarType, AllowedTypeBits)) + auto& SPIRV = ShaderStages[s].SPIRVs[i]; + auto& Resources = *Shaders[i]->GetShaderResources(); + for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) { - AddResource(static_cast(s), Layout, Resources, UB); + const auto& UB = Resources.GetUB(n); + auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + AddResource(static_cast(s), Layout, Resources, UB, NameToIdx, SPIRV); + } } } } @@ -519,15 +615,21 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // Second, process all storage buffers for (size_t s = 0; s < ShaderStages.size(); ++s) { + auto& Shaders = ShaderStages[s].Shaders; auto& Layout = Layouts[s]; - auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) + auto& NameToIdx = ResourceNameToIndexArray[s]; + for (size_t i = 0; i < Shaders.size(); ++i) { - const auto& SB = Resources.GetSB(n); - auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc); - if (IsAllowedType(VarType, AllowedTypeBits)) + auto& Resources = *Shaders[i]->GetShaderResources(); + auto& SPIRV = ShaderStages[s].SPIRVs[i]; + for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) { - AddResource(static_cast(s), Layout, Resources, SB); + const auto& SB = Resources.GetSB(n); + auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + AddResource(static_cast(s), Layout, Resources, SB, NameToIdx, SPIRV); + } } } } @@ -536,51 +638,62 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende for (size_t s = 0; s < ShaderStages.size(); ++s) { auto& Layout = Layouts[s]; - auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - // clang-format off - Resources.ProcessResources( - [&](const SPIRVShaderResourceAttribs& UB, Uint32) - { - VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); - // Skip - }, - [&](const SPIRVShaderResourceAttribs& SB, Uint32) - { - VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || SB.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer); - // Skip - }, - [&](const SPIRVShaderResourceAttribs& Img, Uint32) - { - VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); - AddResource(static_cast(s), Layout, Resources, Img); - }, - [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) - { - VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - AddResource(static_cast(s), Layout, Resources, SmplImg); - }, - [&](const SPIRVShaderResourceAttribs& AC, Uint32) - { - VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); - AddResource(static_cast(s), Layout, Resources, AC); - }, - [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) - { - VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); - AddResource(static_cast(s), Layout, Resources, SepSmpl); - }, - [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) - { - VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - AddResource(static_cast(s), Layout, Resources, SepImg); - }, - [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32) - { - VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment); - AddResource(static_cast(s), Layout, Resources, InputAtt); - } - ); - // clang-format on + auto& Shaders = ShaderStages[s].Shaders; + auto& NameToIdx = ResourceNameToIndexArray[s]; + for (size_t i = 0; i < Shaders.size(); ++i) + { + auto& Resources = *Shaders[i]->GetShaderResources(); + auto& SPIRV = ShaderStages[s].SPIRVs[i]; + // clang-format off + Resources.ProcessResources( + [&](const SPIRVShaderResourceAttribs& UB, Uint32) + { + VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); + // Skip + }, + [&](const SPIRVShaderResourceAttribs& SB, Uint32) + { + VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || SB.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer); + // Skip + }, + [&](const SPIRVShaderResourceAttribs& Img, Uint32) + { + VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); + AddResource(static_cast(s), Layout, Resources, Img, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) + { + VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); + AddResource(static_cast(s), Layout, Resources, SmplImg, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& AC, Uint32) + { + VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); + AddResource(static_cast(s), Layout, Resources, AC, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) + { + VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); + AddResource(static_cast(s), Layout, Resources, SepSmpl, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) + { + VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); + AddResource(static_cast(s), Layout, Resources, SepImg, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32) + { + VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment); + AddResource(static_cast(s), Layout, Resources, InputAtt, NameToIdx, SPIRV); + }, + [&](const SPIRVShaderResourceAttribs& AccelStruct, Uint32) + { + VERIFY_EXPR(AccelStruct.Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure); + AddResource(static_cast(s), Layout, Resources, AccelStruct, NameToIdx, SPIRV); + } + ); + // clang-format on + } } #ifdef DILIGENT_DEBUG @@ -593,28 +706,32 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende } // Some immutable samplers may never be initialized if they are not present in shaders VERIFY_EXPR(CurrImmutableSamplerInd[s] <= Layout.m_NumImmutableSamplers); + + VERIFY_EXPR(Layout.m_StringPool.GetRemainingSize() == 0); } #endif } -void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, - uint32_t ArrayElement, - const VkDescriptorImageInfo* pImageInfo, - const VkDescriptorBufferInfo* pBufferInfo, - const VkBufferView* pTexelBufferView) const + +void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, + uint32_t ArrayElement, + const VkDescriptorImageInfo* pImageInfo, + const VkDescriptorBufferInfo* pBufferInfo, + const VkBufferView* pTexelBufferView, + const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo) const { VERIFY_EXPR(vkDescrSet != VK_NULL_HANDLE); VkWriteDescriptorSet WriteDescrSet; WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescrSet.pNext = nullptr; + WriteDescrSet.pNext = pAccelStructInfo; WriteDescrSet.dstSet = vkDescrSet; WriteDescrSet.dstBinding = Binding; WriteDescrSet.dstArrayElement = ArrayElement; WriteDescrSet.descriptorCount = 1; // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding. // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4) - WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(SpirvAttribs); + WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(Type); WriteDescrSet.pImageInfo = pImageInfo; WriteDescrSet.pBufferInfo = pBufferInfo; WriteDescrSet.pTexelBufferView = pTexelBufferView; @@ -654,10 +771,10 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* Uint32 ArrayInd, Uint16& DynamicBuffersCounter) const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected"); + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected"); RefCntAutoPtr pBufferVk{pBuffer, IID_BufferVk}; #ifdef DILIGENT_DEVELOPMENT - VerifyConstantBufferBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); #endif auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) { @@ -691,8 +808,8 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* Uint16& DynamicBuffersCounter) const { // clang-format off - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || + Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer, "Storage buffer resource is expected"); // clang-format on @@ -700,8 +817,8 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT { // HLSL buffer SRVs are mapped to storge buffers in GLSL - auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS; - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS; + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); if (pBufferViewVk != nullptr) { const auto& ViewDesc = pBufferViewVk->GetDesc(); @@ -709,7 +826,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); + Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); } } } @@ -747,8 +864,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* Uint16& DynamicBuffersCounter) const { // clang-format off - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer || + Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer, "Uniform or storage buffer resource is expected"); // clang-format on @@ -756,8 +873,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT { // HLSL buffer SRVs are mapped to storge buffers in GLSL - auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE; - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE; + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); if (pBufferViewVk != nullptr) { const auto& ViewDesc = pBufferViewVk->GetDesc(); @@ -765,7 +882,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW)) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", - SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected."); + Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected."); } } } @@ -805,9 +922,9 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* TCacheSampler CacheSampler) const { // clang-format off - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || - SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || + Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || + Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage, "Storage image, separate image or sampled image resource is expected"); // clang-format on @@ -815,8 +932,8 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* #ifdef DILIGENT_DEVELOPMENT { // HLSL buffer SRVs are mapped to storge buffers in GLSL - auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE; - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE; + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); } #endif if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {})) @@ -824,11 +941,11 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* // We can do RawPtr here safely since UpdateCachedResource() returned true auto* pTexViewVk = DstRes.pObject.RawPtr(); #ifdef DILIGENT_DEVELOPMENT - if (SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned()) + if (Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned()) { if (pTexViewVk->GetSampler() == nullptr) { - LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '", SpirvAttribs.GetPrintName(ArrayInd), + LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. No sampler is assigned to the view"); } } @@ -844,11 +961,11 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* if (SamplerInd != InvalidSamplerInd) { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, "Only separate images can be assigned separate samplers when using HLSL-style combined samplers."); VERIFY(!IsImmutableSamplerAssigned(), "Separate image can't be assigned an immutable sampler."); const auto& SamplerAttribs = ParentResLayout.GetResource(GetVariableType(), SamplerInd); - VERIFY_EXPR(SamplerAttribs.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); + VERIFY_EXPR(SamplerAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); if (!SamplerAttribs.IsImmutableSamplerAssigned()) { auto* pSampler = pTexViewVk->GetSampler(); @@ -858,8 +975,8 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* } else { - LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name, - "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", + LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.Name, + "' assigned to separate image '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\''); } } @@ -872,20 +989,20 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* VkDescriptorSet vkDescrSet, Uint32 ArrayInd) const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected"); + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected"); VERIFY(!IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler"); RefCntAutoPtr pSamplerVk{pSampler, IID_Sampler}; #ifdef DILIGENT_DEVELOPMENT if (pSampler != nullptr && pSamplerVk == nullptr) { - LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", SpirvAttribs.GetPrintName(ArrayInd), + LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. Unexpected object type: sampler is expected"); } if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr && DstRes.pObject != pSamplerVk) { auto VarTypeStr = GetShaderVariableTypeLiteralName(GetVariableType()); - LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd), + LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. Attempting to bind another sampler or null is an error and may " "cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."); @@ -908,10 +1025,10 @@ void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject* VkDescriptorSet vkDescrSet, Uint32 ArrayInd) const { - VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected"); + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected"); RefCntAutoPtr pTexViewVk0{pTexView, IID_TextureViewVk}; #ifdef DILIGENT_DEVELOPMENT - VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); #endif if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {})) { @@ -926,9 +1043,32 @@ void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject* } } +void ShaderResourceLayoutVk::VkResource::CacheAccelerationStructure(IDeviceObject* pTLAS, + ShaderResourceCacheVk::Resource& DstRes, + VkDescriptorSet vkDescrSet, + Uint32 ArrayInd) const +{ + // VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected"); + // RefCntAutoPtr pTLASVk{pTLAS, IID_TopLevelASVk}; + //#ifdef DILIGENT_DEVELOPMENT + // // AZ TODO + //#endif + // if (UpdateCachedResource(DstRes, std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {})) + // { + // // Do not update descriptor for a dynamic TLAS. All dynamic resource descriptors + // // are updated at once by CommitDynamicResources() when SRB is committed. + // if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) + // { + // VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = DstRes.GetAccelerationStructureWriteInfo(); + // UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, nullptr, &DescrASInfo); + // } + // // + // } +} + void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const { - VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize); + VERIFY_EXPR(ArrayIndex < ArraySize); auto& DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet); auto vkDescrSet = DstDescrSet.GetVkDescriptorSet(); @@ -951,12 +1091,12 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 } #endif auto& DstRes = DstDescrSet.GetResource(CacheOffset + ArrayIndex); - VERIFY(DstRes.Type == SpirvAttribs.Type, "Inconsistent types"); + VERIFY(DstRes.Type == Type, "Inconsistent types"); if (pObj) { - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below"); - switch (SpirvAttribs.Type) + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + switch (Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: CacheUniformBuffer(pObj, DstRes, vkDescrSet, ArrayIndex, ResourceCache.GetDynamicBuffersCounter()); @@ -977,15 +1117,15 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 case SPIRVShaderResourceAttribs::ResourceType::SampledImage: CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex, [&](const VkResource& SeparateSampler, ISampler* pSampler) { - VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.SpirvAttribs.Name, "' is assigned an immutable sampler"); - VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); - DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize, - "Array size (", SeparateSampler.SpirvAttribs.ArraySize, + VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.Name, "' is assigned an immutable sampler"); + VERIFY_EXPR(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + DEV_CHECK_ERR(SeparateSampler.ArraySize == 1 || SeparateSampler.ArraySize == ArraySize, + "Array size (", SeparateSampler.ArraySize, ") of separate sampler variable '", - SeparateSampler.SpirvAttribs.Name, - "' must be one or the same as the array size (", SpirvAttribs.ArraySize, - ") of separate image variable '", SpirvAttribs.Name, "' it is assigned to"); - Uint32 SamplerArrInd = SeparateSampler.SpirvAttribs.ArraySize == 1 ? 0 : ArrayIndex; + SeparateSampler.Name, + "' must be one or the same as the array size (", ArraySize, + ") of separate image variable '", Name, "' it is assigned to"); + Uint32 SamplerArrInd = SeparateSampler.ArraySize == 1 ? 0 : ArrayIndex; SeparateSampler.BindResource(pSampler, SamplerArrInd, ResourceCache); }); break; @@ -999,7 +1139,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 { // Immutable samplers are permanently bound into the set layout; later binding a sampler // into an immutable sampler slot in a descriptor set is not allowed (13.2.1) - LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", SpirvAttribs.Name, '\''); + LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", Name, '\''); } break; @@ -1007,14 +1147,18 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 CacheInputAttachment(pObj, DstRes, vkDescrSet, ArrayIndex); break; - default: UNEXPECTED("Unknown resource type ", static_cast(SpirvAttribs.Type)); + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + CacheAccelerationStructure(pObj, DstRes, vkDescrSet, ArrayIndex); + break; + + default: UNEXPECTED("Unknown resource type ", static_cast(Type)); } } else { if (DstRes.pObject && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { - LOG_ERROR_MESSAGE("Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), + LOG_ERROR_MESSAGE("Shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. " "Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource."); } @@ -1025,7 +1169,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3 bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const { - VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize); + VERIFY_EXPR(ArrayIndex < ArraySize); if (DescriptorSet < ResourceCache.GetNumDescriptorSets()) { @@ -1040,6 +1184,72 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader return false; } +ShaderResourceDesc ShaderResourceLayoutVk::VkResource::GetResourceDesc() const +{ + ShaderResourceDesc ResourceDesc; + ResourceDesc.Name = Name; + ResourceDesc.ArraySize = ArraySize; + + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + switch (Type) + { + case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; + break; + + case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer: + // Read-only storage buffers map to buffer SRV + // https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide#read-write-vs-read-only-resources-for-hlsl + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::StorageImage: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::SampledImage: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter: + LOG_WARNING_MESSAGE("There is no appropriate shader resource type for atomic counter resource '", Name, "'"); + ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::SeparateImage: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + break; + + case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER; + break; + + case SPIRVShaderResourceAttribs::ResourceType::InputAttachment: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT; + break; + + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT; + break; + + default: + UNEXPECTED("Unknown SPIRV resource type"); + } + return ResourceDesc; +} + void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout, const ShaderResourceCacheVk& SrcResourceCache, @@ -1055,21 +1265,21 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou // Get resource attributes const auto& DstRes = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); const auto& SrcRes = SrcLayout.GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); - VERIFY(SrcRes.Binding == SrcRes.SpirvAttribs.Type, "Unexpected binding"); - VERIFY(SrcRes.SpirvAttribs.ArraySize == DstRes.SpirvAttribs.ArraySize, "Inconsistent array size"); + VERIFY(SrcRes.Binding == SrcRes.Type, "Unexpected binding"); + VERIFY(SrcRes.ArraySize == DstRes.ArraySize, "Inconsistent array size"); - if (DstRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + if (DstRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && DstRes.IsImmutableSamplerAssigned()) continue; // Skip immutable samplers - for (Uint32 ArrInd = 0; ArrInd < DstRes.SpirvAttribs.ArraySize; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < DstRes.ArraySize; ++ArrInd) { auto SrcOffset = SrcRes.CacheOffset + ArrInd; const auto& SrcCachedSet = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet); const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset); IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr(); if (!pObject) - LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); auto DstOffset = DstRes.CacheOffset + ArrInd; IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject; @@ -1093,15 +1303,15 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso { const auto& Res = GetResource(VarType, r); VERIFY(Res.GetVariableType() == VarType, "Unexpected variable type"); - for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd) { const auto& CachedDescrSet = ResourceCache.GetDescriptorSet(Res.DescriptorSet); const auto& CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd); - VERIFY(CachedRes.Type == Res.SpirvAttribs.Type, "Inconsistent types"); + VERIFY(CachedRes.Type == Res.Type, "Inconsistent types"); if (CachedRes.pObject == nullptr && - !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned())) + !(Res.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned())) { - LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); + LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); BindingsOK = false; } # ifdef DILIGENT_DEBUG @@ -1136,7 +1346,7 @@ void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCache for (Uint32 r = 0; r < TotalResources; ++r) { const auto& Res = GetResource(r); - ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.SpirvAttribs.ArraySize, Res.SpirvAttribs.Type); + ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.ArraySize, Res.Type); } } @@ -1151,24 +1361,28 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& static constexpr size_t ImgUpdateBatchSize = 4; static constexpr size_t BuffUpdateBatchSize = 2; static constexpr size_t TexelBuffUpdateBatchSize = 2; + static constexpr size_t AccelStructBatchSize = 2; static constexpr size_t WriteDescriptorSetBatchSize = 2; #else static constexpr size_t ImgUpdateBatchSize = 128; static constexpr size_t BuffUpdateBatchSize = 64; static constexpr size_t TexelBuffUpdateBatchSize = 32; + static constexpr size_t AccelStructBatchSize = 32; static constexpr size_t WriteDescriptorSetBatchSize = 32; #endif // Do not zero-initiaize arrays! - std::array DescrImgInfoArr; - std::array DescrBuffInfoArr; - std::array DescrBuffViewArr; - std::array WriteDescrSetArr; + std::array DescrImgInfoArr; + std::array DescrBuffInfoArr; + std::array DescrBuffViewArr; + std::array DescrAccelStructArr; + std::array WriteDescrSetArr; Uint32 ResNum = 0, ArrElem = 0; auto DescrImgIt = DescrImgInfoArr.begin(); auto DescrBuffIt = DescrBuffInfoArr.begin(); auto BuffViewIt = DescrBuffViewArr.begin(); + auto AccelStructIt = DescrAccelStructArr.begin(); auto WriteDescrSetIt = WriteDescrSetArr.begin(); #ifdef DILIGENT_DEBUG @@ -1195,14 +1409,15 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& WriteDescrSetIt->dstArrayElement = ArrElem; // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding. // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4) - WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.SpirvAttribs); + WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.Type); // For every resource type, try to batch as many descriptor updates as we can - switch (Res.SpirvAttribs.Type) + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); + switch (Res.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo(); @@ -1214,7 +1429,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer: case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer: WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo(); @@ -1226,7 +1441,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: WriteDescrSetIt->pTexelBufferView = &(*BuffViewIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && BuffViewIt != DescrBuffViewArr.end()) + while (ArrElem < Res.ArraySize && BuffViewIt != DescrBuffViewArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *BuffViewIt = CachedRes.GetBufferViewWriteInfo(); @@ -1239,7 +1454,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::StorageImage: case SPIRVShaderResourceAttribs::ResourceType::SampledImage: WriteDescrSetIt->pImageInfo = &(*DescrImgIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.IsImmutableSamplerAssigned()); @@ -1259,7 +1474,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& if (!Res.IsImmutableSamplerAssigned()) { WriteDescrSetIt->pImageInfo = &(*DescrImgIt); - while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end()) + while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrImgIt = CachedRes.GetSamplerDescriptorWriteInfo(); @@ -1269,8 +1484,19 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& } else { - ArrElem = Res.SpirvAttribs.ArraySize; - WriteDescrSetIt->dstArrayElement = Res.SpirvAttribs.ArraySize; + ArrElem = Res.ArraySize; + WriteDescrSetIt->dstArrayElement = Res.ArraySize; + } + break; + + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + WriteDescrSetIt->pNext = &(*AccelStructIt); + while (ArrElem < Res.ArraySize && AccelStructIt != DescrAccelStructArr.end()) + { + const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); + *AccelStructIt = CachedRes.GetAccelerationStructureWriteInfo(); + ++AccelStructIt; + ++ArrElem; } break; @@ -1279,7 +1505,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& } WriteDescrSetIt->descriptorCount = ArrElem - WriteDescrSetIt->dstArrayElement; - if (ArrElem == Res.SpirvAttribs.ArraySize) + if (ArrElem == Res.ArraySize) { ArrElem = 0; ++ResNum; @@ -1294,6 +1520,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& DescrImgIt == DescrImgInfoArr.end() || DescrBuffIt == DescrBuffInfoArr.end() || BuffViewIt == DescrBuffViewArr.end() || + AccelStructIt == DescrAccelStructArr.end() || WriteDescrSetIt == WriteDescrSetArr.end()) { auto DescrWriteCount = static_cast(std::distance(WriteDescrSetArr.begin(), WriteDescrSetIt)); @@ -1303,6 +1530,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& DescrImgIt = DescrImgInfoArr.begin(); DescrBuffIt = DescrBuffInfoArr.begin(); BuffViewIt = DescrBuffViewArr.begin(); + AccelStructIt = DescrAccelStructArr.begin(); WriteDescrSetIt = WriteDescrSetArr.begin(); } } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 7e06bd69..062a5725 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -52,7 +52,7 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout // When using HLSL-style combined image samplers, we need to skip separate samplers. // Also always skip immutable separate samplers. - if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + if (SrcRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned())) continue; @@ -96,7 +96,7 @@ void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& Sr { const auto& SrcRes = SrcLayout.GetResource(VarType, r); // Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers. - if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + if (SrcRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned())) continue; @@ -132,7 +132,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) con { auto& Var = m_pVariables[v]; const auto& Res = Var.m_Resource; - if (strcmp(Res.SpirvAttribs.Name, Name) == 0) + if (strcmp(Res.Name, Name) == 0) { pVar = &Var; break; @@ -190,18 +190,18 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, const auto& Res = Var.m_Resource; // There should be no immutable separate samplers - VERIFY(Res.SpirvAttribs.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(), + VERIFY(Res.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(), "There must be no shader resource variables for immutable separate samplers"); if ((Flags & (1 << Res.GetVariableType())) == 0) continue; - for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) + for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd) { if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache)) continue; - const auto* VarName = Res.SpirvAttribs.Name; + const auto* VarName = Res.Name; RefCntAutoPtr pObj; pResourceMapping->GetResource(VarName, &pObj, ArrInd); if (pObj) @@ -212,7 +212,7 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, { if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache)) { - LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd), + LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.GetPrintName(ArrInd), "': resource is not found in the resource mapping. " "Do not use BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED flag to suppress the message if this is not an issue."); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp index 65505ad3..66393e9b 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp @@ -122,9 +122,17 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, SourceLength = GLSLSourceString.length(); } + GLSLangUtils::SpirvVersion spvVersion = GLSLangUtils::SpirvVersion::Vk100; + const auto& ExtFeats = GetDevice()->GetLogicalDevice().GetEnabledExtFeatures(); + if (ExtFeats.Spirv15) + spvVersion = GLSLangUtils::SpirvVersion::Vk120; + else if (ExtFeats.Spirv14) + spvVersion = GLSLangUtils::SpirvVersion::Vk110_Spirv14; + m_SPIRV = GLSLangUtils::GLSLtoSPIRV(m_Desc.ShaderType, ShaderSource, static_cast(SourceLength), Macros, ShaderCI.pShaderSourceStreamFactory, + spvVersion, ShaderCI.ppCompilerOutput); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index a03102d0..825bf872 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -73,16 +73,18 @@ bool VulkanInstance::IsExtensionEnabled(const char* ExtensionName) const return false; } -std::shared_ptr VulkanInstance::Create(bool EnableValidation, +std::shared_ptr VulkanInstance::Create(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator) { - auto Instance = new VulkanInstance{EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator}; + auto Instance = new VulkanInstance{ApiVersion, EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator}; return std::shared_ptr{Instance}; } -VulkanInstance::VulkanInstance(bool EnableValidation, +VulkanInstance::VulkanInstance(uint32_t ApiVersion, + bool EnableValidation, uint32_t GlobalExtensionCount, const char* const* ppGlobalExtensionNames, VkAllocationCallbacks* pVkAllocator) : @@ -184,6 +186,16 @@ VulkanInstance::VulkanInstance(bool EnableValidation, } } +#if DILIGENT_USE_VOLK + if (vkEnumerateInstanceVersion != nullptr && ApiVersion > VK_API_VERSION_1_0) + { + uint32_t MaxApiVersion = 0; + vkEnumerateInstanceVersion(&MaxApiVersion); + ApiVersion = std::min(ApiVersion, MaxApiVersion); + LOG_INFO_MESSAGE("Used Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion)); + } +#endif + VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -192,7 +204,7 @@ VulkanInstance::VulkanInstance(bool EnableValidation, appInfo.applicationVersion = 0; // Developer-supplied version number of the application appInfo.pEngineName = "Diligent Engine"; appInfo.engineVersion = 0; // Developer-supplied version number of the engine used to create the application. - appInfo.apiVersion = VK_API_VERSION_1_0; + appInfo.apiVersion = ApiVersion; VkInstanceCreateInfo InstanceCreateInfo = {}; @@ -229,6 +241,7 @@ VulkanInstance::VulkanInstance(bool EnableValidation, #endif m_EnabledExtensions = std::move(GlobalExtensions); + m_VkVersion = ApiVersion; // If requested, we enable the default validation layers for debugging if (m_DebugUtilsEnabled) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp index f9e190d8..358bdec5 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp @@ -36,9 +36,10 @@ namespace VulkanUtilities std::shared_ptr VulkanLogicalDevice::Create(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator) { - auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, vkAllocator}; + auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, EnabledExtFeatures, vkAllocator}; return std::shared_ptr{LogicalDevice}; } @@ -49,9 +50,11 @@ VulkanLogicalDevice::~VulkanLogicalDevice() VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice, const VkDeviceCreateInfo& DeviceCI, + const ExtensionFeatures& EnabledExtFeatures, const VkAllocationCallbacks* vkAllocator) : m_VkAllocator{vkAllocator}, - m_EnabledFeatures{*DeviceCI.pEnabledFeatures} + m_EnabledFeatures{*DeviceCI.pEnabledFeatures}, + m_EnabledExtFeatures{EnabledExtFeatures} { auto res = vkCreateDevice(PhysicalDevice.GetVkDeviceHandle(), &DeviceCI, vkAllocator, &m_VkDevice); CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device"); @@ -225,6 +228,29 @@ PipelineWrapper VulkanLogicalDevice::CreateGraphicsPipeline(const VkGraphicsPipe return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)}; } +PipelineWrapper VulkanLogicalDevice::CreateRayTracingPipeline(const VkRayTracingPipelineCreateInfoKHR& PipelineCI, VkPipelineCache cache, const char* DebugName) const +{ +#if DILIGENT_USE_VOLK + VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR); + + if (DebugName == nullptr) + DebugName = ""; + + VkPipeline vkPipeline = VK_NULL_HANDLE; + + auto err = vkCreateRayTracingPipelinesKHR(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline); + CHECK_VK_ERROR_AND_THROW(err, "Failed to create ray tracing pipeline '", DebugName, '\''); + + if (*DebugName != 0) + SetPipelineName(m_VkDevice, vkPipeline, DebugName); + + return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)}; +#else + UNSUPPORTED("vkCreateRayTracingPipelinesKHR is only available through Volk"); + return PipelineWrapper{}; +#endif +} + ShaderModuleWrapper VulkanLogicalDevice::CreateShaderModule(const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName) const { VERIFY_EXPR(ShaderModuleCI.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO); @@ -455,6 +481,7 @@ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkI VkMemoryRequirements VulkanLogicalDevice::GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const { VkMemoryRequirements2 MemReqs = {}; + MemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; #if DILIGENT_USE_VOLK vkGetAccelerationStructureMemoryRequirementsKHR(m_VkDevice, &Info, &MemReqs); #else @@ -571,4 +598,14 @@ VkResult VulkanLogicalDevice::ResetDescriptorPool(VkDescriptorPool vkD return err; } +VkResult VulkanLogicalDevice::GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const +{ +#if DILIGENT_USE_VOLK + return vkGetRayTracingShaderGroupHandlesKHR(m_VkDevice, pipeline, firstGroup, groupCount, dataSize, pData); +#else + UNSUPPORTED("vkGetRayTracingShaderGroupHandlesKHR is only available through Volk"); + return VK_ERROR_FEATURE_NOT_PRESENT; +#endif +} + } // namespace VulkanUtilities diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index 3e5f28d4..b66ac8af 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -166,6 +166,17 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.DescriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT; } + // Additional extension that is required for ray tracing shader. + if (IsExtensionSupported(VK_KHR_SPIRV_1_4_EXTENSION_NAME)) + m_ExtFeatures.Spirv14 = true; + + // Some features requires SPIRV 1.4 or 1.5 that added to Vulkan 1.2 core. + if (Instance.GetVkVersion() >= VK_API_VERSION_1_2) + { + m_ExtFeatures.Spirv14 = true; + m_ExtFeatures.Spirv15 = true; + } + // make sure that last pNext is null *NextFeat = nullptr; *NextProp = nullptr; @@ -178,7 +189,6 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, // Emulate KHR extension if (m_ExtFeatures.RayTracingNV) { - //m_ExtFeatures.RayTracing.sType //m_ExtFeatures.RayTracing.rayTracingPrimitiveCulling = true; // AZ TODO m_ExtFeatures.RayTracing.rayTracing = VK_TRUE; @@ -188,7 +198,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment; m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount; m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount; - m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount; + m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount / 3; m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures; m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0; } diff --git a/Graphics/ShaderTools/include/GLSLUtils.hpp b/Graphics/ShaderTools/include/GLSLUtils.hpp index 4c8b92c8..53fbeab7 100644 --- a/Graphics/ShaderTools/include/GLSLUtils.hpp +++ b/Graphics/ShaderTools/include/GLSLUtils.hpp @@ -34,7 +34,7 @@ namespace Diligent { -enum TargetGLSLCompiler +enum class TargetGLSLCompiler { glslang, driver diff --git a/Graphics/ShaderTools/include/GLSLangUtils.hpp b/Graphics/ShaderTools/include/GLSLangUtils.hpp index b61bb5e6..6a459911 100644 --- a/Graphics/ShaderTools/include/GLSLangUtils.hpp +++ b/Graphics/ShaderTools/include/GLSLangUtils.hpp @@ -37,6 +37,14 @@ namespace Diligent namespace GLSLangUtils { +enum class SpirvVersion +{ + Vk100, // SPIRV 1.0 + Vk110, // SPIRV 1.3 + Vk110_Spirv14, // SPIRV 1.4 (extension) + Vk120, // SPIRV 1.4 +}; + void InitializeGlslang(); void FinalizeGlslang(); @@ -45,6 +53,7 @@ std::vector GLSLtoSPIRV(SHADER_TYPE ShaderTyp int SourceCodeLen, const ShaderMacro* Macros, IShaderSourceInputStreamFactory* pShaderSourceStreamFactory, + SpirvVersion Version, IDataBlob** ppCompilerOutput); std::vector HLSLtoSPIRV(const ShaderCreateInfo& ShaderCI, diff --git a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp index 091e2343..338bf602 100644 --- a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp +++ b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp @@ -71,6 +71,7 @@ struct SPIRVShaderResourceAttribs SeparateImage, SeparateSampler, InputAttachment, + AccelerationStructure, NumResourceTypes }; @@ -137,19 +138,6 @@ public: SepSmplrOrImgInd = SepImageInd; } - String GetPrintName(Uint32 ArrayInd) const - { - VERIFY_EXPR(ArrayInd < ArraySize); - if (ArraySize > 1) - { - std::stringstream ss; - ss << Name << '[' << ArrayInd << ']'; - return ss.str(); - } - else - return Name; - } - bool IsCompatibleWith(const SPIRVShaderResourceAttribs& Attribs) const { // clang-format off @@ -211,26 +199,28 @@ public: // clang-format off - Uint32 GetNumUBs ()const noexcept{ return (m_StorageBufferOffset - 0); } - Uint32 GetNumSBs ()const noexcept{ return (m_StorageImageOffset - m_StorageBufferOffset); } - Uint32 GetNumImgs ()const noexcept{ return (m_SampledImageOffset - m_StorageImageOffset); } - Uint32 GetNumSmpldImgs()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); } - Uint32 GetNumACs ()const noexcept{ return (m_SeparateSamplerOffset - m_AtomicCounterOffset); } - Uint32 GetNumSepSmplrs()const noexcept{ return (m_SeparateImageOffset - m_SeparateSamplerOffset);} - Uint32 GetNumSepImgs ()const noexcept{ return (m_InputAttachmentOffset - m_SeparateImageOffset); } - Uint32 GetNumInptAtts ()const noexcept{ return (m_TotalResources - m_InputAttachmentOffset);} - Uint32 GetTotalResources() const noexcept { return m_TotalResources; } + Uint32 GetNumUBs ()const noexcept{ return (m_StorageBufferOffset - 0); } + Uint32 GetNumSBs ()const noexcept{ return (m_StorageImageOffset - m_StorageBufferOffset); } + Uint32 GetNumImgs ()const noexcept{ return (m_SampledImageOffset - m_StorageImageOffset); } + Uint32 GetNumSmpldImgs ()const noexcept{ return (m_AtomicCounterOffset - m_SampledImageOffset); } + Uint32 GetNumACs ()const noexcept{ return (m_SeparateSamplerOffset - m_AtomicCounterOffset); } + Uint32 GetNumSepSmplrs ()const noexcept{ return (m_SeparateImageOffset - m_SeparateSamplerOffset);} + Uint32 GetNumSepImgs ()const noexcept{ return (m_InputAttachmentOffset - m_SeparateImageOffset); } + Uint32 GetNumInptAtts ()const noexcept{ return (m_AccelStructOffset - m_InputAttachmentOffset);} + Uint32 GetNumAccelStructs()const noexcept{ return (m_TotalResources - m_AccelStructOffset); } + Uint32 GetTotalResources () const noexcept { return m_TotalResources; } Uint32 GetNumShaderStageInputs()const noexcept { return m_NumShaderStageInputs; } - const SPIRVShaderResourceAttribs& GetUB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } - const SPIRVShaderResourceAttribs& GetSB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } - const SPIRVShaderResourceAttribs& GetImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } - const SPIRVShaderResourceAttribs& GetSmpldImg(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); } - const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } - const SPIRVShaderResourceAttribs& GetSepSmplr(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); } - const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } - const SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); } - const SPIRVShaderResourceAttribs& GetResource(Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); } + const SPIRVShaderResourceAttribs& GetUB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } + const SPIRVShaderResourceAttribs& GetSB (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } + const SPIRVShaderResourceAttribs& GetImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } + const SPIRVShaderResourceAttribs& GetSmpldImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); } + const SPIRVShaderResourceAttribs& GetAC (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } + const SPIRVShaderResourceAttribs& GetSepSmplr (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); } + const SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } + const SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)const noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); } + const SPIRVShaderResourceAttribs& GetAccelStruct(Uint32 n)const noexcept{ return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructOffset ); } + const SPIRVShaderResourceAttribs& GetResource (Uint32 n)const noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); } // clang-format on @@ -250,14 +240,15 @@ public: struct ResourceCounters { - Uint32 NumUBs = 0; - Uint32 NumSBs = 0; - Uint32 NumImgs = 0; - Uint32 NumSmpldImgs = 0; - Uint32 NumACs = 0; - Uint32 NumSepSmplrs = 0; - Uint32 NumSepImgs = 0; - Uint32 NumInptAtts = 0; + Uint32 NumUBs = 0; + Uint32 NumSBs = 0; + Uint32 NumImgs = 0; + Uint32 NumSmpldImgs = 0; + Uint32 NumACs = 0; + Uint32 NumSepSmplrs = 0; + Uint32 NumSepImgs = 0; + Uint32 NumInptAtts = 0; + Uint32 NumAccelStructs = 0; }; SHADER_TYPE GetShaderType() const noexcept { return m_ShaderType; } @@ -270,15 +261,17 @@ public: typename THandleAC, typename THandleSepSmpl, typename THandleSepImg, - typename THandleInptAtt> - void ProcessResources(THandleUB HandleUB, - THandleSB HandleSB, - THandleImg HandleImg, - THandleSmplImg HandleSmplImg, - THandleAC HandleAC, - THandleSepSmpl HandleSepSmpl, - THandleSepImg HandleSepImg, - THandleInptAtt HandleInptAtt) const + typename THandleInptAtt, + typename THandleAccelStruct> + void ProcessResources(THandleUB HandleUB, + THandleSB HandleSB, + THandleImg HandleImg, + THandleSmplImg HandleSmplImg, + THandleAC HandleAC, + THandleSepSmpl HandleSepSmpl, + THandleSepImg HandleSepImg, + THandleInptAtt HandleInptAtt, + THandleAccelStruct HandleAccelStruct) const { for (Uint32 n = 0; n < GetNumUBs(); ++n) { @@ -328,7 +321,13 @@ public: HandleInptAtt(InptAtt, n); } - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type here, if needed"); + for (Uint32 n = 0; n < GetNumAccelStructs(); ++n) + { + const auto& AccelStruct = GetAccelStruct(n); + HandleAccelStruct(AccelStruct, n); + } + + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type here, if needed"); } template @@ -378,15 +377,16 @@ private: // clang-format off - SPIRVShaderResourceAttribs& GetUB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } - SPIRVShaderResourceAttribs& GetSB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } - SPIRVShaderResourceAttribs& GetImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } - SPIRVShaderResourceAttribs& GetSmpldImg(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); } - SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } - SPIRVShaderResourceAttribs& GetSepSmplr(Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); } - SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } - SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); } - SPIRVShaderResourceAttribs& GetResource(Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); } + SPIRVShaderResourceAttribs& GetUB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumUBs(), 0 ); } + SPIRVShaderResourceAttribs& GetSB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSBs(), m_StorageBufferOffset ); } + SPIRVShaderResourceAttribs& GetImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumImgs(), m_StorageImageOffset ); } + SPIRVShaderResourceAttribs& GetSmpldImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSmpldImgs(), m_SampledImageOffset ); } + SPIRVShaderResourceAttribs& GetAC (Uint32 n)noexcept{ return GetResAttribs(n, GetNumACs(), m_AtomicCounterOffset ); } + SPIRVShaderResourceAttribs& GetSepSmplr (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepSmplrs(), m_SeparateSamplerOffset); } + SPIRVShaderResourceAttribs& GetSepImg (Uint32 n)noexcept{ return GetResAttribs(n, GetNumSepImgs(), m_SeparateImageOffset ); } + SPIRVShaderResourceAttribs& GetInptAtt (Uint32 n)noexcept{ return GetResAttribs(n, GetNumInptAtts(), m_InputAttachmentOffset); } + SPIRVShaderResourceAttribs& GetAccelStruct(Uint32 n)noexcept{ return GetResAttribs(n, GetNumAccelStructs(), m_AccelStructOffset ); } + SPIRVShaderResourceAttribs& GetResource (Uint32 n)noexcept{ return GetResAttribs(n, GetTotalResources(), 0 ); } // clang-format on @@ -410,6 +410,7 @@ private: OffsetType m_SeparateSamplerOffset = 0; OffsetType m_SeparateImageOffset = 0; OffsetType m_InputAttachmentOffset = 0; + OffsetType m_AccelStructOffset = 0; OffsetType m_TotalResources = 0; OffsetType m_NumShaderStageInputs = 0; diff --git a/Graphics/ShaderTools/src/DXCompiler.cpp b/Graphics/ShaderTools/src/DXCompiler.cpp index 1f818af7..75782aaa 100644 --- a/Graphics/ShaderTools/src/DXCompiler.cpp +++ b/Graphics/ShaderTools/src/DXCompiler.cpp @@ -376,6 +376,199 @@ bool DXCompilerImpl::Compile(const CompileAttribs& Attribs) return true; } + +#if D3D12_SUPPORTED +class ShaderReflectionViaLibraryReflection final : public ID3D12ShaderReflection +{ +public: + ShaderReflectionViaLibraryReflection(CComPtr pLib, ID3D12FunctionReflection* pFunc) : + m_pLib{std::move(pLib)}, + m_pFunc{pFunc}, + m_RefCount{0} + {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID* ppv) override + { + return E_FAIL; + } + + ULONG STDMETHODCALLTYPE AddRef() override + { + return Atomics::AtomicIncrement(m_RefCount); + } + + ULONG STDMETHODCALLTYPE Release() override + { + auto RefCount = Atomics::AtomicDecrement(m_RefCount); + VERIFY(RefCount >= 0, "Inconsistent call to ReleaseStrongRef()"); + if (RefCount == 0) + { + delete this; + } + return RefCount; + } + + HRESULT STDMETHODCALLTYPE GetDesc(D3D12_SHADER_DESC* pDesc) override + { + D3D12_FUNCTION_DESC FnDesc = {}; + HRESULT hr = m_pFunc->GetDesc(&FnDesc); + if (FAILED(hr)) + return hr; + + pDesc->Version = FnDesc.Version; + pDesc->Creator = FnDesc.Creator; + pDesc->Flags = FnDesc.Flags; + pDesc->ConstantBuffers = FnDesc.ConstantBuffers; + pDesc->BoundResources = FnDesc.BoundResources; + pDesc->InputParameters = 0; + pDesc->OutputParameters = 0; + pDesc->InstructionCount = FnDesc.InstructionCount; + pDesc->TempRegisterCount = FnDesc.TempRegisterCount; + pDesc->TempArrayCount = FnDesc.TempArrayCount; + pDesc->DefCount = FnDesc.DefCount; + pDesc->DclCount = FnDesc.DclCount; + pDesc->TextureNormalInstructions = FnDesc.TextureNormalInstructions; + pDesc->TextureLoadInstructions = FnDesc.TextureLoadInstructions; + pDesc->TextureCompInstructions = FnDesc.TextureCompInstructions; + pDesc->TextureBiasInstructions = FnDesc.TextureBiasInstructions; + pDesc->TextureGradientInstructions = FnDesc.TextureGradientInstructions; + pDesc->FloatInstructionCount = FnDesc.FloatInstructionCount; + pDesc->IntInstructionCount = FnDesc.IntInstructionCount; + pDesc->UintInstructionCount = FnDesc.UintInstructionCount; + pDesc->StaticFlowControlCount = FnDesc.StaticFlowControlCount; + pDesc->DynamicFlowControlCount = FnDesc.DynamicFlowControlCount; + pDesc->MacroInstructionCount = FnDesc.MacroInstructionCount; + pDesc->ArrayInstructionCount = FnDesc.ArrayInstructionCount; + pDesc->CutInstructionCount = 0; + pDesc->EmitInstructionCount = 0; + pDesc->GSOutputTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + pDesc->GSMaxOutputVertexCount = 0; + pDesc->InputPrimitive = D3D_PRIMITIVE_UNDEFINED; + pDesc->PatchConstantParameters = 0; + pDesc->cGSInstanceCount = 0; + pDesc->cControlPoints = 0; + pDesc->HSOutputPrimitive = D3D_TESSELLATOR_OUTPUT_UNDEFINED; + pDesc->HSPartitioning = D3D_TESSELLATOR_PARTITIONING_UNDEFINED; + pDesc->TessellatorDomain = D3D_TESSELLATOR_DOMAIN_UNDEFINED; + pDesc->cBarrierInstructions = 0; + pDesc->cInterlockedInstructions = 0; + pDesc->cTextureStoreInstructions = 0; + + return S_OK; + } + + ID3D12ShaderReflectionConstantBuffer* STDMETHODCALLTYPE GetConstantBufferByIndex(UINT Index) override + { + return m_pFunc->GetConstantBufferByIndex(Index); + } + + ID3D12ShaderReflectionConstantBuffer* STDMETHODCALLTYPE GetConstantBufferByName(LPCSTR Name) override + { + return m_pFunc->GetConstantBufferByName(Name); + } + + HRESULT STDMETHODCALLTYPE GetResourceBindingDesc(UINT ResourceIndex, D3D12_SHADER_INPUT_BIND_DESC* pDesc) override + { + return m_pFunc->GetResourceBindingDesc(ResourceIndex, pDesc); + } + + HRESULT STDMETHODCALLTYPE GetInputParameterDesc(UINT ParameterIndex, D3D12_SIGNATURE_PARAMETER_DESC* pDesc) override + { + UNEXPECTED("not supported"); + return E_FAIL; + } + + HRESULT STDMETHODCALLTYPE GetOutputParameterDesc(UINT ParameterIndex, D3D12_SIGNATURE_PARAMETER_DESC* pDesc) override + { + UNEXPECTED("not supported"); + return E_FAIL; + } + + HRESULT STDMETHODCALLTYPE GetPatchConstantParameterDesc(UINT ParameterIndex, D3D12_SIGNATURE_PARAMETER_DESC* pDesc) override + { + UNEXPECTED("not supported"); + return E_FAIL; + } + + ID3D12ShaderReflectionVariable* STDMETHODCALLTYPE GetVariableByName(LPCSTR Name) override + { + return m_pFunc->GetVariableByName(Name); + } + + HRESULT STDMETHODCALLTYPE GetResourceBindingDescByName(LPCSTR Name, D3D12_SHADER_INPUT_BIND_DESC* pDesc) override + { + return m_pFunc->GetResourceBindingDescByName(Name, pDesc); + } + + UINT STDMETHODCALLTYPE GetMovInstructionCount() override + { + UNEXPECTED("not supported"); + return 0; + } + + UINT STDMETHODCALLTYPE GetMovcInstructionCount() override + { + UNEXPECTED("not supported"); + return 0; + } + + UINT STDMETHODCALLTYPE GetConversionInstructionCount() override + { + UNEXPECTED("not supported"); + return 0; + } + + UINT STDMETHODCALLTYPE GetBitwiseInstructionCount() override + { + UNEXPECTED("not supported"); + return 0; + } + + D3D_PRIMITIVE STDMETHODCALLTYPE GetGSInputPrimitive() override + { + UNEXPECTED("not supported"); + return D3D_PRIMITIVE_UNDEFINED; + } + + BOOL STDMETHODCALLTYPE IsSampleFrequencyShader() override + { + UNEXPECTED("not supported"); + return FALSE; + } + + UINT STDMETHODCALLTYPE GetNumInterfaceSlots() override + { + UNEXPECTED("not supported"); + return 0; + } + + HRESULT STDMETHODCALLTYPE GetMinFeatureLevel(D3D_FEATURE_LEVEL* pLevel) override + { + UNEXPECTED("not supported"); + return E_FAIL; + } + + UINT STDMETHODCALLTYPE GetThreadGroupSize(UINT* pSizeX, UINT* pSizeY, UINT* pSizeZ) override + { + UNEXPECTED("not supported"); + *pSizeX = *pSizeY = *pSizeZ = 0; + return 0; + } + + UINT64 STDMETHODCALLTYPE GetRequiresFlags() override + { + UNEXPECTED("not supported"); + return 0; + } + +private: + CComPtr m_pLib; + ID3D12FunctionReflection* m_pFunc = nullptr; + Atomics::AtomicLong m_RefCount; +}; +#endif // D3D12_SUPPORTED + + void DXCompilerImpl::GetD3D12ShaderReflection(IDxcBlob* pShaderBytecode, ID3D12ShaderReflection** ppShaderReflection) { @@ -386,9 +579,6 @@ void DXCompilerImpl::GetD3D12ShaderReflection(IDxcBlob* pShaderBy if (CreateInstance == nullptr) return; -# define FOURCC(a, b, c, d) (uint32_t{((d) << 24) | ((c) << 16) | ((b) << 8) | (a)}) - const uint32_t DFCC_DXIL = FOURCC('D', 'X', 'I', 'L'); - CComPtr pReflection; auto hr = CreateInstance(CLSID_DxcContainerReflection, IID_PPV_ARGS(&pReflection)); @@ -401,18 +591,39 @@ void DXCompilerImpl::GetD3D12ShaderReflection(IDxcBlob* pShaderBy UINT32 shaderIdx; - hr = pReflection->FindFirstPartKind(DFCC_DXIL, &shaderIdx); + hr = pReflection->FindFirstPartKind(DXC_PART_DXIL, &shaderIdx); if (SUCCEEDED(hr)) { - hr = pReflection->GetPartReflection(shaderIdx, __uuidof(*ppShaderReflection), reinterpret_cast(ppShaderReflection)); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to get the shader reflection"); + hr = pReflection->GetPartReflection(shaderIdx, IID_PPV_ARGS(ppShaderReflection)); + if (SUCCEEDED(hr)) + return; + + // for ray tracing shaders + CComPtr pLib; + + hr = pReflection->GetPartReflection(shaderIdx, IID_PPV_ARGS(&pLib)); + if (SUCCEEDED(hr)) + { + D3D12_LIBRARY_DESC Desc = {}; + pLib->GetDesc(&Desc); + VERIFY_EXPR(Desc.FunctionCount == 1); + + ID3D12FunctionReflection* pFunc = pLib->GetFunctionByIndex(0); + if (pFunc != nullptr) + { + *ppShaderReflection = new ShaderReflectionViaLibraryReflection{std::move(pLib), pFunc}; + (*ppShaderReflection)->AddRef(); + return; + } + } } + + LOG_ERROR_AND_THROW("Failed to get the shader reflection"); } catch (...) { } -#endif +#endif // D3D12_SUPPORTED } @@ -470,19 +681,28 @@ void DXCompilerImpl::Compile(const ShaderCreateInfo& ShaderCI, DxilArgs.push_back(L"-Qembed_debug"); } #else - DxilArgs.push_back(L"-Od"); // TODO: something goes wrong if optimization is enabled + if (m_MajorVer > 1 || m_MajorVer == 1 && m_MinorVer >= 5) + DxilArgs.push_back(L"-O3"); // Optimization level 3 + else + DxilArgs.push_back(L"-Od"); // TODO: something goes wrong if optimization is enabled #endif } else if (m_Target == DXCompilerTarget::Vulkan) { + const Uint32 RayTracingStages = + SHADER_TYPE_RAY_GEN | SHADER_TYPE_RAY_MISS | SHADER_TYPE_RAY_CLOSEST_HIT | + SHADER_TYPE_RAY_ANY_HIT | SHADER_TYPE_RAY_INTERSECTION | SHADER_TYPE_CALLABLE; + DxilArgs.assign( { L"-spirv", L"-fspv-reflect", - L"-fspv-target-env=vulkan1.0", //L"-WX", // Warnings as errors L"-O3", // Optimization level 3 }); + + if (ShaderCI.Desc.ShaderType & RayTracingStages) + DxilArgs.push_back(L"-fspv-target-env=vulkan1.2"); } else { diff --git a/Graphics/ShaderTools/src/GLSLangUtils.cpp b/Graphics/ShaderTools/src/GLSLangUtils.cpp index f23a46a3..75d97528 100644 --- a/Graphics/ShaderTools/src/GLSLangUtils.cpp +++ b/Graphics/ShaderTools/src/GLSLangUtils.cpp @@ -455,6 +455,11 @@ std::vector HLSLtoSPIRV(const ShaderCreateInfo& ShaderCI, VERIFY_EXPR(ShaderCI.SourceLanguage == SHADER_SOURCE_LANGUAGE_HLSL); + VERIFY(ShLang != EShLangRayGen && ShLang != EShLangIntersect && ShLang != EShLangAnyHit && ShLang != EShLangClosestHit && ShLang != EShLangMiss && ShLang != EShLangCallable, + "ray tracing shaders are not supported, use DXCompiler to build SPIRV from HLSL"); + VERIFY(ShLang != EShLangTaskNV && ShLang != EShLangMeshNV, + "mesh shaders are not supported, use DXCompiler to build SPIRV from HLSL"); + Shader.setEnvInput(::glslang::EShSourceHlsl, ShLang, ::glslang::EShClientVulkan, 100); Shader.setEnvClient(::glslang::EShClientVulkan, ::glslang::EShTargetVulkan_1_0); Shader.setEnvTarget(::glslang::EShTargetSpv, ::glslang::EShTargetSpv_1_0); @@ -513,12 +518,41 @@ std::vector GLSLtoSPIRV(SHADER_TYPE ShaderTyp int SourceCodeLen, const ShaderMacro* Macros, IShaderSourceInputStreamFactory* pShaderSourceStreamFactory, + SpirvVersion Version, IDataBlob** ppCompilerOutput) { VERIFY_EXPR(ShaderSource != nullptr && SourceCodeLen > 0); EShLanguage ShLang = ShaderTypeToShLanguage(ShaderType); ::glslang::TShader Shader(ShLang); + spv_target_env spvTarget = SPV_ENV_VULKAN_1_0; + + switch (Version) + { + case SpirvVersion::Vk100: + // keep default + break; + case SpirvVersion::Vk110: + Shader.setEnvInput(::glslang::EShSourceGlsl, ShLang, ::glslang::EShClientVulkan, 110); + Shader.setEnvClient(::glslang::EShClientVulkan, ::glslang::EShTargetVulkan_1_1); + Shader.setEnvTarget(::glslang::EShTargetSpv, ::glslang::EShTargetSpv_1_3); + spvTarget = SPV_ENV_VULKAN_1_1; + break; + case SpirvVersion::Vk110_Spirv14: + Shader.setEnvInput(::glslang::EShSourceGlsl, ShLang, ::glslang::EShClientVulkan, 110); + Shader.setEnvClient(::glslang::EShClientVulkan, ::glslang::EShTargetVulkan_1_1); + Shader.setEnvTarget(::glslang::EShTargetSpv, ::glslang::EShTargetSpv_1_4); + spvTarget = SPV_ENV_VULKAN_1_1_SPIRV_1_4; + break; + case SpirvVersion::Vk120: + Shader.setEnvInput(::glslang::EShSourceGlsl, ShLang, ::glslang::EShClientVulkan, 120); + Shader.setEnvClient(::glslang::EShClientVulkan, ::glslang::EShTargetVulkan_1_2); + Shader.setEnvTarget(::glslang::EShTargetSpv, ::glslang::EShTargetSpv_1_4); + spvTarget = SPV_ENV_VULKAN_1_2; + break; + default: + UNEXPECTED("Unknown SPIRV version"); + } EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); @@ -539,7 +573,7 @@ std::vector GLSLtoSPIRV(SHADER_TYPE ShaderTyp if (SPIRV.empty()) return SPIRV; - spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0); + spvtools::Optimizer SpirvOptimizer(spvTarget); SpirvOptimizer.RegisterPerformancePasses(); std::vector OptimizedSPIRV; if (SpirvOptimizer.Run(SPIRV.data(), SPIRV.size(), &OptimizedSPIRV)) diff --git a/Graphics/ShaderTools/src/HLSLUtils.cpp b/Graphics/ShaderTools/src/HLSLUtils.cpp index 613eea25..72f201b7 100644 --- a/Graphics/ShaderTools/src/HLSLUtils.cpp +++ b/Graphics/ShaderTools/src/HLSLUtils.cpp @@ -68,17 +68,25 @@ String BuildHLSLSourceString(const ShaderCreateInfo& ShaderCI, String GetHLSLProfileString(SHADER_TYPE ShaderType, ShaderVersion ShaderModel) { String strShaderProfile; + + static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type"); switch (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_AMPLIFICATION: strShaderProfile = "as"; break; - case SHADER_TYPE_MESH: strShaderProfile = "ms"; 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; + case SHADER_TYPE_RAY_GEN: + case SHADER_TYPE_RAY_MISS: + case SHADER_TYPE_RAY_CLOSEST_HIT: + case SHADER_TYPE_RAY_ANY_HIT: + case SHADER_TYPE_RAY_INTERSECTION: + case SHADER_TYPE_CALLABLE: strShaderProfile = "lib"; break; // clang-format on default: UNEXPECTED("Unknown shader type"); } diff --git a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp index cda18772..7f1d78d5 100644 --- a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp +++ b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp @@ -133,7 +133,7 @@ ShaderResourceDesc SPIRVShaderResourceAttribs::GetResourceDesc() const ResourceDesc.Name = Name; ResourceDesc.ArraySize = ArraySize; - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below"); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); switch (Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: @@ -183,6 +183,10 @@ ShaderResourceDesc SPIRVShaderResourceAttribs::GetResourceDesc() const ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT; break; + case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT; + break; + default: UNEXPECTED("Unknown SPIRV resource type"); } @@ -299,7 +303,7 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, size_t ResourceNamesPoolSize = 0; for (const auto& ub : resources.uniform_buffers) ResourceNamesPoolSize += GetUBName(Compiler, ub, ParsedIRSource).length() + 1; - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please account for the new resource type below"); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please account for the new resource type below"); for (auto* pResType : { &resources.storage_buffers, @@ -308,7 +312,8 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, &resources.atomic_counters, &resources.separate_images, &resources.separate_samplers, - &resources.subpass_inputs + &resources.subpass_inputs, + &resources.acceleration_structures // clang-format off }) // clang-format on @@ -371,15 +376,16 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, } ResourceCounters ResCounters; - ResCounters.NumUBs = static_cast(resources.uniform_buffers.size()); - ResCounters.NumSBs = static_cast(resources.storage_buffers.size()); - ResCounters.NumImgs = static_cast(resources.storage_images.size()); - ResCounters.NumSmpldImgs = static_cast(resources.sampled_images.size()); - ResCounters.NumACs = static_cast(resources.atomic_counters.size()); - ResCounters.NumSepSmplrs = static_cast(resources.separate_samplers.size()); - ResCounters.NumSepImgs = static_cast(resources.separate_images.size()); - ResCounters.NumInptAtts = static_cast(resources.subpass_inputs.size()); - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please set the new resource type counter here"); + ResCounters.NumUBs = static_cast(resources.uniform_buffers.size()); + ResCounters.NumSBs = static_cast(resources.storage_buffers.size()); + ResCounters.NumImgs = static_cast(resources.storage_images.size()); + ResCounters.NumSmpldImgs = static_cast(resources.sampled_images.size()); + ResCounters.NumACs = static_cast(resources.atomic_counters.size()); + ResCounters.NumSepSmplrs = static_cast(resources.separate_samplers.size()); + ResCounters.NumSepImgs = static_cast(resources.separate_images.size()); + ResCounters.NumInptAtts = static_cast(resources.subpass_inputs.size()); + ResCounters.NumAccelStructs = static_cast(resources.acceleration_structures.size()); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please set the new resource type counter here"); // Resource names pool is only needed to facilitate string allocation. StringPool ResourceNamesPool; @@ -543,7 +549,20 @@ SPIRVShaderResources::SPIRVShaderResources(IMemoryAllocator& Allocator, VERIFY_EXPR(CurrSubpassInput == GetNumInptAtts()); } - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please initialize SPIRVShaderResourceAttribs for the new resource type here"); + { + Uint32 CurrAccelStruct = 0; + for (const auto& AccelStruct : resources.acceleration_structures) + { + new (&GetAccelStruct(CurrAccelStruct++)) + SPIRVShaderResourceAttribs(Compiler, + AccelStruct, + ResourceNamesPool.CopyString(AccelStruct.name), + SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure); + } + VERIFY_EXPR(CurrAccelStruct == GetNumAccelStructs()); + } + + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please initialize SPIRVShaderResourceAttribs for the new resource type here"); if (CombinedSamplerSuffix != nullptr) { @@ -609,8 +628,9 @@ void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator, m_SeparateSamplerOffset = AdvanceOffset(Counters.NumSepSmplrs); m_SeparateImageOffset = AdvanceOffset(Counters.NumSepImgs); m_InputAttachmentOffset = AdvanceOffset(Counters.NumInptAtts); + m_AccelStructOffset = AdvanceOffset(Counters.NumAccelStructs); m_TotalResources = AdvanceOffset(0); - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please update the new resource type offset"); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please update the new resource type offset"); VERIFY(NumShaderStageInputs <= MaxOffset, "Max offset exceeded"); m_NumShaderStageInputs = static_cast(NumShaderStageInputs); @@ -623,14 +643,16 @@ void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator, m_NumShaderStageInputs * sizeof(SPIRVShaderStageInputAttribs) + AlignedResourceNamesPoolSize * sizeof(char); - VERIFY_EXPR(GetNumUBs() == Counters.NumUBs); - VERIFY_EXPR(GetNumSBs() == Counters.NumSBs); - VERIFY_EXPR(GetNumImgs() == Counters.NumImgs); - VERIFY_EXPR(GetNumSmpldImgs() == Counters.NumSmpldImgs); - VERIFY_EXPR(GetNumACs() == Counters.NumACs); - VERIFY_EXPR(GetNumSepSmplrs() == Counters.NumSepSmplrs); - VERIFY_EXPR(GetNumSepImgs() == Counters.NumSepImgs); - VERIFY_EXPR(GetNumInptAtts() == Counters.NumInptAtts); + VERIFY_EXPR(GetNumUBs() == Counters.NumUBs); + VERIFY_EXPR(GetNumSBs() == Counters.NumSBs); + VERIFY_EXPR(GetNumImgs() == Counters.NumImgs); + VERIFY_EXPR(GetNumSmpldImgs() == Counters.NumSmpldImgs); + VERIFY_EXPR(GetNumACs() == Counters.NumACs); + VERIFY_EXPR(GetNumSepSmplrs() == Counters.NumSepSmplrs); + VERIFY_EXPR(GetNumSepImgs() == Counters.NumSepImgs); + VERIFY_EXPR(GetNumInptAtts() == Counters.NumInptAtts); + VERIFY_EXPR(GetNumAccelStructs() == Counters.NumAccelStructs); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please update the new resource count verification"); // clang-format on if (MemorySize) @@ -670,8 +692,13 @@ SPIRVShaderResources::~SPIRVShaderResources() for (Uint32 n = 0; n < GetNumInptAtts(); ++n) GetInptAtt(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumAccelStructs(); ++n) + GetAccelStruct(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumShaderStageInputs(); ++n) GetShaderStageInputAttribs(n).~SPIRVShaderStageInputAttribs(); + + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please add destructor for the new resource"); } @@ -710,7 +737,7 @@ std::string SPIRVShaderResources::DumpResources() { VERIFY(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Unexpected resource type"); ss << std::endl - << std::setw(3) << ResNum << " Uniform Buffer "; + << std::setw(3) << ResNum << " Uniform Buffer "; DumpResource(UB); }, [&](const SPIRVShaderResourceAttribs& SB, Uint32) // @@ -720,7 +747,7 @@ std::string SPIRVShaderResources::DumpResources() "Unexpected resource type"); ss << std::endl << std::setw(3) << ResNum - << (SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? " RO Storage Buffer" : " RW Storage Buffer"); + << (SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? " RO Storage Buffer " : " RW Storage Buffer "); DumpResource(SB); }, [&](const SPIRVShaderResourceAttribs& Img, Uint32) // @@ -728,12 +755,12 @@ std::string SPIRVShaderResources::DumpResources() if (Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage) { ss << std::endl - << std::setw(3) << ResNum << " Storage Image "; + << std::setw(3) << ResNum << " Storage Image "; } else if (Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer) { ss << std::endl - << std::setw(3) << ResNum << " Storage Txl Buff "; + << std::setw(3) << ResNum << " Storage Txl Buff "; } else UNEXPECTED("Unexpected resource type"); @@ -744,12 +771,12 @@ std::string SPIRVShaderResources::DumpResources() if (SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage) { ss << std::endl - << std::setw(3) << ResNum << " Sampled Image "; + << std::setw(3) << ResNum << " Sampled Image "; } else if (SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer) { ss << std::endl - << std::setw(3) << ResNum << " Uniform Txl Buff "; + << std::setw(3) << ResNum << " Uniform Txl Buff "; } else UNEXPECTED("Unexpected resource type"); @@ -759,29 +786,36 @@ std::string SPIRVShaderResources::DumpResources() { VERIFY(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter, "Unexpected resource type"); ss << std::endl - << std::setw(3) << ResNum << " Atomic Cntr "; + << std::setw(3) << ResNum << " Atomic Cntr "; DumpResource(AC); }, [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) // { VERIFY(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Unexpected resource type"); ss << std::endl - << std::setw(3) << ResNum << " Separate Smpl "; + << std::setw(3) << ResNum << " Separate Smpl "; DumpResource(SepSmpl); }, [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) // { VERIFY(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, "Unexpected resource type"); ss << std::endl - << std::setw(3) << ResNum << " Separate Img "; + << std::setw(3) << ResNum << " Separate Img "; DumpResource(SepImg); }, [&](const SPIRVShaderResourceAttribs& InptAtt, Uint32) // { VERIFY(InptAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Unexpected resource type"); ss << std::endl - << std::setw(3) << ResNum << " Input Attachment "; + << std::setw(3) << ResNum << " Input Attachment "; DumpResource(InptAtt); + }, + [&](const SPIRVShaderResourceAttribs& AccelStruct, Uint32) // + { + VERIFY(AccelStruct.Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Unexpected resource type"); + ss << std::endl + << std::setw(3) << ResNum << " Acceleration Struct"; + DumpResource(AccelStruct); } // ); VERIFY_EXPR(ResNum == GetTotalResources()); @@ -801,10 +835,12 @@ bool SPIRVShaderResources::IsCompatibleWith(const SPIRVShaderResources& Resource GetNumACs() != Resources.GetNumACs() || GetNumSepImgs() != Resources.GetNumSepImgs() || GetNumSepSmplrs() != Resources.GetNumSepSmplrs() || - GetNumInptAtts() != Resources.GetNumInptAtts()) + GetNumInptAtts() != Resources.GetNumInptAtts() || + GetNumAccelStructs() != Resources.GetNumAccelStructs()) return false; // clang-format on VERIFY_EXPR(GetTotalResources() == Resources.GetTotalResources()); + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please update comparison with the new resource"); bool IsCompatible = true; ProcessResources( diff --git a/Graphics/ShaderTools/src/ShaderToolsCommon.cpp b/Graphics/ShaderTools/src/ShaderToolsCommon.cpp index dfb12bec..41d73b4a 100644 --- a/Graphics/ShaderTools/src/ShaderToolsCommon.cpp +++ b/Graphics/ShaderTools/src/ShaderToolsCommon.cpp @@ -35,30 +35,43 @@ namespace Diligent namespace { -const ShaderMacro VSMacros[] = {{"VERTEX_SHADER", "1"}, {}}; -const ShaderMacro PSMacros[] = {{"FRAGMENT_SHADER", "1"}, {"PIXEL_SHADER", "1"}, {}}; -const ShaderMacro GSMacros[] = {{"GEOMETRY_SHADER", "1"}, {}}; -const ShaderMacro HSMacros[] = {{"TESS_CONTROL_SHADER", "1"}, {"HULL_SHADER", "1"}, {}}; -const ShaderMacro DSMacros[] = {{"TESS_EVALUATION_SHADER", "1"}, {"DOMAIN_SHADER", "1"}, {}}; -const ShaderMacro CSMacros[] = {{"COMPUTE_SHADER", "1"}, {}}; -const ShaderMacro ASMacros[] = {{"TASK_SHADER", "1"}, {"AMPLIFICATION_SHADER", "1"}, {}}; -const ShaderMacro MSMacros[] = {{"MESH_SHADER", "1"}, {}}; +const ShaderMacro VSMacros[] = {{"VERTEX_SHADER", "1"}, {}}; +const ShaderMacro PSMacros[] = {{"FRAGMENT_SHADER", "1"}, {"PIXEL_SHADER", "1"}, {}}; +const ShaderMacro GSMacros[] = {{"GEOMETRY_SHADER", "1"}, {}}; +const ShaderMacro HSMacros[] = {{"TESS_CONTROL_SHADER", "1"}, {"HULL_SHADER", "1"}, {}}; +const ShaderMacro DSMacros[] = {{"TESS_EVALUATION_SHADER", "1"}, {"DOMAIN_SHADER", "1"}, {}}; +const ShaderMacro CSMacros[] = {{"COMPUTE_SHADER", "1"}, {}}; +const ShaderMacro ASMacros[] = {{"TASK_SHADER", "1"}, {"AMPLIFICATION_SHADER", "1"}, {}}; +const ShaderMacro MSMacros[] = {{"MESH_SHADER", "1"}, {}}; +const ShaderMacro RGMacros[] = {{"RAY_GEN_SHADER", "1"}, {}}; +const ShaderMacro RMMacros[] = {{"RAY_MISS_SHADER", "1"}, {}}; +const ShaderMacro RCHMacros[] = {{"RAY_CLOSEST_HIT_SHADER", "1"}, {}}; +const ShaderMacro RAHMacros[] = {{"RAY_ANY_HIT_SHADER", "1"}, {}}; +const ShaderMacro RIMacros[] = {{"RAY_INTERSECTION_SHADER", "1"}, {}}; +const ShaderMacro RCMacros[] = {{"RAY_CALLABLE_SHADER", "1"}, {}}; } // namespace const ShaderMacro* GetShaderTypeMacros(SHADER_TYPE Type) { + static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type"); switch (Type) { // clang-format off - case SHADER_TYPE_VERTEX: return VSMacros; - case SHADER_TYPE_PIXEL: return PSMacros; - case SHADER_TYPE_GEOMETRY: return GSMacros; - case SHADER_TYPE_HULL: return HSMacros; - case SHADER_TYPE_DOMAIN: return DSMacros; - case SHADER_TYPE_COMPUTE: return CSMacros; - case SHADER_TYPE_AMPLIFICATION: return ASMacros; - case SHADER_TYPE_MESH: return MSMacros; + case SHADER_TYPE_VERTEX: return VSMacros; + case SHADER_TYPE_PIXEL: return PSMacros; + case SHADER_TYPE_GEOMETRY: return GSMacros; + case SHADER_TYPE_HULL: return HSMacros; + case SHADER_TYPE_DOMAIN: return DSMacros; + case SHADER_TYPE_COMPUTE: return CSMacros; + case SHADER_TYPE_AMPLIFICATION: return ASMacros; + case SHADER_TYPE_MESH: return MSMacros; + case SHADER_TYPE_RAY_GEN: return RGMacros; + case SHADER_TYPE_RAY_MISS: return RMMacros; + case SHADER_TYPE_RAY_CLOSEST_HIT: return RCHMacros; + case SHADER_TYPE_RAY_ANY_HIT: return RAHMacros; + case SHADER_TYPE_RAY_INTERSECTION: return RIMacros; + case SHADER_TYPE_CALLABLE: return RCMacros; // clang-format on default: UNEXPECTED("Unexpected shader type"); -- cgit v1.2.3