From bc393d8fd195f2d4400b6aeb42fa40b92d6b4b68 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Thu, 21 Jun 2018 21:33:43 -0700 Subject: Improved memory allocation for shader variables and resource cache in Vk backend --- .../GraphicsEngineVulkan/include/PipelineLayout.h | 1 + .../include/PipelineStateVkImpl.h | 53 +++---- .../include/ShaderResourceCacheVk.h | 1 + .../include/ShaderVariableVk.h | 5 + .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 15 +- .../src/PipelineStateVkImpl.cpp | 152 +++++++++++++-------- .../src/ShaderResourceCacheVk.cpp | 10 ++ .../GraphicsEngineVulkan/src/ShaderVariableVk.cpp | 31 +++-- 8 files changed, 161 insertions(+), 107 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h index 0003c5f8..d179b959 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h @@ -51,6 +51,7 @@ public: void Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice); VkPipelineLayout GetVkPipelineLayout()const{return m_LayoutMgr.GetVkPipelineLayout();} + std::array GetDescriptorSetSizes(Uint32& NumSets)const; void InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, class ShaderResourceCacheVk& ResourceCache, IMemoryAllocator& CacheMemAllocator)const; void AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs, diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h index 061aaa23..3e3a2134 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h @@ -33,16 +33,16 @@ #include "PipelineStateBase.h" #include "PipelineLayout.h" #include "ShaderResourceLayoutVk.h" -#include "AdaptiveFixedBlockAllocator.h" +#include "FixedBlockMemoryAllocator.h" #include "VulkanUtilities/VulkanObjectWrappers.h" #include "VulkanUtilities/VulkanCommandBuffer.h" #include "PipelineLayout.h" -/// Namespace for the Direct3D11 implementation of the graphics engine namespace Diligent { class FixedBlockMemoryAllocator; + /// Implementation of the Diligent::IRenderDeviceVk interface class PipelineStateVkImpl : public PipelineStateBase { @@ -84,12 +84,14 @@ public: return m_ShaderResourceLayouts[ShaderInd]; } - IMemoryAllocator& GetResourceCacheDataAllocator(){return m_ResourceCacheDataAllocator;} + IMemoryAllocator& GetResourceCacheDataAllocator() + { + return m_ResourceCacheDataAllocator != nullptr ? *m_ResourceCacheDataAllocator : GetRawAllocator(); + } IMemoryAllocator& GetShaderVariableDataAllocator(Uint32 ActiveShaderInd) { VERIFY_EXPR(ActiveShaderInd < m_NumShaders); - auto* pAllocator = m_VariableDataAllocators.GetAllocator(ActiveShaderInd); - return pAllocator != nullptr ?* pAllocator : GetRawAllocator(); + return m_VariableDataAllocators != nullptr ? m_VariableDataAllocators[ActiveShaderInd] : GetRawAllocator(); } IShaderVariable *GetDummyShaderVar(){return &m_DummyVar;} @@ -99,46 +101,23 @@ private: void CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice); DummyShaderVariable m_DummyVar; + + ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; - // Looks like there may be a bug in msvc: when allocators are declared as - // an array and if an exception is thrown from constructor, the app crashes - class VariableDataAllocators - { - public: - ~VariableDataAllocators() - { - for(size_t i=0; i < _countof(m_pAllocators); ++i) - if(m_pAllocators[i] != nullptr) - DESTROY_POOL_OBJECT(m_pAllocators[i]); - } - void Init(Uint32 NumActiveShaders, Uint32 SRBAllocationGranularity) - { - VERIFY_EXPR(NumActiveShaders <= _countof(m_pAllocators) ); - for(Uint32 i=0; i < NumActiveShaders; ++i) - m_pAllocators[i] = NEW_POOL_OBJECT(AdaptiveFixedBlockAllocator, "Shader variable data allocator", GetRawAllocator(), SRBAllocationGranularity); - } - AdaptiveFixedBlockAllocator *GetAllocator(Uint32 ActiveShaderInd) - { - VERIFY_EXPR(ActiveShaderInd < _countof(m_pAllocators) ); - return m_pAllocators[ActiveShaderInd]; - } - private: - AdaptiveFixedBlockAllocator *m_pAllocators[5] = {}; - }m_VariableDataAllocators; // Allocators must be defined before default SRB - - ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; - - AdaptiveFixedBlockAllocator m_ResourceCacheDataAllocator; // Use separate allocator for every shader stage - std::array m_ShaderModules; + // Use separate fixed-block allocator allocator for every shader stage + FixedBlockMemoryAllocator* m_VariableDataAllocators = nullptr; + FixedBlockMemoryAllocator* m_ResourceCacheDataAllocator = nullptr; + + std::array m_ShaderModules; // Do not use strong reference to avoid cyclic references // Default SRB must be defined after allocators std::unique_ptr > m_pDefaultShaderResBinding; VulkanUtilities::RenderPassWrapper m_RenderPass; - VulkanUtilities::PipelineWrapper m_Pipeline; + VulkanUtilities::PipelineWrapper m_Pipeline; PipelineLayout m_PipelineLayout; - bool m_HasStaticResources = false; + bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h index 5bd7eebc..b4a0e3b6 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h @@ -82,6 +82,7 @@ public: ~ShaderResourceCacheVk(); + static size_t GetRequiredMemorySize(Uint32 NumSets, Uint32 SetSizes[]); void InitializeSets(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]); void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type); diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h index e533a4b0..d531084b 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h @@ -85,6 +85,11 @@ public: void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags); + static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables); + private: friend ShaderVariableVkImpl; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index e9098c6e..3fb20bab 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -383,10 +383,9 @@ void PipelineLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice& Logica m_LayoutMgr.Finalize(LogicalDevice); } - -void PipelineLayout::InitResourceCache(RenderDeviceVkImpl *pDeviceVkImpl, ShaderResourceCacheVk& ResourceCache, IMemoryAllocator &CacheMemAllocator)const +std::array PipelineLayout::GetDescriptorSetSizes(Uint32& NumSets)const { - Uint32 NumSets = 0; + NumSets = 0; std::array SetSizes = {}; const auto &StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC); @@ -402,10 +401,20 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl *pDeviceVkImpl, Shader NumSets = std::max(NumSets, static_cast(DynamicSet.SetIndex + 1)); SetSizes[DynamicSet.SetIndex] = DynamicSet.TotalDescriptors; } + + return SetSizes; +} + +void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, ShaderResourceCacheVk& ResourceCache, IMemoryAllocator& CacheMemAllocator)const +{ + Uint32 NumSets = 0; + auto SetSizes = GetDescriptorSetSizes(NumSets); // This call only initializes descriptor sets (ShaderResourceCacheVk::DescriptorSet) in the resource cache // Resources are initialized by source layout when shader resource binding objects are created ResourceCache.InitializeSets(CacheMemAllocator, NumSets, SetSizes.data()); + + const auto &StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC); if (StaticAndMutSet.SetIndex >= 0) { DescriptorPoolAllocation SetAllocation = pDeviceVkImpl->AllocateDescriptorSet(StaticAndMutSet.VkLayout); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index dafd736f..91baace8 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -39,7 +39,7 @@ namespace Diligent void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice) { // NOTE: framebuffer cache and clear commands assume that depth buffer - // attachment alwasy goes first followed by all color attachments + // attachment always goes first followed by all color attachments const auto& GraphicsPipeline = m_Desc.GraphicsPipeline; // Create render pass (7.1) @@ -67,10 +67,10 @@ void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalD DepthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render // area are written to memory. For attachments with a depth/stencil format, // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. - DepthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + DepthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; DepthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - DepthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - DepthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + DepthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + DepthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; ++AttachmentInd; } @@ -91,10 +91,10 @@ void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalD ColorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render // area are written to memory. For attachments with a color format, // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. - ColorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + ColorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; ColorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - ColorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - ColorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ColorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ColorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } RenderPassCI.pAttachments = Attachments.data(); @@ -110,13 +110,13 @@ void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalD SubpassDesc.flags = 0; // All bits for this type are defined by extensions SubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Currently, only graphics subpasses are supported. SubpassDesc.inputAttachmentCount = 0; - SubpassDesc.pInputAttachments = nullptr; + SubpassDesc.pInputAttachments = nullptr; SubpassDesc.colorAttachmentCount = GraphicsPipeline.NumRenderTargets; - SubpassDesc.pColorAttachments = ColorAttachmentReferences.data(); - SubpassDesc.pResolveAttachments = nullptr; + SubpassDesc.pColorAttachments = ColorAttachmentReferences.data(); + SubpassDesc.pResolveAttachments = nullptr; SubpassDesc.pDepthStencilAttachment = GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN ? &DepthAttachmentReference : nullptr; SubpassDesc.preserveAttachmentCount = 0; - SubpassDesc.pPreserveAttachments = nullptr; + SubpassDesc.pPreserveAttachments = nullptr; std::string RenderPassName = "Render pass for '"; RenderPassName += m_Desc.Name; @@ -129,18 +129,17 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters const PipelineStateDesc& PipelineDesc) : TPipelineStateBase(pRefCounters, pDeviceVk, PipelineDesc), m_DummyVar(*this), - m_ResourceCacheDataAllocator(GetRawAllocator(), PipelineDesc.SRBAllocationGranularity), m_pDefaultShaderResBinding(nullptr, STDDeleter(pDeviceVk->GetSRBAllocator()) ) { - const auto &LogicalDevice = pDeviceVk->GetLogicalDevice(); + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); // Initialize shader resource layouts - auto &ShaderResLayoutAllocator = GetRawAllocator(); + auto& ShaderResLayoutAllocator = GetRawAllocator(); std::array, MaxShadersInPipeline> ShaderResources; std::array, MaxShadersInPipeline> ShaderSPIRVs; - auto *pRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", sizeof(ShaderResourceLayoutVk) * m_NumShaders); - m_ShaderResourceLayouts = reinterpret_cast(pRawMem); - for(Uint32 s=0; s < m_NumShaders; ++s) + auto* pResLayoutRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", sizeof(ShaderResourceLayoutVk) * m_NumShaders); + m_ShaderResourceLayouts = reinterpret_cast(pResLayoutRawMem); + for (Uint32 s=0; s < m_NumShaders; ++s) { new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(*this, LogicalDevice, GetRawAllocator()); auto *pShaderVk = ValidatedCast(m_ppShaders[s]); @@ -150,6 +149,28 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters ShaderResourceLayoutVk::Initialize(m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(), ShaderSPIRVs.data(), m_PipelineLayout); m_PipelineLayout.Finalize(LogicalDevice); + if (PipelineDesc.SRBAllocationGranularity > 1) + { + { + auto* pVarAllocatorsRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for m_VariableDataAllocators", sizeof(FixedBlockMemoryAllocator) * m_NumShaders); + m_VariableDataAllocators = reinterpret_cast(pVarAllocatorsRawMem); + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + std::array AllowedVarTypes = { SHADER_VARIABLE_TYPE_STATIC, SHADER_VARIABLE_TYPE_MUTABLE }; + Uint32 UnusedNumVars = 0; + auto RequiredMemSize = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes.data(), static_cast(AllowedVarTypes.size()), UnusedNumVars); + new(m_VariableDataAllocators + s)FixedBlockMemoryAllocator(GetRawAllocator(), RequiredMemSize, PipelineDesc.SRBAllocationGranularity); + } + } + + { + Uint32 NumSets = 0; + auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets); + m_ResourceCacheDataAllocator = reinterpret_cast(ALLOCATE(ShaderResLayoutAllocator, "Raw memory for m_ResourceCacheDataAllocator", sizeof(FixedBlockMemoryAllocator))); + auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data()); + new(m_ResourceCacheDataAllocator) FixedBlockMemoryAllocator(GetRawAllocator(), CacheMemorySize, PipelineDesc.SRBAllocationGranularity); + } + } // Create shader modules and initialize shader stages std::array ShaderStages = {}; @@ -158,7 +179,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters auto *pShader = m_ppShaders[s]; auto ShaderType = pShader->GetDesc().ShaderType; - auto &StageCI = ShaderStages[s]; + auto& StageCI = ShaderStages[s]; StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; StageCI.pNext = nullptr; StageCI.flags = 0; // reserved for future use @@ -190,9 +211,9 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters // Create pipeline if (m_Desc.IsComputePipeline) { - auto &ComputePipeline = m_Desc.ComputePipeline; + auto& ComputePipeline = m_Desc.ComputePipeline; - if( ComputePipeline.pCS == nullptr ) + if ( ComputePipeline.pCS == nullptr ) LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc"); VkComputePipelineCreateInfo PipelineCI = {}; @@ -211,9 +232,9 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters } else { - const auto &PhysicalDevice = pDeviceVk->GetPhysicalDevice(); + const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); - auto &GraphicsPipeline = m_Desc.GraphicsPipeline; + auto& GraphicsPipeline = m_Desc.GraphicsPipeline; CreateRenderPass(LogicalDevice); @@ -268,7 +289,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters } else { - const auto &Props = PhysicalDevice.GetProperties(); + const auto& Props = PhysicalDevice.GetProperties(); // There are limitiations on the viewport width and height (23.5), but // it is not clear if there are limitations on the scissor rect width and // height @@ -332,7 +353,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters // with vkCmdSetStencilReference }; - if(GraphicsPipeline.RasterizerDesc.ScissorEnable) + if (GraphicsPipeline.RasterizerDesc.ScissorEnable) { // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles @@ -353,26 +374,23 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters m_Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name); } - if(PipelineDesc.SRBAllocationGranularity > 1) - m_VariableDataAllocators.Init(m_NumShaders, PipelineDesc.SRBAllocationGranularity); - m_HasStaticResources = false; m_HasNonStaticResources = false; for (Uint32 s=0; s < m_NumShaders; ++s) { - const auto &Layout = m_ShaderResourceLayouts[s]; - if(Layout.GetResourceCount(SHADER_VARIABLE_TYPE_STATIC) != 0) + const auto& Layout = m_ShaderResourceLayouts[s]; + if (Layout.GetResourceCount(SHADER_VARIABLE_TYPE_STATIC) != 0) m_HasStaticResources = true; - if(Layout.GetResourceCount(SHADER_VARIABLE_TYPE_MUTABLE) != 0 || + if (Layout.GetResourceCount(SHADER_VARIABLE_TYPE_MUTABLE) != 0 || Layout.GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0) m_HasNonStaticResources = true; } // If there are only static resources, create default shader resource binding - if(m_HasStaticResources && !m_HasNonStaticResources) + if (m_HasStaticResources && !m_HasNonStaticResources) { - auto &SRBAllocator = pDeviceVk->GetSRBAllocator(); + auto& SRBAllocator = pDeviceVk->GetSRBAllocator(); // Default shader resource binding must be initialized after resource layouts are parsed! m_pDefaultShaderResBinding.reset( NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingVkImpl instance", ShaderResourceBindingVkImpl, this)(this, true) ); } @@ -388,44 +406,64 @@ PipelineStateVkImpl::~PipelineStateVkImpl() pDeviceVkImpl->SafeReleaseVkObject(std::move(m_Pipeline)); m_PipelineLayout.Release(pDeviceVkImpl); - for(auto &ShaderModule : m_ShaderModules) + for (auto& ShaderModule : m_ShaderModules) { - if(ShaderModule != VK_NULL_HANDLE) + if (ShaderModule != VK_NULL_HANDLE) { pDeviceVkImpl->SafeReleaseVkObject(std::move(ShaderModule)); } } + // Default SRB must be destroyed before shader variable and + // shader resource cache memory allocators + m_pDefaultShaderResBinding.reset(); + + auto& RawAllocator = GetRawAllocator(); + + if (m_ResourceCacheDataAllocator != nullptr) + { + m_ResourceCacheDataAllocator->~FixedBlockMemoryAllocator(); + RawAllocator.Free(m_ResourceCacheDataAllocator); + } + + if (m_VariableDataAllocators != nullptr) + { + for (Uint32 s=0; s < m_NumShaders; ++s) + { + m_VariableDataAllocators[s].~FixedBlockMemoryAllocator(); + } + RawAllocator.Free(m_VariableDataAllocators); + } + for (Uint32 s=0; s < m_NumShaders; ++s) { m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); } - auto &ShaderResLayoutAllocator = GetRawAllocator(); - ShaderResLayoutAllocator.Free(m_ShaderResourceLayouts); + RawAllocator.Free(m_ShaderResourceLayouts); } IMPLEMENT_QUERY_INTERFACE( PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase ) void PipelineStateVkImpl::BindShaderResources(IResourceMapping *pResourceMapping, Uint32 Flags) { - if( m_Desc.IsComputePipeline ) + if ( m_Desc.IsComputePipeline ) { - if(m_pCS)m_pCS->BindResources(pResourceMapping, Flags); + if (m_pCS)m_pCS->BindResources(pResourceMapping, Flags); } else { - if(m_pVS)m_pVS->BindResources(pResourceMapping, Flags); - if(m_pPS)m_pPS->BindResources(pResourceMapping, Flags); - if(m_pGS)m_pGS->BindResources(pResourceMapping, Flags); - if(m_pDS)m_pDS->BindResources(pResourceMapping, Flags); - if(m_pHS)m_pHS->BindResources(pResourceMapping, Flags); + if (m_pVS)m_pVS->BindResources(pResourceMapping, Flags); + if (m_pPS)m_pPS->BindResources(pResourceMapping, Flags); + if (m_pGS)m_pGS->BindResources(pResourceMapping, Flags); + if (m_pDS)m_pDS->BindResources(pResourceMapping, Flags); + if (m_pHS)m_pHS->BindResources(pResourceMapping, Flags); } } void PipelineStateVkImpl::CreateShaderResourceBinding(IShaderResourceBinding **ppShaderResourceBinding) { auto *pRenderDeviceVk = GetDevice(); - auto &SRBAllocator = pRenderDeviceVk->GetSRBAllocator(); + auto& SRBAllocator = pRenderDeviceVk->GetSRBAllocator(); auto pResBindingVk = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingVkImpl instance", ShaderResourceBindingVkImpl)(this, false); pResBindingVk->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast(ppShaderResourceBinding)); } @@ -449,7 +487,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState *pPSO)const if (m_NumShaders != pPSOVk->m_NumShaders) IsCompatibleShaders = false; - if(IsCompatibleShaders) + if (IsCompatibleShaders) { for (Uint32 s = 0; s < m_NumShaders; ++s) { @@ -470,7 +508,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState *pPSO)const } } - if(IsCompatibleShaders) + if (IsCompatibleShaders) VERIFY(IsSamePipelineLayout, "Compatible shaders must have same pipeline layouts"); } #endif @@ -485,7 +523,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind bool TransitionResources, PipelineLayout::DescriptorSetBindInfo* pDescrSetBindInfo)const { - if(!m_HasStaticResources && !m_HasNonStaticResources) + if (!m_HasStaticResources && !m_HasNonStaticResources) return; #ifdef VERIFY_SHADER_BINDINGS @@ -510,10 +548,10 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind } #endif - auto &ResourceCache = pResBindingVkImpl->GetResourceCache(); + auto& ResourceCache = pResBindingVkImpl->GetResourceCache(); // First time only, copy static shader resources to the cache - if(!pResBindingVkImpl->StaticResourcesInitialized()) + if (!pResBindingVkImpl->StaticResourcesInitialized()) { for (Uint32 s = 0; s < m_NumShaders; ++s) { @@ -521,8 +559,8 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind #ifdef VERIFY_SHADER_BINDINGS pShaderVk->DbgVerifyStaticResourceBindings(); #endif - auto &StaticResLayout = pShaderVk->GetStaticResLayout(); - auto &StaticResCache = pShaderVk->GetStaticResCache(); + auto& StaticResLayout = pShaderVk->GetStaticResLayout(); + auto& StaticResCache = pShaderVk->GetStaticResCache(); m_ShaderResourceLayouts[s].InitializeStaticResources(StaticResLayout, StaticResCache, ResourceCache); } pResBindingVkImpl->SetStaticResourcesInitialized(); @@ -535,9 +573,9 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind } #endif - if(CommitResources) + if (CommitResources) { - if(TransitionResources) + if (TransitionResources) ResourceCache.TransitionResources(pCtxVkImpl); else { @@ -548,15 +586,15 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind DescriptorPoolAllocation DynamicDescrSetAllocation; auto DynamicDescriptorSetVkLayout = m_PipelineLayout.GetDynamicDescriptorSetVkLayout(); - if(DynamicDescriptorSetVkLayout != VK_NULL_HANDLE) + if (DynamicDescriptorSetVkLayout != VK_NULL_HANDLE) { // Allocate vulkan descriptor set for dynamic resources DynamicDescrSetAllocation = pCtxVkImpl->AllocateDynamicDescriptorSet(DynamicDescriptorSetVkLayout); // Commit all dynamic resource descriptors - for(Uint32 s=0; s < m_NumShaders; ++s) + for (Uint32 s=0; s < m_NumShaders; ++s) { - const auto &Layout = m_ShaderResourceLayouts[s]; - if(Layout.GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0) + const auto& Layout = m_ShaderResourceLayouts[s]; + if (Layout.GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0) Layout.CommitDynamicResources(ResourceCache, DynamicDescrSetAllocation.GetVkDescriptorSet()); } } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 5f162ddd..ec05b846 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -34,6 +34,15 @@ namespace Diligent { +size_t ShaderResourceCacheVk::GetRequiredMemorySize(Uint32 NumSets, Uint32 SetSizes[]) +{ + Uint32 TotalResources = 0; + for(Uint32 t=0; t < NumSets; ++t) + TotalResources += SetSizes[t]; + auto MemorySize = NumSets * sizeof(DescriptorSet) + TotalResources * sizeof(Resource); + return MemorySize; +} + void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, Uint32 SetSizes[]) { // Memory layout: @@ -53,6 +62,7 @@ void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint3 for(Uint32 t=0; t < NumSets; ++t) m_TotalResources += SetSizes[t]; auto MemorySize = NumSets * sizeof(DescriptorSet) + m_TotalResources * sizeof(Resource); + VERIFY_EXPR(MemorySize == GetRequiredMemorySize(NumSets, SetSizes)); if(MemorySize > 0) { m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 3c0a2dd8..15107306 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -28,6 +28,21 @@ namespace Diligent { +size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, + const SHADER_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables) +{ + NumVariables = 0; + Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) + { + NumVariables += IsAllowedType(VarType, AllowedTypeBits) ? Layout.GetResourceCount(VarType) : 0; + } + + return NumVariables*sizeof(ShaderVariableVkImpl); +} + // Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout, IMemoryAllocator& Allocator, @@ -36,29 +51,25 @@ void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout ShaderResourceCacheVk& ResourceCache) { m_pResourceLayout = &SrcLayout; - m_pResourceCache = &ResourceCache; + m_pResourceCache = &ResourceCache; #ifdef _DEBUG m_pDbgAllocator = &Allocator; #endif + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); VERIFY_EXPR(m_NumVariables == 0); - m_NumVariables = 0; - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) - { - m_NumVariables += IsAllowedType(VarType, AllowedTypeBits) ? SrcLayout.GetResourceCount(VarType) : 0; - } + auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); if(m_NumVariables == 0) return; - - auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader variables", m_NumVariables*sizeof(ShaderVariableVkImpl)); + + auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader variables", MemSize); m_pVariables = reinterpret_cast(pRawMem); Uint32 VarInd = 0; for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) { - if( !IsAllowedType(VarType, AllowedTypeBits)) + if (!IsAllowedType(VarType, AllowedTypeBits)) continue; Uint32 NumResources = SrcLayout.GetResourceCount(VarType); -- cgit v1.2.3