From c734bab37ee6434acc6145579af3740488f81d68 Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 21 Aug 2023 14:05:48 -0700 Subject: [PATCH] GLTFResourceManager: added TransitionResourceStates method --- AssetLoader/interface/GLTFResourceManager.hpp | 60 ++++++++++++++++ AssetLoader/src/GLTFResourceManager.cpp | 71 +++++++++++++++---- 2 files changed, 119 insertions(+), 12 deletions(-) diff --git a/AssetLoader/interface/GLTFResourceManager.hpp b/AssetLoader/interface/GLTFResourceManager.hpp index 0a6a2c72..6c610ac0 100644 --- a/AssetLoader/interface/GLTFResourceManager.hpp +++ b/AssetLoader/interface/GLTFResourceManager.hpp @@ -233,6 +233,64 @@ class ResourceManager final : public ObjectBase /// Otherwise, returns the net usage stats for all pools. VertexPoolUsageStats GetVertexPoolUsageStats(const VertexLayoutKey& Key = VertexLayoutKey{}); + /// Parameters of the TransitionResourceStates() method. + struct TransitionResourceStatesInfo + { + /// Vertex buffers transition info. + struct VertexBuffersInfo + { + /// Old state that is passed to the OldState member of the StateTransitionDesc structure. + RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; + + /// New state that is passed to the NewState member of the StateTransitionDesc structure. + /// + /// If NewState is RESOURCE_STATE_UNKNOWN, the vertex buffers states will not be changed. + RESOURCE_STATE NewState = RESOURCE_STATE_UNKNOWN; + + /// Flags that are passed to the Flags member of the StateTransitionDesc structure. + STATE_TRANSITION_FLAGS Flags = STATE_TRANSITION_FLAG_UPDATE_STATE; + } VertexBuffers; + + /// Index buffer transition info. + struct IndexBufferInfo + { + /// Old state that is passed to the OldState member of the StateTransitionDesc structure. + RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; + + /// New state that is passed to the NewState member of the StateTransitionDesc structure. + /// + /// If NewState is RESOURCE_STATE_UNKNOWN, the index buffer state will not be changed. + RESOURCE_STATE NewState = RESOURCE_STATE_UNKNOWN; + + /// Flags that are passed to the Flags member of the StateTransitionDesc structure. + STATE_TRANSITION_FLAGS Flags = STATE_TRANSITION_FLAG_UPDATE_STATE; + } IndexBuffer; + + /// Texture atlases transition info. + struct TextureAtlasesInfo + { + /// Old state that is passed to the OldState member of the StateTransitionDesc structure. + RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN; + + /// New state that is passed to the NewState member of the StateTransitionDesc structure. + /// + /// If NewState is RESOURCE_STATE_UNKNOWN, the texture atlases states will not be changed. + RESOURCE_STATE NewState = RESOURCE_STATE_UNKNOWN; + + /// Flags that are passed to the Flags member of the StateTransitionDesc structure. + STATE_TRANSITION_FLAGS Flags = STATE_TRANSITION_FLAG_UPDATE_STATE; + } TextureAtlases; + }; + + /// Transitions resource states of all vertex buffers, index buffer and texture atlases. + /// + /// \param[in] pDevice - Pointer to the render device. + /// \param[in] pContext - Pointer to the device context. + /// \param[in] Info - Resource state transition info, see Diligent::ResourceManager::TransitionResourceStatesInfo. + /// + /// \remarks This function is thread-safe. + void TransitionResourceStates(IRenderDevice* pDevice, IDeviceContext* pContext, const TransitionResourceStatesInfo& Info); + private: template friend class Diligent::MakeNewRCObj; @@ -262,6 +320,8 @@ class ResourceManager final : public ObjectBase using TexAllocationsHashMapType = std::unordered_map>; std::mutex m_TexAllocationsMtx; TexAllocationsHashMapType m_TexAllocations; + + std::vector m_Barriers; }; } // namespace GLTF diff --git a/AssetLoader/src/GLTFResourceManager.cpp b/AssetLoader/src/GLTFResourceManager.cpp index 8ad10c6a..8a86432a 100644 --- a/AssetLoader/src/GLTFResourceManager.cpp +++ b/AssetLoader/src/GLTFResourceManager.cpp @@ -121,7 +121,7 @@ RefCntAutoPtr ResourceManager::FindTextureAllocation if (CacheId != nullptr && *CacheId != 0) { - std::lock_guard Lock{m_TexAllocationsMtx}; + std::lock_guard Guard{m_TexAllocationsMtx}; auto it = m_TexAllocations.find(CacheId); if (it != m_TexAllocations.end()) @@ -152,7 +152,7 @@ RefCntAutoPtr ResourceManager::AllocateTextureSpace( { decltype(m_Atlases)::iterator cache_it; // NB: can't initialize it without locking the mutex { - std::lock_guard Lock{m_AtlasesMtx}; + std::lock_guard Guard{m_AtlasesMtx}; cache_it = m_Atlases.find(Fmt); if (cache_it == m_Atlases.end()) { @@ -187,7 +187,7 @@ RefCntAutoPtr ResourceManager::AllocateTextureSpace( if (CacheId != nullptr && *CacheId != 0) { - std::lock_guard Lock{m_TexAllocationsMtx}; + std::lock_guard Guard{m_TexAllocationsMtx}; // Note that the same allocation may potentially be created by more // than one thread if it has not been found in the cache originally m_TexAllocations.emplace(CacheId, pAllocation); @@ -223,7 +223,7 @@ RefCntAutoPtr ResourceManager::AllocateVertices(const Ver decltype(m_VertexPools)::iterator pool_it; // NB: can't initialize it without locking the mutex { - std::lock_guard Lock{m_VertexPoolsMtx}; + std::lock_guard Guard{m_VertexPoolsMtx}; pool_it = m_VertexPools.find(LayoutKey); if (pool_it == m_VertexPools.end()) { @@ -281,7 +281,7 @@ Uint32 ResourceManager::GetTextureVersion() { Uint32 Version = 0; - std::lock_guard Lock{m_AtlasesMtx}; + std::lock_guard Guard{m_AtlasesMtx}; for (auto atlas_it : m_Atlases) Version += atlas_it.second->GetVersion(); @@ -298,7 +298,7 @@ Uint32 ResourceManager::GetVertexPoolsVersion() { Uint32 Version = 0; - std::lock_guard Lock{m_VertexPoolsMtx}; + std::lock_guard Guard{m_VertexPoolsMtx}; for (auto pool_it : m_VertexPools) Version += pool_it.second->GetVersion(); @@ -316,7 +316,7 @@ IVertexPool* ResourceManager::GetVertexPool(const VertexLayoutKey& Key) { decltype(m_VertexPools)::iterator pool_it; // NB: can't initialize it without locking the mutex { - std::lock_guard Lock{m_VertexPoolsMtx}; + std::lock_guard Guard{m_VertexPoolsMtx}; pool_it = m_VertexPools.find(Key); if (pool_it == m_VertexPools.end()) return nullptr; @@ -329,7 +329,7 @@ ITexture* ResourceManager::GetTexture(TEXTURE_FORMAT Fmt, IRenderDevice* pDevice { decltype(m_Atlases)::iterator cache_it; // NB: can't initialize it without locking the mutex { - std::lock_guard Lock{m_AtlasesMtx}; + std::lock_guard Guard{m_AtlasesMtx}; cache_it = m_Atlases.find(Fmt); if (cache_it == m_Atlases.end()) return nullptr; @@ -341,7 +341,7 @@ ITexture* ResourceManager::GetTexture(TEXTURE_FORMAT Fmt, IRenderDevice* pDevice TextureDesc ResourceManager::GetAtlasDesc(TEXTURE_FORMAT Fmt) { { - std::lock_guard Lock{m_AtlasesMtx}; + std::lock_guard Guard{m_AtlasesMtx}; auto cache_it = m_Atlases.find(Fmt); if (cache_it != m_Atlases.end()) @@ -357,7 +357,7 @@ TextureDesc ResourceManager::GetAtlasDesc(TEXTURE_FORMAT Fmt) Uint32 ResourceManager::GetAllocationAlignment(TEXTURE_FORMAT Fmt, Uint32 Width, Uint32 Height) { { - std::lock_guard Lock{m_AtlasesMtx}; + std::lock_guard Guard{m_AtlasesMtx}; auto cache_it = m_Atlases.find(Fmt); if (cache_it != m_Atlases.end()) @@ -381,7 +381,7 @@ DynamicTextureAtlasUsageStats ResourceManager::GetAtlasUsageStats(TEXTURE_FORMAT { DynamicTextureAtlasUsageStats Stats; { - std::lock_guard Lock{m_AtlasesMtx}; + std::lock_guard Guard{m_AtlasesMtx}; if (Fmt != TEX_FORMAT_UNKNOWN) { auto cache_it = m_Atlases.find(Fmt); @@ -410,7 +410,7 @@ VertexPoolUsageStats ResourceManager::GetVertexPoolUsageStats(const VertexLayout { VertexPoolUsageStats Stats; { - std::lock_guard Lock{m_VertexPoolsMtx}; + std::lock_guard Guard{m_VertexPoolsMtx}; if (Key != VertexLayoutKey{}) { auto pool_it = m_VertexPools.find(Key); @@ -436,6 +436,53 @@ VertexPoolUsageStats ResourceManager::GetVertexPoolUsageStats(const VertexLayout return Stats; } +void ResourceManager::TransitionResourceStates(IRenderDevice* pDevice, IDeviceContext* pContext, const TransitionResourceStatesInfo& Info) +{ + m_Barriers.clear(); + + if (Info.VertexBuffers.NewState != RESOURCE_STATE_UNKNOWN) + { + std::lock_guard Guard{m_VertexPoolsMtx}; + for (auto it : m_VertexPools) + { + const auto& pPool = it.second; + const auto& Desc = pPool->GetDesc(); + for (Uint32 elem = 0; elem < Desc.NumElements; ++elem) + { + if (auto* pVertBuffer = pPool->GetBuffer(elem, pDevice, pContext)) + { + m_Barriers.emplace_back(pVertBuffer, Info.VertexBuffers.OldState, Info.VertexBuffers.NewState, Info.VertexBuffers.Flags); + } + } + } + } + + if (Info.IndexBuffer.NewState != RESOURCE_STATE_UNKNOWN) + { + if (auto* pIndexBuffer = GetIndexBuffer(pDevice, pContext)) + { + m_Barriers.emplace_back(pIndexBuffer, Info.IndexBuffer.OldState, Info.IndexBuffer.NewState, Info.IndexBuffer.Flags); + } + } + + if (Info.TextureAtlases.NewState != RESOURCE_STATE_UNKNOWN) + { + std::lock_guard Guard{m_AtlasesMtx}; + for (auto it : m_Atlases) + { + if (auto* pTexture = it.second->GetTexture(pDevice, pContext)) + { + m_Barriers.emplace_back(pTexture, Info.TextureAtlases.OldState, Info.TextureAtlases.NewState, Info.TextureAtlases.Flags); + } + } + } + + if (!m_Barriers.empty()) + { + pContext->TransitionResourceStates(static_cast(m_Barriers.size()), m_Barriers.data()); + } +} + } // namespace GLTF } // namespace Diligent