From 13b0b54987db2684e46e337d2e5be5b81366083b Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 20 Oct 2020 13:26:21 -0700 Subject: Improved exception safety of pipeline state object construction --- .../GraphicsEngine/include/PipelineStateBase.hpp | 8 +- .../include/PipelineStateD3D11Impl.hpp | 4 +- .../include/ShaderResourceCacheD3D11.hpp | 2 +- .../include/ShaderResourceLayoutD3D11.hpp | 23 +- .../src/PipelineStateD3D11Impl.cpp | 210 +++++---- .../src/ShaderResourceBindingD3D11Impl.cpp | 23 +- .../src/ShaderResourceCacheD3D11.cpp | 93 ++-- .../src/ShaderResourceLayoutD3D11.cpp | 23 +- .../include/PipelineStateD3D12Impl.hpp | 4 +- .../include/ShaderResourceCacheD3D12.hpp | 2 +- .../include/ShaderResourceLayoutD3D12.hpp | 25 +- .../include/ShaderVariableD3D12.hpp | 18 +- .../src/PipelineStateD3D12Impl.cpp | 501 +++++++++++---------- .../src/ShaderResourceBindingD3D12Impl.cpp | 17 +- .../src/ShaderResourceLayoutD3D12.cpp | 27 +- .../src/ShaderVariableD3D12.cpp | 23 +- .../include/ShaderResources.hpp | 2 +- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 2 +- .../include/GLProgramResourceCache.hpp | 2 +- .../include/PipelineStateGLImpl.hpp | 2 + .../src/GLProgramResourceCache.cpp | 4 +- .../src/PipelineStateGLImpl.cpp | 130 ++++-- .../include/PipelineStateVkImpl.hpp | 10 +- .../include/ShaderResourceCacheVk.hpp | 2 +- .../include/ShaderResourceLayoutVk.hpp | 2 +- .../include/ShaderVariableVk.hpp | 24 +- .../src/PipelineStateVkImpl.cpp | 123 +++-- .../src/ShaderResourceBindingVkImpl.cpp | 3 +- .../GraphicsEngineVulkan/src/ShaderVariableVk.cpp | 29 +- 29 files changed, 738 insertions(+), 600 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index c108f663..1effd32f 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -222,7 +222,7 @@ protected: void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) + LinearAllocator& MemPool) noexcept { MemPool.AddSpace(); ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); @@ -240,7 +240,7 @@ protected: } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) const + LinearAllocator& MemPool) const noexcept { ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); } @@ -448,7 +448,7 @@ protected: } private: - void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) const + static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept { if (SrcLayout.Variables != nullptr) { @@ -471,7 +471,7 @@ private: } } - void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) const + static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) { if (SrcLayout.Variables != nullptr) { diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 0fa62606..520e9bb0 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -138,11 +138,13 @@ public: private: template - LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, const std::vector>& ShaderStages); + void Destruct(); + CComPtr m_pd3d11BlendState; CComPtr m_pd3d11RasterizerState; CComPtr m_pd3d11DepthStencilState; diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp index dc70eec1..7aa7126d 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp @@ -51,7 +51,7 @@ namespace Diligent class ShaderResourceCacheD3D11 { public: - ShaderResourceCacheD3D11() + ShaderResourceCacheD3D11() noexcept {} ~ShaderResourceCacheD3D11(); diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp index 4b4d13b2..9b2c2d9b 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp @@ -47,14 +47,19 @@ namespace Diligent class ShaderResourceLayoutD3D11 { public: - ShaderResourceLayoutD3D11(IObject& Owner, - std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - ShaderResourceCacheD3D11& ResourceCache, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator); + ShaderResourceLayoutD3D11(IObject& Owner, + ShaderResourceCacheD3D11& ResourceCache) noexcept : + m_Owner{Owner}, + m_ResourceCache{ResourceCache} + { + } + + void Initialize(std::shared_ptr pSrcResources, + const PipelineResourceLayoutDesc& ResourceLayout, + const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, + Uint32 NumVarTypes, + IMemoryAllocator& ResCacheDataAllocator, + IMemoryAllocator& ResLayoutDataAllocator); ~ShaderResourceLayoutD3D11(); // clang-format off @@ -68,7 +73,7 @@ public: static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, const PipelineResourceLayoutDesc& ResourceLayout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes); + Uint32 NumAllowedTypes) noexcept; void CopyResources(ShaderResourceCacheD3D11& DstCache) const; diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 722318f2..108f149c 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -36,30 +36,42 @@ namespace Diligent { template -LinearAllocator PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo) +void PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo) { m_ResourceLayoutIndex.fill(-1); std::vector> ShaderStages; ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_pStaticResourceLayouts = MemPool.Allocate(GetNumShaderStages()); - m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); + m_pStaticResourceCaches = MemPool.ConstructArray(NumShaderStages); + + // The memory is now owned by PipelineStateD3D11Impl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_pStaticResourceCaches); + (void)Ptr; + + m_pStaticResourceLayouts = MemPool.Allocate(NumShaderStages); + for (Uint32 i = 0; i < NumShaderStages; ++i) + new (m_pStaticResourceLayouts + i) ShaderResourceLayoutD3D11{*this, m_pStaticResourceCaches[i]}; // noexcept InitializePipelineDesc(CreateInfo, MemPool); - InitResourceLayouts(CreateInfo, ShaderStages); - return MemPool; + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(CreateInfo, ShaderStages); } @@ -77,9 +89,11 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* m_ImmutableSamplers (STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { - auto MemPool = InitInternalObjects(CreateInfo); + try + { + InitInternalObjects(CreateInfo); - auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + auto& GraphicsPipeline = GetGraphicsPipelineDesc(); #define INIT_SHADER(ShortName, ExpectedType) \ do \ @@ -94,52 +108,55 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* HashCombine(m_ShaderResourceLayoutHash, pShader->GetD3D11Resources()->GetHash()); \ } while (false) - INIT_SHADER(VS, SHADER_TYPE_VERTEX); - INIT_SHADER(PS, SHADER_TYPE_PIXEL); - INIT_SHADER(GS, SHADER_TYPE_GEOMETRY); - INIT_SHADER(DS, SHADER_TYPE_DOMAIN); - INIT_SHADER(HS, SHADER_TYPE_HULL); + INIT_SHADER(VS, SHADER_TYPE_VERTEX); + INIT_SHADER(PS, SHADER_TYPE_PIXEL); + INIT_SHADER(GS, SHADER_TYPE_GEOMETRY); + INIT_SHADER(DS, SHADER_TYPE_DOMAIN); + INIT_SHADER(HS, SHADER_TYPE_HULL); #undef INIT_SHADER - if (m_pVS == nullptr) - { - LOG_ERROR_AND_THROW("Vertex shader is null"); - } + if (m_pVS == nullptr) + { + LOG_ERROR_AND_THROW("Vertex shader is null"); + } - auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); + auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); - D3D11_BLEND_DESC D3D11BSDesc = {}; - BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState), - "Failed to create D3D11 blend state object"); + D3D11_BLEND_DESC D3D11BSDesc = {}; + BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState), + "Failed to create D3D11 blend state object"); - D3D11_RASTERIZER_DESC D3D11RSDesc = {}; - RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, D3D11RSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState), - "Failed to create D3D11 rasterizer state"); + D3D11_RASTERIZER_DESC D3D11RSDesc = {}; + RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, D3D11RSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState), + "Failed to create D3D11 rasterizer state"); - D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {}; - DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState), - "Failed to create D3D11 depth stencil state"); + D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {}; + DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState), + "Failed to create D3D11 depth stencil state"); - // Create input layout - const auto& InputLayout = GraphicsPipeline.InputLayout; - if (InputLayout.NumElements > 0) - { - std::vector> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); - LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements); + // Create input layout + const auto& InputLayout = GraphicsPipeline.InputLayout; + if (InputLayout.NumElements > 0) + { + std::vector> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); + LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements); - ID3DBlob* pVSByteCode = m_pVS.RawPtr()->GetBytecode(); - if (!pVSByteCode) - LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist"); + ID3DBlob* pVSByteCode = m_pVS.RawPtr()->GetBytecode(); + if (!pVSByteCode) + LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist"); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateInputLayout(d311InputElements.data(), static_cast(d311InputElements.size()), pVSByteCode->GetBufferPointer(), pVSByteCode->GetBufferSize(), &m_pd3d11InputLayout), - "Failed to create the Direct3D11 input layout"); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateInputLayout(d311InputElements.data(), static_cast(d311InputElements.size()), pVSByteCode->GetBufferPointer(), pVSByteCode->GetBufferSize(), &m_pd3d11InputLayout), + "Failed to create the Direct3D11 input layout"); + } + } + catch (...) + { + Destruct(); + throw; } - - auto* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); } PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, @@ -156,38 +173,55 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { - auto MemPool = InitInternalObjects(CreateInfo); - - m_pCS = ValidatedCast(CreateInfo.pCS); - if (m_pCS == nullptr) + try { - LOG_ERROR_AND_THROW("Compute shader is null"); - } + InitInternalObjects(CreateInfo); - if (m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE) + m_pCS = ValidatedCast(CreateInfo.pCS); + if (m_pCS == nullptr) + { + LOG_ERROR_AND_THROW("Compute shader is null"); + } + + if (m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE) + { + LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided"); + } + m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash(); + } + catch (...) { - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided"); + Destruct(); + throw; } - m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash(); - - auto* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); } PipelineStateD3D11Impl::~PipelineStateD3D11Impl() { - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + Destruct(); +} + +void PipelineStateD3D11Impl::Destruct() +{ + if (m_pStaticResourceLayouts != nullptr) { - m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); + for (Uint32 l = 0; l < GetNumShaderStages(); ++l) + { + m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); + } } - for (Uint32 l = 0; l < GetNumShaderStages(); ++l) + if (m_pStaticResourceCaches != nullptr) { - m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + { + m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); + m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); + } } - // m_pStaticResourceLayouts and m_pStaticResourceCaches are allocated in contiguous chunks of memory. - if (auto* pRawMem = m_pStaticResourceLayouts) + + // All subobjects are allocated in contiguous chunks of memory. + if (auto* pRawMem = m_pStaticResourceCaches) GetRawAllocator().Free(pRawMem); } @@ -213,42 +247,36 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& } #endif - decltype(m_ImmutableSamplers) ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")); + decltype(m_ImmutableSamplers) ImmutableSamplers{STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")}; + std::array ShaderResLayoutDataSizes = {}; std::array ShaderResCacheDataSizes = {}; for (Uint32 s = 0; s < ShaderStages.size(); ++s) { - const auto* pShader = ShaderStages[s].second; - const auto& ShaderDesc = pShader->GetDesc(); - const auto& ShaderResources = *pShader->GetD3D11Resources(); - VERIFY_EXPR(ShaderDesc.ShaderType == ShaderResources.GetShaderType()); + const auto* pShader = ShaderStages[s].second; + const auto& ShaderDesc = pShader->GetDesc(); + const auto& Resources = *pShader->GetD3D11Resources(); + VERIFY_EXPR(ShaderDesc.ShaderType == Resources.GetShaderType()); - new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D11; - // Do not initialize the cache as this will be performed by the resource layout + // The cache will be initialized by the resource layout // Shader resource layout will only contain dynamic and mutable variables const SHADER_RESOURCE_VARIABLE_TYPE StaticVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - // clang-format off - new (m_pStaticResourceLayouts + s) - ShaderResourceLayoutD3D11 - { - *this, - pShader->GetD3D11Resources(), - m_Desc.ResourceLayout, - StaticVarTypes, - _countof(StaticVarTypes), - m_pStaticResourceCaches[s], - GetRawAllocator(), - GetRawAllocator() - }; - // clang-format on + m_pStaticResourceLayouts[s].Initialize( + pShader->GetD3D11Resources(), + m_Desc.ResourceLayout, + StaticVarTypes, + _countof(StaticVarTypes), + GetRawAllocator(), + GetRawAllocator() // + ); // Initialize immutable samplers - for (Uint32 sam = 0; sam < ShaderResources.GetNumSamplers(); ++sam) + for (Uint32 sam = 0; sam < Resources.GetNumSamplers(); ++sam) { - const auto& SamplerAttribs = ShaderResources.GetSampler(sam); + const auto& SamplerAttribs = Resources.GetSampler(sam); constexpr bool LogImtblSamplerArrayError = true; - auto SrcImtblSamplerInd = ShaderResources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); + auto SrcImtblSamplerInd = Resources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); if (SrcImtblSamplerInd >= 0) { const auto& SrcImtblSamplerInfo = ResourceLayout.ImmutableSamplers[SrcImtblSamplerInd]; @@ -267,8 +295,8 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC // }; - ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(ShaderResources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes)); - ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(ShaderResources); + ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(Resources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes)); + ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(Resources); } auto ShaderInd = GetShaderTypePipelineIndex(ShaderDesc.ShaderType, m_Desc.PipelineType); diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 5e95db97..f7ce059b 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -77,20 +77,15 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter // Shader resource layout will only contain dynamic and mutable variables // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache#Shader-Resource-Cache-Initialization SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; - // clang-format off - new (m_pResourceLayouts + s) - ShaderResourceLayoutD3D11 - { - *this, - pShaderD3D11->GetD3D11Resources(), - PSODesc.ResourceLayout, - VarTypes, - _countof(VarTypes), - m_pBoundResourceCaches[s], - ResCacheDataAllocator, - ResLayoutDataAllocator - }; - // clang-format on + new (m_pResourceLayouts + s) ShaderResourceLayoutD3D11{*this, m_pBoundResourceCaches[s]}; + m_pResourceLayouts[s].Initialize( + pShaderD3D11->GetD3D11Resources(), + PSODesc.ResourceLayout, + VarTypes, + _countof(VarTypes), + ResCacheDataAllocator, + ResLayoutDataAllocator // + ); const auto ShaderType = pShaderD3D11->GetDesc().ShaderType; const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PSODesc.PipelineType); diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp index 28086285..3aaf82b7 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp @@ -148,61 +148,60 @@ void ShaderResourceCacheD3D11::Initialize(Uint32 CBCount, Uint32 SRVCount, Uint3 void ShaderResourceCacheD3D11::Destroy(IMemoryAllocator& MemAllocator) { - VERIFY(IsInitialized(), "Resource cache is not initialized"); + if (!IsInitialized()) + return; + VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources"); - if (IsInitialized()) + // Explicitly destory all objects + auto CBCount = GetCBCount(); + if (CBCount != 0) { - // Explicitly destory all objects - auto CBCount = GetCBCount(); - if (CBCount != 0) - { - CachedCB* CBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - GetCBArrays(CBs, d3d11CBs); - for (size_t cb = 0; cb < CBCount; ++cb) - CBs[cb].~CachedCB(); - } + CachedCB* CBs = nullptr; + ID3D11Buffer** d3d11CBs = nullptr; + GetCBArrays(CBs, d3d11CBs); + for (size_t cb = 0; cb < CBCount; ++cb) + CBs[cb].~CachedCB(); + } - auto SRVCount = GetSRVCount(); - if (SRVCount != 0) - { - CachedResource* SRVResources = nullptr; - ID3D11ShaderResourceView** d3d11SRVs = nullptr; - GetSRVArrays(SRVResources, d3d11SRVs); - for (size_t srv = 0; srv < SRVCount; ++srv) - SRVResources[srv].~CachedResource(); - } + auto SRVCount = GetSRVCount(); + if (SRVCount != 0) + { + CachedResource* SRVResources = nullptr; + ID3D11ShaderResourceView** d3d11SRVs = nullptr; + GetSRVArrays(SRVResources, d3d11SRVs); + for (size_t srv = 0; srv < SRVCount; ++srv) + SRVResources[srv].~CachedResource(); + } - auto SamplerCount = GetSamplerCount(); - if (SamplerCount != 0) - { - CachedSampler* Samplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - GetSamplerArrays(Samplers, d3d11Samplers); - for (size_t sam = 0; sam < SamplerCount; ++sam) - Samplers[sam].~CachedSampler(); - } + auto SamplerCount = GetSamplerCount(); + if (SamplerCount != 0) + { + CachedSampler* Samplers = nullptr; + ID3D11SamplerState** d3d11Samplers = nullptr; + GetSamplerArrays(Samplers, d3d11Samplers); + for (size_t sam = 0; sam < SamplerCount; ++sam) + Samplers[sam].~CachedSampler(); + } - auto UAVCount = GetUAVCount(); - if (UAVCount != 0) - { - CachedResource* UAVResources = nullptr; - ID3D11UnorderedAccessView** d3d11UAVs = nullptr; - GetUAVArrays(UAVResources, d3d11UAVs); - for (size_t uav = 0; uav < UAVCount; ++uav) - UAVResources[uav].~CachedResource(); - } + auto UAVCount = GetUAVCount(); + if (UAVCount != 0) + { + CachedResource* UAVResources = nullptr; + ID3D11UnorderedAccessView** d3d11UAVs = nullptr; + GetUAVArrays(UAVResources, d3d11UAVs); + for (size_t uav = 0; uav < UAVCount; ++uav) + UAVResources[uav].~CachedResource(); + } - m_SRVOffset = InvalidResourceOffset; - m_SamplerOffset = InvalidResourceOffset; - m_UAVOffset = InvalidResourceOffset; - m_MemoryEndOffset = InvalidResourceOffset; + m_SRVOffset = InvalidResourceOffset; + m_SamplerOffset = InvalidResourceOffset; + m_UAVOffset = InvalidResourceOffset; + m_MemoryEndOffset = InvalidResourceOffset; - if (m_pResourceData != nullptr) - MemAllocator.Free(m_pResourceData); - m_pResourceData = nullptr; - } + if (m_pResourceData != nullptr) + MemAllocator.Free(m_pResourceData); + m_pResourceData = nullptr; } ShaderResourceCacheD3D11::~ShaderResourceCacheD3D11() diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index c1e6e65a..f7c1958d 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -84,7 +84,7 @@ ShaderResourceLayoutD3D11::~ShaderResourceLayoutD3D11() size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, const PipelineResourceLayoutDesc& ResourceLayout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes) + Uint32 NumAllowedTypes) noexcept { // Skip immutable samplers as they are initialized directly in the resource cache by the PSO constexpr bool CountImtblSamplers = false; @@ -101,20 +101,15 @@ size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D } -ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& Owner, - std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - ShaderResourceCacheD3D11& ResourceCache, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator) : - // clang-format off - m_Owner {Owner}, - m_pResources {std::move(pSrcResources)}, - m_ResourceCache {ResourceCache} -// clang-format on +void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr pSrcResources, + const PipelineResourceLayoutDesc& ResourceLayout, + const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, + Uint32 NumVarTypes, + IMemoryAllocator& ResCacheDataAllocator, + IMemoryAllocator& ResLayoutDataAllocator) { + m_pResources = std::move(pSrcResources); + // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-layout#Shader-Resource-Layout-Initialization const auto AllowedTypeBits = GetAllowedTypeBits(VarTypes, NumVarTypes); diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index 31d95179..fa761fc7 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -133,11 +133,13 @@ private: }; template - LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& ShaderStages); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& ShaderStages); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, std::vector& ShaderStages); + void Destruct(); + CComPtr m_pd3d12PSO; RootSignature m_RootSig; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp index 1a0362ab..8a8f7b25 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp @@ -110,7 +110,7 @@ public: SRBResources }; - ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) + ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) noexcept // clang-format off #ifdef DILIGENT_DEBUG : m_DbgContentType diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp index 5426d98b..719345fc 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp @@ -112,21 +112,24 @@ namespace Diligent class ShaderResourceLayoutD3D12 final { public: - // There are two modes a layout can be constructed: + explicit ShaderResourceLayoutD3D12(IObject& Owner) noexcept : + m_Owner{Owner} + {} + + // There are two modes a layout can be initialized: // - initialize static resource layout and initialize shader resource cache to hold static resources // - initialize reference layouts that address all types of resources (static, mutable, dynamic). // Root indices and descriptor table offsets are assigned during the initialization; // no shader resource cache is provided - ShaderResourceLayoutD3D12(IObject& Owner, - ID3D12Device* pd3d12Device, - PIPELINE_TYPE PipelineType, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - class RootSignature* pRootSig); + void Initialize(ID3D12Device* pd3d12Device, + PIPELINE_TYPE PipelineType, + const PipelineResourceLayoutDesc& ResourceLayout, + std::shared_ptr pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + class RootSignature* pRootSig); // clang-format off ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp index 213748d9..c30d8296 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp @@ -76,12 +76,16 @@ class ShaderVariableD3D12Impl; class ShaderVariableManagerD3D12 { public: - ShaderVariableManagerD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& Layout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache); + ShaderVariableManagerD3D12(IObject& Owner, + ShaderResourceCacheD3D12& ResourceCache) noexcept : + m_Owner{Owner}, + m_ResourceCache{ResourceCache} + {} + + void Initialize(const ShaderResourceLayoutD3D12& Layout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes); ~ShaderVariableManagerD3D12(); void Destroy(IMemoryAllocator& Allocator); @@ -120,7 +124,7 @@ private: Uint32 m_NumVariables = 0; #ifdef DILIGENT_DEBUG - IMemoryAllocator& m_DbgAllocator; + IMemoryAllocator* m_pDbgAllocator = nullptr; #endif // clang-format on }; diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index b65ad4fc..2d31e70d 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -99,34 +99,47 @@ private: }; template -LinearAllocator PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& ShaderStages) +void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& ShaderStages) { m_ResourceLayoutIndex.fill(-1); ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(GetNumShaderStages() * 2); - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout); + m_pStaticResourceCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateD3D12Impl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_pStaticResourceCaches); + (void)Ptr; - m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); - m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); - m_pStaticVarManagers = MemPool.Allocate(GetNumShaderStages()); + m_pShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, std::ref(*this)); + + m_pStaticVarManagers = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_pStaticVarManagers + s) ShaderVariableManagerD3D12{*this, GetStaticShaderResCache(s)}; InitializePipelineDesc(CreateInfo, MemPool); - InitResourceLayouts(CreateInfo, ShaderStages); - return MemPool; + m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(CreateInfo, ShaderStages); } @@ -136,197 +149,202 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector ShaderStages; - - auto MemPool = InitInternalObjects(CreateInfo, ShaderStages); - - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) + try { - const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + std::vector ShaderStages; - D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; + InitInternalObjects(CreateInfo, ShaderStages); - for (const auto& Stage : ShaderStages) + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) { - auto* pShaderD3D12 = Stage.pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - VERIFY_EXPR(ShaderType == Stage.Type); + const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) + for (const auto& Stage : ShaderStages) { - // clang-format off + auto* pShaderD3D12 = Stage.pShader; + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off case SHADER_TYPE_VERTEX: pd3d12ShaderBytecode = &d3d12PSODesc.VS; break; case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; case SHADER_TYPE_GEOMETRY: pd3d12ShaderBytecode = &d3d12PSODesc.GS; break; case SHADER_TYPE_HULL: pd3d12ShaderBytecode = &d3d12PSODesc.HS; break; case SHADER_TYPE_DOMAIN: pd3d12ShaderBytecode = &d3d12PSODesc.DS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); - } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); + memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); - // The sample mask for the blend state. - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); + // The sample mask for the blend state. + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); - std::vector> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); + std::vector> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); - const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout; - if (InputLayout.NumElements > 0) - { - LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); - d3d12PSODesc.InputLayout.NumElements = static_cast(d312InputElements.size()); - d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); - } - else - { - d3d12PSODesc.InputLayout.NumElements = 0; - d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; - } + const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout; + if (InputLayout.NumElements > 0) + { + LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); + d3d12PSODesc.InputLayout.NumElements = static_cast(d312InputElements.size()); + d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); + } + else + { + d3d12PSODesc.InputLayout.NumElements = 0; + d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; + } - d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; - static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; - d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; + d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; + d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; - d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormats); ++rt) - d3d12PSODesc.RTVFormats[rt] = DXGI_FORMAT_UNKNOWN; - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormats); ++rt) + d3d12PSODesc.RTVFormats[rt] = DXGI_FORMAT_UNKNOWN; + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; + d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); - } + HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + } #ifdef D3D12_H_HAS_MESH_SHADER - else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH) - { - const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); - - struct MESH_SHADER_PIPELINE_STATE_DESC + else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH) { - PSS_SubObject Flags; - PSS_SubObject NodeMask; - PSS_SubObject pRootSignature; - PSS_SubObject PS; - PSS_SubObject AS; - PSS_SubObject MS; - PSS_SubObject BlendState; - PSS_SubObject DepthStencilState; - PSS_SubObject RasterizerState; - PSS_SubObject SampleDesc; - PSS_SubObject SampleMask; - PSS_SubObject DSVFormat; - PSS_SubObject RTVFormatArray; - PSS_SubObject CachedPSO; - }; - MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; - - for (const auto& Stage : ShaderStages) - { - auto* pShaderD3D12 = Stage.pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - VERIFY_EXPR(ShaderType == Stage.Type); + const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) + struct MESH_SHADER_PIPELINE_STATE_DESC { - // clang-format off + PSS_SubObject Flags; + PSS_SubObject NodeMask; + PSS_SubObject pRootSignature; + PSS_SubObject PS; + PSS_SubObject AS; + PSS_SubObject MS; + PSS_SubObject BlendState; + PSS_SubObject DepthStencilState; + PSS_SubObject RasterizerState; + PSS_SubObject SampleDesc; + PSS_SubObject SampleMask; + PSS_SubObject DSVFormat; + PSS_SubObject RTVFormatArray; + PSS_SubObject CachedPSO; + }; + MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; + + for (const auto& Stage : ShaderStages) + { + auto* pShaderD3D12 = Stage.pShader; + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off case SHADER_TYPE_AMPLIFICATION: pd3d12ShaderBytecode = &d3d12PSODesc.AS; break; case SHADER_TYPE_MESH: pd3d12ShaderBytecode = &d3d12PSODesc.MS; break; case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); - } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); - d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormatArray->RTFormats); ++rt) - d3d12PSODesc.RTVFormatArray->RTFormats[rt] = DXGI_FORMAT_UNKNOWN; - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormatArray->RTFormats); ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = DXGI_FORMAT_UNKNOWN; + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; + d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; - streamDesc.SizeInBytes = sizeof(d3d12PSODesc); - streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; + D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; + streamDesc.SizeInBytes = sizeof(d3d12PSODesc); + streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; - auto* device2 = pDeviceD3D12->GetD3D12Device2(); + auto* device2 = pDeviceD3D12->GetD3D12Device2(); - CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); - } + CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); + } #endif // D3D12_H_HAS_MESH_SHADER - else - { - LOG_ERROR_AND_THROW("Unsupported pipeline type"); - } + else + { + LOG_ERROR_AND_THROW("Unsupported pipeline type"); + } - if (*m_Desc.Name != 0) + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + } + catch (...) { - m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); - String RootSignatureDesc("Root signature for PSO '"); - RootSignatureDesc.append(m_Desc.Name); - RootSignatureDesc.push_back('\''); - m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + Destruct(); + throw; } - - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pShaderResourceLayouts); } PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, @@ -335,67 +353,92 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector ShaderStages; + try + { + std::vector ShaderStages; - auto MemPool = InitInternalObjects(CreateInfo, ShaderStages); + InitInternalObjects(CreateInfo, ShaderStages); - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; + D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; - VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); - auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); - d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); - d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); + VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); + auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); + d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); + d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); + HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); - if (*m_Desc.Name != 0) + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + } + catch (...) { - m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); - String RootSignatureDesc("Root signature for PSO '"); - RootSignatureDesc.append(m_Desc.Name); - RootSignatureDesc.push_back('\''); - m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + Destruct(); + throw; } - - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pShaderResourceLayouts); } PipelineStateD3D12Impl::~PipelineStateD3D12Impl() +{ + Destruct(); +} + +void PipelineStateD3D12Impl::Destruct() { auto& ShaderResLayoutAllocator = GetRawAllocator(); for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - m_pStaticVarManagers[s].Destroy(GetRawAllocator()); - m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); - m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); - m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); + if (m_pStaticVarManagers != nullptr) + { + m_pStaticVarManagers[s].Destroy(GetRawAllocator()); + m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); + } + + if (m_pShaderResourceLayouts != nullptr) + { + m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); + m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); + } + + if (m_pStaticResourceCaches != nullptr) + { + m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); + } + } + // All internal objects are allocated in contiguous chunks of memory. + if (auto* pRawMem = m_pStaticResourceCaches) + { + ShaderResLayoutAllocator.Free(pRawMem); } - // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in - // contiguous chunks of memory. - auto* pRawMem = m_pShaderResourceLayouts; - ShaderResLayoutAllocator.Free(pRawMem); - // D3D12 object can only be destroyed when it is no longer used by the GPU - m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); + if (m_pd3d12PSO) + { + // D3D12 object can only be destroyed when it is no longer used by the GPU + m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); + } } IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase) @@ -429,49 +472,37 @@ void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& m_ResourceLayoutIndex[ShaderInd] = static_cast(s); - new (m_pShaderResourceLayouts + s) - ShaderResourceLayoutD3D12 // - { - *this, - pd3d12Device, - m_Desc.PipelineType, - ResourceLayout, - pShaderD3D12->GetShaderResources(), - GetRawAllocator(), - nullptr, - 0, - nullptr, - &m_RootSig // - }; - - new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D12{ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources}; + m_pShaderResourceLayouts[s].Initialize( + pd3d12Device, + m_Desc.PipelineType, + ResourceLayout, + pShaderD3D12->GetShaderResources(), + GetRawAllocator(), + nullptr, + 0, + nullptr, + &m_RootSig // + ); const SHADER_RESOURCE_VARIABLE_TYPE StaticVarType[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - new (m_pShaderResourceLayouts + GetNumShaderStages() + s) - ShaderResourceLayoutD3D12 // - { - *this, - pd3d12Device, - m_Desc.PipelineType, - ResourceLayout, - pShaderD3D12->GetShaderResources(), - GetRawAllocator(), - StaticVarType, - _countof(StaticVarType), - m_pStaticResourceCaches + s, - nullptr // - }; - - new (m_pStaticVarManagers + s) - ShaderVariableManagerD3D12 // - { - *this, - GetStaticShaderResLayout(static_cast(s)), - GetRawAllocator(), - nullptr, - 0, - GetStaticShaderResCache(static_cast(s)) // - }; + m_pShaderResourceLayouts[GetNumShaderStages() + s].Initialize( + pd3d12Device, + m_Desc.PipelineType, + ResourceLayout, + pShaderD3D12->GetShaderResources(), + GetRawAllocator(), + StaticVarType, + _countof(StaticVarType), + m_pStaticResourceCaches + s, + nullptr // + ); + + m_pStaticVarManagers[s].Initialize( + GetStaticShaderResLayout(static_cast(s)), + GetRawAllocator(), + nullptr, + 0 // + ); } m_RootSig.Finalize(pd3d12Device); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 3293283a..1c5ae5f5 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -67,16 +67,13 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; const auto& SrcLayout = pPSO->GetShaderResLayout(s); // Create shader variable manager in place - new (m_pShaderVarMgrs + s) - ShaderVariableManagerD3D12 // - { - *this, - SrcLayout, - VarDataAllocator, - AllowedVarTypes, - _countof(AllowedVarTypes), - m_ShaderResourceCache // - }; + new (m_pShaderVarMgrs + s) ShaderVariableManagerD3D12{*this, m_ShaderResourceCache}; + m_pShaderVarMgrs[s].Initialize( + SrcLayout, + VarDataAllocator, + AllowedVarTypes, + _countof(AllowedVarTypes) // + ); m_ResourceLayoutIndex[ShaderInd] = static_cast(s); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 06e902fb..c0428e7e 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -113,22 +113,19 @@ void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator& // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Resource-Layouts-in-a-Pipeline-State -ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& Owner, - ID3D12Device* pd3d12Device, - PIPELINE_TYPE PipelineType, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - RootSignature* pRootSig) : - // clang-format off - m_Owner {Owner}, - m_pd3d12Device {pd3d12Device}, - m_pResources {std::move(pSrcResources)} -// clang-format on +void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, + PIPELINE_TYPE PipelineType, + const PipelineResourceLayoutDesc& ResourceLayout, + std::shared_ptr pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + RootSignature* pRootSig) { + m_pd3d12Device = pd3d12Device; + m_pResources = std::move(pSrcResources); + VERIFY_EXPR((pResourceCache != nullptr) ^ (pRootSig != nullptr)); const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp index f7c23096..fd58eacf 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp @@ -54,20 +54,15 @@ size_t ShaderVariableManagerD3D12::GetRequiredMemorySize(const ShaderResourceLay } // Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes -ShaderVariableManagerD3D12::ShaderVariableManagerD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache) : - // clang-format off - m_Owner {Owner}, - m_ResourceCache {ResourceCache} +void ShaderVariableManagerD3D12::Initialize(const ShaderResourceLayoutD3D12& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes) +{ #ifdef DILIGENT_DEBUG - , m_DbgAllocator {Allocator} + m_pDbgAllocator = &Allocator; #endif -// clang-format on -{ + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); VERIFY_EXPR(m_NumVariables == 0); auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); @@ -113,10 +108,10 @@ ShaderVariableManagerD3D12::~ShaderVariableManagerD3D12() void ShaderVariableManagerD3D12::Destroy(IMemoryAllocator& Allocator) { - VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor"); - if (m_pVariables != nullptr) { + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + for (Uint32 v = 0; v < m_NumVariables; ++v) m_pVariables[v].~ShaderVariableD3D12Impl(); Allocator.Free(m_pVariables); diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp index f15d2e74..efbff703 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -385,7 +385,7 @@ public: const ShaderResources* const pShaderResources[], Uint32 NumShaders, bool VerifyVariables, - bool VerifyImmutableSamplers); + bool VerifyImmutableSamplers) noexcept; #endif void GetShaderModel(Uint32& Major, Uint32& Minor) const diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 86a7fc35..b975b506 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -219,7 +219,7 @@ void ShaderResources::DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& const ShaderResources* const pShaderResources[], Uint32 NumShaders, bool VerifyVariables, - bool VerifyImmutableSamplers) + bool VerifyImmutableSamplers) noexcept { auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) // { diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp index eab96f6a..07c8f39e 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp @@ -45,7 +45,7 @@ namespace Diligent class GLProgramResourceCache { public: - GLProgramResourceCache() + GLProgramResourceCache() noexcept {} ~GLProgramResourceCache(); diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index 0c5692d0..93180774 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -114,6 +114,8 @@ private: void InitResourceLayouts(const std::vector& ShaderStages, LinearAllocator& MemPool); + void Destruct(); + // Linked GL programs for every shader stage. Every pipeline needs to have its own programs // because resource bindings assigned by GLProgramResources::LoadUniforms depend on other // shader stages. diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp index 95557557..84cdc46e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp @@ -92,7 +92,9 @@ GLProgramResourceCache::~GLProgramResourceCache() void GLProgramResourceCache::Destroy(IMemoryAllocator& MemAllocator) { - VERIFY(IsInitialized(), "Resource cache is not initialized"); + if (!IsInitialized()) + return; + VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources"); for (Uint32 cb = 0; cb < GetUBCount(); ++cb) diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 8bc3802e..8b429094 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -40,22 +40,37 @@ namespace Diligent template void PipelineStateGLImpl::Initialize(const PSOCreateInfoType& CreateInfo, const std::vector& ShaderStages) { - // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; + VERIFY_EXPR(m_NumShaderStages > 0 && m_NumShaderStages == ShaderStages.size()); + if (!GetDevice()->GetDeviceCaps().Features.SeparablePrograms) + m_NumShaderStages = 1; - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + const auto NumPrograms = GetNumShaderStages(); + + MemPool.AddSpace(NumPrograms); + MemPool.AddSpace(NumPrograms); MemPool.AddSpace(m_Desc.ResourceLayout.NumImmutableSamplers); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - InitResourceLayouts(ShaderStages, MemPool); - InitializePipelineDesc(CreateInfo, MemPool); + m_GLPrograms = MemPool.ConstructArray(NumPrograms, false); - void* Ptr = MemPool.Release(); + // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); VERIFY_EXPR(Ptr == m_GLPrograms); + (void)Ptr; + + m_ProgramResources = MemPool.ConstructArray(NumPrograms); + + m_ImmutableSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumImmutableSamplers); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, MemPool); } PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, @@ -74,26 +89,33 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* m_StaticResourceLayout{*this} // clang-format on { - std::vector ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); + try + { + std::vector ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + RefCntAutoPtr pTempPS; + if (CreateInfo.pPS == nullptr) + { + // Some OpenGL implementations fail if fragment shader is not present, so + // create a dummy one. + ShaderCreateInfo ShaderCI; + ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL; + ShaderCI.Source = "void main(){}"; + ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; + ShaderCI.Desc.Name = "Dummy fragment shader"; + pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); + + ShaderStages.emplace_back(SHADER_TYPE_PIXEL, pTempPS); + m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL; + } - RefCntAutoPtr pTempPS; - if (CreateInfo.pPS == nullptr) + Initialize(CreateInfo, ShaderStages); + } + catch (...) { - // Some OpenGL implementations fail if fragment shader is not present, so - // create a dummy one. - ShaderCreateInfo ShaderCI; - ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL; - ShaderCI.Source = "void main(){}"; - ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; - ShaderCI.Desc.Name = "Dummy fragment shader"; - pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); - - ShaderStages.emplace_back(SHADER_TYPE_PIXEL, pTempPS); - m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL; + Destruct(); } - - Initialize(CreateInfo, ShaderStages); } PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, @@ -112,30 +134,54 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* p m_StaticResourceLayout{*this} // clang-format on { - std::vector ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); + try + { + std::vector ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); - Initialize(CreateInfo, ShaderStages); + Initialize(CreateInfo, ShaderStages); + } + catch (...) + { + Destruct(); + } } PipelineStateGLImpl::~PipelineStateGLImpl() +{ + Destruct(); +} + +void PipelineStateGLImpl::Destruct() { auto& RawAllocator = GetRawAllocator(); m_StaticResourceCache.Destroy(RawAllocator); GetDevice()->OnDestroyPSO(this); - for (Uint32 i = 0; i < GetNumShaderStages(); ++i) + if (m_ImmutableSamplers != nullptr) { - m_GLPrograms[i].~GLProgramObj(); - m_ProgramResources[i].~GLProgramResources(); + for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumImmutableSamplers; ++i) + { + m_ImmutableSamplers[i].~SamplerPtr(); + } } - for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumImmutableSamplers; ++i) + + for (Uint32 i = 0; i < GetNumShaderStages(); ++i) { - m_ImmutableSamplers[i].~SamplerPtr(); + if (m_GLPrograms != nullptr) + { + m_GLPrograms[i].~GLProgramObj(); + } + if (m_ProgramResources != nullptr) + { + m_ProgramResources[i].~GLProgramResources(); + } } - void* pRawMem = m_GLPrograms; - RawAllocator.Free(pRawMem); + if (void* pRawMem = m_GLPrograms) + { + RawAllocator.Free(pRawMem); + } } IMPLEMENT_QUERY_INTERFACE(PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase) @@ -145,8 +191,8 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vectorGetDeviceCaps(); - VERIFY(DeviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); + const auto& deviceCaps = pDeviceGL->GetDeviceCaps(); + VERIFY(deviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); auto pImmediateCtx = m_pDevice->GetImmediateContext(); VERIFY_EXPR(pImmediateCtx); @@ -157,18 +203,16 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()); - m_ProgramResources = MemPool.ConstructArray(ShaderStages.size()); for (size_t i = 0; i < ShaderStages.size(); ++i) { auto* pShaderGL = ShaderStages[i].pShader; const auto& ShaderDesc = pShaderGL->GetDesc(); - new (m_GLPrograms + i) GLProgramObj{ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)}; + m_GLPrograms[i] = GLProgramObj{ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)}; // Load uniforms and assign bindings m_ProgramResources[i].LoadUniforms(ShaderDesc.ShaderType, m_GLPrograms[i], GLState, m_TotalUniformBufferBindings, @@ -191,8 +235,7 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(ShaderStages.size()), false)); - m_ProgramResources = MemPool.Construct(); + m_GLPrograms[0] = ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(Shaders.size()), false); m_ProgramResources[0].LoadUniforms(ActiveStages, m_GLPrograms[0], GLState, m_TotalUniformBufferBindings, @@ -204,10 +247,9 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); + m_ResourceLayout.Initialize(m_ProgramResources, GetNumShaderStages(), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); } - m_ImmutableSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumImmutableSamplers); for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumImmutableSamplers; ++s) { pDeviceGL->CreateSampler(m_Desc.ResourceLayout.ImmutableSamplers[s].Desc, &m_ImmutableSamplers[s]); @@ -216,7 +258,7 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); + m_StaticResourceLayout.Initialize(m_ProgramResources, GetNumShaderStages(), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); InitImmutableSamplersInResourceCache(m_StaticResourceLayout, m_StaticResourceCache); } } diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 96b34008..d4f2fc36 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -129,13 +129,15 @@ private: using TShaderStages = ShaderResourceLayoutVk::TShaderStages; template - LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& vkShaderStages, - std::vector& ShaderModules); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& vkShaderStages, + std::vector& ShaderModules); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); + void Destruct(); + const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const { VERIFY_EXPR(ShaderInd < GetNumShaderStages()); @@ -148,7 +150,7 @@ private: return m_StaticResCaches[ShaderInd]; } - ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const + const ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const { VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_StaticVarsMgrs[ShaderInd]; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp index a5278cb7..7d77ff48 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp @@ -75,7 +75,7 @@ public: }; // clang-format off - ShaderResourceCacheVk(DbgCacheContentType dbgContentType) + ShaderResourceCacheVk(DbgCacheContentType dbgContentType) noexcept #ifdef DILIGENT_DEBUG : m_DbgContentType{dbgContentType} #endif diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 0013fe23..9452a390 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -128,7 +128,7 @@ public: }; using TShaderStages = std::vector; - ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) : + ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept : m_LogicalDevice{LogicalDevice} { } diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp index 9039e04e..27689c1e 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp @@ -73,21 +73,25 @@ class ShaderVariableVkImpl; class ShaderVariableManagerVk { public: - ShaderVariableManagerVk(IObject& Owner, - const ShaderResourceLayoutVk& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheVk& ResourceCache); + ShaderVariableManagerVk(IObject& Owner, + ShaderResourceCacheVk& ResourceCache) noexcept : + m_Owner{Owner}, + m_ResourceCache{ResourceCache} + {} + + void Initialize(const ShaderResourceLayoutVk& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes); ~ShaderVariableManagerVk(); void DestroyVariables(IMemoryAllocator& Allocator); - ShaderVariableVkImpl* GetVariable(const Char* Name); - ShaderVariableVkImpl* GetVariable(Uint32 Index); + ShaderVariableVkImpl* GetVariable(const Char* Name) const; + ShaderVariableVkImpl* GetVariable(Uint32 Index) const; - void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags); + void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const; static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, @@ -115,7 +119,7 @@ private: Uint32 m_NumVariables = 0; #ifdef DILIGENT_DEBUG - IMemoryAllocator& m_DbgAllocator; + IMemoryAllocator* m_pDbgAllocator = nullptr; #endif }; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 6cbe5da9..83512870 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -413,15 +413,12 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre const auto ShaderType = StageInfo.Type; const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); - new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice}; - m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); - auto* pStaticResLayout = new (m_ShaderResourceLayouts + ShaderStages.size() + s) ShaderResourceLayoutVk{LogicalDevice}; - auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources}; - pStaticResLayout->InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); + auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s]; + StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); - new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache}; + m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0); } ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(), m_Desc.ResourceLayout, m_PipelineLayout, @@ -464,37 +461,52 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre } template -LinearAllocator PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& vkShaderStages, - std::vector& ShaderModules) +void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& vkShaderStages, + std::vector& ShaderModules) { m_ResourceLayoutIndex.fill(-1); TShaderStages ShaderStages; ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(GetNumShaderStages() * 2); - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_ShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); - m_StaticResCaches = MemPool.Allocate(GetNumShaderStages()); - m_StaticVarsMgrs = MemPool.Allocate(GetNumShaderStages()); + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + + m_StaticResCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_StaticResCaches); + (void)Ptr; + + m_ShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, LogicalDevice); + + m_StaticVarsMgrs = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; InitializePipelineDesc(CreateInfo, MemPool); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + InitResourceLayouts(CreateInfo, ShaderStages); // Create shader modules and initialize shader stages InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); - - return MemPool; } PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, @@ -503,15 +515,20 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector vkShaderStages; - std::vector ShaderModules; - - auto MemPool = InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + try + { + std::vector vkShaderStages; + std::vector ShaderModules; - CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); + CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); + } + catch (...) + { + Destruct(); + throw; + } } @@ -521,39 +538,59 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector vkShaderStages; - std::vector ShaderModules; - - auto MemPool = InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + try + { + std::vector vkShaderStages; + std::vector ShaderModules; - CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); + CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); + } + catch (...) + { + Destruct(); + throw; + } } PipelineStateVkImpl::~PipelineStateVkImpl() +{ + Destruct(); +} + +void PipelineStateVkImpl::Destruct() { m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask); m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask); auto& RawAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < GetNumShaderStages() * 2; ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); + if (m_StaticVarsMgrs != nullptr) + { + m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); + m_StaticVarsMgrs[s].~ShaderVariableManagerVk(); + } + + if (m_ShaderResourceLayouts != nullptr) + { + m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); + m_ShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutVk(); + } + + if (m_StaticResCaches != nullptr) + { + m_StaticResCaches[s].~ShaderResourceCacheVk(); + } } - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + // All internal objects are allocted in contiguous chunks of memory. + if (void* pRawMem = m_StaticResCaches) { - m_StaticResCaches[s].~ShaderResourceCacheVk(); - m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); - m_StaticVarsMgrs[s].~ShaderVariableManagerVk(); + RawAllocator.Free(pRawMem); } - // m_ShaderResourceLayouts, m_StaticResCaches and m_StaticVarsMgrs are allocted in - // contiguous chunks of memory. - void* pRawMem = m_ShaderResourceLayouts; - RawAllocator.Free(pRawMem); } IMPLEMENT_QUERY_INTERFACE(PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase) @@ -746,7 +783,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY if (LayoutInd < 0) return nullptr; - auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); return StaticVarMgr.GetVariable(Index); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 91008811..21b216db 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -75,7 +75,8 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR // Initialize vars manager to reference mutable and dynamic variables // Note that the cache has space for all variable types const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; - new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes), m_ShaderResourceCache}; + new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, m_ShaderResourceCache}; + m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes)); } #ifdef DILIGENT_DEBUG m_ShaderResourceCache.DbgVerifyResourceInitialization(); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 82d26b44..7e06bd69 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -65,20 +65,15 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout } // Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes -ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner, - const ShaderResourceLayoutVk& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheVk& ResourceCache) : - // clang-format off - m_Owner {Owner }, - m_ResourceCache{ResourceCache} +void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes) +{ #ifdef DILIGENT_DEBUG - , m_DbgAllocator {Allocator} + m_pDbgAllocator = &Allocator; #endif -// clang-format on -{ + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); VERIFY_EXPR(m_NumVariables == 0); auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); @@ -119,10 +114,10 @@ ShaderVariableManagerVk::~ShaderVariableManagerVk() void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator) { - VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor"); - if (m_pVariables != nullptr) { + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + for (Uint32 v = 0; v < m_NumVariables; ++v) m_pVariables[v].~ShaderVariableVkImpl(); Allocator.Free(m_pVariables); @@ -130,7 +125,7 @@ void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator) } } -ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) +ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) const { ShaderVariableVkImpl* pVar = nullptr; for (Uint32 v = 0; v < m_NumVariables; ++v) @@ -147,7 +142,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) } -ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index) +ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index) const { if (Index >= m_NumVariables) { @@ -178,7 +173,7 @@ Uint32 ShaderVariableManagerVk::GetVariableIndex(const ShaderVariableVkImpl& Var } } -void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) +void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const { if (!pResourceMapping) { -- cgit v1.2.3