summaryrefslogtreecommitdiffstats
path: root/AssetLoader/src/GLTFResourceManager.cpp
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-12-09 02:48:28 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-12-09 02:48:28 +0000
commit60ce41d5b736dbb7c5799897bdadfc2a34d6c16a (patch)
treeeaa25323ad47521d745a1a354754ed99907c6d38 /AssetLoader/src/GLTFResourceManager.cpp
parentGLTF Loader: enabled caching compressed textures (diff)
downloadDiligentTools-60ce41d5b736dbb7c5799897bdadfc2a34d6c16a.tar.gz
DiligentTools-60ce41d5b736dbb7c5799897bdadfc2a34d6c16a.zip
Reworked GLTF resource manager to use BufferSuballocator and DynamicTextureAtlas
Diffstat (limited to 'AssetLoader/src/GLTFResourceManager.cpp')
-rw-r--r--AssetLoader/src/GLTFResourceManager.cpp274
1 files changed, 46 insertions, 228 deletions
diff --git a/AssetLoader/src/GLTFResourceManager.cpp b/AssetLoader/src/GLTFResourceManager.cpp
index e9b37a3..a30e265 100644
--- a/AssetLoader/src/GLTFResourceManager.cpp
+++ b/AssetLoader/src/GLTFResourceManager.cpp
@@ -28,256 +28,67 @@
#include "GLTFResourceManager.hpp"
#include "DefaultRawMemoryAllocator.hpp"
#include "Align.hpp"
+#include "GraphicsAccessories.hpp"
namespace Diligent
{
-GLTFResourceManager::BufferCache::BufferCache(GLTFResourceManager& Owner,
- IRenderDevice* pDevice,
- const BufferDesc& BuffDesc) :
- m_Owner{Owner},
- m_Mgr{BuffDesc.uiSizeInBytes, DefaultRawMemoryAllocator::GetAllocator()}
+namespace GLTF
{
- pDevice->CreateBuffer(BuffDesc, nullptr, &m_pBuffer);
-}
-
-IBuffer* GLTFResourceManager::BufferCache::GetBuffer(IRenderDevice* pDevice, IDeviceContext* pContext)
-{
- std::lock_guard<std::mutex> Lock{m_Mtx};
-
- const auto& BuffDesc = m_pBuffer->GetDesc();
- const auto MgrSize = m_Mgr.GetMaxSize();
- if (BuffDesc.uiSizeInBytes < MgrSize)
- {
- // Extend the buffer
- auto NewBuffDesc = BuffDesc;
-
- NewBuffDesc.uiSizeInBytes = static_cast<Uint32>(MgrSize);
-
- RefCntAutoPtr<IBuffer> 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_pBuffer = std::move(pNewBuffer);
- }
-
- return m_pBuffer.RawPtr();
-}
-
-RefCntAutoPtr<GLTFResourceManager::BufferAllocation> GLTFResourceManager::BufferCache::Allocate(Uint32 Size, Uint32 Alignment)
-{
- VERIFY_EXPR(Size > 0 && IsPowerOfTwo(Alignment));
-
- std::lock_guard<std::mutex> Lock{m_Mtx};
-
- auto Region = m_Mgr.Allocate(Size, Alignment);
- while (!Region.IsValid())
- {
- m_Mgr.Extend(m_Mgr.GetMaxSize());
- Region = m_Mgr.Allocate(Size, Alignment);
- }
-
- return RefCntAutoPtr<BufferAllocation>{
- MakeNewRCObj<BufferAllocation>()(
- RefCntAutoPtr<GLTFResourceManager>{&m_Owner},
- *this,
- std::move(Region) //
- ) //
- };
-}
-
-GLTFResourceManager::TextureCache::TextureCache(GLTFResourceManager& Owner,
- IRenderDevice* pDevice,
- const TextureCacheAttribs& CacheCI) :
- m_Owner{Owner},
- m_Attribs{CacheCI}
-{
- m_Attribs.Desc.Name = m_TexName.c_str();
-
- 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, ")");
-
- if (pDevice != nullptr)
- {
- pDevice->CreateTexture(Desc, nullptr, &m_pTexture);
- }
-}
-
-
-ITexture* GLTFResourceManager::TextureCache::GetTexture(IRenderDevice* pDevice, IDeviceContext* pContext)
-{
- 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);
- const auto& TexDesc = m_Attribs.Desc;
- if (Width > TexDesc.Width || Height > TexDesc.Height)
- {
- LOG_ERROR_MESSAGE("Requested size ", Width, " x ", Height, " exceeds the texture size ", TexDesc.Width, " x ", TexDesc.Height);
- return {};
- }
-
- const auto Granularity = m_Attribs.Granularity;
- for (Uint32 Slice = 0; Slice < m_Attribs.MaxSlices; ++Slice)
- {
- 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(Uint32 Slice, DynamicAtlasManager::Region&& 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));
-}
-
-
-
-RefCntAutoPtr<GLTFResourceManager> GLTFResourceManager::Create(IRenderDevice* pDevice,
- const CreateInfo& CI)
+RefCntAutoPtr<ResourceManager> ResourceManager::Create(IRenderDevice* pDevice,
+ const CreateInfo& CI)
{
- return RefCntAutoPtr<GLTFResourceManager>{MakeNewRCObj<GLTFResourceManager>()(pDevice, CI)};
+ return RefCntAutoPtr<ResourceManager>{MakeNewRCObj<ResourceManager>()(pDevice, CI)};
}
-GLTFResourceManager::GLTFResourceManager(IReferenceCounters* pRefCounters,
- IRenderDevice* pDevice,
- const CreateInfo& CI) :
+ResourceManager::ResourceManager(IReferenceCounters* pRefCounters,
+ IRenderDevice* pDevice,
+ const CreateInfo& CI) :
TBase{pRefCounters},
- m_DefaultTexDesc{CI.DefaultTexDesc},
- m_DefaultExtraSliceCount{CI.DefaultExtraSliceCount}
+ m_DefaultAtlasDesc{CI.DefaultAtlasDesc},
+ m_DefaultAtlasName{CI.DefaultAtlasDesc.Desc.Name != nullptr ? CI.DefaultAtlasDesc.Desc.Name : "GLTF texture atlas"}
{
- m_Buffers.reserve(CI.NumBuffers);
- for (Uint32 i = 0; i < CI.NumBuffers; ++i)
+ m_DefaultAtlasDesc.Desc.Name = m_DefaultAtlasName.c_str();
+ m_BufferSuballocators.resize(CI.NumBuffSuballocators);
+ for (Uint32 i = 0; i < CI.NumBuffSuballocators; ++i)
{
- m_Buffers.emplace_back(*this, pDevice, CI.Buffers[i]);
+ CreateBufferSuballocator(pDevice, CI.BuffSuballocators[i], &m_BufferSuballocators[i]);
}
- m_Textures.reserve(CI.NumTextures);
- for (Uint32 i = 0; i < CI.NumTextures; ++i)
+ m_Atlases.reserve(CI.NumTexAtlases);
+ for (Uint32 i = 0; i < CI.NumTexAtlases; ++i)
{
- m_Textures.emplace(CI.Textures[i].Desc.Format, TextureCache{*this, pDevice, CI.Textures[i]});
+ RefCntAutoPtr<IDynamicTextureAtlas> pAtlas;
+ CreateDynamicTextureAtlas(pDevice, CI.TexAtlases[i], &pAtlas);
+ m_Atlases.emplace(CI.TexAtlases[i].Desc.Format, std::move(pAtlas));
}
}
-RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::FindAllocation(const char* CacheId)
+RefCntAutoPtr<ITextureAtlasSuballocation> ResourceManager::FindAllocation(const char* CacheId)
{
- RefCntAutoPtr<TextureAllocation> pAllocation;
+ RefCntAutoPtr<ITextureAtlasSuballocation> pAllocation;
- std::lock_guard<std::mutex> Lock{m_AllocationsMtx};
+ std::lock_guard<std::mutex> Lock{m_TexAllocationsMtx};
- auto it = m_Allocations.find(CacheId);
- if (it != m_Allocations.end())
+ auto it = m_TexAllocations.find(CacheId);
+ if (it != m_TexAllocations.end())
{
pAllocation = it->second.Lock();
if (!pAllocation)
- m_Allocations.erase(it);
+ m_TexAllocations.erase(it);
}
return pAllocation;
}
-RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::AllocateTextureSpace(
+RefCntAutoPtr<ITextureAtlasSuballocation> ResourceManager::AllocateTextureSpace(
TEXTURE_FORMAT Fmt,
Uint32 Width,
Uint32 Height,
const char* CacheId)
{
- RefCntAutoPtr<TextureAllocation> pAllocation;
+ RefCntAutoPtr<ITextureAtlasSuballocation> pAllocation;
if (CacheId != nullptr && *CacheId != 0)
{
pAllocation = FindAllocation(CacheId);
@@ -285,33 +96,40 @@ RefCntAutoPtr<GLTFResourceManager::TextureAllocation> GLTFResourceManager::Alloc
if (!pAllocation)
{
- decltype(m_Textures)::iterator cache_it; // NB: can't initialize it without locking the mutex
+ decltype(m_Atlases)::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())
+ std::lock_guard<std::mutex> Lock{m_AtlasesMtx};
+ cache_it = m_Atlases.find(Fmt);
+ if (cache_it == m_Atlases.end())
{
- DEV_CHECK_ERR(m_DefaultTexDesc.Width > 0 && m_DefaultTexDesc.Height > 0, "Default texture description is not initialized");
- TextureCacheAttribs NewCacheAttribs;
- NewCacheAttribs.Desc = m_DefaultTexDesc;
+ DEV_CHECK_ERR(m_DefaultAtlasDesc.Desc.Width > 0 &&
+ m_DefaultAtlasDesc.Desc.Height > 0 &&
+ m_DefaultAtlasDesc.Desc.Type != RESOURCE_DIM_UNDEFINED,
+ "Default texture description is not initialized");
- NewCacheAttribs.Desc.Name = "GLTF Texture cache";
- NewCacheAttribs.Desc.Format = Fmt;
+ auto AtalsCreateInfo = m_DefaultAtlasDesc;
+ AtalsCreateInfo.Desc.Format = Fmt;
- cache_it = m_Textures.emplace(Fmt, TextureCache{*this, nullptr, NewCacheAttribs}).first;
+ RefCntAutoPtr<IDynamicTextureAtlas> pAtlas;
+ CreateDynamicTextureAtlas(nullptr, AtalsCreateInfo, &pAtlas);
+ DEV_CHECK_ERR(pAtlas, "Failed to create new texture atlas");
+
+ cache_it = m_Atlases.emplace(Fmt, std::move(pAtlas)).first;
}
}
// Allocate outside of mutex
- pAllocation = cache_it->second.Allocate(Width, Height);
+ cache_it->second->Allocate(Width, Height, &pAllocation);
}
if (CacheId != nullptr && *CacheId != 0)
{
- auto inserted = m_Allocations.emplace(CacheId, pAllocation).second;
+ auto inserted = m_TexAllocations.emplace(CacheId, pAllocation).second;
VERIFY_EXPR(inserted);
}
return pAllocation;
}
+} // namespace GLTF
+
} // namespace Diligent