From dfb3f98a83a646abff564a159d556f03432826ac Mon Sep 17 00:00:00 2001 From: azhirnov Date: Mon, 25 Jan 2021 18:58:28 +0300 Subject: removed empty signature, added test for partially compatible pipeline layouts --- .../include/DeviceContextVkImpl.hpp | 29 +++++---- .../include/PipelineLayoutVk.hpp | 1 - .../include/PipelineStateVkImpl.hpp | 17 +++++ .../include/RenderDeviceVkImpl.hpp | 5 -- .../src/DeviceContextVkImpl.cpp | 75 ++++++++++------------ .../GraphicsEngineVulkan/src/PipelineLayoutVk.cpp | 22 +++---- .../src/PipelineStateVkImpl.cpp | 45 +++++++++++++ .../src/RenderDeviceVkImpl.cpp | 6 -- 8 files changed, 124 insertions(+), 76 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index 146742b3..70ff48f4 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -486,23 +486,24 @@ private: // Do not use strong references! using ShaderResourceArray = std::array; using VkDescSetArray = std::array; - using BoolArray = std::bitset; + using Bitfield = Uint8; + static_assert(sizeof(Bitfield) * 8 >= MAX_RESOURCE_SIGNATURES, "AZ TODO"); - ShaderResourceArray Resources = {}; - VkDescSetArray vkSets = {}; - BoolArray PendingVkSet = {}; // 'true' if new descriptor set must be bound - BoolArray PendingDynamicDescriptors = {}; // 'true' if dynamic descriptor set must be bound // AZ TODO: remove ? - BoolArray DynamicBuffersPresent = {}; + Bitfield ActiveSRBMask = 0; // indicates which SRB is active in current PSO + Bitfield PendingSRB = 0; // 1 bit if new descriptor set must be bound + Bitfield DynamicBuffersPresent = 0; + ShaderResourceArray Resources = {}; + VkDescSetArray vkSets = {}; DescriptorSetBindInfo() {} void Reset() { - PendingVkSet.reset(); - DynamicBuffersPresent.reset(); - PendingDynamicDescriptors.reset(); - Resources.fill({}); + ActiveSRBMask = 0; + PendingSRB = 0; + DynamicBuffersPresent = 0; + Resources.fill(nullptr); #ifdef DILIGENT_DEBUG vkSets.fill(VK_NULL_HANDLE); @@ -511,8 +512,14 @@ private: __forceinline bool RequireUpdate(bool Intact = false) const { - return PendingVkSet.any() || PendingDynamicDescriptors.any() || (DynamicBuffersPresent.any() && !Intact); + return (PendingSRB & ActiveSRBMask) || ((DynamicBuffersPresent & ActiveSRBMask) && !Intact); } + + void SetPendingSRB(Uint32 Index) { PendingSRB |= static_cast(1u << Index); } + void ResetPendingSRB(Uint32 Index) { PendingSRB &= static_cast(~(1u << Index)); } + + void SetDynamicBuffersPresent(Uint32 Index) { DynamicBuffersPresent |= static_cast(1u << Index); } + void ResetDynamicBuffersPresent(Uint32 Index) { DynamicBuffersPresent &= static_cast(~(1u << Index)); } }; void BindShaderResources(PipelineStateVkImpl* pPipelineStateVk); diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp index 1658dd06..660815f6 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp @@ -53,7 +53,6 @@ public: VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; } Uint32 GetSignatureCount() const { return m_SignatureCount; } - //Uint32 GetDescriptorSetCount() const { return m_DescrSetCount; } PipelineResourceSignatureVkImpl* GetSignature(Uint32 index) const { diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 438b09e9..cafb6518 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -79,6 +79,23 @@ public: /// Implementation of IPipelineState::GetResourceSignature() in Vulkan backend. virtual IPipelineResourceSignature* DILIGENT_CALL_TYPE GetResourceSignature(Uint32 Index) const override final { return m_PipelineLayout.GetSignature(Index); } + /// Implementation of IPipelineState::CreateShaderResourceBinding() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, + bool InitStaticResources) override final; + + /// Implementation of IPipelineState::GetStaticVariableByName() in Vulkan backend. + virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, + const Char* Name) override final; + + /// Implementation of IPipelineState::GetStaticVariableByIndex() in Vulkan backend. + virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, + Uint32 Index) override final; + + /// Implementation of IPipelineState::GetStaticVariableCount() in Vulkan backend. + virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; + + virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) override final; + const PipelineLayoutVk& GetPipelineLayout() const { return m_PipelineLayout; } static RenderPassDesc GetImplicitRenderPassDesc(Uint32 NumRenderTargets, diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index baa3b786..126bff8c 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -233,9 +233,6 @@ public: return m_Properties; } - IPipelineResourceSignature* GetEmptySignature() const { return m_pEmptySignature.RawPtr(); } - PipelineResourceSignatureVkImpl* GetEmptySignatureVk() const { return m_pEmptySignature.RawPtr(); } - private: template void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState); @@ -272,8 +269,6 @@ private: std::unique_ptr m_pDxCompiler; Properties m_Properties; - - RefCntAutoPtr m_pEmptySignature; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index ad6be668..315ffeae 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -352,12 +352,12 @@ __forceinline void DeviceContextVkImpl::BindShaderResources(PipelineStateVkImpl* { VERIFY_EXPR(pPipelineStateVk != nullptr); - const auto& Layout = pPipelineStateVk->GetPipelineLayout(); - const auto BindIndex = PipelineTypeToBindPointIndex(pPipelineStateVk->GetDesc().PipelineType); - auto& BindInfo = m_DescrSetBindInfo[BindIndex]; - auto& Resources = BindInfo.Resources; - const auto SignCount = Layout.GetSignatureCount(); - Uint32 CompatSignCount = SignCount; + const auto& Layout = pPipelineStateVk->GetPipelineLayout(); + const auto BindIndex = PipelineTypeToBindPointIndex(pPipelineStateVk->GetDesc().PipelineType); + auto& BindInfo = m_DescrSetBindInfo[BindIndex]; + const auto SignCount = Layout.GetSignatureCount(); + + BindInfo.ActiveSRBMask = (1u << SignCount) - 1; // Layout compatibility means that descriptor sets can be bound to a command buffer // for use by any pipeline created with a compatible pipeline layout, and without having bound @@ -366,33 +366,32 @@ __forceinline void DeviceContextVkImpl::BindShaderResources(PipelineStateVkImpl* // (14.2.2. Pipeline Layouts, clause 'Pipeline Layout Compatibility') // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#descriptorsets-compatibility - #ifdef DILIGENT_DEBUG - // unbind incompatible descriptor sets + auto& Resources = BindInfo.Resources; + Uint32 CompatSignCount = SignCount; + + // find first incompatible shader resource bindings for (Uint32 i = 0; i < SignCount; ++i) { const auto* LayoutSign = Layout.GetSignature(i); - const auto* ResSign = Resources[i] != nullptr ? Resources[i]->GetSignature() : ValidatedCast(GetDevice())->GetEmptySignatureVk(); - - VERIFY_EXPR(LayoutSign != nullptr); - VERIFY_EXPR(ResSign != nullptr); + if (LayoutSign == nullptr) + continue; - if (LayoutSign->IsIncompatibleWith(*ResSign)) + if (Resources[i] == nullptr || LayoutSign->IsIncompatibleWith(*Resources[i]->GetSignature())) { CompatSignCount = i; break; } } - // reset unused states - for (Uint32 i = CompatSignCount; i < MAX_RESOURCE_SIGNATURES; ++i) + // unbind incompatible shader resource bindings + for (Uint32 i = CompatSignCount; i < SignCount; ++i) { - BindInfo.PendingVkSet[i] = false; - BindInfo.PendingDynamicDescriptors[i] = false; - BindInfo.DynamicBuffersPresent[i] = false; - Resources[i] = nullptr; + BindInfo.ResetPendingSRB(i); + BindInfo.ResetDynamicBuffersPresent(i); + BindInfo.vkSets[i * MAX_DESCR_SET_PER_SIGNATURE + 0] = VK_NULL_HANDLE; BindInfo.vkSets[i * MAX_DESCR_SET_PER_SIGNATURE + 1] = VK_NULL_HANDLE; } @@ -410,12 +409,15 @@ void DeviceContextVkImpl::BindDescriptorSetsWithDynamicOffsets(DescriptorSetBind auto& Offsets = m_DynamicBufferOffsets; const auto VkLayout = Layout.GetVkPipelineLayout(); - for (Uint32 i = 0; i < SignCount; ++i) + while (true) { - VERIFY_EXPR(Resources[i] != nullptr); + Uint32 i = PlatformMisc::GetLSB(Uint32{BindInfo.PendingSRB}); - if ((BindInfo.PendingVkSet[i] || BindInfo.PendingDynamicDescriptors[i]) && Resources[i] != nullptr) + if (i < SignCount) { + VERIFY_EXPR(Resources[i] != nullptr); + BindInfo.ResetPendingSRB(i); + const auto* pSignature = Resources[i]->GetSignature(); const Uint32 DescrSetIdx = Layout.GetFirstDescrSetIndex(pSignature); const auto& ResourceCache = Resources[i]->GetResourceCache(); @@ -441,20 +443,17 @@ void DeviceContextVkImpl::BindDescriptorSetsWithDynamicOffsets(DescriptorSetBind // (either compute or graphics, according to the pipelineBindPoint). Any bindings that were previously // applied via these sets are no longer valid (13.2.5) m_CommandBuffer.BindDescriptorSets(BindPoint, VkLayout, DescrSetIdx, DSCount, &BindInfo.vkSets[DSOffset], static_cast(Offsets.size()), Offsets.data()); - BindInfo.PendingDynamicDescriptors[i] = false; } else { - VERIFY_EXPR(!BindInfo.PendingDynamicDescriptors[i]); m_CommandBuffer.BindDescriptorSets(BindPoint, VkLayout, DescrSetIdx, DSCount, &BindInfo.vkSets[DSOffset], 0, nullptr); } - - BindInfo.PendingVkSet[i] = false; } + else + break; } - VERIFY_EXPR(!BindInfo.PendingVkSet.any()); - VERIFY_EXPR(!BindInfo.PendingDynamicDescriptors.any()); + VERIFY_EXPR(!(BindInfo.PendingSRB & BindInfo.ActiveSRBMask)); } void DeviceContextVkImpl::ValidateShaderResources() @@ -470,10 +469,7 @@ void DeviceContextVkImpl::ValidateShaderResources() { auto* LayoutSign = Layout.GetSignature(i); if (LayoutSign == nullptr) - { - LOG_ERROR_MESSAGE("Pipeline resource signature for index (", i, ") is null, this may indicate a bug"); - return; - } + continue; if (BindInfo.Resources[i] == nullptr) { @@ -491,8 +487,7 @@ void DeviceContextVkImpl::ValidateShaderResources() } // You must call BindDescriptorSetsWithDynamicOffsets() before validation. - VERIFY_EXPR(!BindInfo.PendingVkSet[i]); - VERIFY_EXPR(!BindInfo.PendingDynamicDescriptors[i]); + VERIFY_EXPR(!(BindInfo.PendingSRB & BindInfo.ActiveSRBMask)); const auto DSCount = LayoutSign->GetNumDescriptorSets(); const auto DSOffset = i * MAX_DESCR_SET_PER_SIGNATURE; @@ -562,9 +557,12 @@ void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderR const auto DSCount = ResourceCache.GetNumDescriptorSets(); Uint32 DSIndex = 0; - BindInfo.PendingVkSet[Index] = true; - BindInfo.PendingDynamicDescriptors[Index] = false; - BindInfo.DynamicBuffersPresent[Index] = ResourceCache.GetNumDynamicBuffers() > 0; + BindInfo.SetPendingSRB(Index); + + if (ResourceCache.GetNumDynamicBuffers() > 0) + BindInfo.SetDynamicBuffersPresent(Index); + else + BindInfo.ResetDynamicBuffersPresent(Index); if (pSignature->HasStaticDescrSet()) { @@ -595,9 +593,6 @@ void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderR ++DSIndex; } - if (pSignature->GetDynamicOffsetCount() > 0) - BindInfo.PendingDynamicDescriptors[Index] = true; - VERIFY_EXPR(DSIndex == DSCount); BindInfo.Resources[Index] = pResBindingVkImpl; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp index 50f1c5c8..7d1d2c7c 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp @@ -80,15 +80,7 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi m_Signatures[Index] = pSignature; } - auto* pEmptySign = ValidatedCast(pDeviceVk->GetEmptySignature()); - - for (Uint32 i = 0; i < m_SignatureCount; ++i) - { - if (m_Signatures[i] == nullptr) - m_Signatures[i] = pEmptySign; - } - - std::array DescSetLayouts = {}; + std::array DescSetLayouts; Uint32 DescSetLayoutCount = 0; Uint32 DynamicUniformBufferCount = 0; @@ -97,7 +89,8 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi for (Uint32 i = 0; i < m_SignatureCount; ++i) { const auto& pSignature = m_Signatures[i]; - VERIFY_EXPR(pSignature != nullptr); + if (pSignature == nullptr) + continue; VERIFY(DescSetLayoutCount <= std::numeric_limits::max(), "Descriptor set layout count (", DescSetLayoutCount, ") exceeds the maximum representable value"); @@ -156,8 +149,10 @@ size_t PipelineLayoutVk::GetHash() const HashCombine(hash, m_SignatureCount); for (Uint32 i = 0; i < m_SignatureCount; ++i) { - VERIFY_EXPR(m_Signatures[i] != nullptr); - HashCombine(hash, m_Signatures[i]->GetHash()); + if (m_Signatures[i] != nullptr) + HashCombine(hash, m_Signatures[i]->GetHash()); + else + HashCombine(hash, 0); } return hash; } @@ -167,7 +162,8 @@ bool PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage, Reso for (Uint32 i = 0, DSCount = GetSignatureCount(); i < DSCount; ++i) { auto* pSignature = GetSignature(i); - VERIFY_EXPR(pSignature != nullptr); + if (pSignature == nullptr) + continue; for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r) { diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index cf6e366a..dc184e1b 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -998,4 +998,49 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const return false; } +void PipelineStateVkImpl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, + bool InitStaticResources) +{ + *ppShaderResourceBinding = nullptr; + + if (GetResourceSignatureCount() != 1) + return; + + return GetResourceSignature(0)->CreateShaderResourceBinding(ppShaderResourceBinding, InitStaticResources); +} + +IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByName(SHADER_TYPE ShaderType, + const Char* Name) +{ + if (GetResourceSignatureCount() != 1) + return nullptr; + + return GetResourceSignature(0)->GetStaticVariableByName(ShaderType, Name); +} + +IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TYPE ShaderType, + Uint32 Index) +{ + if (GetResourceSignatureCount() != 1) + return nullptr; + + return GetResourceSignature(0)->GetStaticVariableByIndex(ShaderType, Index); +} + +Uint32 PipelineStateVkImpl::GetStaticVariableCount(SHADER_TYPE ShaderType) const +{ + if (GetResourceSignatureCount() != 1) + return 0; + + return GetResourceSignature(0)->GetStaticVariableCount(ShaderType); +} + +void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) +{ + if (GetResourceSignatureCount() != 1) + return; + + return GetResourceSignature(0)->BindStaticResources(ShaderFlags, pResourceMapping, Flags); +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index edfcb670..dcf812b6 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -276,16 +276,10 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* SamCaps.BorderSamplingModeSupported = True; SamCaps.AnisotropicFilteringSupported = vkEnabledFeatures.samplerAnisotropy; SamCaps.LODBiasSupported = True; - - PipelineResourceSignatureDesc Desc; - Desc.Name = "Empty resource signature"; - CreatePipelineResourceSignature(Desc, &m_pEmptySignature, true); } RenderDeviceVkImpl::~RenderDeviceVkImpl() { - m_pEmptySignature.Release(); - // Explicitly destroy dynamic heap. This will move resources owned by // the heap into release queues m_DynamicMemoryManager.Destroy(); -- cgit v1.2.3