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 --- .../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 +- 18 files changed, 956 insertions(+), 431 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') 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"); } } } -- cgit v1.2.3