From d81817038a73aac29846928ebd1fcd8d8ace0f60 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 1 Dec 2020 18:13:42 -0800 Subject: Refcactored GLTFResourceManager: made allocations ref-counted objects --- AssetLoader/src/GLTFLoader.cpp | 36 +++---- AssetLoader/src/GLTFResourceManager.cpp | 185 +++++++++++++++++++------------- 2 files changed, 125 insertions(+), 96 deletions(-) (limited to 'AssetLoader/src') diff --git a/AssetLoader/src/GLTFLoader.cpp b/AssetLoader/src/GLTFLoader.cpp index 9fe0cd2..9b690a0 100644 --- a/AssetLoader/src/GLTFLoader.cpp +++ b/AssetLoader/src/GLTFLoader.cpp @@ -270,18 +270,6 @@ Model::~Model() { if (CacheInfo.pResourceMgr != nullptr) { - for (auto& Buff : Buffers) - { - if (Buff.CacheAllocation.Region.IsValid()) - CacheInfo.pResourceMgr->FreeBufferSpace(std::move(Buff.CacheAllocation)); - } - - for (auto& Tex : Textures) - { - if (Tex.CacheAllocation.IsValid()) - CacheInfo.pResourceMgr->FreeTextureSpace(std::move(Tex.CacheAllocation)); - } - CacheInfo.pResourceMgr->Release(); } } @@ -758,12 +746,12 @@ void Model::LoadTextures(IRenderDevice* pDevice, { if (CacheInfo.pResourceMgr != nullptr) { - TexInfo.CacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(0, gltf_image.width, gltf_image.height); - if (TexInfo.CacheAllocation.IsValid()) + TexInfo.pCacheAllocation = CacheInfo.pResourceMgr->AllocateTextureSpace(0, gltf_image.width, gltf_image.height); + if (TexInfo.pCacheAllocation) { - const auto& TexDesc = CacheInfo.pResourceMgr->GetTexture(TexInfo.CacheAllocation)->GetDesc(); + const auto& TexDesc = TexInfo.pCacheAllocation->GetTexDesc(); - const auto& Region = TexInfo.CacheAllocation.Region; + const auto& Region = TexInfo.pCacheAllocation->GetRegion(); TexInitData = PrepareGLTFTextureInitData(gltf_image, AlphaCutoff, Region.x, Region.y, TexDesc.MipLevels); TexInfo.UVScaleBias.x = static_cast(gltf_image.width) / static_cast(TexDesc.Width); @@ -844,7 +832,7 @@ void Model::LoadTextures(IRenderDevice* pDevice, } } -void Model::PrepareGPUResources(IDeviceContext* pCtx) +void Model::PrepareGPUResources(IRenderDevice* pDevice, IDeviceContext* pCtx) { if (!InitData) return; @@ -854,7 +842,7 @@ void Model::PrepareGPUResources(IDeviceContext* pCtx) VERIFY_EXPR(InitData->Textures.size() == Textures.size()); for (Uint32 i = 0; i < Textures.size(); ++i) { - auto* pTexture = GetTexture(i); + auto* pTexture = GetTexture(i, pDevice, pCtx); if (!pTexture) continue; @@ -895,9 +883,9 @@ void Model::PrepareGPUResources(IDeviceContext* pCtx) auto UpdateBuffer = [&](BUFFER_ID BuffId, const void* pData, size_t Size) // { - auto* pBuffer = GetBuffer(BuffId); + auto* pBuffer = GetBuffer(BuffId, pDevice, pCtx); VERIFY_EXPR(pBuffer != nullptr); - auto Offset = Buffers[BuffId].CacheAllocation.IsValid() ? Buffers[BuffId].CacheAllocation.Region.UnalignedOffset : 0; + auto Offset = Buffers[BuffId].pCacheAllocation ? Buffers[BuffId].pCacheAllocation->GetRegion().UnalignedOffset : 0; pCtx->UpdateBuffer(pBuffer, static_cast(Offset), static_cast(Size), pData, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); if (Buffers[BuffId].pBuffer != nullptr) { @@ -1581,7 +1569,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, auto BufferSize = static_cast(VertexData0.size() * sizeof(VertexData0[0])); if (CacheInfo.pResourceMgr != nullptr) { - Buffers[BUFFER_ID_VERTEX0].CacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer0Idx, BufferSize, 1); + Buffers[BUFFER_ID_VERTEX0].pCacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer0Idx, BufferSize, 1); } else { @@ -1605,7 +1593,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, auto BufferSize = static_cast(VertexData1.size() * sizeof(VertexData1[0])); if (CacheInfo.pResourceMgr != nullptr) { - Buffers[BUFFER_ID_VERTEX1].CacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer1Idx, BufferSize, 1); + Buffers[BUFFER_ID_VERTEX1].pCacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.VertexBuffer1Idx, BufferSize, 1); } else { @@ -1630,7 +1618,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, auto BufferSize = static_cast(IndexBuffer.size() * sizeof(IndexBuffer[0])); if (CacheInfo.pResourceMgr != nullptr) { - Buffers[BUFFER_ID_INDEX].CacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.IndexBufferIdx, BufferSize, 1); + Buffers[BUFFER_ID_INDEX].pCacheAllocation = CacheInfo.pResourceMgr->AllocateBufferSpace(CacheInfo.IndexBufferIdx, BufferSize, 1); } else { @@ -1649,7 +1637,7 @@ void Model::LoadFromFile(IRenderDevice* pDevice, if (pContext != nullptr) { - PrepareGPUResources(pContext); + PrepareGPUResources(pDevice, pContext); } GetSceneDimensions(); diff --git a/AssetLoader/src/GLTFResourceManager.cpp b/AssetLoader/src/GLTFResourceManager.cpp index c6f627c..05dfa28 100644 --- a/AssetLoader/src/GLTFResourceManager.cpp +++ b/AssetLoader/src/GLTFResourceManager.cpp @@ -32,112 +32,153 @@ namespace Diligent { -GLTFResourceManager::BufferCache::BufferCache(IRenderDevice* pDevice, const BufferDesc& BuffDesc) : - Mgr{BuffDesc.uiSizeInBytes, DefaultRawMemoryAllocator::GetAllocator()} +GLTFResourceManager::BufferCache::BufferCache(GLTFResourceManager& Owner, + IRenderDevice* pDevice, + const BufferDesc& BuffDesc) : + m_Owner{Owner}, + m_Mgr{BuffDesc.uiSizeInBytes, DefaultRawMemoryAllocator::GetAllocator()} { - pDevice->CreateBuffer(BuffDesc, nullptr, &pBuffer); + pDevice->CreateBuffer(BuffDesc, nullptr, &m_pBuffer); } -GLTFResourceManager::TextureCache::TextureCache(IRenderDevice* pDevice, const TextureCacheAttribs& CacheCI) : - Mgr{CacheCI.Desc.Width / CacheCI.Granularity, CacheCI.Desc.Height / CacheCI.Granularity}, - Granularity{CacheCI.Granularity} +IBuffer* GLTFResourceManager::BufferCache::GetBuffer(IRenderDevice* pDevice, IDeviceContext* pContext) { - DEV_CHECK_ERR(IsPowerOfTwo(CacheCI.Granularity), "Granularity (", CacheCI.Granularity, ") must be a power of two"); - DEV_CHECK_ERR((CacheCI.Desc.Width % CacheCI.Granularity) == 0, "Atlas width (", CacheCI.Desc.Width, ") is not multiple of granularity (", CacheCI.Granularity, ")"); - DEV_CHECK_ERR((CacheCI.Desc.Height % CacheCI.Granularity) == 0, "Atlas height (", CacheCI.Desc.Height, ") is not multiple of granularity (", CacheCI.Granularity, ")"); + std::lock_guard Lock{m_Mtx}; - pDevice->CreateTexture(CacheCI.Desc, nullptr, &pTexture); -} + const auto& BuffDesc = m_pBuffer->GetDesc(); + const auto MgrSize = m_Mgr.GetMaxSize(); + if (BuffDesc.uiSizeInBytes < MgrSize) + { + // Extend the buffer + auto NewBuffDesc = BuffDesc; -RefCntAutoPtr GLTFResourceManager::Create(IRenderDevice* pDevice, - const CreateInfo& CI) -{ - return RefCntAutoPtr{MakeNewRCObj()(pDevice, CI)}; -} + NewBuffDesc.uiSizeInBytes = static_cast(MgrSize); -GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters, - IRenderDevice* pDevice, - const CreateInfo& CI) : - TBase{pRefCounters} -{ - m_Buffers.reserve(CI.NumBuffers); - for (Uint32 i = 0; i < CI.NumBuffers; ++i) - { - m_Buffers.emplace_back(pDevice, CI.Buffers[i]); - } + RefCntAutoPtr pNewBuffer; + pDevice->CreateBuffer(NewBuffDesc, nullptr, &pNewBuffer); + pContext->CopyBuffer(m_pBuffer, 0, RESOURCE_STATE_TRANSITION_MODE_TRANSITION, + pNewBuffer, 0, BuffDesc.uiSizeInBytes, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - m_Textures.reserve(CI.NumTextures); - for (Uint32 i = 0; i < CI.NumTextures; ++i) - { - m_Textures.emplace_back(pDevice, CI.Textures[i]); + m_pBuffer = std::move(pNewBuffer); } + + return m_pBuffer.RawPtr(); } -GLTFResourceManager::BufferAllocation GLTFResourceManager::AllocateBufferSpace(Uint32 BufferIndex, Uint32 Size, Uint32 Alignment) +RefCntAutoPtr GLTFResourceManager::BufferCache::Allocate(Uint32 Size, Uint32 Alignment) { - auto& BuffCache = m_Buffers[BufferIndex]; + std::lock_guard Lock{m_Mtx}; - std::lock_guard Lock{BuffCache.Mtx}; + auto Region = m_Mgr.Allocate(Size, Alignment); + while (!Region.IsValid()) + { + m_Mgr.Extend(m_Mgr.GetMaxSize()); + Region = m_Mgr.Allocate(Size, Alignment); + } - BufferAllocation Allocation; - Allocation.Region = BuffCache.Mgr.Allocate(Size, Alignment); - if (Allocation.Region.IsValid()) - Allocation.BufferIndex = BufferIndex; - return Allocation; + return RefCntAutoPtr{ + MakeNewRCObj()( + RefCntAutoPtr{&m_Owner}, + *this, + std::move(Region) // + ) // + }; } -void GLTFResourceManager::FreeBufferSpace(BufferAllocation&& Allocation) +GLTFResourceManager::TextureCache::TextureCache(GLTFResourceManager& Owner, + IRenderDevice* pDevice, + const TextureCacheAttribs& CacheCI) : + m_Owner{Owner}, + m_TexDesc{CacheCI.Desc}, + m_Mgr{CacheCI.Desc.Width / CacheCI.Granularity, CacheCI.Desc.Height / CacheCI.Granularity}, + m_Granularity{CacheCI.Granularity} { - VERIFY_EXPR(Allocation.IsValid()); + m_TexDesc.Name = m_TexName.c_str(); - auto& BuffCache = m_Buffers[Allocation.BufferIndex]; + DEV_CHECK_ERR(IsPowerOfTwo(CacheCI.Granularity), "Granularity (", CacheCI.Granularity, ") must be a power of two"); + DEV_CHECK_ERR((CacheCI.Desc.Width % CacheCI.Granularity) == 0, "Atlas width (", CacheCI.Desc.Width, ") is not multiple of granularity (", CacheCI.Granularity, ")"); + DEV_CHECK_ERR((CacheCI.Desc.Height % CacheCI.Granularity) == 0, "Atlas height (", CacheCI.Desc.Height, ") is not multiple of granularity (", CacheCI.Granularity, ")"); - std::lock_guard Lock{BuffCache.Mtx}; - BuffCache.Mgr.Free(std::move(Allocation.Region)); + pDevice->CreateTexture(CacheCI.Desc, nullptr, &m_pTexture); } -GLTFResourceManager::TextureAllocation GLTFResourceManager::AllocateTextureSpace(Uint32 TextureIndex, Uint32 Width, Uint32 Height) + +ITexture* GLTFResourceManager::TextureCache::GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext) { - auto& TexCache = m_Textures[TextureIndex]; + // TODO: handle resizes + return m_pTexture; +} - Width = (Width + TexCache.Granularity - 1) / TexCache.Granularity; - Height = (Height + TexCache.Granularity - 1) / TexCache.Granularity; +RefCntAutoPtr GLTFResourceManager::TextureCache::Allocate(Uint32 Width, Uint32 Height) +{ + Width = (Width + m_Granularity - 1) / m_Granularity; + Height = (Height + m_Granularity - 1) / m_Granularity; - std::lock_guard Lock{TexCache.Mtx}; + std::lock_guard Lock{m_Mtx}; - TextureAllocation Allocation; - Allocation.Region = TexCache.Mgr.Allocate(Width, Height); - if (!Allocation.Region.IsEmpty()) + auto Region = m_Mgr.Allocate(Width, Height); + if (!Region.IsEmpty()) { - Allocation.TextureIndex = TextureIndex; - - Allocation.Region.x *= TexCache.Granularity; - Allocation.Region.y *= TexCache.Granularity; - Allocation.Region.width *= TexCache.Granularity; - Allocation.Region.height *= TexCache.Granularity; + Region.x *= m_Granularity; + Region.y *= m_Granularity; + Region.width *= m_Granularity; + Region.height *= m_Granularity; + + return RefCntAutoPtr{ + MakeNewRCObj()( + RefCntAutoPtr{&m_Owner}, + *this, + std::move(Region) // + ) // + }; + } + else + { + // TODO: handle resize + return RefCntAutoPtr{}; } - return Allocation; } -void GLTFResourceManager::FreeTextureSpace(TextureAllocation&& Allocation) +void GLTFResourceManager::TextureCache::FreeAllocation(DynamicAtlasManager::Region&& Allocation) { - VERIFY_EXPR(Allocation.IsValid()); + VERIFY((Allocation.x % m_Granularity) == 0, "Allocation x (", Allocation.x, ") is not multiple of granularity (", m_Granularity, ")"); + VERIFY((Allocation.y % m_Granularity) == 0, "Allocation y (", Allocation.y, ") is not multiple of granularity (", m_Granularity, ")"); + VERIFY((Allocation.width % m_Granularity) == 0, "Allocation width (", Allocation.width, ") is not multiple of granularity (", m_Granularity, ")"); + VERIFY((Allocation.height % m_Granularity) == 0, "Allocation height (", Allocation.height, ") is not multiple of granularity (", m_Granularity, ")"); + + Allocation.x /= m_Granularity; + Allocation.y /= m_Granularity; + Allocation.width /= m_Granularity; + Allocation.height /= m_Granularity; + + std::lock_guard Lock{m_Mtx}; + m_Mgr.Free(std::move(Allocation)); +} - auto& TexCache = m_Textures[Allocation.TextureIndex]; - auto& Region = Allocation.Region; - DEV_CHECK_ERR((Region.x % TexCache.Granularity) == 0, "Allocation x (", Region.x, ") is not multiple of granularity (", TexCache.Granularity, ")"); - DEV_CHECK_ERR((Region.y % TexCache.Granularity) == 0, "Allocation y (", Region.y, ") is not multiple of granularity (", TexCache.Granularity, ")"); - DEV_CHECK_ERR((Region.width % TexCache.Granularity) == 0, "Allocation width (", Region.width, ") is not multiple of granularity (", TexCache.Granularity, ")"); - DEV_CHECK_ERR((Region.height % TexCache.Granularity) == 0, "Allocation height (", Region.height, ") is not multiple of granularity (", TexCache.Granularity, ")"); - Region.x /= TexCache.Granularity; - Region.y /= TexCache.Granularity; - Region.width /= TexCache.Granularity; - Region.height /= TexCache.Granularity; +RefCntAutoPtr GLTFResourceManager::Create(IRenderDevice* pDevice, + const CreateInfo& CI) +{ + return RefCntAutoPtr{MakeNewRCObj()(pDevice, CI)}; +} - std::lock_guard Lock{TexCache.Mtx}; - TexCache.Mgr.Free(std::move(Region)); +GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters, + IRenderDevice* pDevice, + const CreateInfo& CI) : + TBase{pRefCounters} +{ + m_Buffers.reserve(CI.NumBuffers); + for (Uint32 i = 0; i < CI.NumBuffers; ++i) + { + m_Buffers.emplace_back(*this, pDevice, CI.Buffers[i]); + } + + m_Textures.reserve(CI.NumTextures); + for (Uint32 i = 0; i < CI.NumTextures; ++i) + { + m_Textures.emplace_back(*this, pDevice, CI.Textures[i]); + } } } // namespace Diligent -- cgit v1.2.3