Skip to content

Commit aec1fce

Browse files
GLTF Resource Manager: enabled support of multiple vertex pools
1 parent e91fdd7 commit aec1fce

File tree

2 files changed

+118
-50
lines changed

2 files changed

+118
-50
lines changed

AssetLoader/interface/GLTFResourceManager.hpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
#include "../../../DiligentCore/Common/interface/ObjectBase.hpp"
3939
#include "../../../DiligentCore/Graphics/GraphicsTools/interface/BufferSuballocator.h"
4040
#include "../../../DiligentCore/Graphics/GraphicsTools/interface/DynamicTextureAtlas.h"
41-
#include "../../../DiligentCore/Graphics/GraphicsTools/interface/VertexPool.h"
41+
#include "../../../DiligentCore/Graphics/GraphicsTools/interface/VertexPoolX.hpp"
4242

4343
namespace Diligent
4444
{
@@ -191,7 +191,13 @@ class ResourceManager final : public ObjectBase<IObject>
191191
/// \remarks If the vertex pool for the given key does not exist and if the default
192192
/// pool description allows creating new pools (VertexCount != 0),
193193
/// new pool will be added.
194-
/// Otherwise, the function will return null.
194+
///
195+
/// If existing pools run out of space, a new vertex pool will be created and
196+
/// vertices will be allocated from this pool.
197+
///
198+
/// If no pull exists for the given key and the default
199+
/// pool description does not allow creating new pools
200+
/// (VertexCount == 0), the function returns null.
195201
RefCntAutoPtr<IVertexPoolAllocation> AllocateVertices(const VertexLayoutKey& LayoutKey, Uint32 VertexCount);
196202

197203

@@ -216,8 +222,17 @@ class ResourceManager final : public ObjectBase<IObject>
216222

217223
/// Returns a pointer to the vertex pool for the given key.
218224
/// If the pool does not exist, null is returned.
225+
///
226+
/// \remarks If there are multiple vertex pools for the same key,
227+
/// any pool may be returned. An application should use
228+
/// GetVertexPools() to get all pools for the given key
229+
/// if it expects that multiple pools may exist.
219230
IVertexPool* GetVertexPool(const VertexLayoutKey& Key);
220231

232+
/// Returns all vertex pools for the given key.
233+
std::vector<IVertexPool*> GetVertexPools(const VertexLayoutKey& Key);
234+
235+
221236
/// Updates the atlas texture for the given format.
222237
/// If the atlas does not exist, null is returned.
223238
ITexture* UpdateTexture(TEXTURE_FORMAT Fmt, IRenderDevice* pDevice, IDeviceContext* pContext);
@@ -325,6 +340,9 @@ class ResourceManager final : public ObjectBase<IObject>
325340
IRenderDevice* pDevice,
326341
const CreateInfo& CI);
327342

343+
RefCntAutoPtr<IVertexPool> CreateVertexPoolForLayout(const VertexLayoutKey& Key) const;
344+
345+
private:
328346
const RENDER_DEVICE_TYPE m_DeviceType;
329347

330348
const std::string m_DefaultVertPoolName;
@@ -335,7 +353,9 @@ class ResourceManager final : public ObjectBase<IObject>
335353

336354
RefCntAutoPtr<IBufferSuballocator> m_pIndexBufferAllocator;
337355

338-
using VertexPoolsHashMapType = std::unordered_map<VertexLayoutKey, RefCntAutoPtr<IVertexPool>, VertexLayoutKey::Hasher>;
356+
std::unordered_map<VertexLayoutKey, VertexPoolCreateInfoX, VertexLayoutKey::Hasher> m_VertexPoolCIs;
357+
358+
using VertexPoolsHashMapType = std::unordered_multimap<VertexLayoutKey, RefCntAutoPtr<IVertexPool>, VertexLayoutKey::Hasher>;
339359
std::mutex m_VertexPoolsMtx;
340360
VertexPoolsHashMapType m_VertexPools;
341361

AssetLoader/src/GLTFResourceManager.cpp

Lines changed: 95 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,11 @@ ResourceManager::ResourceManager(IReferenceCounters* pRefCounters,
8585
}
8686

