diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-12-05 17:19:28 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-12-05 17:19:28 +0000 |
| commit | e3bad5a7fcedc170a10aed3ee644310ec8c982fe (patch) | |
| tree | 1ebedbfb4a1a415bc9615ded4f46fa1e8e694fc6 /AssetLoader/src/GLTFResourceManager.cpp | |
| parent | GLTF Loader: fixed names of Material::ALPHA_MODE enum members (diff) | |
| download | DiligentTools-e3bad5a7fcedc170a10aed3ee644310ec8c982fe.tar.gz DiligentTools-e3bad5a7fcedc170a10aed3ee644310ec8c982fe.zip | |
GLTF Resource manager: implemented texture array resizing
Diffstat (limited to 'AssetLoader/src/GLTFResourceManager.cpp')
| -rw-r--r-- | AssetLoader/src/GLTFResourceManager.cpp | 188 |
1 files changed, 137 insertions, 51 deletions
diff --git a/AssetLoader/src/GLTFResourceManager.cpp b/AssetLoader/src/GLTFResourceManager.cpp index dc4febf..fa1008b 100644 --- a/AssetLoader/src/GLTFResourceManager.cpp +++ b/AssetLoader/src/GLTFResourceManager.cpp @@ -91,71 +91,139 @@ 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} + m_Attribs{CacheCI} { - m_TexDesc.Name = m_TexName.c_str(); + m_Attribs.Desc.Name = m_TexName.c_str(); - 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, ")"); + const auto& Desc = m_Attribs.Desc; + for (Uint32 slice = 0; slice < Desc.ArraySize; ++slice) + { + m_Slices.emplace_back(new SliceManager{Desc.Width / m_Attribs.Granularity, Desc.Height / m_Attribs.Granularity}); + } + + DEV_CHECK_ERR(IsPowerOfTwo(m_Attribs.Granularity), "Granularity (", m_Attribs.Granularity, ") must be a power of two"); + DEV_CHECK_ERR((Desc.Width % m_Attribs.Granularity) == 0, "Atlas width (", Desc.Width, ") is not multiple of granularity (", m_Attribs.Granularity, ")"); + DEV_CHECK_ERR((Desc.Height % m_Attribs.Granularity) == 0, "Atlas height (", Desc.Height, ") is not multiple of granularity (", m_Attribs.Granularity, ")"); - pDevice->CreateTexture(CacheCI.Desc, nullptr, &m_pTexture); + if (pDevice != nullptr) + { + pDevice->CreateTexture(Desc, nullptr, &m_pTexture); + } } ITexture* GLTFResourceManager::TextureCache::GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext) { - // TODO: handle resizes + RefCntAutoPtr<ITexture> pNewTexture; + { + std::lock_guard<std::mutex> Lock{m_SlicesMtx}; + if (!m_pTexture || m_pTexture->GetDesc().ArraySize < m_Slices.size()) + { + m_Attribs.Desc.ArraySize = static_cast<Uint32>(m_Slices.size()); + VERIFY_EXPR(pDevice != nullptr); + pDevice->CreateTexture(m_Attribs.Desc, nullptr, &pNewTexture); + } + if (pNewTexture) + { + if (m_pTexture) + { + const auto& OldDesc = m_pTexture->GetDesc(); + + CopyTextureAttribs CopyAttribs; + CopyAttribs.pSrcTexture = m_pTexture; + CopyAttribs.pDstTexture = pNewTexture; + CopyAttribs.SrcTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION; + CopyAttribs.DstTextureTransitionMode = RESOURCE_STATE_TRANSITION_MODE_TRANSITION; + + for (Uint32 slice = 0; slice < OldDesc.ArraySize; ++slice) + { + for (Uint32 mip = 0; mip < OldDesc.MipLevels; ++mip) + { + CopyAttribs.SrcSlice = slice; + CopyAttribs.DstSlice = slice; + CopyAttribs.SrcMipLevel = mip; + CopyAttribs.DstMipLevel = mip; + pContext->CopyTexture(CopyAttribs); + } + } + } + m_pTexture = std::move(pNewTexture); + m_Owner.m_ResourceVersion.fetch_add(1); + } + } + return m_pTexture; } RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::TextureCache::Allocate(Uint32 Width, Uint32 Height) { VERIFY_EXPR(Width > 0 && Height > 0); - - std::lock_guard<std::mutex> Lock{m_Mtx}; - - auto Region = m_Mgr.Allocate((Width + m_Granularity - 1) / m_Granularity, (Height + m_Granularity - 1) / m_Granularity); - if (!Region.IsEmpty()) + const auto& TexDesc = m_Attribs.Desc; + if (Width > TexDesc.Width || Height > TexDesc.Height) { - Region.x *= m_Granularity; - Region.y *= m_Granularity; - Region.width *= m_Granularity; - Region.height *= m_Granularity; - - return RefCntAutoPtr<TextureAllocation>{ - MakeNewRCObj<TextureAllocation>()( - RefCntAutoPtr<GLTFResourceManager>{&m_Owner}, - *this, - Width, - Height, - std::move(Region) // - ) // - }; + LOG_ERROR_MESSAGE("Requested size ", Width, " x ", Height, " exceeds the texture size ", TexDesc.Width, " x ", TexDesc.Height); + return {}; } - else + + const auto Granularity = m_Attribs.Granularity; + for (Uint32 Slice = 0; Slice < m_Attribs.MaxSlices; ++Slice) { - // TODO: handle resize - return RefCntAutoPtr<TextureAllocation>{}; + SliceManager* pSliceMgr = nullptr; + { + std::lock_guard<std::mutex> Lock{m_SlicesMtx}; + if (Slice == m_Slices.size()) + { + for (Uint32 ExtraSlice = 0; ExtraSlice < m_Attribs.ExtraSliceCount && Slice + ExtraSlice < m_Attribs.MaxSlices; ++ExtraSlice) + { + m_Slices.emplace_back(new SliceManager{TexDesc.Width / Granularity, TexDesc.Height / Granularity}); + } + } + pSliceMgr = m_Slices[Slice].get(); + } + + auto Region = pSliceMgr->Allocate((Width + Granularity - 1) / Granularity, (Height + Granularity - 1) / Granularity); + if (!Region.IsEmpty()) + { + Region.x *= Granularity; + Region.y *= Granularity; + Region.width *= Granularity; + Region.height *= Granularity; + + return RefCntAutoPtr<TextureAllocation>{ + MakeNewRCObj<TextureAllocation>()( + RefCntAutoPtr<GLTFResourceManager>{&m_Owner}, + *this, + Width, + Height, + Slice, + std::move(Region) // + ) // + }; + } } + + return RefCntAutoPtr<TextureAllocation>{}; } -void GLTFResourceManager::TextureCache::FreeAllocation(DynamicAtlasManager::Region&& Allocation) +void GLTFResourceManager::TextureCache::FreeAllocation(Uint32 Slice, DynamicAtlasManager::Region&& Allocation) { - 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<std::mutex> Lock{m_Mtx}; - m_Mgr.Free(std::move(Allocation)); + const auto Granularity = m_Attribs.Granularity; + VERIFY((Allocation.x % Granularity) == 0, "Allocation x (", Allocation.x, ") is not multiple of granularity (", Granularity, ")"); + VERIFY((Allocation.y % Granularity) == 0, "Allocation y (", Allocation.y, ") is not multiple of granularity (", Granularity, ")"); + VERIFY((Allocation.width % Granularity) == 0, "Allocation width (", Allocation.width, ") is not multiple of granularity (", Granularity, ")"); + VERIFY((Allocation.height % Granularity) == 0, "Allocation height (", Allocation.height, ") is not multiple of granularity (", Granularity, ")"); + + Allocation.x /= Granularity; + Allocation.y /= Granularity; + Allocation.width /= Granularity; + Allocation.height /= Granularity; + + SliceManager* pSliceMgr = nullptr; + { + std::lock_guard<std::mutex> Lock{m_SlicesMtx}; + pSliceMgr = m_Slices[Slice].get(); + } + pSliceMgr->Free(std::move(Allocation)); } @@ -169,7 +237,9 @@ RefCntAutoPtr<GLTFResourceManager> GLTFResourceManager::Create(IRenderDevice* GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters, IRenderDevice* pDevice, const CreateInfo& CI) : - TBase{pRefCounters} + TBase{pRefCounters}, + m_DefaultTexDesc{CI.DefaultTexDesc}, + m_DefaultExtraSliceCount{CI.DefaultExtraSliceCount} { m_Buffers.reserve(CI.NumBuffers); for (Uint32 i = 0; i < CI.NumBuffers; ++i) @@ -180,7 +250,7 @@ GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters, m_Textures.reserve(CI.NumTextures); for (Uint32 i = 0; i < CI.NumTextures; ++i) { - m_Textures.emplace_back(*this, pDevice, CI.Textures[i]); + m_Textures.emplace(CI.Textures[i].Desc.Format, TextureCache{*this, pDevice, CI.Textures[i]}); } } @@ -202,10 +272,10 @@ RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::FindA } RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::AllocateTextureSpace( - Uint32 TextureIndex, - Uint32 Width, - Uint32 Height, - const char* CacheId) + TEXTURE_FORMAT Fmt, + Uint32 Width, + Uint32 Height, + const char* CacheId) { RefCntAutoPtr<TextureAllocation> pAllocation; if (CacheId != nullptr && *CacheId != 0) @@ -215,7 +285,23 @@ RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::Alloc if (!pAllocation) { - pAllocation = m_Textures[TextureIndex].Allocate(Width, Height); + decltype(m_Textures)::iterator cache_it; // NB: can't initialize it without locking the mutex + { + std::lock_guard<std::mutex> Lock{m_TexturesMtx}; + cache_it = m_Textures.find(Fmt); + if (cache_it == m_Textures.end()) + { + TextureCacheAttribs NewCacheAttribs; + NewCacheAttribs.Desc = m_DefaultTexDesc; + + NewCacheAttribs.Desc.Name = "GLTF Texture cache"; + NewCacheAttribs.Desc.Format = Fmt; + + cache_it = m_Textures.emplace(Fmt, TextureCache{*this, nullptr, NewCacheAttribs}).first; + } + } + // Allocate outside of mutex + pAllocation = cache_it->second.Allocate(Width, Height); } if (CacheId != nullptr && *CacheId != 0) |
