diff options
| author | azhirnov <zh1dron@gmail.com> | 2021-03-04 13:23:50 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:38:14 +0000 |
| commit | 44fe2cc66cdc8d81f8e1595689ed1ec7ffea56b6 (patch) | |
| tree | 2859d94f4f907c744e95c5ffdbb91788125ca682 /Graphics/GraphicsEngineOpenGL | |
| parent | Vulkan: update for new Vulkan SDK (diff) | |
| download | DiligentCore-44fe2cc66cdc8d81f8e1595689ed1ec7ffea56b6.tar.gz DiligentCore-44fe2cc66cdc8d81f8e1595689ed1ec7ffea56b6.zip | |
OpenGL: added SRB memory allocator, some minor improvements
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
12 files changed, 261 insertions, 293 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp index ca9b7a1a..5c5d7c53 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineResourceSignatureGLImpl.hpp @@ -35,6 +35,7 @@ #include "PipelineResourceSignatureBase.hpp" #include "ShaderResourceCacheGL.hpp" #include "ShaderResourcesGL.hpp" +#include "SRBMemoryAllocator.hpp" namespace Diligent { @@ -174,7 +175,12 @@ public: return GetHash() != Other.GetHash() || m_BindingCount != Other.m_BindingCount; } - void InitSRBResourceCache(ShaderResourceCacheGL& ResourceCache) const; + SRBMemoryAllocator& GetSRBMemoryAllocator() + { + return m_SRBMemAllocator; + } + + void InitSRBResourceCache(ShaderResourceCacheGL& ResourceCache, IMemoryAllocator& CacheMemAllocator) const; #ifdef DILIGENT_DEVELOPMENT /// Verifies committed resource attribs using the SPIRV resource attributes from the PSO. @@ -215,6 +221,8 @@ private: using SamplerPtr = RefCntAutoPtr<ISampler>; SamplerPtr* m_ImmutableSamplers = nullptr; // [m_Desc.NumImmutableSamplers] + + SRBMemoryAllocator m_SRBMemAllocator; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index 40c536e6..476a742b 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -77,8 +77,6 @@ public: void CommitProgram(GLContextState& State); - Uint32 GetSignatureCount() const { return m_SignatureCount; } - PipelineResourceSignatureGLImpl* GetSignature(Uint32 index) const { VERIFY_EXPR(index < m_SignatureCount); @@ -91,8 +89,7 @@ public: #endif private: - using ShaderStageInfo = ShaderGLImpl::ShaderStageInfo; - using TShaderStages = std::vector<ShaderStageInfo>; + using TShaderStages = std::vector<ShaderGLImpl*>; GLObjectWrappers::GLPipelineObj& GetGLProgramPipeline(GLContext::NativeGLContextType Context); @@ -184,4 +181,9 @@ private: #endif }; +__forceinline SHADER_TYPE GetShaderStageType(const ShaderGLImpl* pShader) +{ + return pShader->GetDesc().ShaderType; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp index 263d0518..b958d59d 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp @@ -92,14 +92,7 @@ public: /// Implementation of IShader::GetResource() in OpenGL backend. virtual void DILIGENT_CALL_TYPE GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final; - struct ShaderStageInfo - { - ShaderStageInfo(const ShaderGLImpl* _pShader); - - SHADER_TYPE Type = SHADER_TYPE_UNKNOWN; - const ShaderGLImpl* pShader = nullptr; - }; - static GLObjectWrappers::GLProgramObj LinkProgram(const ShaderStageInfo* pShaderStagess, Uint32 NumShaders, bool IsSeparableProgram); + static GLObjectWrappers::GLProgramObj LinkProgram(ShaderGLImpl* const* ppShaders, Uint32 NumShaders, bool IsSeparableProgram); const std::shared_ptr<const ShaderResourcesGL>& GetShaderResources() const { return m_pShaderResources; } diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp index be86d3c3..35e340cc 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderResourceCacheGL.hpp @@ -119,11 +119,10 @@ public: RefCntAutoPtr<BufferViewGLImpl> pBufferView; }; + using TResourceCount = std::array<Uint32, 4>; // same as PipelineResourceSignatureGLImpl::TBindings. + static size_t GetRequriedMemorySize(const TResourceCount& ResCount); - static size_t GetRequriedMemorySize(Uint32 UBCount, Uint32 TextureCount, Uint32 ImageCount, Uint32 SSBOCount); - - void Initialize(Uint32 UBCount, Uint32 TextureCount, Uint32 ImageCount, Uint32 SSBOCount, IMemoryAllocator& MemAllocator); - void Destroy(IMemoryAllocator& MemAllocator); + void Initialize(const TResourceCount& Count, IMemoryAllocator& MemAllocator); void SetUniformBuffer(Uint32 CacheOffset, RefCntAutoPtr<BufferGLImpl>&& pBuff) { @@ -275,6 +274,7 @@ private: return const_cast<CachedSSBO&>(const_cast<const ShaderResourceCacheGL*>(this)->GetConstSSBO(CacheOffset)); } +private: static constexpr const Uint16 InvalidResourceOffset = 0xFFFF; static constexpr const Uint16 m_UBsOffset = 0; @@ -283,14 +283,12 @@ private: Uint16 m_SSBOsOffset = InvalidResourceOffset; Uint16 m_MemoryEndOffset = InvalidResourceOffset; - Uint8* m_pResourceData = nullptr; + Uint8* m_pResourceData = nullptr; + IMemoryAllocator* m_pAllocator = nullptr; // Indicates what types of resources are stored in the cache const CacheContentType m_ContentType; -#ifdef DILIGENT_DEBUG - IMemoryAllocator* m_pdbgMemoryAllocator = nullptr; -#endif #ifdef DILIGENT_DEVELOPMENT bool m_bStaticResourcesInitialized = false; #endif diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderVariableGL.hpp b/Graphics/GraphicsEngineOpenGL/include/ShaderVariableGL.hpp index 78ea737a..f03d3c2a 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderVariableGL.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderVariableGL.hpp @@ -88,6 +88,8 @@ public: ~ShaderVariableManagerGL(); + void DestroyVariables(IMemoryAllocator& Allocator); + // No copies, only moves are allowed // clang-format off ShaderVariableManagerGL (const ShaderVariableManagerGL&) = delete; @@ -97,6 +99,7 @@ public: // clang-format on void Initialize(const PipelineResourceSignatureGLImpl& Signature, + IMemoryAllocator& Allocator, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes, SHADER_TYPE ShaderType); @@ -122,6 +125,7 @@ public: struct GLVariableBase : public ShaderVariableBase<ShaderVariableManagerGL> { + public: using TBase = ShaderVariableBase<ShaderVariableManagerGL>; GLVariableBase(ShaderVariableManagerGL& ParentLayout, Uint32 ResIndex) : TBase{ParentLayout}, @@ -149,6 +153,7 @@ public: return m_ParentManager.GetVariableIndex(*this); } + private: const Uint32 m_ResIndex; }; @@ -185,9 +190,9 @@ public: }; - struct SamplerBindInfo final : GLVariableBase + struct TextureBindInfo final : GLVariableBase { - SamplerBindInfo(ShaderVariableManagerGL& ParentLayout, Uint32 ResIndex) : + TextureBindInfo(ShaderVariableManagerGL& ParentLayout, Uint32 ResIndex) : GLVariableBase{ParentLayout, ResIndex} {} @@ -211,8 +216,10 @@ public: virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final { - VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); - return m_ParentManager.m_ResourceCache.IsTextureBound(GetAttribs().CacheOffset + ArrayIndex, GetDesc().ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV); + const auto& Desc = GetDesc(); + VERIFY_EXPR(ArrayIndex < Desc.ArraySize); + const bool IsTexView = (Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || Desc.ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT); + return m_ParentManager.m_ResourceCache.IsTextureBound(GetAttribs().CacheOffset + ArrayIndex, IsTexView); } }; @@ -243,8 +250,10 @@ public: virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final { - VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); - return m_ParentManager.m_ResourceCache.IsImageBound(GetAttribs().CacheOffset + ArrayIndex, GetDesc().ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); + const auto& Desc = GetDesc(); + VERIFY_EXPR(ArrayIndex < Desc.ArraySize); + const bool IsImgView = (Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); + return m_ParentManager.m_ResourceCache.IsImageBound(GetAttribs().CacheOffset + ArrayIndex, IsImgView); } }; @@ -298,7 +307,7 @@ public: // clang-format off Uint32 GetNumUBs() const { return (m_TextureOffset - m_UBOffset) / sizeof(UniformBuffBindInfo); } - Uint32 GetNumTextures() const { return (m_ImageOffset - m_TextureOffset) / sizeof(SamplerBindInfo); } + Uint32 GetNumTextures() const { return (m_ImageOffset - m_TextureOffset) / sizeof(TextureBindInfo); } Uint32 GetNumImages() const { return (m_StorageBufferOffset - m_ImageOffset) / sizeof(ImageBindInfo) ; } Uint32 GetNumStorageBuffers() const { return (m_VariableEndOffset - m_StorageBufferOffset) / sizeof(StorageBufferBindInfo); } // clang-format on @@ -310,7 +319,7 @@ public: { VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>(), ")"); auto Offset = GetResourceOffset<ResourceType>(); - return reinterpret_cast<const ResourceType*>(reinterpret_cast<const Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex]; + return reinterpret_cast<const ResourceType*>(reinterpret_cast<const Uint8*>(m_ResourceBuffer) + Offset)[ResIndex]; } Uint32 GetVariableIndex(const GLVariableBase& Var) const; @@ -346,26 +355,26 @@ private: { VERIFY(ResIndex < GetNumResources<ResourceType>(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources<ResourceType>() - 1, ")"); auto Offset = GetResourceOffset<ResourceType>(); - return reinterpret_cast<ResourceType*>(reinterpret_cast<Uint8*>(m_ResourceBuffer.get()) + Offset)[ResIndex]; + return reinterpret_cast<ResourceType*>(reinterpret_cast<Uint8*>(m_ResourceBuffer) + Offset)[ResIndex]; } template <typename ResourceType> IShaderResourceVariable* GetResourceByName(const Char* Name) const; template <typename THandleUB, - typename THandleSampler, + typename THandleTexture, typename THandleImage, typename THandleStorageBuffer> void HandleResources(THandleUB HandleUB, - THandleSampler HandleSampler, + THandleTexture HandleTexture, THandleImage HandleImage, THandleStorageBuffer HandleStorageBuffer) { for (Uint32 ub = 0; ub < GetNumResources<UniformBuffBindInfo>(); ++ub) HandleUB(GetResource<UniformBuffBindInfo>(ub)); - for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s) - HandleSampler(GetResource<SamplerBindInfo>(s)); + for (Uint32 s = 0; s < GetNumResources<TextureBindInfo>(); ++s) + HandleTexture(GetResource<TextureBindInfo>(s)); for (Uint32 i = 0; i < GetNumResources<ImageBindInfo>(); ++i) HandleImage(GetResource<ImageBindInfo>(i)); @@ -375,19 +384,19 @@ private: } template <typename THandleUB, - typename THandleSampler, + typename THandleTexture, typename THandleImage, typename THandleStorageBuffer> void HandleConstResources(THandleUB HandleUB, - THandleSampler HandleSampler, + THandleTexture HandleTexture, THandleImage HandleImage, THandleStorageBuffer HandleStorageBuffer) const { for (Uint32 ub = 0; ub < GetNumResources<UniformBuffBindInfo>(); ++ub) HandleUB(GetConstResource<UniformBuffBindInfo>(ub)); - for (Uint32 s = 0; s < GetNumResources<SamplerBindInfo>(); ++s) - HandleSampler(GetConstResource<SamplerBindInfo>(s)); + for (Uint32 s = 0; s < GetNumResources<TextureBindInfo>(); ++s) + HandleTexture(GetConstResource<TextureBindInfo>(s)); for (Uint32 i = 0; i < GetNumResources<ImageBindInfo>(); ++i) HandleImage(GetConstResource<ImageBindInfo>(i)); @@ -405,14 +414,18 @@ private: IObject& m_Owner; // No need to use shared pointer, as the resource cache is either part of the same // ShaderGLImpl object, or ShaderResourceBindingGLImpl object - ShaderResourceCacheGL& m_ResourceCache; - std::unique_ptr<void, STDDeleterRawMem<void>> m_ResourceBuffer; + ShaderResourceCacheGL& m_ResourceCache; + void* m_ResourceBuffer = nullptr; static constexpr OffsetType m_UBOffset = 0; OffsetType m_TextureOffset = 0; OffsetType m_ImageOffset = 0; OffsetType m_StorageBufferOffset = 0; OffsetType m_VariableEndOffset = 0; + +#ifdef DILIGENT_DEBUG + IMemoryAllocator* m_pDbgAllocator = nullptr; +#endif }; @@ -423,7 +436,7 @@ inline Uint32 ShaderVariableManagerGL::GetNumResources<ShaderVariableManagerGL:: } template <> -inline Uint32 ShaderVariableManagerGL::GetNumResources<ShaderVariableManagerGL::SamplerBindInfo>() const +inline Uint32 ShaderVariableManagerGL::GetNumResources<ShaderVariableManagerGL::TextureBindInfo>() const { return GetNumTextures(); } @@ -451,7 +464,7 @@ inline ShaderVariableManagerGL::OffsetType ShaderVariableManagerGL:: template <> inline ShaderVariableManagerGL::OffsetType ShaderVariableManagerGL:: - GetResourceOffset<ShaderVariableManagerGL::SamplerBindInfo>() const + GetResourceOffset<ShaderVariableManagerGL::TextureBindInfo>() const { return m_TextureOffset; } diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 1c20b5bb..7c843321 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -156,7 +156,7 @@ void DeviceContextGLImpl::SetPipelineState(IPipelineState* pPipelineState) // the draw command. m_pPipelineState->CommitProgram(m_ContextState); - const auto SignCount = m_pPipelineState->GetSignatureCount(); + const auto SignCount = m_pPipelineState->GetResourceSignatureCount(); m_BindInfo.ActiveSRBMask = 0; for (Uint32 s = 0; s < SignCount; ++s) @@ -708,14 +708,14 @@ void DeviceContextGLImpl::BindProgramResources() { Uint32 sign = PlatformMisc::GetLSB(ActiveSRBMask); Uint32 SigBit = (1u << sign); - VERIFY_EXPR(sign < m_pPipelineState->GetSignatureCount()); + VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount()); ActiveSRBMask &= ~SigBit; const auto* pSRB = m_BindInfo.SRBs[sign]; VERIFY_EXPR(pSRB); - //if (m_BindInfo.StaleSRBMask & SigBit) + if (m_BindInfo.StaleSRBMask & SigBit) { BindProgramResources(m_CommitedResourcesTentativeBarriers, pSRB, Bindings); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp index e321e4d5..07f97f3d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineResourceSignatureGLImpl.cpp @@ -53,7 +53,7 @@ struct PatchedPipelineResourceSignatureDesc : PipelineResourceSignatureDesc PatchedPipelineResourceSignatureDesc(RenderDeviceGLImpl* pDeviceGL, const PipelineResourceSignatureDesc& Desc) : PipelineResourceSignatureDesc{Desc} { - if (NumImmutableSamplers > 0 && !pDeviceGL->GetDeviceCaps().Features.SeparablePrograms) + if (NumImmutableSamplers > 0 && ImmutableSamplers != nullptr && !pDeviceGL->GetDeviceCaps().Features.SeparablePrograms) { m_ImmutableSamplers.resize(NumImmutableSamplers); @@ -97,16 +97,17 @@ BINDING_RANGE PipelineResourceToBindingRange(const PipelineResourceDesc& Desc) switch (Desc.ResourceType) { // clang-format off - case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: return BINDING_RANGE_UNIFORM_BUFFER; - case SHADER_RESOURCE_TYPE_TEXTURE_SRV: return BINDING_RANGE_TEXTURE; - case SHADER_RESOURCE_TYPE_BUFFER_SRV: return (Desc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? BINDING_RANGE_TEXTURE : BINDING_RANGE_STORAGE_BUFFER; - case SHADER_RESOURCE_TYPE_TEXTURE_UAV: return BINDING_RANGE_IMAGE; - case SHADER_RESOURCE_TYPE_BUFFER_UAV: return (Desc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? BINDING_RANGE_IMAGE : BINDING_RANGE_STORAGE_BUFFER; - // clang-format on + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: return BINDING_RANGE_UNIFORM_BUFFER; + case SHADER_RESOURCE_TYPE_TEXTURE_SRV: return BINDING_RANGE_TEXTURE; + case SHADER_RESOURCE_TYPE_BUFFER_SRV: return (Desc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? BINDING_RANGE_TEXTURE : BINDING_RANGE_STORAGE_BUFFER; + case SHADER_RESOURCE_TYPE_TEXTURE_UAV: return BINDING_RANGE_IMAGE; + case SHADER_RESOURCE_TYPE_BUFFER_UAV: return (Desc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? BINDING_RANGE_IMAGE : BINDING_RANGE_STORAGE_BUFFER; + case SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT: return BINDING_RANGE_TEXTURE; + // clang-format on case SHADER_RESOURCE_TYPE_SAMPLER: - case SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT: case SHADER_RESOURCE_TYPE_ACCEL_STRUCT: default: + UNEXPECTED("Unsupported resource type"); return BINDING_RANGE_UNKNOWN; } } @@ -124,7 +125,8 @@ PipelineResourceSignatureGLImpl::PipelineResourceSignatureGLImpl(IReferenceCount const PipelineResourceSignatureDesc& Desc, bool bIsDeviceInternal, int) : - TPipelineResourceSignatureBase{pRefCounters, pDeviceGL, Desc, bIsDeviceInternal} + TPipelineResourceSignatureBase{pRefCounters, pDeviceGL, Desc, bIsDeviceInternal}, + m_SRBMemAllocator{GetRawAllocator()} { try { @@ -145,6 +147,8 @@ PipelineResourceSignatureGLImpl::PipelineResourceSignatureGLImpl(IReferenceCount MemPool.Reserve(); + static_assert(std::is_trivially_destructible<ResourceAttribs>::value, + "ResourceAttribs objects must be constructed to be properly destructed in case an excpetion is thrown"); m_pResourceAttribs = MemPool.Allocate<ResourceAttribs>(std::max(1u, m_Desc.NumResources)); m_ImmutableSamplers = MemPool.ConstructArray<SamplerPtr>(m_Desc.NumImmutableSamplers); @@ -173,11 +177,25 @@ PipelineResourceSignatureGLImpl::PipelineResourceSignatureGLImpl(IReferenceCount { VERIFY_EXPR(static_cast<Uint32>(Idx) < NumStaticResStages); const auto ShaderType = GetShaderTypeFromPipelineIndex(i, GetPipelineType()); - m_StaticVarsMgrs[Idx].Initialize(*this, AllowedVarTypes, _countof(AllowedVarTypes), ShaderType); + m_StaticVarsMgrs[Idx].Initialize(*this, GetRawAllocator(), AllowedVarTypes, _countof(AllowedVarTypes), ShaderType); } } } + if (m_Desc.SRBAllocationGranularity > 1) + { + std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVariableDataSizes = {}; + for (Uint32 s = 0; s < GetNumActiveShaderStages(); ++s) + { + constexpr SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + + ShaderVariableDataSizes[s] = ShaderVariableManagerGL::GetRequiredMemorySize(*this, AllowedVarTypes, _countof(AllowedVarTypes), GetActiveShaderStageType(s)); + } + + const size_t CacheMemorySize = ShaderResourceCacheGL::GetRequriedMemorySize(m_BindingCount); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumActiveShaderStages(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize); + } + m_Hash = CalculateHash(); } catch (...) @@ -189,7 +207,7 @@ PipelineResourceSignatureGLImpl::PipelineResourceSignatureGLImpl(IReferenceCount void PipelineResourceSignatureGLImpl::CreateLayouts() { - std::array<Uint32, BINDING_RANGE_COUNT> StaticCounter = {}; + TBindings StaticCounter = {}; for (Uint32 s = 0; s < m_Desc.NumImmutableSamplers; ++s) GetDevice()->CreateSampler(m_Desc.ImmutableSamplers[s].Desc, &m_ImmutableSamplers[s]); @@ -248,11 +266,7 @@ void PipelineResourceSignatureGLImpl::CreateLayouts() if (m_pStaticResCache) { - m_pStaticResCache->Initialize(StaticCounter[BINDING_RANGE_UNIFORM_BUFFER], - StaticCounter[BINDING_RANGE_TEXTURE], - StaticCounter[BINDING_RANGE_IMAGE], - StaticCounter[BINDING_RANGE_STORAGE_BUFFER], - GetRawAllocator()); + m_pStaticResCache->Initialize(StaticCounter, GetRawAllocator()); // Set immutable samplers for static resources. const auto ResIdxRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); @@ -326,14 +340,17 @@ void PipelineResourceSignatureGLImpl::Destruct() for (auto Idx : m_StaticResStageIndex) { if (Idx >= 0) + { + m_StaticVarsMgrs[Idx].DestroyVariables(RawAllocator); m_StaticVarsMgrs[Idx].~ShaderVariableManagerGL(); + } } m_StaticVarsMgrs = nullptr; } if (m_pStaticResCache) { - m_pStaticResCache->Destroy(RawAllocator); + m_pStaticResCache->~ShaderResourceCacheGL(); m_pStaticResCache = nullptr; } @@ -358,14 +375,14 @@ void PipelineResourceSignatureGLImpl::ApplyBindings(GLObjectWrappers::GLProgramO { const auto& ResDesc = m_Desc.Resources[r]; const auto& ResAttr = m_pResourceAttribs[r]; - const auto Range = PipelineResourceToBindingRange(ResDesc); - if (Range == BINDING_RANGE_UNKNOWN) + if (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER) continue; if ((ResDesc.ShaderStages & Stages) == 0) continue; + const auto Range = PipelineResourceToBindingRange(ResDesc); const Uint32 BindingIndex = Bindings[Range] + ResAttr.CacheOffset; static_assert(BINDING_RANGE_COUNT == 4, "Please update the switch below to handle the new shader resource range"); @@ -630,13 +647,9 @@ void PipelineResourceSignatureGLImpl::CopyStaticResources(ShaderResourceCacheGL& #endif } -void PipelineResourceSignatureGLImpl::InitSRBResourceCache(ShaderResourceCacheGL& ResourceCache) const +void PipelineResourceSignatureGLImpl::InitSRBResourceCache(ShaderResourceCacheGL& ResourceCache, IMemoryAllocator& CacheMemAllocator) const { - ResourceCache.Initialize(m_BindingCount[BINDING_RANGE_UNIFORM_BUFFER], - m_BindingCount[BINDING_RANGE_TEXTURE], - m_BindingCount[BINDING_RANGE_IMAGE], - m_BindingCount[BINDING_RANGE_STORAGE_BUFFER], - GetRawAllocator()); + ResourceCache.Initialize(m_BindingCount, CacheMemAllocator); } bool PipelineResourceSignatureGLImpl::IsCompatibleWith(const PipelineResourceSignatureGLImpl& Other) const @@ -715,7 +728,8 @@ bool PipelineResourceSignatureGLImpl::DvpValidateCommittedResource(const ShaderR case BINDING_RANGE_TEXTURE: for (Uint32 ArrInd = 0; ArrInd < ResDesc.ArraySize; ++ArrInd) { - if (!ResourceCache.IsTextureBound(ResAttr.CacheOffset + ArrInd, ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV)) + const bool IsTexView = (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || ResDesc.ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT); + if (!ResourceCache.IsTextureBound(ResAttr.CacheOffset + ArrInd, IsTexView)) { LOG_ERROR_MESSAGE("No resource is bound to variable '", GetShaderResourcePrintName(GLAttribs, ArrInd), "' in shader '", ShaderName, "' of PSO '", PSOName, "'"); @@ -733,7 +747,8 @@ bool PipelineResourceSignatureGLImpl::DvpValidateCommittedResource(const ShaderR case BINDING_RANGE_IMAGE: for (Uint32 ArrInd = 0; ArrInd < ResDesc.ArraySize; ++ArrInd) { - if (!ResourceCache.IsImageBound(ResAttr.CacheOffset + ArrInd, ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV)) + const bool IsImgView = (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); + if (!ResourceCache.IsImageBound(ResAttr.CacheOffset + ArrInd, IsImgView)) { LOG_ERROR_MESSAGE("No resource is bound to variable '", GetShaderResourcePrintName(GLAttribs, ArrInd), "' in shader '", ShaderName, "' of PSO '", PSOName, "'"); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 4aff0b55..959653e0 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -133,7 +133,7 @@ void PipelineStateGLImpl::CreateDefaultSignature(const PipelineStateCreateInfo& { for (size_t i = 0; i < ShaderStages.size(); ++i) { - auto* pShaderGL = ShaderStages[i].pShader; + auto* pShaderGL = ShaderStages[i]; pShaderGL->GetShaderResources()->ProcessConstResources(HandleUB, HandleTexture, HandleImage, HandleSB); } } @@ -234,7 +234,7 @@ void PipelineStateGLImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre { for (size_t i = 0; i < ShaderStages.size(); ++i) { - auto* pShaderGL = ShaderStages[i].pShader; + auto* pShaderGL = ShaderStages[i]; DvpValidateShaderResources(pShaderGL->GetShaderResources(), pShaderGL->GetDesc().Name, pShaderGL->GetDesc().ShaderType); } } @@ -272,9 +272,9 @@ void PipelineStateGLImpl::InitInternalObjects(const PSOCreateInfoType& CreateInf // Get active shader stages. SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; - for (auto& Stage : ShaderStages) + for (auto* pShaderGL : ShaderStages) { - const auto ShaderType = Stage.pShader->GetDesc().ShaderType; + const auto ShaderType = pShaderGL->GetDesc().ShaderType; VERIFY((ActiveStages & ShaderType) == 0, "Shader stage ", GetShaderTypeLiteralName(ShaderType), " is already active"); ActiveStages |= ShaderType; } @@ -282,10 +282,11 @@ void PipelineStateGLImpl::InitInternalObjects(const PSOCreateInfoType& CreateInf // Create programs. if (m_IsProgramPipelineSupported) { + VERIFY_EXPR(m_ShaderTypes.size() >= ShaderStages.size()); m_GLPrograms = MemPool.ConstructArray<GLProgramObj>(ShaderStages.size(), false); for (size_t i = 0; i < ShaderStages.size(); ++i) { - auto* pShaderGL = ShaderStages[i].pShader; + auto* pShaderGL = ShaderStages[i]; m_GLPrograms[i] = GLProgramObj{ShaderGLImpl::LinkProgram(&ShaderStages[i], 1, true)}; m_ShaderTypes[i] = pShaderGL->GetDesc().ShaderType; } @@ -417,10 +418,10 @@ bool PipelineStateGLImpl::IsCompatibleWith(const IPipelineState* pPSO) const const auto& lhs = *this; const auto& rhs = *ValidatedCast<const PipelineStateGLImpl>(pPSO); - if (lhs.GetSignatureCount() != rhs.GetSignatureCount()) + if (lhs.GetResourceSignatureCount() != rhs.GetResourceSignatureCount()) return false; - for (Uint32 s = 0, SigCount = lhs.GetSignatureCount(); s < SigCount; ++s) + for (Uint32 s = 0, SigCount = lhs.GetResourceSignatureCount(); s < SigCount; ++s) { if (!lhs.GetSignature(s)->IsCompatibleWith(*rhs.GetSignature(s))) return false; @@ -475,7 +476,7 @@ GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLCon #ifdef DILIGENT_DEVELOPMENT PipelineStateGLImpl::ResourceAttribution PipelineStateGLImpl::GetResourceAttribution(const char* Name, SHADER_TYPE Stage) const { - const auto SignCount = GetSignatureCount(); + const auto SignCount = GetResourceSignatureCount(); for (Uint32 sign = 0; sign < SignCount; ++sign) { const auto* const pSignature = GetSignature(sign); @@ -500,7 +501,7 @@ void PipelineStateGLImpl::DvpValidateShaderResources(const std::shared_ptr<const m_ShaderResources.emplace_back(pShaderResources); m_ShaderNames.emplace_back(ShaderName); - const auto HandleResource = [&](const ShaderResourcesGL::GLResourceAttribs& Attribs, SHADER_RESOURCE_TYPE ReadOnlyResourceType, PIPELINE_RESOURCE_FLAGS Flags) // + const auto HandleResource = [&](const ShaderResourcesGL::GLResourceAttribs& Attribs, SHADER_RESOURCE_TYPE AltResourceType, PIPELINE_RESOURCE_FLAGS Flags) // { m_ResourceAttibutions.emplace_back(); auto& ResAttribution = m_ResourceAttibutions.back(); @@ -521,22 +522,14 @@ void PipelineStateGLImpl::DvpValidateShaderResources(const std::shared_ptr<const const auto& ResDesc = pSignature->GetResourceDesc(ResAttribution.ResourceIndex); // Shader reflection does not contain read-only flag, so image and storage buffer can be UAV or SRV. - if (Attribs.ResourceType != ResDesc.ResourceType && - ReadOnlyResourceType != ResDesc.ResourceType) - { - LOG_ERROR_AND_THROW("Shader '", ShaderName, "' contains resource with name '", Attribs.Name, - "' and type '", GetShaderResourceTypeLiteralName(Attribs.ResourceType), "' that is not compatible with type '", - GetShaderResourceTypeLiteralName(ResDesc.ResourceType), "' in pipeline resource signature '", pSignature->GetDesc().Name, "'."); - } + // Texture SRV is same as input attachment. + const auto Type = (AltResourceType == ResDesc.ResourceType ? AltResourceType : Attribs.ResourceType); - if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER)) - { - LOG_ERROR_AND_THROW("Shader '", ShaderName, "' contains resource '", Attribs.Name, - "' that is", ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), - " labeled as formatted buffer, while the same resource specified by the pipeline resource signature '", - pSignature->GetDesc().Name, "' is", ((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), - " labeled as such."); - } + ValidatePipelineResourceCompatibility(ResDesc, Type, Flags, Attribs.ArraySize, ShaderName, pSignature->GetDesc().Name); + } + else + { + UNEXPECTED("Resource index should be valid"); } }; @@ -547,7 +540,7 @@ void PipelineStateGLImpl::DvpValidateShaderResources(const std::shared_ptr<const const auto HandleTexture = [&](const ShaderResourcesGL::TextureInfo& Attribs) { const bool IsTexelBuffer = (Attribs.ResourceType != SHADER_RESOURCE_TYPE_TEXTURE_SRV); HandleResource(Attribs, - Attribs.ResourceType, + IsTexelBuffer ? Attribs.ResourceType : SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT, IsTexelBuffer ? PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER : PIPELINE_RESOURCE_FLAG_COMBINED_SAMPLER); }; diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp index bc480a06..931ab3f2 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp @@ -41,11 +41,6 @@ using namespace Diligent; namespace Diligent { -ShaderGLImpl::ShaderStageInfo::ShaderStageInfo(const ShaderGLImpl* _pShader) : - Type{_pShader->GetDesc().ShaderType}, - pShader{_pShader} -{} - ShaderGLImpl::ShaderGLImpl(IReferenceCounters* pRefCounters, RenderDeviceGLImpl* pDeviceGL, const ShaderCreateInfo& ShaderCI, @@ -163,7 +158,7 @@ ShaderGLImpl::ShaderGLImpl(IReferenceCounters* pRefCounters, if (deviceCaps.Features.SeparablePrograms) { - ShaderStageInfo ThisShader[] = {ShaderStageInfo{this}}; + ShaderGLImpl* const ThisShader[] = {this}; GLObjectWrappers::GLProgramObj Program = LinkProgram(ThisShader, 1, true); auto pImmediateCtx = m_pDevice->GetImmediateContext(); VERIFY_EXPR(pImmediateCtx); @@ -182,7 +177,7 @@ ShaderGLImpl::~ShaderGLImpl() IMPLEMENT_QUERY_INTERFACE(ShaderGLImpl, IID_ShaderGL, TShaderBase) -GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(const ShaderStageInfo* pShaderStagess, Uint32 NumShaders, bool IsSeparableProgram) +GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(ShaderGLImpl* const* ppShaders, Uint32 NumShaders, bool IsSeparableProgram) { VERIFY(!IsSeparableProgram || NumShaders == 1, "Number of shaders must be 1 when separable program is created"); @@ -194,7 +189,7 @@ GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(const ShaderStageInfo* for (Uint32 i = 0; i < NumShaders; ++i) { - auto* pCurrShader = pShaderStagess[i].pShader; + auto* pCurrShader = ppShaders[i]; glAttachShader(GLProg, pCurrShader->m_GLShaderObj); CHECK_GL_ERROR("glAttachShader() failed"); } @@ -233,7 +228,7 @@ GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(const ShaderStageInfo* for (Uint32 i = 0; i < NumShaders; ++i) { - auto* pCurrShader = ValidatedCast<const ShaderGLImpl>(pShaderStagess[i].pShader); + auto* pCurrShader = ValidatedCast<const ShaderGLImpl>(ppShaders[i]); glDetachShader(GLProg, pCurrShader->m_GLShaderObj); CHECK_GL_ERROR("glDetachShader() failed"); } diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp index 06f364c6..637dcb6d 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceBindingGLImpl.cpp @@ -62,7 +62,11 @@ ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl(IReferenceCounters* // It is important to construct all objects before initializing them because if an exception is thrown, // destructors will be called for all objects - pPRS->InitSRBResourceCache(m_ShaderResourceCache); + // This will only allocate memory and initialize descriptor sets in the resource cache + // Resources will be initialized by InitializeResourceMemoryInCache() + auto& SRBMemAllocator = pPRS->GetSRBMemoryAllocator(); + auto& ResourceCacheDataAllocator = SRBMemAllocator.GetResourceCacheDataAllocator(0); + pPRS->InitSRBResourceCache(m_ShaderResourceCache, ResourceCacheDataAllocator); for (Uint32 s = 0; s < NumShaders; ++s) { @@ -71,11 +75,13 @@ ShaderResourceBindingGLImpl::ShaderResourceBindingGLImpl(IReferenceCounters* const auto MgrInd = m_ActiveShaderStageIndex[ShaderInd]; VERIFY_EXPR(MgrInd >= 0 && MgrInd < static_cast<int>(NumShaders)); + auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s); + // Create shader variable manager in place // 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}; - m_pShaderVarMgrs[MgrInd].Initialize(*pPRS, VarTypes, _countof(VarTypes), ShaderType); + m_pShaderVarMgrs[MgrInd].Initialize(*pPRS, VarDataAllocator, VarTypes, _countof(VarTypes), ShaderType); } } catch (...) @@ -92,19 +98,19 @@ ShaderResourceBindingGLImpl::~ShaderResourceBindingGLImpl() void ShaderResourceBindingGLImpl::Destruct() { - auto& RawAllocator = GetRawAllocator(); - if (m_pShaderVarMgrs != nullptr) { - const auto NumShaders = GetNumShaders(); - for (Uint32 s = 0; s < NumShaders; ++s) + auto& SRBMemAllocator = GetSignature()->GetSRBMemoryAllocator(); + for (Uint32 s = 0; s < GetNumShaders(); ++s) + { + auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s); + m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator); m_pShaderVarMgrs[s].~ShaderVariableManagerGL(); + } - RawAllocator.Free(m_pShaderVarMgrs); + GetRawAllocator().Free(m_pShaderVarMgrs); m_pShaderVarMgrs = nullptr; } - - m_ShaderResourceCache.Destroy(RawAllocator); } IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingGLImpl, IID_ShaderResourceBindingGL, TBase) diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp index 05a6f038..fe1a2078 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderResourceCacheGL.cpp @@ -27,44 +27,48 @@ #include "pch.h" #include "ShaderResourceCacheGL.hpp" +#include "PipelineResourceSignatureGLImpl.hpp" namespace Diligent { -size_t ShaderResourceCacheGL::GetRequriedMemorySize(Uint32 UBCount, Uint32 TextureCount, Uint32 ImageCount, Uint32 SSBOCount) +size_t ShaderResourceCacheGL::GetRequriedMemorySize(const TResourceCount& ResCount) { + static_assert(std::is_same<TResourceCount, PipelineResourceSignatureGLImpl::TBindings>::value, + "ShaderResourceCacheGL::TResourceCount must be the same type as PipelineResourceSignatureGLImpl::TBindings"); // clang-format off auto MemSize = - sizeof(CachedUB) * UBCount + - sizeof(CachedResourceView) * TextureCount + - sizeof(CachedResourceView) * ImageCount + - sizeof(CachedSSBO) * SSBOCount; + sizeof(CachedUB) * ResCount[BINDING_RANGE_UNIFORM_BUFFER] + + sizeof(CachedResourceView) * ResCount[BINDING_RANGE_TEXTURE] + + sizeof(CachedResourceView) * ResCount[BINDING_RANGE_IMAGE] + + sizeof(CachedSSBO) * ResCount[BINDING_RANGE_STORAGE_BUFFER]; // clang-format on + VERIFY(MemSize < InvalidResourceOffset, "Memory size exeed the maximum allowed size."); return MemSize; } -void ShaderResourceCacheGL::Initialize(Uint32 UBCount, Uint32 TextureCount, Uint32 ImageCount, Uint32 SSBOCount, IMemoryAllocator& MemAllocator) +void ShaderResourceCacheGL::Initialize(const TResourceCount& ResCount, IMemoryAllocator& MemAllocator) { + VERIFY(m_pAllocator == nullptr && m_pResourceData == nullptr, "Cache already initialized"); + m_pAllocator = &MemAllocator; + // clang-format off - m_TexturesOffset = static_cast<Uint16>(m_UBsOffset + sizeof(CachedUB) * UBCount); - m_ImagesOffset = static_cast<Uint16>(m_TexturesOffset + sizeof(CachedResourceView) * TextureCount); - m_SSBOsOffset = static_cast<Uint16>(m_ImagesOffset + sizeof(CachedResourceView) * ImageCount); - m_MemoryEndOffset = static_cast<Uint16>(m_SSBOsOffset + sizeof(CachedSSBO) * SSBOCount); - - VERIFY_EXPR(GetUBCount() == static_cast<Uint32>(UBCount)); - VERIFY_EXPR(GetTextureCount() == static_cast<Uint32>(TextureCount)); - VERIFY_EXPR(GetImageCount() == static_cast<Uint32>(ImageCount)); - VERIFY_EXPR(GetSSBOCount() == static_cast<Uint32>(SSBOCount)); + m_TexturesOffset = static_cast<Uint16>(m_UBsOffset + sizeof(CachedUB) * ResCount[BINDING_RANGE_UNIFORM_BUFFER]); + m_ImagesOffset = static_cast<Uint16>(m_TexturesOffset + sizeof(CachedResourceView) * ResCount[BINDING_RANGE_TEXTURE]); + m_SSBOsOffset = static_cast<Uint16>(m_ImagesOffset + sizeof(CachedResourceView) * ResCount[BINDING_RANGE_IMAGE]); + m_MemoryEndOffset = static_cast<Uint16>(m_SSBOsOffset + sizeof(CachedSSBO) * ResCount[BINDING_RANGE_STORAGE_BUFFER]); + + VERIFY_EXPR(GetUBCount() == static_cast<Uint32>(ResCount[BINDING_RANGE_UNIFORM_BUFFER])); + VERIFY_EXPR(GetTextureCount() == static_cast<Uint32>(ResCount[BINDING_RANGE_TEXTURE])); + VERIFY_EXPR(GetImageCount() == static_cast<Uint32>(ResCount[BINDING_RANGE_IMAGE])); + VERIFY_EXPR(GetSSBOCount() == static_cast<Uint32>(ResCount[BINDING_RANGE_STORAGE_BUFFER])); // clang-format on VERIFY_EXPR(m_pResourceData == nullptr); size_t BufferSize = m_MemoryEndOffset; - VERIFY_EXPR(BufferSize == GetRequriedMemorySize(UBCount, TextureCount, ImageCount, SSBOCount)); + VERIFY_EXPR(BufferSize == GetRequriedMemorySize(ResCount)); -#ifdef DILIGENT_DEBUG - m_pdbgMemoryAllocator = &MemAllocator; -#endif if (BufferSize > 0) { m_pResourceData = ALLOCATE(MemAllocator, "Shader resource cache data buffer", Uint8, BufferSize); @@ -72,51 +76,44 @@ void ShaderResourceCacheGL::Initialize(Uint32 UBCount, Uint32 TextureCount, Uint } // Explicitly construct all objects - for (Uint32 cb = 0; cb < UBCount; ++cb) + for (Uint32 cb = 0; cb < GetUBCount(); ++cb) new (&GetUB(cb)) CachedUB; - for (Uint32 s = 0; s < TextureCount; ++s) + for (Uint32 s = 0; s < GetTextureCount(); ++s) new (&GetTexture(s)) CachedResourceView; - for (Uint32 i = 0; i < ImageCount; ++i) + for (Uint32 i = 0; i < GetImageCount(); ++i) new (&GetImage(i)) CachedResourceView; - for (Uint32 s = 0; s < SSBOCount; ++s) + for (Uint32 s = 0; s < GetSSBOCount(); ++s) new (&GetSSBO(s)) CachedSSBO; } ShaderResourceCacheGL::~ShaderResourceCacheGL() { - VERIFY(!IsInitialized(), "Shader resource cache memory must be released with ShaderResourceCacheGL::Destroy()"); -} - -void ShaderResourceCacheGL::Destroy(IMemoryAllocator& MemAllocator) -{ - 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) - GetUB(cb).~CachedUB(); + if (IsInitialized()) + { + for (Uint32 cb = 0; cb < GetUBCount(); ++cb) + GetUB(cb).~CachedUB(); - for (Uint32 s = 0; s < GetTextureCount(); ++s) - GetTexture(s).~CachedResourceView(); + for (Uint32 s = 0; s < GetTextureCount(); ++s) + GetTexture(s).~CachedResourceView(); - for (Uint32 i = 0; i < GetImageCount(); ++i) - GetImage(i).~CachedResourceView(); + for (Uint32 i = 0; i < GetImageCount(); ++i) + GetImage(i).~CachedResourceView(); - for (Uint32 s = 0; s < GetSSBOCount(); ++s) - GetSSBO(s).~CachedSSBO(); + for (Uint32 s = 0; s < GetSSBOCount(); ++s) + GetSSBO(s).~CachedSSBO(); - if (m_pResourceData != nullptr) - MemAllocator.Free(m_pResourceData); + if (m_pResourceData != nullptr) + m_pAllocator->Free(m_pResourceData); - m_pResourceData = nullptr; - m_TexturesOffset = InvalidResourceOffset; - m_ImagesOffset = InvalidResourceOffset; - m_SSBOsOffset = InvalidResourceOffset; - m_MemoryEndOffset = InvalidResourceOffset; + m_pResourceData = nullptr; + m_TexturesOffset = InvalidResourceOffset; + m_ImagesOffset = InvalidResourceOffset; + m_SSBOsOffset = InvalidResourceOffset; + m_MemoryEndOffset = InvalidResourceOffset; + } } } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderVariableGL.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderVariableGL.cpp index af9f8f34..aa36a7aa 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderVariableGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderVariableGL.cpp @@ -44,7 +44,8 @@ void ShaderVariableManagerGL::CountResources(const PipelineResourceSignatureGLIm { ProcessSignatureResources( Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, - [&](Uint32 Index) { + [&](Uint32 Index) // + { const auto& ResDesc = Signature.GetResourceDesc(Index); static_assert(BINDING_RANGE_COUNT == 4, "Please update the switch below to handle the new shader resource range"); switch (PipelineResourceToBindingRange(ResDesc)) @@ -103,7 +104,7 @@ size_t ShaderVariableManagerGL::GetRequiredMemorySize(const PipelineResourceSign // clang-format off size_t RequiredSize = Counters.NumUBs * sizeof(UniformBuffBindInfo) + - Counters.NumTextures * sizeof(SamplerBindInfo) + + Counters.NumTextures * sizeof(TextureBindInfo) + Counters.NumImages * sizeof(ImageBindInfo) + Counters.NumStorageBlocks * sizeof(StorageBufferBindInfo); // clang-format on @@ -111,10 +112,15 @@ size_t ShaderVariableManagerGL::GetRequiredMemorySize(const PipelineResourceSign } void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& Signature, + IMemoryAllocator& Allocator, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes, SHADER_TYPE ShaderType) { +#ifdef DILIGENT_DEBUG + m_pDbgAllocator = &Allocator; +#endif + ResourceCounters Counters; CountResources(Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, Counters); @@ -135,7 +141,7 @@ void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& // clang-format off auto UBOffset = AdvanceOffset(Counters.NumUBs * sizeof(UniformBuffBindInfo) ); (void)UBOffset; // To suppress warning - m_TextureOffset = AdvanceOffset(Counters.NumTextures * sizeof(SamplerBindInfo) ); + m_TextureOffset = AdvanceOffset(Counters.NumTextures * sizeof(TextureBindInfo) ); m_ImageOffset = AdvanceOffset(Counters.NumImages * sizeof(ImageBindInfo) ); m_StorageBufferOffset = AdvanceOffset(Counters.NumStorageBlocks * sizeof(StorageBufferBindInfo)); m_VariableEndOffset = AdvanceOffset(0); @@ -143,11 +149,9 @@ void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& auto TotalMemorySize = m_VariableEndOffset; VERIFY_EXPR(TotalMemorySize == GetRequiredMemorySize(Signature, AllowedVarTypes, NumAllowedTypes, ShaderType)); - auto& ResLayoutDataAllocator = GetRawAllocator(); if (TotalMemorySize) { - auto* pRawMem = ALLOCATE_RAW(ResLayoutDataAllocator, "Raw memory buffer for shader resource layout resources", TotalMemorySize); - m_ResourceBuffer = std::unique_ptr<void, STDDeleterRawMem<void> >(pRawMem, ResLayoutDataAllocator); + m_ResourceBuffer = ALLOCATE_RAW(Allocator, "Raw memory buffer for shader resource layout resources", TotalMemorySize); } // clang-format off @@ -162,7 +166,8 @@ void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& ProcessSignatureResources( Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, - [&](Uint32 Index) { + [&](Uint32 Index) // + { const auto& ResDesc = Signature.GetResourceDesc(Index); static_assert(BINDING_RANGE_COUNT == 4, "Please update the switch below to handle the new shader resource range"); switch (PipelineResourceToBindingRange(ResDesc)) @@ -171,7 +176,7 @@ void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& new (&GetResource<UniformBuffBindInfo>(VarCounters.NumUBs++)) UniformBuffBindInfo{*this, Index}; break; case BINDING_RANGE_TEXTURE: - new (&GetResource<SamplerBindInfo>(VarCounters.NumTextures++)) SamplerBindInfo{*this, Index}; + new (&GetResource<TextureBindInfo>(VarCounters.NumTextures++)) TextureBindInfo{*this, Index}; break; case BINDING_RANGE_IMAGE: new (&GetResource<ImageBindInfo>(VarCounters.NumImages++)) ImageBindInfo{*this, Index}; @@ -186,7 +191,7 @@ void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& // clang-format off VERIFY(VarCounters.NumUBs == GetNumUBs(), "Not all UBs are initialized which will cause a crash when dtor is called"); - VERIFY(VarCounters.NumTextures == GetNumTextures(), "Not all Samplers are initialized which will cause a crash when dtor is called"); + VERIFY(VarCounters.NumTextures == GetNumTextures(), "Not all Textures are initialized which will cause a crash when dtor is called"); VERIFY(VarCounters.NumImages == GetNumImages(), "Not all Images are initialized which will cause a crash when dtor is called"); VERIFY(VarCounters.NumStorageBlocks == GetNumStorageBuffers(), "Not all SSBOs are initialized which will cause a crash when dtor is called"); // clang-format on @@ -194,29 +199,31 @@ void ShaderVariableManagerGL::Initialize(const PipelineResourceSignatureGLImpl& ShaderVariableManagerGL::~ShaderVariableManagerGL() { - // clang-format off + VERIFY(m_ResourceBuffer == nullptr, "DestroyVariables() has not been called"); +} + +void ShaderVariableManagerGL::DestroyVariables(IMemoryAllocator& Allocator) +{ + if (m_ResourceBuffer == nullptr) + return; + + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + HandleResources( - [&](UniformBuffBindInfo& ub) - { + [&](UniformBuffBindInfo& ub) { ub.~UniformBuffBindInfo(); }, - - [&](SamplerBindInfo& sam) - { - sam.~SamplerBindInfo(); + [&](TextureBindInfo& tex) { + tex.~TextureBindInfo(); }, - - [&](ImageBindInfo& img) - { + [&](ImageBindInfo& img) { img.~ImageBindInfo(); }, - - [&](StorageBufferBindInfo& ssbo) - { + [&](StorageBufferBindInfo& ssbo) { ssbo.~StorageBufferBindInfo(); - } - ); - // clang-format on + }); + + m_ResourceBuffer = nullptr; } void ShaderVariableManagerGL::UniformBuffBindInfo::BindResource(IDeviceObject* pBuffer, @@ -245,8 +252,7 @@ void ShaderVariableManagerGL::UniformBuffBindInfo::BindResource(IDeviceObject* p -void ShaderVariableManagerGL::SamplerBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) +void ShaderVariableManagerGL::TextureBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) { const auto& Desc = GetDesc(); const auto& Attr = GetAttribs(); @@ -254,10 +260,8 @@ void ShaderVariableManagerGL::SamplerBindInfo::BindResource(IDeviceObject* pView DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); auto& ResourceCache = m_ParentManager.m_ResourceCache; - VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV || - Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV); - - if (Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) + if (Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || + Desc.ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT) { // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type @@ -270,7 +274,11 @@ void ShaderVariableManagerGL::SamplerBindInfo::BindResource(IDeviceObject* pView RESOURCE_DIM_UNDEFINED, false, CachedTexSampler.pView.RawPtr()); if (Attr.IsImmutableSamplerAssigned() && ResourceCache.StaticResourcesInitialized()) { - VERIFY(CachedTexSampler.pSampler != nullptr, "Immutable samplers must be initialized by PipelineStateGLImpl::InitializeSRBResourceCache!"); + VERIFY(CachedTexSampler.pSampler != nullptr, "Immutable samplers must be initialized by PipelineResourceSignatureGLImpl::InitializeSRBResourceCache!"); + } + if (Desc.ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT) + { + DEV_CHECK_ERR(!Attr.IsSamplerAssigned(), "Input attachment must not have assigned sampler."); } } #endif @@ -309,8 +317,7 @@ void ShaderVariableManagerGL::SamplerBindInfo::BindResource(IDeviceObject* pView } -void ShaderVariableManagerGL::ImageBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) +void ShaderVariableManagerGL::ImageBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) { const auto& Desc = GetDesc(); const auto& Attr = GetAttribs(); @@ -367,8 +374,7 @@ void ShaderVariableManagerGL::ImageBindInfo::BindResource(IDeviceObject* pView, -void ShaderVariableManagerGL::StorageBufferBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) +void ShaderVariableManagerGL::StorageBufferBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) { const auto& Desc = GetDesc(); const auto& Attr = GetAttribs(); @@ -404,55 +410,6 @@ void ShaderVariableManagerGL::StorageBufferBindInfo::BindResource(IDeviceObject* ResourceCache.SetSSBO(Attr.CacheOffset + ArrayIndex, std::move(pViewGL)); } - - -// Helper template class that facilitates binding CBs, SRVs, and UAVs -class BindResourceHelper -{ -public: - BindResourceHelper(IResourceMapping& RM, Uint32 Fl) : - // clang-format off - ResourceMapping {RM}, - Flags {Fl} - // clang-format on - { - } - - template <typename ResourceType> - void Bind(ResourceType& Res) - { - if ((Flags & (1 << Res.GetType())) == 0) - return; - - const auto& ResDesc = Res.GetDesc(); - - for (Uint16 elem = 0; elem < ResDesc.ArraySize; ++elem) - { - if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(elem)) - continue; - - const auto* VarName = ResDesc.Name; - RefCntAutoPtr<IDeviceObject> pRes; - ResourceMapping.GetResource(VarName, &pRes, elem); - if (pRes) - { - // Call non-virtual function - Res.BindResource(pRes, elem); - } - else - { - if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(elem)) - LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", VarName, "': resource is not found in the resource mapping"); - } - } - } - -private: - IResourceMapping& ResourceMapping; - const Uint32 Flags; -}; - - void ShaderVariableManagerGL::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) { if (pResourceMapping == nullptr) @@ -464,31 +421,19 @@ void ShaderVariableManagerGL::BindResources(IResourceMapping* pResourceMapping, if ((Flags & BIND_SHADER_RESOURCES_UPDATE_ALL) == 0) Flags |= BIND_SHADER_RESOURCES_UPDATE_ALL; - BindResourceHelper BindResHelper(*pResourceMapping, Flags); - - // clang-format off HandleResources( - [&](UniformBuffBindInfo& ub) - { - BindResHelper.Bind(ub); + [&](UniformBuffBindInfo& ub) { + ub.BindResources<UniformBuffBindInfo>(pResourceMapping, Flags); }, - - [&](SamplerBindInfo& sam) - { - BindResHelper.Bind(sam); + [&](TextureBindInfo& tex) { + tex.BindResources<TextureBindInfo>(pResourceMapping, Flags); }, - - [&](ImageBindInfo& img) - { - BindResHelper.Bind(img); + [&](ImageBindInfo& img) { + img.BindResources<ImageBindInfo>(pResourceMapping, Flags); }, - - [&](StorageBufferBindInfo& ssbo) - { - BindResHelper.Bind(ssbo); - } - ); - // clang-format on + [&](StorageBufferBindInfo& ssbo) { + ssbo.BindResources<StorageBufferBindInfo>(pResourceMapping, Flags); + }); } @@ -513,8 +458,8 @@ IShaderResourceVariable* ShaderVariableManagerGL::GetVariable(const Char* Name) if (auto* pUB = GetResourceByName<UniformBuffBindInfo>(Name)) return pUB; - if (auto* pSampler = GetResourceByName<SamplerBindInfo>(Name)) - return pSampler; + if (auto* pTexture = GetResourceByName<TextureBindInfo>(Name)) + return pTexture; if (auto* pImage = GetResourceByName<ImageBindInfo>(Name)) return pImage; @@ -567,8 +512,8 @@ IShaderResourceVariable* ShaderVariableManagerGL::GetVariable(Uint32 Index) cons if (auto* pUB = VarLocator.TryResource<UniformBuffBindInfo>(GetNumUBs())) return pUB; - if (auto* pSampler = VarLocator.TryResource<SamplerBindInfo>(GetNumTextures())) - return pSampler; + if (auto* pTexture = VarLocator.TryResource<TextureBindInfo>(GetNumTextures())) + return pTexture; if (auto* pImage = VarLocator.TryResource<ImageBindInfo>(GetNumImages())) return pImage; @@ -588,7 +533,7 @@ public: ShaderVariableIndexLocator(const ShaderVariableManagerGL& _Layout, const ShaderVariableManagerGL::GLVariableBase& Variable) : // clang-format off Layout {_Layout}, - VarOffset(reinterpret_cast<const Uint8*>(&Variable) - reinterpret_cast<const Uint8*>(_Layout.m_ResourceBuffer.get())) + VarOffset(reinterpret_cast<const Uint8*>(&Variable) - reinterpret_cast<const Uint8*>(_Layout.m_ResourceBuffer)) // clang-format on {} @@ -635,7 +580,7 @@ Uint32 ShaderVariableManagerGL::GetVariableIndex(const GLVariableBase& Var) cons if (IdxLocator.TryResource<UniformBuffBindInfo>(m_TextureOffset, GetNumUBs())) return IdxLocator.GetIndex(); - if (IdxLocator.TryResource<SamplerBindInfo>(m_ImageOffset, GetNumTextures())) + if (IdxLocator.TryResource<TextureBindInfo>(m_ImageOffset, GetNumTextures())) return IdxLocator.GetIndex(); if (IdxLocator.TryResource<ImageBindInfo>(m_StorageBufferOffset, GetNumImages())) @@ -657,8 +602,9 @@ bool ShaderVariableManagerGL::dvpVerifyBindings(const ShaderResourceCacheGL& Res HandleConstResources( [&](const UniformBuffBindInfo& ub) // { - const auto& Desc = GetResourceDesc(ub.m_ResIndex); - const auto& Attr = GetAttribs(ub.m_ResIndex); + const auto& Desc = ub.GetDesc(); + const auto& Attr = ub.GetAttribs(); + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER); for (Uint32 ArrInd = 0; ArrInd < Desc.ArraySize; ++ArrInd) { if (!ResourceCache.IsUBBound(Attr.CacheOffset + ArrInd)) @@ -669,23 +615,23 @@ bool ShaderVariableManagerGL::dvpVerifyBindings(const ShaderResourceCacheGL& Res } }, - [&](const SamplerBindInfo& sam) // + [&](const TextureBindInfo& tex) // { - const auto& Desc = GetResourceDesc(sam.m_ResIndex); - const auto& Attr = GetAttribs(sam.m_ResIndex); + const auto& Desc = tex.GetDesc(); + const auto& Attr = tex.GetAttribs(); + const bool IsTexView = (Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || Desc.ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT); + VERIFY_EXPR(IsTexView || Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV); for (Uint32 ArrInd = 0; ArrInd < Desc.ArraySize; ++ArrInd) { - VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || - Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV); - if (!ResourceCache.IsTextureBound(Attr.CacheOffset + ArrInd, Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV)) + if (!ResourceCache.IsTextureBound(Attr.CacheOffset + ArrInd, IsTexView)) { - LOG_MISSING_BINDING("texture", sam, ArrInd); + LOG_MISSING_BINDING("texture", tex, ArrInd); BindingsOK = false; } else { - const auto& CachedSampler = ResourceCache.GetConstTexture(Attr.CacheOffset + ArrInd); - if (Attr.IsImmutableSamplerAssigned() && CachedSampler.pSampler == nullptr) + const auto& CachedTex = ResourceCache.GetConstTexture(Attr.CacheOffset + ArrInd); + if (Attr.IsImmutableSamplerAssigned() && CachedTex.pSampler == nullptr) { LOG_ERROR_MESSAGE("Immutable sampler is not initialized for texture '", Desc.Name, "'"); BindingsOK = false; @@ -696,13 +642,13 @@ bool ShaderVariableManagerGL::dvpVerifyBindings(const ShaderResourceCacheGL& Res [&](const ImageBindInfo& img) // { - const auto& Desc = GetResourceDesc(img.m_ResIndex); - const auto& Attr = GetAttribs(img.m_ResIndex); + const auto& Desc = img.GetDesc(); + const auto& Attr = img.GetAttribs(); + const bool IsTexView = (Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); + VERIFY_EXPR(IsTexView || Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV); for (Uint32 ArrInd = 0; ArrInd < Desc.ArraySize; ++ArrInd) { - VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV || - Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV); - if (!ResourceCache.IsImageBound(Attr.CacheOffset + ArrInd, Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV)) + if (!ResourceCache.IsImageBound(Attr.CacheOffset + ArrInd, IsTexView)) { LOG_MISSING_BINDING("texture UAV", img, ArrInd); BindingsOK = false; @@ -712,8 +658,10 @@ bool ShaderVariableManagerGL::dvpVerifyBindings(const ShaderResourceCacheGL& Res [&](const StorageBufferBindInfo& ssbo) // { - const auto& Desc = GetResourceDesc(ssbo.m_ResIndex); - const auto& Attr = GetAttribs(ssbo.m_ResIndex); + const auto& Desc = ssbo.GetDesc(); + const auto& Attr = ssbo.GetAttribs(); + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV || + Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV); for (Uint32 ArrInd = 0; ArrInd < Desc.ArraySize; ++ArrInd) { if (!ResourceCache.IsSSBOBound(Attr.CacheOffset + ArrInd)) |