8787
m_VertexPools.reserve(CI.NumVertexPools);
88+
m_VertexPoolCIs.reserve(CI.NumVertexPools);
8889
for (Uint32 pool = 0; pool < CI.NumVertexPools; ++pool)
8990
{
9091
const auto& PoolCI = CI.pVertexPoolCIs[pool];
9192

92-
RefCntAutoPtr<IVertexPool> pVtxPool;
93-
CreateVertexPool(pDevice, PoolCI, &pVtxPool);
94-
VERIFY_EXPR(pVtxPool);
95-
9693
VertexLayoutKey Key;
9794
Key.Elements.reserve(PoolCI.Desc.NumElements);
9895
for (size_t i = 0; i < PoolCI.Desc.NumElements; ++i)
@@ -101,8 +98,15 @@ ResourceManager::ResourceManager(IReferenceCounters* pRefCounters,
10198
Key.Elements.emplace_back(PoolElem.Size, PoolElem.BindFlags);
10299
}
103100

104-
if (!m_VertexPools.emplace(Key, std::move(pVtxPool)).second)
101+
if (!m_VertexPoolCIs.emplace(Key, PoolCI).second)
105102
LOG_ERROR_AND_THROW("Different vertex pools with the same layout key are not allowed.");
103+
104+
RefCntAutoPtr<IVertexPool> pVtxPool;
105+
CreateVertexPool(pDevice, PoolCI, &pVtxPool);
106+
VERIFY_EXPR(pVtxPool);
107+
108+
m_VertexPools.emplace(Key, std::move(pVtxPool));
109+
VERIFY_EXPR(m_VertexPools.count(Key) == 1);
106110
}
107111

108112
m_Atlases.reserve(CI.NumTexAtlases);
@@ -212,6 +216,49 @@ RefCntAutoPtr<IBufferSuballocation> ResourceManager::AllocateIndices(Uint32 Size
212216
return pIndices;
213217
}
214218

219+
RefCntAutoPtr<IVertexPool> ResourceManager::CreateVertexPoolForLayout(const VertexLayoutKey& Key) const
220+
{
221+
RefCntAutoPtr<IVertexPool> pVtxPool;
222+
223+
auto pool_ci_it = m_VertexPoolCIs.find(Key);
224+
if (pool_ci_it != m_VertexPoolCIs.end())
225+
{
226+
// Create additional vertex pool using the existing CI.
227+
CreateVertexPool(nullptr, pool_ci_it->second, &pVtxPool);
228+
DEV_CHECK_ERR(pVtxPool, "Failed to create vertex pool");
229+
}
230+
else if (m_DefaultVertPoolDesc.VertexCount != 0)
231+
{
232+
// Create additional vertex pool using the default CI.
233+
VertexPoolCreateInfo PoolCI;
234+
PoolCI.Desc.Name = m_DefaultVertPoolDesc.Name;
235+
PoolCI.Desc.VertexCount = m_DefaultVertPoolDesc.VertexCount;
236+
237+
std::vector<VertexPoolElementDesc> PoolElems(Key.Elements.size());
238+
for (size_t i = 0; i < PoolElems.size(); ++i)
239+
{
240+
auto& ElemDesc = PoolElems[i];
241+
242+
ElemDesc.Size = Key.Elements[i].Size;
243+
ElemDesc.BindFlags = Key.Elements[i].BindFlags;
244+
ElemDesc.Usage = m_DefaultVertPoolDesc.Usage;
245+
ElemDesc.CPUAccessFlags = m_DefaultVertPoolDesc.CPUAccessFlags;
246+
ElemDesc.Mode = m_DefaultVertPoolDesc.Mode;
247+
if (ElemDesc.Usage == USAGE_SPARSE && (ElemDesc.BindFlags & (BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER)) != 0 && m_DeviceType == RENDER_DEVICE_TYPE_D3D11)
248+
{
249+
// Direct3D11 does not support sparse vertex or index buffers
250+
ElemDesc.Usage = USAGE_DEFAULT;
251+
}
252+
}
253+
PoolCI.Desc.NumElements = static_cast<Uint32>(PoolElems.size());
254+
PoolCI.Desc.pElements = PoolElems.data();
255+
256+
CreateVertexPool(nullptr, PoolCI, &pVtxPool);
257+
DEV_CHECK_ERR(pVtxPool, "Failed to create vertex pool");
258+
}
259+
260+
return pVtxPool;
261+
}
215262

