diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2021-03-06 22:06:26 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:38:16 +0000 |
| commit | 30a65df99cfc678a431a89b0cff02a515416c78a (patch) | |
| tree | 2d3ed68bf8ec028879e22ff6d1ec386df723677e /Graphics | |
| parent | Moved GetResourceAttribution() function to PipelineStateBase to eliminate dup... (diff) | |
| download | DiligentCore-30a65df99cfc678a431a89b0cff02a515416c78a.tar.gz DiligentCore-30a65df99cfc678a431a89b0cff02a515416c78a.zip | |
Unified resource signature handling by pipeline state in D3D12, Vk and GL
Diffstat (limited to 'Graphics')
12 files changed, 286 insertions, 400 deletions
diff --git a/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp b/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp index 68d4aa8a..0942ffcf 100644 --- a/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineResourceSignatureBase.hpp @@ -231,58 +231,22 @@ public: return this->m_Desc.ImmutableSamplers[SampIndex]; } - static Uint32 CalcMaxSignatureBindIndex(const Uint32 SignatureCount, - IPipelineResourceSignature* ppResourceSignatures[]) + static bool SignaturesCompatible(const PipelineResourceSignatureImplType* pSign0, + const PipelineResourceSignatureImplType* pSign1) { - Uint32 MaxSignatureBindingIndex = 0; - for (Uint32 i = 0; i < SignatureCount; ++i) - { - const auto* pSignature = 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}); - } - return MaxSignatureBindingIndex; - } + if (pSign0 == pSign1) + return true; - template <typename TPipelineResourceSignature> - static Uint32 CopyResourceSignatures(PIPELINE_TYPE PipelineType, - const Uint32 SignatureCount, - IPipelineResourceSignature* ppResourceSignatures[], - RefCntAutoPtr<TPipelineResourceSignature> DstSignatures[], - const size_t MaxDstSignatureCount) - { - Uint32 MaxSignatureBindIndex = 0; - for (Uint32 i = 0; i < SignatureCount; ++i) - { - auto* pSignature = ValidatedCast<TPipelineResourceSignature>(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; + bool IsNull0 = pSign0 == nullptr || (pSign0->GetTotalResourceCount() == 0 && pSign0->GetImmutableSamplerCount() == 0); + bool IsNull1 = pSign1 == nullptr || (pSign1->GetTotalResourceCount() == 0 && pSign1->GetImmutableSamplerCount() == 0); + if (IsNull0 && IsNull1) + return true; -#ifdef DILIGENT_DEBUG - VERIFY(Index < MaxDstSignatureCount, - "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", MaxDstSignatureCount - 1, - "). This error should've been caught by ValidatePipelineResourceSignatureDesc."); + if (IsNull0 != IsNull1) + return false; - VERIFY(DstSignatures[Index] == nullptr, - "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index}, - " conflicts with another resource signature '", DstSignatures[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) - { - const auto ShaderType = pSignature->GetActiveShaderStageType(s); - VERIFY(IsConsistentShaderType(ShaderType, PipelineType), - "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index}, - " has shader stage '", GetShaderTypeLiteralName(ShaderType), "' that is not compatible with pipeline type '", - GetPipelineTypeString(PipelineType), "'."); - } -#endif - - MaxSignatureBindIndex = std::max<Uint32>(MaxSignatureBindIndex, Index); - DstSignatures[Index] = pSignature; - } - return MaxSignatureBindIndex; + VERIFY_EXPR(pSign0 != nullptr && pSign1 != nullptr); + return pSign0->IsCompatibleWith(pSign1); } protected: diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index f831f4ea..dcdd82d9 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -231,6 +231,13 @@ public: m_pRayTracingPipelineData->~RayTracingPipelineData(); } + if (m_Signatures != nullptr) + { + for (Uint32 i = 0; i < m_SignatureCount; ++i) + m_Signatures[i].~SignatureAutoPtrType(); + m_Signatures = nullptr; + } + if (m_pPipelineDataRawMem) { GetRawAllocator().Free(m_pPipelineDataRawMem); @@ -404,6 +411,45 @@ public: return this->GetResourceSignature(0)->InitializeStaticSRBResources(pSRB); } + /// Implementation of IPipelineState::GetResourceSignatureCount(). + virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final + { + return m_SignatureCount; + } + + /// Implementation of IPipelineState::GetResourceSignature(). + virtual PipelineResourceSignatureImplType* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final + { + VERIFY_EXPR(Index < m_SignatureCount); + return m_Signatures[Index]; + } + + /// Implementation of IPipelineState::IsCompatibleWith(). + virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override // May be overriden + { + DEV_CHECK_ERR(pPSO != nullptr, "pPSO must not be null"); + + if (pPSO == this) + return true; + + const auto& lhs = *static_cast<const PipelineStateImplType*>(this); + const auto& rhs = *ValidatedCast<const PipelineStateImplType>(pPSO); + + const auto SignCount = lhs.GetResourceSignatureCount(); + if (SignCount != rhs.GetResourceSignatureCount()) + return false; + + for (Uint32 s = 0; s < SignCount; ++s) + { + const auto* pLhsSign = GetResourceSignature(s); + const auto* pRhsSign = rhs.GetResourceSignature(s); + if (!PipelineResourceSignatureImplType::SignaturesCompatible(pLhsSign, pRhsSign)) + return false; + } + + return true; + } + protected: using TNameToGroupIndexMap = std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>; @@ -412,6 +458,7 @@ protected: { MemPool.AddSpace<GraphicsPipelineData>(); ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + ReserveResourceSignatures(CreateInfo, MemPool); const auto& InputLayout = CreateInfo.GraphicsPipeline.InputLayout; Uint32 BufferSlotsUsed = 0; @@ -429,13 +476,14 @@ protected: } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, - FixedLinearAllocator& MemPool) const noexcept + FixedLinearAllocator& MemPool) noexcept { ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + ReserveResourceSignatures(CreateInfo, MemPool); } void ReserveSpaceForPipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, - FixedLinearAllocator& MemPool) const noexcept + FixedLinearAllocator& MemPool) noexcept { size_t RTDataSize = sizeof(RayTracingPipelineData); // Reserve space for shader handles @@ -459,6 +507,7 @@ protected: } ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + ReserveResourceSignatures(CreateInfo, MemPool); } @@ -604,6 +653,7 @@ protected: CorrectGraphicsPipelineDesc(GraphicsPipeline); CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + CopyResourceSignatures(CreateInfo, MemPool); pRenderPass = GraphicsPipeline.pRenderPass; if (pRenderPass) @@ -730,6 +780,7 @@ protected: m_pPipelineDataRawMem = MemPool.ReleaseOwnership(); CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + CopyResourceSignatures(CreateInfo, MemPool); } void InitializePipelineDesc(const RayTracingPipelineStateCreateInfo& CreateInfo, @@ -756,6 +807,7 @@ protected: CopyRTShaderGroupNames(NameToGroupIndex, CreateInfo, MemPool); CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + CopyResourceSignatures(CreateInfo, MemPool); } @@ -890,6 +942,73 @@ private: } } + void ReserveResourceSignatures(const PipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool) + { + if (m_UsingImplicitSignature) + { + VERIFY_EXPR(CreateInfo.ResourceSignaturesCount == 0 || CreateInfo.ppResourceSignatures == nullptr); + m_SignatureCount = 1; + } + else + { + VERIFY_EXPR(CreateInfo.ResourceSignaturesCount > 0 && CreateInfo.ppResourceSignatures != nullptr); + Uint32 MaxSignatureBindingIndex = 0; + for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i) + { + const auto* pSignature = ValidatedCast<PipelineResourceSignatureImplType>(CreateInfo.ppResourceSignatures[i]); + VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures."); + + Uint32 Index = pSignature->GetDesc().BindingIndex; + VERIFY(Index < MAX_RESOURCE_SIGNATURES, + "Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", MAX_RESOURCE_SIGNATURES - 1, + "). This error should've been caught by ValidatePipelineResourceSignatureDesc."); + + MaxSignatureBindingIndex = std::max(MaxSignatureBindingIndex, Uint32{Index}); + } + VERIFY_EXPR(MaxSignatureBindingIndex < MAX_RESOURCE_SIGNATURES); + m_SignatureCount = static_cast<decltype(m_SignatureCount)>(MaxSignatureBindingIndex + 1); + VERIFY_EXPR(m_SignatureCount == MaxSignatureBindingIndex + 1); + } + + MemPool.AddSpace<SignatureAutoPtrType>(m_SignatureCount); + } + + void CopyResourceSignatures(const PipelineStateCreateInfo& CreateInfo, FixedLinearAllocator& MemPool) + { + m_Signatures = MemPool.ConstructArray<SignatureAutoPtrType>(m_SignatureCount); + if (!m_UsingImplicitSignature) + { + VERIFY_EXPR(CreateInfo.ResourceSignaturesCount != 0 && CreateInfo.ppResourceSignatures != nullptr); + for (Uint32 i = 0; i < CreateInfo.ResourceSignaturesCount; ++i) + { + auto* pSignature = ValidatedCast<PipelineResourceSignatureImplType>(CreateInfo.ppResourceSignatures[i]); + VERIFY_EXPR(pSignature != nullptr); + + const Uint32 Index = pSignature->GetDesc().BindingIndex; + +#ifdef DILIGENT_DEBUG + VERIFY_EXPR(Index < m_SignatureCount); + + VERIFY(m_Signatures[Index] == nullptr, + "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index}, + " conflicts with another resource signature '", m_Signatures[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) + { + const auto ShaderType = pSignature->GetActiveShaderStageType(s); + VERIFY(IsConsistentShaderType(ShaderType, CreateInfo.PSODesc.PipelineType), + "Pipeline resource signature '", pSignature->GetDesc().Name, "' at index ", Uint32{Index}, + " has shader stage '", GetShaderTypeLiteralName(ShaderType), "' that is not compatible with pipeline type '", + GetPipelineTypeString(CreateInfo.PSODesc.PipelineType), "'."); + } +#endif + + m_Signatures[Index] = pSignature; + } + } + } + protected: /// Shader stages that are active in this PSO. SHADER_TYPE m_ActiveShaderStages = SHADER_TYPE_UNKNOWN; @@ -897,6 +1016,16 @@ protected: /// True if the pipeline was created using implicit root signature. const bool m_UsingImplicitSignature; + /// The number of signatures in m_Signatures array. + /// Note that this is not necessarily the same as the number of signatures + /// that were used to create the pipeline, because signatures are arranged + /// by their binding index. + Uint8 m_SignatureCount = 0; + + /// Resource signatures arranged by their binding indices + using SignatureAutoPtrType = RefCntAutoPtr<PipelineResourceSignatureImplType>; + SignatureAutoPtrType* m_Signatures = nullptr; // [m_SignatureCount] + struct GraphicsPipelineData { GraphicsPipelineDesc Desc; diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index 4c0f954b..c8f35d36 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -60,16 +60,6 @@ public: /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D12 backend. virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final; - /// Implementation of IPipelineState::GetResourceSignatureCount() in Direct3D12 backend. - virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_RootSig->GetSignatureCount(); } - - /// Implementation of IPipelineState::GetResourceSignature() in Direct3D12 backend. - virtual PipelineResourceSignatureD3D12Impl* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final - { - VERIFY_EXPR(Index < GetResourceSignatureCount()); - return m_ResourceSignatures[Index]; - } - /// Implementation of IPipelineStateD3D12::GetD3D12PipelineState(). virtual ID3D12PipelineState* DILIGENT_CALL_TYPE GetD3D12PipelineState() const override final { return static_cast<ID3D12PipelineState*>(m_pd3d12PSO.p); } @@ -111,7 +101,7 @@ private: TShaderStages& ShaderStages, LocalRootSignatureD3D12* pLocalRootSig); - static RefCntAutoPtr<IPipelineResourceSignature> CreateDefaultResourceSignature( + static RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> CreateDefaultResourceSignature( RenderDeviceD3D12Impl* pDevice, const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages, @@ -128,7 +118,6 @@ private: // 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<RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[]> m_ResourceSignatures; #ifdef DILIGENT_DEVELOPMENT // Shader resources for all shaders in all shader stages in the pipeline. diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index f27d39dc..94e8b8b4 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -414,7 +414,7 @@ size_t PipelineStateD3D12Impl::ShaderStageInfo::Count() const } -RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultResourceSignature( +RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> PipelineStateD3D12Impl::CreateDefaultResourceSignature( RenderDeviceD3D12Impl* pDevice, const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages, @@ -513,7 +513,7 @@ RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultR } } - RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature; + RefCntAutoPtr<PipelineResourceSignatureD3D12Impl> pImplicitSignature; if (Resources.size()) { PipelineResourceSignatureDesc ResSignDesc; @@ -526,7 +526,11 @@ RefCntAutoPtr<IPipelineResourceSignature> PipelineStateD3D12Impl::CreateDefaultR ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr; ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix; - pDevice->CreatePipelineResourceSignature(ResSignDesc, &pImplicitSignature, true); + // Always initialize default resource signature as internal device object. + // This is necessary to avoud cyclic references from GenerateMips. + // This may never be a problem as the PSO keeps the reference to the device if necessary. + constexpr bool bIsDeviceInternal = true; + pDevice->CreatePipelineResourceSignature(ResSignDesc, pImplicitSignature.DblPtr<IPipelineResourceSignature>(), bIsDeviceInternal); if (!pImplicitSignature) LOG_ERROR_AND_THROW("Failed to create implicit resource signature for pipeline state '", (CreateInfo.PSODesc.Name ? CreateInfo.PSODesc.Name : ""), "'."); @@ -539,31 +543,14 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr TShaderStages& ShaderStages, LocalRootSignatureD3D12* pLocalRootSig) { - Uint32 SignatureCount = 0; - if (CreateInfo.ResourceSignaturesCount == 0 || CreateInfo.ppResourceSignatures == nullptr) + if (m_UsingImplicitSignature) { - auto pImplicitSignature = CreateDefaultResourceSignature(GetDevice(), CreateInfo, ShaderStages, pLocalRootSig); - if (pImplicitSignature) - { - VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0); - SignatureCount = 1; - m_ResourceSignatures.reset(new RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[SignatureCount]); - m_ResourceSignatures[0] = pImplicitSignature.RawPtr<PipelineResourceSignatureD3D12Impl>(); - } - } - else - { - Uint32 MaxSignatureBindingIndex = PipelineResourceSignatureD3D12Impl::CalcMaxSignatureBindIndex(CreateInfo.ResourceSignaturesCount, CreateInfo.ppResourceSignatures); - SignatureCount = MaxSignatureBindingIndex + 1; - m_ResourceSignatures.reset(new RefCntAutoPtr<PipelineResourceSignatureD3D12Impl>[SignatureCount]); - - auto DbgMaxSignatureBindingIndex = - PipelineResourceSignatureD3D12Impl::CopyResourceSignatures(CreateInfo.PSODesc.PipelineType, CreateInfo.ResourceSignaturesCount, - CreateInfo.ppResourceSignatures, m_ResourceSignatures.get(), SignatureCount); - VERIFY_EXPR(DbgMaxSignatureBindingIndex == MaxSignatureBindingIndex); + VERIFY_EXPR(m_SignatureCount == 1); + m_Signatures[0] = CreateDefaultResourceSignature(GetDevice(), CreateInfo, ShaderStages, pLocalRootSig); + VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0); } - m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_ResourceSignatures.get(), SignatureCount); + m_RootSig = GetDevice()->GetRootSignatureCache().GetRootSig(m_Signatures, m_SignatureCount); if (!m_RootSig) LOG_ERROR_AND_THROW("Failed to create root signature for pipeline '", m_Desc.Name, "'."); @@ -587,9 +574,9 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr ResourceBinding::TMap ResourceMap; // 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) + for (Uint32 sign = 0; sign < m_SignatureCount; ++sign) { - const PipelineResourceSignatureD3D12Impl* const pSignature = m_ResourceSignatures[sign]; + const PipelineResourceSignatureD3D12Impl* const pSignature = m_Signatures[sign]; if (pSignature == nullptr) continue; @@ -1118,12 +1105,14 @@ void PipelineStateD3D12Impl::Destruct() bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const { - VERIFY_EXPR(pPSO != nullptr); + DEV_CHECK_ERR(pPSO != nullptr, "pPSO must not be null"); if (pPSO == this) return true; - return (m_RootSig == ValidatedCast<const PipelineStateD3D12Impl>(pPSO)->m_RootSig); + bool IsCompatible = (m_RootSig == ValidatedCast<const PipelineStateD3D12Impl>(pPSO)->m_RootSig); + VERIFY_EXPR(IsCompatible == TPipelineStateBase::IsCompatibleWith(pPSO)); + return IsCompatible; } } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index 20f1965a..37fef0ba 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -60,19 +60,6 @@ public: /// Queries the specific interface, see IObject::QueryInterface() for details virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override; - /// Implementation of IPipelineState::GetResourceSignatureCount() in OpenGL backend. - virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_SignatureCount; } - - /// Implementation of IPipelineState::GetResourceSignature() in OpenGL backend. - virtual PipelineResourceSignatureGLImpl* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final - { - VERIFY_EXPR(Index < m_SignatureCount); - return m_Signatures[Index].RawPtr<PipelineResourceSignatureGLImpl>(); - } - - /// Implementation of IPipelineState::IsCompatibleWith() in OpenGL backend. - virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final; - void CommitProgram(GLContextState& State); #ifdef DILIGENT_DEVELOPMENT @@ -92,10 +79,10 @@ private: const TShaderStages& ShaderStages, SHADER_TYPE ActiveStages); - void CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo, - const TShaderStages& ShaderStages, - SHADER_TYPE ActiveStages, - IPipelineResourceSignature** ppSignature); + RefCntAutoPtr<PipelineResourceSignatureGLImpl> CreateDefaultSignature( + const PipelineStateCreateInfo& CreateInfo, + const TShaderStages& ShaderStages, + SHADER_TYPE ActiveStages); void Destruct(); @@ -115,10 +102,6 @@ private: std::vector<std::pair<GLContext::NativeGLContextType, GLObjectWrappers::GLPipelineObj>> m_GLProgPipelines; - using SignatureArrayType = std::array<RefCntAutoPtr<PipelineResourceSignatureGLImpl>, MAX_RESOURCE_SIGNATURES>; - SignatureArrayType m_Signatures = {}; - Uint8 m_SignatureCount = 0; - Uint8 m_NumPrograms = 0; bool m_IsProgramPipelineSupported = false; std::array<SHADER_TYPE, 5> m_ShaderTypes = {}; diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 693c0d1a..334b20d7 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -41,10 +41,10 @@ namespace Diligent { -void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo, - const TShaderStages& ShaderStages, - SHADER_TYPE ActiveStages, - IPipelineResourceSignature** ppSignature) +RefCntAutoPtr<PipelineResourceSignatureGLImpl> PipelineStateGLImpl::CreateDefaultSignature( + const PipelineStateCreateInfo& CreateInfo, + const TShaderStages& ShaderStages, + SHADER_TYPE ActiveStages) { std::vector<PipelineResourceDesc> Resources; @@ -152,6 +152,7 @@ void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo& ProgramResources.ProcessConstResources(HandleUB, HandleTexture, HandleImage, HandleSB); } + RefCntAutoPtr<PipelineResourceSignatureGLImpl> pSignature; if (Resources.size()) { String SignName = String{"Implicit signature for PSO '"} + m_Desc.Name + '\''; @@ -167,37 +168,28 @@ void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo& ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity; ResSignDesc.UseCombinedTextureSamplers = true; - GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppSignature, true); + // Always initialize default resource signature as internal device object. + // This is necessary to avoud cyclic references from TexRegionRenderer. + // This may never be a problem as the PSO keeps the reference to the device if necessary. + constexpr bool bIsDeviceInternal = true; + GetDevice()->CreatePipelineResourceSignature(ResSignDesc, pSignature.DblPtr<IPipelineResourceSignature>(), bIsDeviceInternal); - if (*ppSignature == nullptr) + if (!pSignature) LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state"); } + + return pSignature; } void PipelineStateGLImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, const TShaderStages& ShaderStages, SHADER_TYPE ActiveStages) { - const Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount; - RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature; - - if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr) - { - CreateDefaultSignature(CreateInfo, ShaderStages, ActiveStages, &pImplicitSignature); - if (pImplicitSignature != nullptr) - { - VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0); - m_Signatures[0] = ValidatedCast<PipelineResourceSignatureGLImpl>(pImplicitSignature.RawPtr()); - m_SignatureCount = 1; - } - } - else + if (m_UsingImplicitSignature) { - const auto MaxBindingIndex = - PipelineResourceSignatureGLImpl::CopyResourceSignatures(CreateInfo.PSODesc.PipelineType, SignatureCount, CreateInfo.ppResourceSignatures, - m_Signatures.data(), m_Signatures.size()); - m_SignatureCount = static_cast<decltype(m_SignatureCount)>(MaxBindingIndex + 1); - VERIFY_EXPR(m_SignatureCount == MaxBindingIndex + 1); + VERIFY_EXPR(m_SignatureCount == 1); + m_Signatures[0] = CreateDefaultSignature(CreateInfo, ShaderStages, ActiveStages); + VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0); } // Apply resource bindings to programs. @@ -393,10 +385,7 @@ void PipelineStateGLImpl::Destruct() m_GLPrograms = nullptr; } - m_Signatures.fill({}); - - m_SignatureCount = 0; - m_NumPrograms = 0; + m_NumPrograms = 0; TPipelineStateBase::Destruct(); } @@ -409,26 +398,6 @@ SHADER_TYPE PipelineStateGLImpl::GetShaderStageType(Uint32 Index) const return m_ShaderTypes[Index]; } -bool PipelineStateGLImpl::IsCompatibleWith(const IPipelineState* pPSO) const -{ - VERIFY_EXPR(pPSO != nullptr); - - if (pPSO == this) - return true; - - const auto& lhs = *this; - const auto& rhs = *ValidatedCast<const PipelineStateGLImpl>(pPSO); - - if (lhs.GetResourceSignatureCount() != rhs.GetResourceSignatureCount()) - return false; - - for (Uint32 s = 0, SigCount = lhs.GetResourceSignatureCount(); s < SigCount; ++s) - { - if (!lhs.GetResourceSignature(s)->IsCompatibleWith(*rhs.GetResourceSignature(s))) - return false; - } - return true; -} void PipelineStateGLImpl::CommitProgram(GLContextState& State) { diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp index 25bbcb6b..3ef58d49 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp @@ -29,15 +29,16 @@ /// \file /// Declaration of Diligent::PipelineLayoutVk class + #include <array> -#include "PipelineResourceSignatureVkImpl.hpp" #include "VulkanUtilities/VulkanObjectWrappers.hpp" namespace Diligent { -class ShaderResourceCacheVk; +class RenderDeviceVkImpl; +class PipelineResourceSignatureVkImpl; /// Implementation of the Diligent::PipelineLayoutVk class class PipelineLayoutVk @@ -46,68 +47,32 @@ public: PipelineLayoutVk(); ~PipelineLayoutVk(); - void Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE PipelineType, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount); + void Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[], Uint32 SignatureCount); void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask); - size_t GetHash() const; - VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; } - Uint32 GetSignatureCount() const { return m_SignatureCount; } - PipelineResourceSignatureVkImpl* GetSignature(Uint32 index) const + // Returns the index of the first descriptor set used by the resource signature at the given bind index + Uint32 GetFirstDescrSetIndex(Uint32 Index) const { - VERIFY_EXPR(index < m_SignatureCount); - return m_Signatures[index].RawPtr<PipelineResourceSignatureVkImpl>(); - } - - // Returns the index of the first descriptor set used by the given resource signature - Uint32 GetFirstDescrSetIndex(const PipelineResourceSignatureVkImpl* pPRS) const - { - VERIFY_EXPR(pPRS != nullptr); - Uint32 Index = pPRS->GetDesc().BindingIndex; - - VERIFY_EXPR(Index < m_SignatureCount); - VERIFY_EXPR(m_Signatures[Index] != nullptr); - VERIFY_EXPR(!m_Signatures[Index]->IsIncompatibleWith(*pPRS)); - + VERIFY_EXPR(Index <= m_DbgMaxBindIndex); return m_FirstDescrSetIndex[Index]; } - struct ResourceInfo - { - PipelineResourceSignatureVkImpl* Signature = nullptr; - SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN; - // Index in m_Desc.Resources for a resource, or ~0U for an immutable sampler. - Uint32 ResIndex = ~0U; - Uint32 DescrSetIndex = ~0U; - Uint32 BindingIndex = ~0U; - - explicit operator bool() const - { - return Signature != nullptr && Type != SHADER_RESOURCE_TYPE_UNKNOWN; - } - }; - ResourceInfo GetResourceInfo(const char* Name, SHADER_TYPE Stage) const; - ResourceInfo GetImmutableSamplerInfo(const char* Name, SHADER_TYPE Stage) const; - private: - using SignatureArray = std::array<RefCntAutoPtr<PipelineResourceSignatureVkImpl>, MAX_RESOURCE_SIGNATURES>; - using FirstDescrSetIndexArrayType = std::array<Uint8, MAX_RESOURCE_SIGNATURES>; - VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout; + using FirstDescrSetIndexArrayType = std::array<Uint8, MAX_RESOURCE_SIGNATURES>; // Index of the first descriptor set, for every resource signature. FirstDescrSetIndexArrayType m_FirstDescrSetIndex = {}; - // The number of resource signatures used by this pipeline layout - // (Maximum is MAX_RESOURCE_SIGNATURES) - Uint8 m_SignatureCount = 0; - // The total number of descriptor sets used by this pipeline layout // (Maximum is MAX_RESOURCE_SIGNATURES * 2) Uint8 m_DescrSetCount = 0; - SignatureArray m_Signatures; +#ifdef DILIGENT_DEBUG + Uint32 m_DbgMaxBindIndex = 0; +#endif }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index d2f289af..f36611df 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -44,6 +44,7 @@ #include "VulkanUtilities/VulkanCommandBuffer.hpp" #include "RenderDeviceVkImpl.hpp" #include "PipelineLayoutVk.hpp" +#include "PipelineResourceSignatureVkImpl.hpp" namespace Diligent { @@ -66,21 +67,12 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineStateVk, TPipelineStateBase) - /// Implementation of IPipelineState::IsCompatibleWith() in Vulkan backend. - virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final; - /// Implementation of IPipelineStateVk::GetRenderPass(). virtual IRenderPassVk* DILIGENT_CALL_TYPE GetRenderPass() const override final { return GetRenderPassPtr().RawPtr<IRenderPassVk>(); } /// Implementation of IPipelineStateVk::GetVkPipeline(). virtual VkPipeline DILIGENT_CALL_TYPE GetVkPipeline() const override final { return m_Pipeline; } - /// Implementation of IPipelineState::GetResourceSignatureCount() in Vulkan backend. - virtual Uint32 DILIGENT_CALL_TYPE GetResourceSignatureCount() const override final { return m_PipelineLayout.GetSignatureCount(); } - - /// Implementation of IPipelineState::GetResourceSignature() in Vulkan backend. - virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final { return m_PipelineLayout.GetSignature(Index); } - const PipelineLayoutVk& GetPipelineLayout() const { return m_PipelineLayout; } static RenderPassDesc GetImplicitRenderPassDesc(Uint32 NumRenderTargets, @@ -115,7 +107,7 @@ public: // Performs validation of SRB resource parameters that are not possible to validate // when resource is bound. using SRBArray = std::array<ShaderResourceBindingVkImpl*, MAX_RESOURCE_SIGNATURES>; - void DvpVerifySRBResources(SRBArray& SRBs) const; + void DvpVerifySRBResources(const SRBArray& SRBs) const; #endif private: @@ -127,9 +119,9 @@ private: void InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); - void CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo, - const TShaderStages& ShaderStages, - IPipelineResourceSignature** ppSignature); + RefCntAutoPtr<PipelineResourceSignatureVkImpl> CreateDefaultSignature( + const PipelineStateCreateInfo& CreateInfo, + const TShaderStages& ShaderStages); void Destruct(); @@ -139,8 +131,8 @@ private: #ifdef DILIGENT_DEVELOPMENT // Shader resources for all shaders in all shader stages std::vector<std::shared_ptr<const SPIRVShaderResources>> m_ShaderResources; - // Resource info for every resource in m_ShaderResources, in the same order - std::vector<PipelineLayoutVk::ResourceInfo> m_ResInfo; + // Resource attributions for every resource in m_ShaderResources, in the same order + std::vector<ResourceAttribution> m_ResourceAttibutions; #endif }; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 878cf9a9..0ac9c0fb 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -318,14 +318,14 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState) const auto& Layout = pPipelineStateVk->GetPipelineLayout(); auto& BindInfo = GetDescriptorSetBindInfo(PSODesc.PipelineType); - const auto SignCount = Layout.GetSignatureCount(); + const auto SignCount = pPipelineStateVk->GetResourceSignatureCount(); BindInfo.vkPipelineLayout = Layout.GetVkPipelineLayout(); BindInfo.ActiveSRBMask = 0; for (Uint32 i = 0; i < SignCount; ++i) { - auto* pSignature = Layout.GetSignature(i); + auto* pSignature = pPipelineStateVk->GetResourceSignature(i); if (pSignature == nullptr || pSignature->GetNumDescriptorSets() == 0) continue; @@ -333,7 +333,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState) auto& ResInfo = BindInfo.Resources[i]; - ResInfo.DescriptorSetBaseInd = Layout.GetFirstDescrSetIndex(pSignature); + ResInfo.DescriptorSetBaseInd = Layout.GetFirstDescrSetIndex(pSignature->GetDesc().BindingIndex); ResInfo.DynamicOffsetCount = pSignature->GetDynamicOffsetCount(); } @@ -349,7 +349,7 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState) Uint32 sign = 0; for (; sign < SignCount; ++sign) { - const auto* pLayoutSign = Layout.GetSignature(sign); + const auto* pLayoutSign = pPipelineStateVk->GetResourceSignature(sign); const auto* pSRBSign = BindInfo.SRBs[sign] != nullptr ? BindInfo.SRBs[sign]->GetSignature() : nullptr; if ((pLayoutSign == nullptr || pLayoutSign->GetNumDescriptorSets() == 0) != (pSRBSign == nullptr || pSRBSign->GetNumDescriptorSets() == 0)) @@ -414,7 +414,7 @@ void DeviceContextVkImpl::CommitDescriptorSets(DescriptorSetBindInfo& BindInfo) while (StaleSRBFlags != 0) { Uint32 sign = PlatformMisc::GetLSB(StaleSRBFlags); - VERIFY_EXPR(sign < m_pPipelineState->GetPipelineLayout().GetSignatureCount()); + VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount()); StaleSRBFlags &= ~(Uint32{1} << sign); auto& ResInfo = BindInfo.Resources[sign]; @@ -461,17 +461,16 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources() if (m_State.CommittedResourcesValidated) return; - const auto& Layout = m_pPipelineState->GetPipelineLayout(); - auto& BindInfo = GetDescriptorSetBindInfo(m_pPipelineState->GetDesc().PipelineType); - const auto SignCount = Layout.GetSignatureCount(); + const auto& BindInfo = GetDescriptorSetBindInfo(m_pPipelineState->GetDesc().PipelineType); + const auto SignCount = m_pPipelineState->GetResourceSignatureCount(); for (Uint32 i = 0; i < SignCount; ++i) { - auto* pLayoutSign = Layout.GetSignature(i); - if (pLayoutSign == nullptr) + const auto* pSign = m_pPipelineState->GetResourceSignature(i); + if (pSign == nullptr) continue; - if (pLayoutSign->GetNumDescriptorSets() == 0) + if (pSign->GetNumDescriptorSets() == 0) { // Skip signatures without any resources continue; @@ -487,7 +486,7 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources() const auto* pSRBSign = pSRB->GetSignature(); DEV_CHECK_ERR(pSRBSign != nullptr, "SRB must not be null"); - if (!pLayoutSign->IsCompatibleWith(*pSRBSign)) + if (!pSign->IsCompatibleWith(*pSRBSign)) { LOG_ERROR_MESSAGE("Shader resource binding at index ", i, " with signature '", pSRBSign->GetDesc().Name, "' is not compatible with pipeline layout in current pipeline '", m_pPipelineState->GetDesc().Name, "'."); @@ -496,12 +495,12 @@ void DeviceContextVkImpl::DvpValidateCommittedShaderResources() DEV_CHECK_ERR((BindInfo.StaleSRBMask & BindInfo.ActiveSRBMask) == 0, "CommitDescriptorSets() must be called before validation."); const auto& ResInfo = BindInfo.Resources[i]; - const auto DSCount = pLayoutSign->GetNumDescriptorSets(); + const auto DSCount = pSign->GetNumDescriptorSets(); for (Uint32 s = 0; s < DSCount; ++s) { DEV_CHECK_ERR(ResInfo.vkSets[s] != VK_NULL_HANDLE, "descriptor set with index ", s, " is not bound for resource signature '", - pLayoutSign->GetDesc().Name, "', binding index ", i, "."); + pSign->GetDesc().Name, "', binding index ", i, "."); } DEV_CHECK_ERR(ResInfo.LastBoundDSBaseInd == ResInfo.DescriptorSetBaseInd, diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp index f8fae8ee..14183e97 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp @@ -34,6 +34,7 @@ #include "RenderDeviceVkImpl.hpp" #include "VulkanTypeConversions.hpp" #include "StringTools.hpp" +#include "PipelineResourceSignatureVkImpl.hpp" namespace Diligent { @@ -56,16 +57,9 @@ void PipelineLayoutVk::Release(RenderDeviceVkImpl* pDeviceVk, Uint64 CommandQueu } } -void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE PipelineType, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount) +void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, RefCntAutoPtr<PipelineResourceSignatureVkImpl> ppSignatures[], Uint32 SignatureCount) { - VERIFY(m_SignatureCount == 0 && m_DescrSetCount == 0 && !m_VkPipelineLayout, - "This pipeline layout is already initialized"); - - auto MaxSignatureBindIndex = - PipelineResourceSignatureVkImpl::CopyResourceSignatures(PipelineType, SignatureCount, ppSignatures, - m_Signatures.data(), m_Signatures.size()); - m_SignatureCount = static_cast<Uint8>(MaxSignatureBindIndex + 1); - VERIFY_EXPR(m_SignatureCount == MaxSignatureBindIndex + 1); + VERIFY(m_DescrSetCount == 0 && !m_VkPipelineLayout, "This pipeline layout is already initialized"); std::array<VkDescriptorSetLayout, MAX_RESOURCE_SIGNATURES * PipelineResourceSignatureVkImpl::MAX_DESCRIPTOR_SETS> DescSetLayouts; @@ -73,9 +67,9 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel Uint32 DynamicUniformBufferCount = 0; Uint32 DynamicStorageBufferCount = 0; - for (Uint32 i = 0; i < m_SignatureCount; ++i) + for (Uint32 i = 0; i < SignatureCount; ++i) { - const auto& pSignature = m_Signatures[i]; + const auto& pSignature = ppSignatures[i]; if (pSignature == nullptr) continue; @@ -91,6 +85,9 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel DynamicUniformBufferCount += pSignature->GetDynamicUniformBufferCount(); DynamicStorageBufferCount += pSignature->GetDynamicStorageBufferCount(); +#ifdef DILIGENT_DEBUG + m_DbgMaxBindIndex = std::max(m_DbgMaxBindIndex, Uint32{pSignature->GetDesc().BindingIndex}); +#endif } VERIFY_EXPR(DescSetLayoutCount <= MAX_RESOURCE_SIGNATURES * 2); @@ -130,76 +127,4 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel m_DescrSetCount = static_cast<Uint8>(DescSetLayoutCount); } -size_t PipelineLayoutVk::GetHash() const -{ - if (m_SignatureCount == 0) - return 0; - - size_t hash = 0; - HashCombine(hash, m_SignatureCount); - for (Uint32 i = 0; i < m_SignatureCount; ++i) - { - if (m_Signatures[i] != nullptr) - HashCombine(hash, m_Signatures[i]->GetHash()); - else - HashCombine(hash, 0); - } - return hash; -} - -PipelineLayoutVk::ResourceInfo PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage) const -{ - ResourceInfo Info; - for (Uint32 sign = 0, SignCount = GetSignatureCount(); sign < SignCount && !Info; ++sign) - { - auto* const pSignature = GetSignature(sign); - if (pSignature == nullptr) - continue; - - for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r) - { - const auto& ResDesc = pSignature->GetResourceDesc(r); - const auto& Attr = pSignature->GetResourceAttribs(r); - - if ((ResDesc.ShaderStages & Stage) != 0 && strcmp(ResDesc.Name, Name) == 0) - { - Info.Signature = pSignature; - Info.Type = ResDesc.ResourceType; - Info.ResIndex = r; - Info.BindingIndex = Attr.BindingIndex; - Info.DescrSetIndex = m_FirstDescrSetIndex[sign] + Attr.DescrSet; - break; - } - } - } - return Info; -} - -PipelineLayoutVk::ResourceInfo PipelineLayoutVk::GetImmutableSamplerInfo(const char* Name, SHADER_TYPE Stage) const -{ - ResourceInfo Info; - for (Uint32 sign = 0, SignCount = GetSignatureCount(); sign < SignCount && !Info; ++sign) - { - auto* const pSignature = GetSignature(sign); - if (pSignature == nullptr) - continue; - - for (Uint32 s = 0, SampCount = pSignature->GetImmutableSamplerCount(); s < SampCount; ++s) - { - const auto& Desc = pSignature->GetImmutableSamplerDesc(s); - const auto& Attr = pSignature->GetImmutableSamplerAttribs(s); - - if (Attr.Ptr && (Desc.ShaderStages & Stage) != 0 && StreqSuff(Name, Desc.SamplerOrTextureName, pSignature->GetCombinedSamplerSuffix())) - { - Info.Signature = pSignature; - Info.Type = SHADER_RESOURCE_TYPE_SAMPLER; - Info.BindingIndex = Attr.BindingIndex; - Info.DescrSetIndex = m_FirstDescrSetIndex[sign] + Attr.DescrSet; - break; - } - } - } - return Info; -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 3a3f8092..364d6f1b 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -735,9 +735,9 @@ RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc( return RPDesc; } -void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo, - const TShaderStages& ShaderStages, - IPipelineResourceSignature** ppSignature) +RefCntAutoPtr<PipelineResourceSignatureVkImpl> PipelineStateVkImpl::CreateDefaultSignature( + const PipelineStateCreateInfo& CreateInfo, + const TShaderStages& ShaderStages) { struct UniqueResource { @@ -837,6 +837,7 @@ void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo& } } + RefCntAutoPtr<PipelineResourceSignatureVkImpl> pSignature; if (Resources.size()) { String SignName = String{"Implicit signature for PSO '"} + m_Desc.Name + '\''; @@ -852,38 +853,30 @@ void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo& ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr; ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix; - GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppSignature, true); + // Always initialize default resource signature as internal device object. + // This is necessary to avoud cyclic references. + // This may never be a problem as the PSO keeps the reference to the device if necessary. + constexpr bool bIsDeviceInternal = true; + GetDevice()->CreatePipelineResourceSignature(ResSignDesc, pSignature.DblPtr<IPipelineResourceSignature>(), bIsDeviceInternal); - if (*ppSignature == nullptr) + if (pSignature == nullptr) LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state"); } + + return pSignature; } void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages) { - std::array<IPipelineResourceSignature*, MAX_RESOURCE_SIGNATURES> Signatures = {}; - RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature; - - Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount; - - for (Uint32 i = 0; i < SignatureCount; ++i) - { - Signatures[i] = CreateInfo.ppResourceSignatures[i]; - } - - if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr) + if (m_UsingImplicitSignature) { - CreateDefaultSignature(CreateInfo, ShaderStages, &pImplicitSignature); - if (pImplicitSignature != nullptr) - { - VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0); - Signatures[0] = pImplicitSignature; - SignatureCount = 1; - } + VERIFY_EXPR(m_SignatureCount == 1); + m_Signatures[0] = CreateDefaultSignature(CreateInfo, ShaderStages); + VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0); } - m_PipelineLayout.Create(GetDevice(), CreateInfo.PSODesc.PipelineType, Signatures.data(), SignatureCount); + m_PipelineLayout.Create(GetDevice(), m_Signatures, m_SignatureCount); // Verify that pipeline layout is compatible with shader resources and // remap resource bindings. @@ -908,46 +901,56 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea pShaderResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32) // { - auto Info = m_PipelineLayout.GetResourceInfo(SPIRVAttribs.Name, ShaderType); - if (!Info && SPIRVAttribs.Type == SPIRVShaderResourceAttribs::SeparateSampler) - { - DEV_CHECK_ERR(SPIRVAttribs.ArraySize == 1, "Immutable sampler arrays must also be added to resource list"); - Info = m_PipelineLayout.GetImmutableSamplerInfo(SPIRVAttribs.Name, ShaderType); - if (Info) - { - VERIFY(Info.BindingIndex != ~0u && Info.DescrSetIndex != ~0u, - "Binding index and/or descriptor set index are not initialized. This indicates that the immutable sampler " - "is also present in the list of resources, so it should've been found by GetResourceInfo()."); - } - } - if (!Info) + auto ResAttribution = GetResourceAttribution(SPIRVAttribs.Name, ShaderType); + if (!ResAttribution) { LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", SPIRVAttribs.Name, "' that is not present in any pipeline resource signature used to create pipeline state '", m_Desc.Name, "'."); } + const auto& SignDesc = ResAttribution.pSignature->GetDesc(); + SHADER_RESOURCE_TYPE Type; PIPELINE_RESOURCE_FLAGS Flags; GetShaderResourceTypeAndFlags(SPIRVAttribs.Type, Type, Flags); - if (Type != Info.Type) - { - LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name, - "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '", - GetShaderResourceTypeLiteralName(Info.Type), "' specified in pipeline resource signature '", Info.Signature->GetDesc().Name, "'."); - } - if (Info.ResIndex != ~0u) + Uint32 ResourceBinding = ~0u; + Uint32 DescriptorSet = ~0u; + if (ResAttribution.ResourceIndex != ResourceAttribution::InvalidResourceIndex) { - const auto& ResDesc = Info.Signature->GetResourceDesc(Info.ResIndex); + const auto& ResDesc = ResAttribution.pSignature->GetResourceDesc(ResAttribution.ResourceIndex); ValidatePipelineResourceCompatibility(ResDesc, Type, Flags, SPIRVAttribs.ArraySize, - pShader->GetDesc().Name, Info.Signature->GetDesc().Name); + pShader->GetDesc().Name, SignDesc.Name); + + const auto& ResAttribs{ResAttribution.pSignature->GetResourceAttribs(ResAttribution.ResourceIndex)}; + ResourceBinding = ResAttribs.BindingIndex; + DescriptorSet = ResAttribs.DescrSet; + } + else if (ResAttribution.ImmutableSamplerIndex != ResourceAttribution::InvalidResourceIndex) + { + if (Type != SHADER_RESOURCE_TYPE_SAMPLER) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name, + "' and type '", GetShaderResourceTypeLiteralName(Type), + "' that is not compatible with immutable sampler defined in pipeline resource signature '", + SignDesc.Name, "'."); + } + const auto& SamAttribs{ResAttribution.pSignature->GetImmutableSamplerAttribs(ResAttribution.ImmutableSamplerIndex)}; + ResourceBinding = SamAttribs.BindingIndex; + DescriptorSet = SamAttribs.DescrSet; + } + else + { + UNEXPECTED("Either immutable sampler or resource index should be valid"); } - SPIRV[SPIRVAttribs.BindingDecorationOffset] = Info.BindingIndex; - SPIRV[SPIRVAttribs.DescriptorSetDecorationOffset] = Info.DescrSetIndex; + + VERIFY_EXPR(ResourceBinding != ~0u && DescriptorSet != ~0u); + SPIRV[SPIRVAttribs.BindingDecorationOffset] = ResourceBinding; + SPIRV[SPIRVAttribs.DescriptorSetDecorationOffset] = m_PipelineLayout.GetFirstDescrSetIndex(SignDesc.BindingIndex) + DescriptorSet; #ifdef DILIGENT_DEVELOPMENT - m_ResInfo.emplace_back(Info); + m_ResourceAttibutions.emplace_back(ResAttribution); #endif }); } @@ -963,8 +966,6 @@ PipelineStateVkImpl::TShaderStages PipelineStateVkImpl::InitInternalObjects( TShaderStages ShaderStages; ExtractShaders<ShaderVkImpl>(CreateInfo, ShaderStages); - InitPipelineLayout(CreateInfo, ShaderStages); - FixedLinearAllocator MemPool{GetRawAllocator()}; ReserveSpaceForPipelineDesc(CreateInfo, MemPool); @@ -975,6 +976,8 @@ PipelineStateVkImpl::TShaderStages PipelineStateVkImpl::InitInternalObjects( InitializePipelineDesc(CreateInfo, MemPool); + InitPipelineLayout(CreateInfo, ShaderStages); + // Create shader modules and initialize shader stages InitPipelineShaderStages(LogicalDevice, ShaderStages, ShaderModules, vkShaderStages); @@ -1062,45 +1065,24 @@ void PipelineStateVkImpl::Destruct() TPipelineStateBase::Destruct(); } -bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const -{ - VERIFY_EXPR(pPSO != nullptr); - - if (pPSO == this) - return true; - - const auto& lhs = m_PipelineLayout; - const auto& rhs = ValidatedCast<const PipelineStateVkImpl>(pPSO)->m_PipelineLayout; - - if (lhs.GetSignatureCount() != rhs.GetSignatureCount()) - return false; - - for (Uint32 s = 0, SigCount = lhs.GetSignatureCount(); s < SigCount; ++s) - { - if (!lhs.GetSignature(s)->IsCompatibleWith(*rhs.GetSignature(s))) - return false; - } - return true; -} - #ifdef DILIGENT_DEVELOPMENT -void PipelineStateVkImpl::DvpVerifySRBResources(SRBArray& SRBs) const +void PipelineStateVkImpl::DvpVerifySRBResources(const SRBArray& SRBs) const { - auto res_info = m_ResInfo.begin(); + auto res_info = m_ResourceAttibutions.begin(); for (const auto& pResources : m_ShaderResources) { pResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { - if (res_info->ResIndex != ~0u) // There are also immutable samplers in the list + if (!res_info->IsImmutableSampler()) // There are also immutable samplers in the list { - VERIFY_EXPR(res_info->Signature != nullptr); - const auto& SignDesc = res_info->Signature->GetDesc(); + VERIFY_EXPR(res_info->pSignature != nullptr); + const auto& SignDesc = res_info->pSignature->GetDesc(); const auto SignBindIndex = SignDesc.BindingIndex; if (auto* pSRB = SRBs[SignBindIndex]) { - res_info->Signature->DvpValidateCommittedResource(ResAttribs, res_info->ResIndex, pSRB->GetResourceCache(), - pResources->GetShaderName(), m_Desc.Name); + res_info->pSignature->DvpValidateCommittedResource(ResAttribs, res_info->ResourceIndex, pSRB->GetResourceCache(), + pResources->GetShaderName(), m_Desc.Name); } else { @@ -1111,7 +1093,7 @@ void PipelineStateVkImpl::DvpVerifySRBResources(SRBArray& SRBs) const } // ); } - VERIFY_EXPR(res_info == m_ResInfo.end()); + VERIFY_EXPR(res_info == m_ResourceAttibutions.end()); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp index e6d053ee..3becabff 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp @@ -87,7 +87,7 @@ RenderPassVkImpl* RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key) } RefCntAutoPtr<RenderPassVkImpl> pRenderPass; - m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.GetRawDblPtr<IRenderPass>(), /* IsDeviceInternal = */ true); + m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.RawDblPtr<IRenderPass>(), /* IsDeviceInternal = */ true); VERIFY_EXPR(pRenderPass != nullptr); it = m_Cache.emplace(Key, std::move(pRenderPass)).first; } |
