From 98d5716a98acf9d12eb45d91eef1440614ef13ec Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 21 Feb 2021 20:20:22 -0800 Subject: Reworked shader resource binding remapping in d3d12; updated PipelineStateD3D12Impl and RootSignatureD3D12 --- .../include/PipelineResourceSignatureD3D12Impl.hpp | 12 +- .../include/PipelineStateD3D12Impl.hpp | 33 ++- .../GraphicsEngineD3D12/include/RootSignature.hpp | 50 ++-- .../src/DeviceContextD3D12Impl.cpp | 10 +- .../src/PipelineResourceSignatureD3D12Impl.cpp | 69 +++++ .../src/PipelineStateD3D12Impl.cpp | 302 ++++++++++----------- .../src/RenderDeviceD3D12Impl.cpp | 2 +- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 137 ++++++---- 8 files changed, 351 insertions(+), 264 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp index d46ad3a5..094f5d20 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp @@ -36,6 +36,7 @@ #include "SRBMemoryAllocator.hpp" #include "RootParamsManager.hpp" #include "ShaderResourceCacheD3D12.hpp" +#include "ResourceBindingMap.hpp" namespace Diligent { @@ -48,8 +49,6 @@ class ShaderVariableManagerD3D12; /// Implementation of the Diligent::PipelineResourceSignatureD3D12Impl class class PipelineResourceSignatureD3D12Impl final : public PipelineResourceSignatureBase { - friend class RootSignatureD3D12; - public: using TPipelineResourceSignatureBase = PipelineResourceSignatureBase; @@ -282,6 +281,15 @@ public: bool IsCompute, bool CommitDynamicBuffers) const; + const RootParamsManager& GetRootParams() const { return m_RootParams; } + + // Adds resources and immutable samplers from this signature to the + // resource binding map. + void UpdateShaderResourceBindingMap(ResourceBinding::TMap& ResourceMap, SHADER_TYPE ShaderStage, Uint32 BaseRegisterSpace) const; + + // Returns true if there is an immutable sampler array in the given shader stage. + bool HasImmutableSamplerArray(SHADER_TYPE ShaderStage) const; + private: using StaticResCacheTblSizesArrayType = std::array; void AllocateRootParameters(StaticResCacheTblSizesArrayType& StaticResCacheTblSizes); diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index d9707c22..57a97796 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -35,12 +35,12 @@ #include "PipelineStateBase.hpp" #include "RootSignature.hpp" #include "RenderDeviceD3D12Impl.hpp" -#include "ShaderD3D12Impl.hpp" namespace Diligent { -class FixedBlockMemoryAllocator; +class ShaderD3D12Impl; +class ShaderResourcesD3D12; /// Pipeline state object implementation in Direct3D12 backend. class PipelineStateD3D12Impl final : public PipelineStateBase @@ -75,12 +75,12 @@ public: const RootSignatureD3D12* GetRootSignature() const { return m_RootSig; } - Uint32 GetSignatureCount() const { return m_SignatureCount; } + Uint32 GetSignatureCount() const { return m_RootSig->GetSignatureCount(); } PipelineResourceSignatureD3D12Impl* GetSignature(Uint32 index) const { - VERIFY_EXPR(index < m_SignatureCount); - return m_Signatures[index].RawPtr(); + VERIFY_EXPR(index < GetSignatureCount()); + return m_ResourceSignatures[index]; } private: @@ -107,10 +107,11 @@ private: TShaderStages& ShaderStages, LocalRootSignatureD3D12* pLocalRootSig); - void CreateDefaultResourceSignature(const PipelineStateCreateInfo& CreateInfo, - TShaderStages& ShaderStages, - LocalRootSignatureD3D12* pLocalRootSig, - IPipelineResourceSignature** ppImplicitSignature); + static RefCntAutoPtr CreateDefaultResourceSignature( + RenderDeviceD3D12Impl* pDevice, + const PipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages, + LocalRootSignatureD3D12* pLocalRootSig); void Destruct(); @@ -126,20 +127,22 @@ private: }; ResourceInfo GetResourceInfo(const char* Name, SHADER_TYPE Stage) const; +#ifdef DILIGENT_DEVELOPMENT + void DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig) const; +#endif + private: CComPtr m_pd3d12PSO; RefCntAutoPtr m_RootSig; - using SignatureArrayType = RootSignatureD3D12::SignatureArrayType; - - Uint8 m_SignatureCount = 0; - SignatureArrayType m_Signatures = {}; + // NB: Pipeline resource signatures used to create the PSO may NOT be the same as + // pipeline resource signatures in m_RootSig, because the latter may be used from the + // cache. While the two signatures may be compatible, they resource names may not be identical. + std::unique_ptr[]> m_ResourceSignatures; #ifdef DILIGENT_DEVELOPMENT // Shader resources for all shaders in all shader stages std::vector> m_ShaderResources; - // Resource info for every resource in m_ShaderResources, in the same order - //std::vector m_ResInfo; #endif }; diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp index 9bc47265..51295859 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp @@ -29,21 +29,23 @@ /// \file /// Declaration of Diligent::RootSignatureD3D12 class + #include #include #include +#include #include "D3D12TypeConversions.hpp" #include "ShaderResourceCacheD3D12.hpp" #include "PipelineResourceSignatureD3D12Impl.hpp" #include "PrivateConstants.h" #include "ShaderResources.hpp" +#include "ResourceBindingMap.hpp" namespace Diligent { class RenderDeviceD3D12Impl; -class PipelineResourceSignatureD3D12Impl; class RootSignatureCacheD3D12; /// Implementation of the Diligent::RootSignature class @@ -61,10 +63,10 @@ public: Uint32 GetSignatureCount() const { return m_SignatureCount; } - PipelineResourceSignatureD3D12Impl* GetSignature(Uint32 index) const + PipelineResourceSignatureD3D12Impl* GetResourceSignature(Uint32 index) const { VERIFY_EXPR(index < m_SignatureCount); - return m_Signatures[index].RawPtr(); + return m_ResourceSignatures[index].pSignature; } ID3D12RootSignature* GetD3D12RootSignature() const @@ -73,16 +75,16 @@ public: return m_pd3d12RootSignature; } - Uint32 GetFirstRootIndex(Uint32 BindingIndex) const + Uint32 GetBaseRootIndex(Uint32 BindingIndex) const { VERIFY_EXPR(BindingIndex < m_SignatureCount); - return m_FirstRootIndex[BindingIndex]; + return m_ResourceSignatures[BindingIndex].BaseRootIndex; } - Uint32 GetFirstRegisterSpace(Uint32 BindingIndex) const + Uint32 GetBaseRegisterSpace(Uint32 BindingIndex) const { VERIFY_EXPR(BindingIndex <= m_SignatureCount); - return m_FirstRegisterSpace[BindingIndex]; + return m_ResourceSignatures[BindingIndex].BaseRegisterSpace; } Uint32 GetTotalSpaces() const @@ -90,23 +92,28 @@ public: return m_TotalSpacesUsed; } - using SignatureArrayType = std::array, MAX_RESOURCE_SIGNATURES>; + bool IsCompatibleWith(const RefCntAutoPtr ppSignatures[], Uint32 SignatureCount) const noexcept; private: - std::array m_FirstRootIndex = {}; - std::array m_FirstRegisterSpace = {}; + // The number of pipeline resource signatures used to initialize this root signature. + const Uint32 m_SignatureCount; - // The total number of register spaces used by this root signature + // The total number of register spaces used by this root signature. Uint32 m_TotalSpacesUsed = 0; - // The number of resource signatures used by this root signature - // (Maximum is MAX_RESOURCE_SIGNATURES) - const Uint8 m_SignatureCount; + // Root signature hash. + const size_t m_Hash; - const size_t m_Hash; CComPtr m_pd3d12RootSignature; - SignatureArrayType m_Signatures = {}; + struct ResourceSignatureInfo + { + RefCntAutoPtr pSignature; + + Uint32 BaseRootIndex = 0; + Uint32 BaseRegisterSpace = 0; + }; + std::unique_ptr m_ResourceSignatures; RootSignatureCacheD3D12& m_Cache; }; @@ -118,13 +125,13 @@ class LocalRootSignatureD3D12 public: LocalRootSignatureD3D12(const char* pCBName, Uint32 ShaderRecordSize); - bool IsShaderRecord(const D3DShaderResourceAttribs& CB); + bool IsShaderRecord(const D3DShaderResourceAttribs& CB) const; bool Create(ID3D12Device* pDevice, Uint32 RegisterSpace); ID3D12RootSignature* GetD3D12RootSignature() const { return m_pd3d12RootSignature; } - bool IsDefined() const { return m_ShaderRecordSize > 0 && m_pName != nullptr; } - const char* GetName() const { return m_pName; } + bool IsDefined() const { return m_ShaderRecordSize > 0 && !m_Name.empty(); } + const char* GetName() const { return m_Name.c_str(); } Uint32 GetShaderRegister() const { return 0; } Uint32 GetRegisterSpace() const @@ -134,7 +141,7 @@ public: } private: - const char* m_pName = nullptr; + const std::string m_Name; const Uint32 m_ShaderRecordSize = 0; Uint32 m_RegisterSpace = ~0u; CComPtr m_pd3d12RootSignature; @@ -163,8 +170,7 @@ public: private: RenderDeviceD3D12Impl& m_DeviceD3D12Impl; - std::mutex m_RootSigCacheGuard; - + std::mutex m_RootSigCacheMtx; std::unordered_multimap> m_RootSigCache; }; diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index d5af4ce0..2fba7309 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -310,21 +310,21 @@ void DeviceContextD3D12Impl::CommitRootTables(RootTableInfo& RootInfo) RootInfo.bRootTablesCommited = true; for (Uint32 s = 0; s < RootSig.GetSignatureCount(); ++s) { - auto* pSignature = RootSig.GetSignature(s); + auto* pSignature = RootSig.GetResourceSignature(s); auto* pSRB = RootInfo.SRBs[s]; if (pSignature == nullptr || pSignature->GetTotalResourceCount() == 0) continue; VERIFY_EXPR(pSRB != nullptr); - pSignature->CommitRootTables(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), IsCompute, RootSig.GetFirstRootIndex(s)); + pSignature->CommitRootTables(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), IsCompute, RootSig.GetBaseRootIndex(s)); } } RootInfo.bRootViewsCommitted = true; for (Uint32 s = 0; s < RootSig.GetSignatureCount(); ++s) { - auto* pSignature = RootSig.GetSignature(s); + auto* pSignature = RootSig.GetResourceSignature(s); auto* pSRB = RootInfo.SRBs[s]; if (pSignature == nullptr || pSignature->GetNumRootViews() == 0) @@ -332,7 +332,7 @@ void DeviceContextD3D12Impl::CommitRootTables(RootTableInfo& RootInfo) VERIFY_EXPR(pSRB != nullptr); constexpr auto CommitDynamicBuffers = true; - pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootSig.GetFirstRootIndex(s), IsCompute, CommitDynamicBuffers); + pSignature->CommitRootViews(pSRB->GetResourceCache(), CmdCtx, this, GetContextId(), RootSig.GetBaseRootIndex(s), IsCompute, CommitDynamicBuffers); } } @@ -410,7 +410,7 @@ void DeviceContextD3D12Impl::DvpValidateCommittedShaderResources() for (Uint32 i = 0; i < SignCount; ++i) { - auto* pSignature = RootSig.GetSignature(i); + auto* pSignature = RootSig.GetResourceSignature(i); if (pSignature == nullptr) continue; diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index 32162668..3fc80df0 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -754,6 +754,75 @@ void PipelineResourceSignatureD3D12Impl::CommitRootTables(ShaderResourceCacheD3D } +void PipelineResourceSignatureD3D12Impl::UpdateShaderResourceBindingMap(ResourceBinding::TMap& ResourceMap, SHADER_TYPE ShaderStage, Uint32 BaseRegisterSpace) const +{ + VERIFY(ShaderStage != SHADER_TYPE_UNKNOWN && IsPowerOfTwo(ShaderStage), "Only single shader stage must be provided."); + + for (Uint32 r = 0, ResCount = GetTotalResourceCount(); r < ResCount; ++r) + { + const auto& ResDesc = GetResourceDesc(r); + const auto& Attribs = GetResourceAttribs(r); + + if ((ResDesc.ShaderStages & ShaderStage) != 0) + { + ResourceBinding::BindInfo BindInfo // + { + Attribs.Register, + Attribs.Space + BaseRegisterSpace, + ResDesc.ArraySize // + }; + auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, BindInfo).second; + VERIFY(IsUnique, "Shader resource '", ResDesc.Name, + "' already present in the binding map. Every shader resource in PSO must be unambiguously defined by " + "only one resource signature. This error should've been caught by ValidatePipelineResourceSignatures()."); + } + } + + for (Uint32 samp = 0, SampCount = GetImmutableSamplerCount(); samp < SampCount; ++samp) + { + const auto& ImtblSam = GetImmutableSamplerDesc(samp); + const auto& SampAttr = GetImmutableSamplerAttribs(samp); + + if ((ImtblSam.ShaderStages & ShaderStage) != 0) + { + String SampName{ImtblSam.SamplerOrTextureName}; + if (IsUsingCombinedSamplers()) + SampName += GetCombinedSamplerSuffix(); + + ResourceBinding::BindInfo BindInfo // + { + SampAttr.ShaderRegister, + SampAttr.RegisterSpace + BaseRegisterSpace, + SampAttr.ArraySize // + }; + + auto it_inserted = ResourceMap.emplace(HashMapStringKey{SampName}, BindInfo); +#ifdef DILIGENT_DEBUG + if (!it_inserted.second) + { + const auto& ExistingBindInfo = it_inserted.first->second; + VERIFY(ExistingBindInfo.BindPoint == BindInfo.BindPoint, + "Bind point defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource."); + VERIFY(ExistingBindInfo.Space == BindInfo.Space, + "Register space defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource."); + } +#endif + } + } +} + +bool PipelineResourceSignatureD3D12Impl::HasImmutableSamplerArray(SHADER_TYPE ShaderStage) const +{ + for (Uint32 s = 0; s < GetImmutableSamplerCount(); ++s) + { + const auto& ImtblSam = GetImmutableSamplerDesc(s); + const auto& SampAttr = GetImmutableSamplerAttribs(s); + if ((ImtblSam.ShaderStages & ShaderStage) != 0 && SampAttr.ArraySize > 1) + return true; + } + return false; +} + namespace { diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 642a9f98..5a0ed88c 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -35,11 +35,9 @@ #include "D3D12TypeConversions.hpp" #include "RenderDeviceD3D12Impl.hpp" #include "DXGITypeConversions.hpp" -#include "ShaderResourceBindingD3D12Impl.hpp" #include "CommandContext.hpp" #include "EngineMemory.h" #include "StringTools.hpp" -#include "ShaderVariableD3D12.hpp" #include "DynamicLinearAllocator.hpp" #include "DXBCUtils.hpp" #include "DXCompiler.hpp" @@ -47,6 +45,7 @@ namespace Diligent { + namespace { #ifdef _MSC_VER @@ -119,7 +118,6 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateI std::array StagesPtr = {}; std::array ShaderIndices = {}; - // prepare for (auto& Stage : ShaderStages) { const auto Idx = GetShaderTypePipelineIndex(Stage.Type, PIPELINE_TYPE_RAY_TRACING); @@ -292,7 +290,7 @@ void GetShaderResourceTypeAndFlags(const D3DShaderResourceAttribs& Attribs, { OutFlags = PIPELINE_RESOURCE_FLAG_UNKNOWN; - switch (static_cast(Attribs.GetInputType())) + switch (int{Attribs.GetInputType()}) { case D3D_SIT_CBUFFER: OutType = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; @@ -361,6 +359,7 @@ void VerifyResourceMerge(const D3DShaderResourceAttribs& ExistingRes, "' exists in multiple shaders from the same shader stage, but its array size is not consistent between " "shaders. All variables with the same name from the same shader stage must have the same array size."); } + } // namespace @@ -401,36 +400,39 @@ size_t PipelineStateD3D12Impl::ShaderStageInfo::Count() const } -void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateCreateInfo& CreateInfo, - TShaderStages& ShaderStages, - LocalRootSignatureD3D12* pLocalRootSig, - IPipelineResourceSignature** ppImplicitSignature) +RefCntAutoPtr PipelineStateD3D12Impl::CreateDefaultResourceSignature( + RenderDeviceD3D12Impl* pDevice, + const PipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages, + LocalRootSignatureD3D12* pLocalRootSig) { + const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout; + struct UniqueResource { - D3DShaderResourceAttribs const* Attribs = nullptr; - Uint32 DescIndex = ~0u; + const D3DShaderResourceAttribs& Attribs; + + // Resource index + const Uint32 DescIndex; }; - using ResourceNameToIndex_t = std::unordered_map; + std::unordered_map UniqueNames; std::vector Resources; - ResourceNameToIndex_t UniqueNames; const char* pCombinedSamplerSuffix = nullptr; - const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout; for (auto& Stage : ShaderStages) { UniqueNames.clear(); for (auto* pShader : Stage.Shaders) { - const auto DefaultVarType = LayoutDesc.DefaultVariableType; - auto& ShaderResources = *pShader->GetShaderResources(); - const auto HandleResource = [&](const D3DShaderResourceAttribs& Res, Uint32) // + const auto& ShaderResources = *pShader->GetShaderResources(); + + const auto HandleResource = [&](const D3DShaderResourceAttribs& Res, Uint32) // { if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Res)) return; - auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{&Res, static_cast(Resources.size())}); + auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{Res, static_cast(Resources.size())}); if (IterAndAssigned.second) { SHADER_RESOURCE_TYPE Type; @@ -439,15 +441,15 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC if (Res.BindCount == 0) { - LOG_ERROR_AND_THROW("Is shader '", pShader->GetDesc().Name, "' resource '", Res.Name, "' uses runtime sized array, ", - "you must explicitlly set resource signature to specify array size"); + LOG_ERROR_AND_THROW("Resource '", Res.Name, "' in shader '", pShader->GetDesc().Name, "' is a runtime-sized array. ", + "Use explicit resource signature to specify the array size."); } - Resources.emplace_back(Stage.Type, Res.Name, Res.BindCount, Type, DefaultVarType, Flags); + Resources.emplace_back(Stage.Type, Res.Name, Res.BindCount, Type, LayoutDesc.DefaultVariableType, Flags); } else { - VerifyResourceMerge(*IterAndAssigned.first->second.Attribs, Res); + VerifyResourceMerge(IterAndAssigned.first->second.Attribs, Res); } }; @@ -481,8 +483,8 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC // apply new variable type to sampler too if (ShaderResources.IsUsingCombinedTextureSamplers() && Res.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) { - String SampName = String{Var.Name} + ShaderResources.GetCombinedSamplerSuffix(); - auto SampIter = UniqueNames.find(HashMapStringKey{SampName.c_str()}); + auto SampName = String{Var.Name} + ShaderResources.GetCombinedSamplerSuffix(); + auto SampIter = UniqueNames.find(HashMapStringKey{SampName.c_str()}); if (SampIter != UniqueNames.end()) Resources[SampIter->second.DescIndex].VarType = Var.Type; } @@ -492,6 +494,7 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC } } + RefCntAutoPtr pImplicitSignature; if (Resources.size()) { PipelineResourceSignatureDesc ResSignDesc; @@ -504,11 +507,13 @@ void PipelineStateD3D12Impl::CreateDefaultResourceSignature(const PipelineStateC ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr; ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix; - GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppImplicitSignature, true); + pDevice->CreatePipelineResourceSignature(ResSignDesc, &pImplicitSignature, true); - if (*ppImplicitSignature == nullptr) + if (!pImplicitSignature) LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state"); } + + return pImplicitSignature; } PipelineStateD3D12Impl::ResourceInfo PipelineStateD3D12Impl::GetResourceInfo(const char* Name, SHADER_TYPE Stage) const @@ -539,39 +544,43 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr TShaderStages& ShaderStages, LocalRootSignatureD3D12* pLocalRootSig) { - const Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount; - RefCntAutoPtr pImplicitSignature; - - if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr) + Uint32 SignatureCount = 0; + if (CreateInfo.ResourceSignaturesCount == 0 || CreateInfo.ppResourceSignatures == nullptr) { - CreateDefaultResourceSignature(CreateInfo, ShaderStages, pLocalRootSig, &pImplicitSignature); - - if (pImplicitSignature != nullptr) + auto pImplicitSignature = CreateDefaultResourceSignature(GetDevice(), CreateInfo, ShaderStages, pLocalRootSig); + if (pImplicitSignature) { VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0); - m_Signatures[0] = ValidatedCast(pImplicitSignature.RawPtr()); - m_SignatureCount = 1; + SignatureCount = 1; + m_ResourceSignatures.reset(new RefCntAutoPtr[SignatureCount]); + m_ResourceSignatures[0] = pImplicitSignature.RawPtr(); } } else { + Uint32 MaxSignatureBindingIndex = 0; + for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i) + { + auto* pSignature = ValidatedCast(CreateInfo.ppResourceSignatures[i]); + VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures."); + MaxSignatureBindingIndex = std::max(MaxSignatureBindingIndex, Uint32{pSignature->GetDesc().BindingIndex}); + } + SignatureCount = MaxSignatureBindingIndex + 1; + m_ResourceSignatures.reset(new RefCntAutoPtr[SignatureCount]); + // TODO: move to base class const auto PipelineType = CreateInfo.PSODesc.PipelineType; - for (Uint32 i = 0; i < SignatureCount; ++i) + for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i) { auto* pSignature = ValidatedCast(CreateInfo.ppResourceSignatures[i]); VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures."); - const Uint8 Index = pSignature->GetDesc().BindingIndex; + const auto Index = pSignature->GetDesc().BindingIndex; #ifdef DILIGENT_DEBUG - VERIFY(Index < m_Signatures.size(), - "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", m_Signatures.size() - 1, - "). This error should've been caught by ValidatePipelineResourceSignatureDesc."); - - VERIFY(m_Signatures[Index] == nullptr, + VERIFY(m_ResourceSignatures[Index] == nullptr, "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index}, - " conflicts with another resource signature '", m_Signatures[Index]->GetDesc().Name, + " conflicts with another resource signature '", m_ResourceSignatures[Index]->GetDesc().Name, "' that uses the same index. This error should've been caught by ValidatePipelineResourceSignatures."); for (Uint32 s = 0, StageCount = pSignature->GetNumActiveShaderStages(); s < StageCount; ++s) @@ -584,12 +593,11 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr } #endif - m_SignatureCount = std::max(m_SignatureCount, Index + 1); - m_Signatures[Index] = pSignature; + m_ResourceSignatures[Index] = pSignature; } } - m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_Signatures.data(), m_SignatureCount); + m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_ResourceSignatures.get(), SignatureCount); if (!m_RootSig) LOG_ERROR_AND_THROW("Failed to create root signature"); @@ -605,79 +613,44 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr for (size_t s = 0; s < ShaderStages.size(); ++s) { - const auto& Shaders = ShaderStages[s].Shaders; - auto& ByteCodes = ShaderStages[s].ByteCodes; - const auto ShaderType = ShaderStages[s].Type; - bool HasImtblSampArray = false; + const auto& Shaders = ShaderStages[s].Shaders; + auto& ByteCodes = ShaderStages[s].ByteCodes; + const auto ShaderType = ShaderStages[s].Type; + bool HasImtblSamArray = false; ResourceBinding::TMap ResourceMap; - for (Uint32 Sig = 0, SigCount = GetSignatureCount(); Sig < SigCount; ++Sig) + // Note that we must use signatures from m_ResourceSignatures for resource binding map, + // because signatures from m_RootSig may have resources with different names. + for (Uint32 sign = 0; sign < SignatureCount; ++sign) { - auto* pSignature = GetSignature(Sig); - if (pSignature != nullptr) - { - const Uint32 FirstSpace = m_RootSig->GetFirstRegisterSpace(Sig); + const PipelineResourceSignatureD3D12Impl* const pSignature = m_ResourceSignatures[sign]; + if (pSignature == nullptr) + continue; - for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r) - { - const auto& ResDesc = pSignature->GetResourceDesc(r); - const auto& Attribs = pSignature->GetResourceAttribs(r); - - if (ResDesc.ShaderStages & ShaderType) - { - auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, ResourceBinding::BindInfo{Attribs.Register, Attribs.Space + FirstSpace, ResDesc.ArraySize}).second; - VERIFY(IsUnique, "resource name must be unique"); - } - } + VERIFY_EXPR(pSignature->GetDesc().BindingIndex == sign); + pSignature->UpdateShaderResourceBindingMap(ResourceMap, ShaderType, m_RootSig->GetBaseRegisterSpace(sign)); - for (Uint32 samp = 0, SampCount = pSignature->GetImmutableSamplerCount(); samp < SampCount; ++samp) - { - const auto& ImtblSam = pSignature->GetImmutableSamplerDesc(samp); - const auto& SampAttr = pSignature->GetImmutableSamplerAttribs(samp); - ResourceBinding::BindInfo BindInfo{SampAttr.ShaderRegister, SampAttr.RegisterSpace + FirstSpace, SampAttr.ArraySize}; - - if (ImtblSam.ShaderStages & ShaderType) - { - HasImtblSampArray = HasImtblSampArray || (SampAttr.ArraySize > 1); - - String SampName{ImtblSam.SamplerOrTextureName}; - if (pSignature->IsUsingCombinedSamplers()) - SampName += pSignature->GetCombinedSamplerSuffix(); - - auto it_inserted = ResourceMap.emplace(HashMapStringKey{SampName}, BindInfo); -#ifdef DILIGENT_DEBUG - if (!it_inserted.second) - { - const auto& ExistingBindInfo = it_inserted.first->second; - VERIFY(ExistingBindInfo.BindPoint == BindInfo.BindPoint, - "Bind point defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource."); - VERIFY(ExistingBindInfo.Space == BindInfo.Space, - "Register space defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource."); - } -#endif - } - } - } + if (pSignature->HasImmutableSamplerArray(ShaderType)) + HasImtblSamArray = true; } if (pLocalRootSig != nullptr && pLocalRootSig->IsDefined()) { bool IsUnique = ResourceMap.emplace(HashMapStringKey{pLocalRootSig->GetName()}, ResourceBinding::BindInfo{pLocalRootSig->GetShaderRegister(), pLocalRootSig->GetRegisterSpace(), 1}).second; if (!IsUnique) - LOG_ERROR_AND_THROW("Shader record constant buffer is already exist in resource signature"); + LOG_ERROR_AND_THROW("Shader record constant buffer already exists in the resource signature"); } for (size_t i = 0; i < Shaders.size(); ++i) { - auto* pShader = Shaders[i]; + const auto* const pShader = Shaders[i]; auto& pBytecode = ByteCodes[i]; - CComPtr pBlob; - Uint32 VerMajor, VerMinor; + Uint32 VerMajor, VerMinor; pShader->GetShaderResources()->GetShaderModel(VerMajor, VerMinor); const bool IsSM51orAbove = ((VerMajor == 5 && VerMinor >= 1) || VerMajor >= 6); - if (HasImtblSampArray && IsSM51orAbove) + if (HasImtblSamArray && IsSM51orAbove) { LOG_ERROR_AND_THROW("One of resource signatures uses immutable sampler array that is not allowed in shader model 5.1 and above."); } @@ -689,6 +662,7 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr "Compile the shader using SM5.1+ or change the resource layout to use only one space."); } + CComPtr pBlob; if (IsDXILBytecode(pBytecode->GetBufferPointer(), pBytecode->GetBufferSize())) { if (!compiler) @@ -708,76 +682,85 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr pBytecode = pBlob; #ifdef DILIGENT_DEVELOPMENT - const auto& pShaderResources = pShader->GetShaderResources(); - m_ShaderResources.emplace_back(pShaderResources); + m_ShaderResources.emplace_back(pShader->GetShaderResources()); + DvpValidateShaderResources(pShader, pLocalRootSig); +#endif + } + } +} - // Check compatibility between shader resources and resource signature. - const auto HandleResource = [&](const D3DShaderResourceAttribs& Attribs, Uint32) // - { - if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Attribs)) - return; +#ifdef DILIGENT_DEVELOPMENT +void PipelineStateD3D12Impl::DvpValidateShaderResources(const ShaderD3D12Impl* pShader, const LocalRootSignatureD3D12* pLocalRootSig) const +{ + const auto& pShaderResources = pShader->GetShaderResources(); + const auto ShaderType = pShader->GetDesc().ShaderType; - if (Attribs.GetInputType() == D3D_SIT_SAMPLER) - return; + // Check compatibility between shader resources and resource signature. + const auto HandleResource = [&](const D3DShaderResourceAttribs& Attribs, Uint32) // + { + if (pLocalRootSig != nullptr && pLocalRootSig->IsShaderRecord(Attribs)) + return; - auto Info = GetResourceInfo(Attribs.Name, ShaderType); - if (!Info) - { - LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, - "' that is not present in any pipeline resource signature that is used to create pipeline state '", - m_Desc.Name, "'."); - } + if (Attribs.GetInputType() == D3D_SIT_SAMPLER) + return; - SHADER_RESOURCE_TYPE Type; - PIPELINE_RESOURCE_FLAGS Flags; - GetShaderResourceTypeAndFlags(Attribs, Type, Flags); - if (Type != Info.ResDesc->ResourceType) - { - LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, - "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '", - GetShaderResourceTypeLiteralName(Info.ResDesc->ResourceType), "' in pipeline resource signature '", Info.Signature->GetDesc().Name, "'."); - } + auto Info = GetResourceInfo(Attribs.Name, ShaderType); + if (!Info) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, + "' that is not present in any pipeline resource signature used to create pipeline state '", + m_Desc.Name, "'."); + } - if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER)) - { - LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, - "' that is", ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), - " labeled as formatted buffer, while the same resource specified by the pipeline resource signature '", - Info.Signature->GetDesc().Name, "' is", ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), - " labeled as such."); - } + SHADER_RESOURCE_TYPE Type; + PIPELINE_RESOURCE_FLAGS Flags; + GetShaderResourceTypeAndFlags(Attribs, Type, Flags); + if (Type != Info.ResDesc->ResourceType) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, + "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '", + GetShaderResourceTypeLiteralName(Info.ResDesc->ResourceType), "' in pipeline resource signature '", Info.Signature->GetDesc().Name, "'."); + } - if (Attribs.BindCount == 0) - { - if ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0) - { - LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, - "' that is runtime-sized array, but in resource signature '", Info.Signature->GetDesc().Name, - "' resource defined without PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY flag."); - } - } - else - { - if (Info.ResDesc->ArraySize < Attribs.BindCount) - { - LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, - "' whose array size (", Attribs.BindCount, ") is greater than the array size (", - Info.ResDesc->ArraySize, ") specified by the pipeline resource signature '", Info.Signature->GetDesc().Name, "'."); - } + if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER)) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, + "' that is", ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), + " labeled as formatted buffer, while the same resource specified by the pipeline resource signature '", + Info.Signature->GetDesc().Name, "' is", ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), + " labeled as such."); + } - if (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) - { - LOG_WARNING_MESSAGE("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, - "' that defined in resource signature '", Info.Signature->GetDesc().Name, - "' with flag PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY, but resource is not a runtime-sized array."); - } - } - }; - pShaderResources->ProcessResources(HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource); -#endif + if (Attribs.BindCount == 0) + { + if ((Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, + "' that is runtime-sized array, but in resource signature '", Info.Signature->GetDesc().Name, + "' resource defined without PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY flag."); + } } - } + else + { + if (Info.ResDesc->ArraySize < Attribs.BindCount) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, + "' whose array size (", Attribs.BindCount, ") is greater than the array size (", + Info.ResDesc->ArraySize, ") specified by the pipeline resource signature '", Info.Signature->GetDesc().Name, "'."); + } + + if (Info.ResDesc->Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) + { + LOG_WARNING_MESSAGE("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, + "' that defined in resource signature '", Info.Signature->GetDesc().Name, + "' with flag PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY, but resource is not a runtime-sized array."); + } + } + }; + pShaderResources->ProcessResources(HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource, HandleResource); } +#endif + template void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, @@ -1100,7 +1083,6 @@ PipelineStateD3D12Impl::~PipelineStateD3D12Impl() void PipelineStateD3D12Impl::Destruct() { - m_Signatures.fill({}); m_RootSig.Release(); if (m_pd3d12PSO) diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index e5a4a2af..03786c50 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -854,7 +854,7 @@ DescriptorHeapAllocation RenderDeviceD3D12Impl::AllocateGPUDescriptors(D3D12_DES void RenderDeviceD3D12Impl::CreateRootSignature(const RefCntAutoPtr* ppSignatures, Uint32 SignatureCount, size_t Hash, RootSignatureD3D12** ppRootSig) { - RootSignatureD3D12* pRootSigD3D12(NEW_RC_OBJ(m_RootSignatureAllocator, "RootSignatureD3D12 instance", RootSignatureD3D12)(this, ppSignatures, SignatureCount, Hash)); + RootSignatureD3D12* pRootSigD3D12{NEW_RC_OBJ(m_RootSignatureAllocator, "RootSignatureD3D12 instance", RootSignatureD3D12)(this, ppSignatures, SignatureCount, Hash)}; pRootSigD3D12->AddRef(); *ppRootSig = pRootSigD3D12; } diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 1f51f4cf..1cd3400c 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -30,8 +30,6 @@ #include "RootSignature.hpp" #include "CommandContext.hpp" #include "RenderDeviceD3D12Impl.hpp" -#include "TextureD3D12Impl.hpp" -#include "TopLevelASD3D12Impl.hpp" #include "D3D12TypeConversions.hpp" #include "HashUtils.hpp" @@ -44,37 +42,41 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters* Uint32 SignatureCount, size_t Hash) : ObjectBase{pRefCounters}, - m_SignatureCount{static_cast(SignatureCount)}, + m_SignatureCount{SignatureCount}, m_Hash{Hash}, m_Cache{pDeviceD3D12Impl->GetRootSignatureCache()} { - VERIFY(m_SignatureCount == SignatureCount, "Signature count (", SignatureCount, ") exceeds maximum representable value"); + if (m_SignatureCount > 0) + { + m_ResourceSignatures.reset(new ResourceSignatureInfo[m_SignatureCount]); + } for (Uint32 i = 0; i < SignatureCount; ++i) { - m_Signatures[i] = ppSignatures[i]; - + m_ResourceSignatures[i].pSignature = ppSignatures[i]; if (ppSignatures[i] != nullptr) { VERIFY(ppSignatures[i]->GetDesc().BindingIndex == i, "Signature placed to another binding index"); } } - D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; - rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - - Uint32 TotalParams = 0; - Uint32 Totald3d12StaticSamplers = 0; - Uint32 TotalDescriptorRanges = 0; + // The total number of root parameters in all resource signatures. + Uint32 TotalParams = 0; + // The total number of static samplers, accounting for array size, in all resource signatures. + Uint32 TotalImmutableSamplers = 0; + // The total number of descriptor ranges in all descriptor tables from all resource signatures. + Uint32 TotalDescriptorRanges = 0; for (Uint32 s = 0; s < m_SignatureCount; ++s) { - auto& pSignature = m_Signatures[s]; + auto& SignInfo = m_ResourceSignatures[s]; + + const PipelineResourceSignatureD3D12Impl* const pSignature = SignInfo.pSignature; if (pSignature == nullptr) continue; - auto& RootParams = pSignature->m_RootParams; + const auto& RootParams = pSignature->GetRootParams(); - m_FirstRootIndex[s] = static_cast(TotalParams); + SignInfo.BaseRootIndex = TotalParams; TotalParams += RootParams.GetNumRootTables() + RootParams.GetNumRootViews(); for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt) @@ -88,41 +90,55 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters* const auto& ImtblSam = pSignature->GetImmutableSamplerAttribs(samp); VERIFY_EXPR(ImtblSam.IsValid()); - Totald3d12StaticSamplers += ImtblSam.ArraySize; + TotalImmutableSamplers += ImtblSam.ArraySize; } } - std::vector> d3d12Parameters(TotalParams, D3D12_ROOT_PARAMETER{}, STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector")); - std::vector> d3d12DescrRanges(TotalDescriptorRanges, D3D12_DESCRIPTOR_RANGE{}, STD_ALLOCATOR_RAW_MEM(D3D12_DESCRIPTOR_RANGE, GetRawAllocator(), "Allocator for vector")); - std::vector> d3d12StaticSamplers(STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector")); - d3d12StaticSamplers.reserve(Totald3d12StaticSamplers); + // Reserve space for all root parameters + std::vector> d3d12Parameters( + TotalParams, + D3D12_ROOT_PARAMETER{static_cast(-1)}, + STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector")); + // ... descriptor ranges, + std::vector> d3d12DescrRanges( + TotalDescriptorRanges, + D3D12_DESCRIPTOR_RANGE{}, + STD_ALLOCATOR_RAW_MEM(D3D12_DESCRIPTOR_RANGE, GetRawAllocator(), "Allocator for vector")); + // ... and static samplers. + std::vector> d3d12StaticSamplers( + STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector")); + d3d12StaticSamplers.reserve(TotalImmutableSamplers); auto descr_range_it = d3d12DescrRanges.begin(); Uint32 BaseRegisterSpace = 0; for (Uint32 sig = 0; sig < m_SignatureCount; ++sig) { - m_FirstRegisterSpace[sig] = static_cast(BaseRegisterSpace); + auto& SignInfo = m_ResourceSignatures[sig]; - const auto& pSignature = m_Signatures[sig]; + SignInfo.BaseRegisterSpace = BaseRegisterSpace; + + const PipelineResourceSignatureD3D12Impl* const pSignature = SignInfo.pSignature; if (pSignature == nullptr) continue; - const auto& RootParams = pSignature->m_RootParams; - const auto FirstRootIndex = m_FirstRootIndex[sig]; + const auto& RootParams = pSignature->GetRootParams(); Uint32 MaxSpaceUsed = 0; for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt) { - const auto& RootTable = RootParams.GetRootTable(rt); - const auto& d3d12SrcParam = RootTable.d3d12RootParam; - const auto& d3d12SrcTbl = d3d12SrcParam.DescriptorTable; - const Uint32 RootIndex = FirstRootIndex + RootTable.RootIndex; + const auto& RootTable = RootParams.GetRootTable(rt); + const auto& d3d12SrcParam = RootTable.d3d12RootParam; + const auto& d3d12SrcTbl = d3d12SrcParam.DescriptorTable; + // Offset root parameter index by the base root index of the current resource signature + const Uint32 RootIndex = SignInfo.BaseRootIndex + RootTable.RootIndex; VERIFY(d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && d3d12SrcParam.DescriptorTable.NumDescriptorRanges > 0, "Non-empty descriptor table is expected"); auto& d3d12DstParam = d3d12Parameters[RootIndex]; auto& d3d12DstTbl = d3d12DstParam.DescriptorTable; d3d12DstParam = d3d12SrcParam; + // Copy all ranges from the source descriptor table and offset register space values by + // the base register space of the current resource signature. memcpy(&*descr_range_it, d3d12SrcTbl.pDescriptorRanges, d3d12SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); d3d12DstTbl.pDescriptorRanges = &*descr_range_it; for (Uint32 r = 0; r < d3d12SrcTbl.NumDescriptorRanges; ++r, ++descr_range_it) @@ -136,14 +152,16 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters* { const auto& RootView = RootParams.GetRootView(rv); const auto& d3d12SrcParam = RootView.d3d12RootParam; - const Uint32 RootIndex = FirstRootIndex + RootView.RootIndex; + const Uint32 RootIndex = SignInfo.BaseRootIndex + RootView.RootIndex; VERIFY((d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV || d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV || d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV), "Root CBV, SRV or UAV is expected"); + MaxSpaceUsed = std::max(MaxSpaceUsed, d3d12SrcParam.Descriptor.RegisterSpace); d3d12Parameters[RootIndex] = d3d12SrcParam; + // Offset register space value by the base register space of the current resource signature. d3d12Parameters[RootIndex].Descriptor.RegisterSpace += BaseRegisterSpace; } @@ -182,17 +200,26 @@ RootSignatureD3D12::RootSignatureD3D12(IReferenceCounters* } m_TotalSpacesUsed = BaseRegisterSpace; +#ifdef DILIGENT_DEBUG + for (size_t i = 0; i < d3d12Parameters.size(); ++i) + { + VERIFY(d3d12Parameters[i].ParameterType != -1, "Root parameter at index ", i, " has not been initialized"); + } +#endif + VERIFY_EXPR(descr_range_it == d3d12DescrRanges.end()); + D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc{}; + rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; rootSignatureDesc.NumParameters = static_cast(d3d12Parameters.size()); - rootSignatureDesc.pParameters = d3d12Parameters.size() ? d3d12Parameters.data() : nullptr; + rootSignatureDesc.pParameters = !d3d12Parameters.empty() ? d3d12Parameters.data() : nullptr; - rootSignatureDesc.NumStaticSamplers = Totald3d12StaticSamplers; + rootSignatureDesc.NumStaticSamplers = TotalImmutableSamplers; rootSignatureDesc.pStaticSamplers = nullptr; if (!d3d12StaticSamplers.empty()) { rootSignatureDesc.pStaticSamplers = d3d12StaticSamplers.data(); - VERIFY_EXPR(d3d12StaticSamplers.size() == Totald3d12StaticSamplers); + VERIFY_EXPR(d3d12StaticSamplers.size() == TotalImmutableSamplers); } CComPtr signature; @@ -217,21 +244,17 @@ RootSignatureD3D12::~RootSignatureD3D12() } LocalRootSignatureD3D12::LocalRootSignatureD3D12(const char* pCBName, Uint32 ShaderRecordSize) : - m_pName{pCBName}, + m_Name{pCBName != nullptr ? pCBName : ""}, m_ShaderRecordSize{ShaderRecordSize} { - VERIFY_EXPR((m_pName != nullptr) == (m_ShaderRecordSize > 0)); + VERIFY_EXPR(!m_Name.empty() == (m_ShaderRecordSize > 0)); } -bool LocalRootSignatureD3D12::IsShaderRecord(const D3DShaderResourceAttribs& CB) +bool LocalRootSignatureD3D12::IsShaderRecord(const D3DShaderResourceAttribs& CB) const { - if (m_ShaderRecordSize > 0 && - CB.GetInputType() == D3D_SIT_CBUFFER && - strcmp(m_pName, CB.Name) == 0) - { - return true; - } - return false; + return (m_ShaderRecordSize > 0 && + CB.GetInputType() == D3D_SIT_CBUFFER && + m_Name == CB.Name); } bool LocalRootSignatureD3D12::Create(ID3D12Device* pDevice, Uint32 RegisterSpace) @@ -267,20 +290,15 @@ bool LocalRootSignatureD3D12::Create(ID3D12Device* pDevice, Uint32 RegisterSpace } -namespace +bool RootSignatureD3D12::IsCompatibleWith(const RefCntAutoPtr ppSignatures[], Uint32 SignatureCount) const noexcept { -bool RootSignatureCompare(const RootSignatureD3D12* lhs, const RefCntAutoPtr* ppSignatures, Uint32 SignatureCount) noexcept -{ - const Uint32 LSigCount = lhs->GetSignatureCount(); - const Uint32 RSigCount = SignatureCount; - - if (LSigCount != RSigCount) + if (GetSignatureCount() != SignatureCount) return false; - for (Uint32 i = 0; i < LSigCount; ++i) + for (Uint32 i = 0; i < SignatureCount; ++i) { - auto* pLSig = lhs->GetSignature(i); - auto* pRSig = ppSignatures[i].RawPtr(); + const PipelineResourceSignatureD3D12Impl* const pLSig = m_ResourceSignatures[i].pSignature; + const PipelineResourceSignatureD3D12Impl* const pRSig = ppSignatures[i]; if (pLSig == pRSig) continue; @@ -288,12 +306,14 @@ bool RootSignatureCompare(const RootSignatureD3D12* lhs, const RefCntAutoPtrIsCompatibleWith(*pRSig)) return false; } return true; } -} // namespace RootSignatureCacheD3D12::RootSignatureCacheD3D12(RenderDeviceD3D12Impl& DeviceD3D12Impl) : m_DeviceD3D12Impl{DeviceD3D12Impl} @@ -301,8 +321,8 @@ RootSignatureCacheD3D12::RootSignatureCacheD3D12(RenderDeviceD3D12Impl& DeviceD3 RootSignatureCacheD3D12::~RootSignatureCacheD3D12() { - std::lock_guard Lock{m_RootSigCacheGuard}; - VERIFY(m_RootSigCache.empty(), "All pipeline layouts must be released"); + std::lock_guard Lock{m_RootSigCacheMtx}; + VERIFY(m_RootSigCache.empty(), "All pipeline resource signatures must be released before the cache is destroyed."); } RefCntAutoPtr RootSignatureCacheD3D12::GetRootSig(const RefCntAutoPtr* ppSignatures, Uint32 SignatureCount) @@ -323,14 +343,14 @@ RefCntAutoPtr RootSignatureCacheD3D12::GetRootSig(const RefC } } - std::lock_guard Lock{m_RootSigCacheGuard}; + std::lock_guard Lock{m_RootSigCacheMtx}; auto Range = m_RootSigCache.equal_range(Hash); for (auto Iter = Range.first; Iter != Range.second; ++Iter) { if (auto Ptr = Iter->second.Lock()) { - if (RootSignatureCompare(Ptr, ppSignatures, SignatureCount)) + if (Ptr->IsCompatibleWith(ppSignatures, SignatureCount)) return Ptr; } } @@ -344,10 +364,9 @@ RefCntAutoPtr RootSignatureCacheD3D12::GetRootSig(const RefC void RootSignatureCacheD3D12::OnDestroyRootSig(RootSignatureD3D12* pRootSig) { - std::lock_guard Lock{m_RootSigCacheGuard}; + std::lock_guard Lock{m_RootSigCacheMtx}; auto Range = m_RootSigCache.equal_range(pRootSig->GetHash()); - for (auto Iter = Range.first; Iter != Range.second;) { if (!Iter->second.IsValid()) -- cgit v1.2.3