216263
RefCntAutoPtr<IVertexPoolAllocation> ResourceManager::AllocateVertices(const VertexLayoutKey& LayoutKey, Uint32 VertexCount)
217264
{
@@ -224,59 +271,47 @@ RefCntAutoPtr<IVertexPoolAllocation> ResourceManager::AllocateVertices(const Ver
224271
}
225272
#endif
226273

227-
decltype(m_VertexPools)::iterator pool_it; // NB: can't initialize it without locking the mutex
274+
std::vector<IVertexPool*> Pools;
275+
276+
static constexpr size_t LuckyAttemptCount = 7;
277+
for (size_t attempt = 0; attempt < LuckyAttemptCount; ++attempt)
228278
{
229-
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
230-
pool_it = m_VertexPools.find(LayoutKey);
231-
if (pool_it == m_VertexPools.end())
279+
// Collect all vertex pools for this key
232280
{
233-
if (m_DefaultVertPoolDesc.VertexCount == 0)
234-
{
235-
// Creating additional vertex pools is not allowed.
236-
return {};
237-
}
238-
239-
VertexPoolCreateInfo PoolCI;
240-
PoolCI.Desc.Name = m_DefaultVertPoolDesc.Name;
241-
PoolCI.Desc.VertexCount = m_DefaultVertPoolDesc.VertexCount;
281+
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
242282

243-
std::vector<VertexPoolElementDesc> PoolElems(LayoutKey.Elements.size());
244-
for (size_t i = 0; i < PoolElems.size(); ++i)
283+
const size_t PoolCount = m_VertexPools.count(LayoutKey);
284+
VERIFY_EXPR(PoolCount >= Pools.size());
285+
if (PoolCount == Pools.size())
245286
{
246-
auto& ElemDesc = PoolElems[i];
247-
248-
ElemDesc.Size = LayoutKey.Elements[i].Size;
249-
ElemDesc.BindFlags = LayoutKey.Elements[i].BindFlags;
250-
ElemDesc.Usage = m_DefaultVertPoolDesc.Usage;
251-
ElemDesc.CPUAccessFlags = m_DefaultVertPoolDesc.CPUAccessFlags;
252-
ElemDesc.Mode = m_DefaultVertPoolDesc.Mode;
253-
if (ElemDesc.Usage == USAGE_SPARSE && (ElemDesc.BindFlags & (BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER)) != 0 && m_DeviceType == RENDER_DEVICE_TYPE_D3D11)
287+
// All pools have been checked or there is no pool for the key. Add a new pool.
288+
if (RefCntAutoPtr<IVertexPool> pNewVtxPool = CreateVertexPoolForLayout(LayoutKey))
254289
{
255-
// Direct3D11 does not support sparse vertex or index buffers
256-
ElemDesc.Usage = USAGE_DEFAULT;
290+
m_VertexPools.emplace(LayoutKey, std::move(pNewVtxPool));
291+
}
292+
else
293+
{
294+
return {};
257295
}
258296
}
259-
PoolCI.Desc.NumElements = static_cast<Uint32>(PoolElems.size());
260-
PoolCI.Desc.pElements = PoolElems.data();
261297

262-
RefCntAutoPtr<IVertexPool> pVtxPool;
263-
CreateVertexPool(nullptr, PoolCI, &pVtxPool);
264-
if (pVtxPool)
265-
{
266-
pool_it = m_VertexPools.emplace(LayoutKey, std::move(pVtxPool)).first;
267-
}
268-
else
269-
{
270-
DEV_ERROR("Failed to create new vertex pool");
271-
return {};
272-
}
298+
auto range_it = m_VertexPools.equal_range(LayoutKey);
299+
Pools.clear();
300+
for (auto pool_it = range_it.first; pool_it != range_it.second; ++pool_it)
301+
Pools.emplace_back(pool_it->second);
302+
}
303+
304+
// Unlock the vertex pools mutex and try allocating from each pool
305+
for (IVertexPool* pPool : Pools)
306+
{
307+
RefCntAutoPtr<IVertexPoolAllocation> pVertices;
308+
pPool->Allocate(VertexCount, &pVertices);
309+
if (pVertices)
310+
return pVertices;
273311
}
274312
}
275313

276-
// Allocate outside of the mutex lock
277-
RefCntAutoPtr<IVertexPoolAllocation> pVertices;
278-
pool_it->second->Allocate(VertexCount, &pVertices);
279-
return pVertices;
314+
return {};
280315
}
281316

282317

@@ -344,6 +379,19 @@ IVertexPool* ResourceManager::GetVertexPool(const VertexLayoutKey& Key)
344379
return pool_it->second;
345380
}
346381

382+
std::vector<IVertexPool*> ResourceManager::GetVertexPools(const VertexLayoutKey& Key)
383+
{
384+
std::vector<IVertexPool*> Pools;
385+
{
386+
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
387+
388+
auto range_it = m_VertexPools.equal_range(Key);
389+
for (auto pool_it = range_it.first; pool_it != range_it.second; ++pool_it)
390+
Pools.emplace_back(pool_it->second);
391+
}
392+
return Pools;
393+
}
394+
347395
ITexture* ResourceManager::UpdateTexture(TEXTURE_FORMAT Fmt, IRenderDevice* pDevice, IDeviceContext* pContext)
348396
{
349397
decltype(m_Atlases)::iterator cache_it; // NB: can't initialize it without locking the mutex

0 commit comments

Comments
 (0)