From 30a65df99cfc678a431a89b0cff02a515416c78a Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 6 Mar 2021 14:06:26 -0800 Subject: Unified resource signature handling by pipeline state in D3D12, Vk and GL --- .../include/PipelineLayoutVk.hpp | 57 ++------- .../include/PipelineStateVkImpl.hpp | 22 +--- .../src/DeviceContextVkImpl.cpp | 27 ++-- .../GraphicsEngineVulkan/src/PipelineLayoutVk.cpp | 91 ++----------- .../src/PipelineStateVkImpl.cpp | 142 +++++++++------------ .../GraphicsEngineVulkan/src/RenderPassCache.cpp | 2 +- 6 files changed, 102 insertions(+), 239 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') 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 -#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 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(); - } - - // 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, MAX_RESOURCE_SIGNATURES>; - using FirstDescrSetIndexArrayType = std::array; - VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout; + using FirstDescrSetIndexArrayType = std::array; // 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(); } /// 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; - 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 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> m_ShaderResources; - // Resource info for every resource in m_ShaderResources, in the same order - std::vector m_ResInfo; + // Resource attributions for every resource in m_ShaderResources, in the same order + std::vector 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 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(MaxSignatureBindIndex + 1); - VERIFY_EXPR(m_SignatureCount == MaxSignatureBindIndex + 1); + VERIFY(m_DescrSetCount == 0 && !m_VkPipelineLayout, "This pipeline layout is already initialized"); std::array 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(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 PipelineStateVkImpl::CreateDefaultSignature( + const PipelineStateCreateInfo& CreateInfo, + const TShaderStages& ShaderStages) { struct UniqueResource { @@ -837,6 +837,7 @@ void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo& } } + RefCntAutoPtr 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(), 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 Signatures = {}; - RefCntAutoPtr 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(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(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 pRenderPass; - m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.GetRawDblPtr(), /* IsDeviceInternal = */ true); + m_DeviceVkImpl.CreateRenderPass(RPDesc, pRenderPass.RawDblPtr(), /* IsDeviceInternal = */ true); VERIFY_EXPR(pRenderPass != nullptr); it = m_Cache.emplace(Key, std::move(pRenderPass)).first; } -- cgit v1.2.3