Skip to content

Commit f544b7a

Browse files
GLTF Resource Manager: reworked multiple vertex pools to use stable indices
1 parent aec1fce commit f544b7a

File tree

2 files changed

+80
-73
lines changed

2 files changed

+80
-73
lines changed

AssetLoader/interface/GLTFResourceManager.hpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,16 @@ class ResourceManager final : public ObjectBase<IObject>
220220
/// Returns a pointer to the index buffer.
221221
IBuffer* GetIndexBuffer() const;
222222

223-
/// Returns a pointer to the vertex pool for the given key.
223+
/// Returns a pointer to the vertex pool for the given key and index.
224224
/// If the pool does not exist, null is returned.
225225
///
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.
230-
IVertexPool* GetVertexPool(const VertexLayoutKey& Key);
226+
/// \remarks If multiple vertex pools with the same key may exist,
227+
/// an application can use the GetVertexPools() method to
228+
/// get all pools for the given key.
229+
IVertexPool* GetVertexPool(const VertexLayoutKey& Key, Uint32 Index = 0);
230+
231+
/// Returns the number of vertex pools for the given key.
232+
size_t GetVertexPoolCount(const VertexLayoutKey& Key);
231233

232234
/// Returns all vertex pools for the given key.
233235
std::vector<IVertexPool*> GetVertexPools(const VertexLayoutKey& Key);
@@ -355,7 +357,7 @@ class ResourceManager final : public ObjectBase<IObject>
355357

356358
std::unordered_map<VertexLayoutKey, VertexPoolCreateInfoX, VertexLayoutKey::Hasher> m_VertexPoolCIs;
357359

358-
using VertexPoolsHashMapType = std::unordered_multimap<VertexLayoutKey, RefCntAutoPtr<IVertexPool>, VertexLayoutKey::Hasher>;
360+
using VertexPoolsHashMapType = std::unordered_map<VertexLayoutKey, std::vector<RefCntAutoPtr<IVertexPool>>, VertexLayoutKey::Hasher>;
359361
std::mutex m_VertexPoolsMtx;
360362
VertexPoolsHashMapType m_VertexPools;
361363

AssetLoader/src/GLTFResourceManager.cpp

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ ResourceManager::ResourceManager(IReferenceCounters* pRefCounters,
105105
CreateVertexPool(pDevice, PoolCI, &pVtxPool);
106106
VERIFY_EXPR(pVtxPool);
107107

108-
m_VertexPools.emplace(Key, std::move(pVtxPool));
109-
VERIFY_EXPR(m_VertexPools.count(Key) == 1);
108+
m_VertexPools[Key].emplace_back(std::move(pVtxPool));
109+
VERIFY_EXPR(m_VertexPools[Key].size() == 1);
110110
}
111111

112112
m_Atlases.reserve(CI.NumTexAtlases);
@@ -271,47 +271,36 @@ RefCntAutoPtr<IVertexPoolAllocation> ResourceManager::AllocateVertices(const Ver
271271
}
272272
#endif
273273

274-
std::vector<IVertexPool*> Pools;
275-
276-
static constexpr size_t LuckyAttemptCount = 7;
277-
for (size_t attempt = 0; attempt < LuckyAttemptCount; ++attempt)
274+
RefCntAutoPtr<IVertexPoolAllocation> pVertices;
275+
for (Uint32 PoolIdx = 0; !pVertices; ++PoolIdx)
278276
{
279-
// Collect all vertex pools for this key
277+
IVertexPool* pPool = nullptr;
280278
{
281279
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
282280

283-
const size_t PoolCount = m_VertexPools.count(LayoutKey);
284-
VERIFY_EXPR(PoolCount >= Pools.size());
285-
if (PoolCount == Pools.size())
281+
auto pools_it = m_VertexPools.find(LayoutKey);
282+
if (pools_it != m_VertexPools.end() && PoolIdx < pools_it->second.size())
283+
{
284+
pPool = pools_it->second[PoolIdx];
285+
}
286+
else
286287
{
287288
// All pools have been checked or there is no pool for the key. Add a new pool.
288289
if (RefCntAutoPtr<IVertexPool> pNewVtxPool = CreateVertexPoolForLayout(LayoutKey))
289290
{
290-
m_VertexPools.emplace(LayoutKey, std::move(pNewVtxPool));
291-
}
292-
else
293-
{
294-
return {};
291+
pPool = pNewVtxPool;
292+
m_VertexPools[LayoutKey].push_back(std::move(pNewVtxPool));
295293
}
296294
}
297-
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);
302295
}
303296

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;
311-
}
297+
if (pPool == nullptr)
298+
break;
299+
300+
pPool->Allocate(VertexCount, &pVertices);
312301
}
313302

314-
return {};
303+
return pVertices;
315304
}
316305

317306

@@ -337,9 +326,11 @@ Uint32 ResourceManager::GetVertexPoolsVersion()
337326
Uint32 Version = 0;
338327

339328
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
340-
for (auto pool_it : m_VertexPools)
341-
Version += pool_it.second->GetVersion();
342-
329+
for (const auto& pools_it : m_VertexPools)
330+
{
331+
for (const auto& Pool : pools_it.second)
332+
Version += Pool->GetVersion();
333+
}
343334
return Version;
344335
}
345336

@@ -360,23 +351,30 @@ IBuffer* ResourceManager::GetIndexBuffer() const
360351
void ResourceManager::UpdateVertexBuffers(IRenderDevice* pDevice, IDeviceContext* pContext)
361352
{
362353
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
363-
for (auto pool_it : m_VertexPools)
354+
for (const auto& pools_it : m_VertexPools)
364355
{
365-
pool_it.second->UpdateAll(pDevice, pContext);
356+
for (const auto& Pool : pools_it.second)
357+
Pool->UpdateAll(pDevice, pContext);
366358
}
367359
}
368360

369-
IVertexPool* ResourceManager::GetVertexPool(const VertexLayoutKey& Key)
361+
IVertexPool* ResourceManager::GetVertexPool(const VertexLayoutKey& Key, Uint32 Index)
370362
{
371-
decltype(m_VertexPools)::iterator pool_it; // NB: can't initialize it without locking the mutex
372-
{
373-
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
374-
pool_it = m_VertexPools.find(Key);
375-
if (pool_it == m_VertexPools.end())
376-
return nullptr;
377-
}
363+
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
364+
365+
const auto pools_it = m_VertexPools.find(Key);
366+
if (pools_it != m_VertexPools.end())
367+
return Index < pools_it->second.size() ? pools_it->second[Index].RawPtr() : nullptr;
368+
else
369+
return nullptr;
370+
}
371+
372+
size_t ResourceManager::GetVertexPoolCount(const VertexLayoutKey& Key)
373+
{
374+
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
378375

379-
return pool_it->second;
376+
const auto pools_it = m_VertexPools.find(Key);
377+
return pools_it != m_VertexPools.end() ? pools_it->second.size() : 0;
380378
}
381379

382380
std::vector<IVertexPool*> ResourceManager::GetVertexPools(const VertexLayoutKey& Key)
@@ -385,9 +383,13 @@ std::vector<IVertexPool*> ResourceManager::GetVertexPools(const VertexLayoutKey&
385383
{
386384
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
387385

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);
386+
const auto pools_it = m_VertexPools.find(Key);
387+
if (pools_it != m_VertexPools.end())
388+
{
389+
Pools.reserve(pools_it->second.size());
390+
for (const auto& Pool : pools_it->second)
391+
Pools.emplace_back(Pool);
392+
}
391393
}
392394
return Pools;
393395
}
@@ -520,27 +522,28 @@ std::vector<TEXTURE_FORMAT> ResourceManager::GetAllocatedAtlasFormats() const
520522
VertexPoolUsageStats ResourceManager::GetVertexPoolUsageStats(const VertexLayoutKey& Key)
521523
{
522524
VertexPoolUsageStats Stats;
525+
526+
auto UpdateStats = [&Stats](const std::vector<RefCntAutoPtr<IVertexPool>>& Pools) {
527+
for (const auto& Pool : Pools)
528+
{
529+
VertexPoolUsageStats PoolStats;
530+
Pool->GetUsageStats(Stats);
531+
Stats += PoolStats;
532+
}
533+
};
534+
523535
{
524536
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
525537
if (Key != VertexLayoutKey{})
526538
{
527-
auto pool_it = m_VertexPools.find(Key);
528-
if (pool_it != m_VertexPools.end())
529-
pool_it->second->GetUsageStats(Stats);
539+
const auto pools_it = m_VertexPools.find(Key);
540+
if (pools_it != m_VertexPools.end())
541+
UpdateStats(pools_it->second);
530542
}
531543
else
532544
{
533-
for (auto it : m_VertexPools)
534-
{
535-
VertexPoolUsageStats PoolStats;
536-
it.second->GetUsageStats(PoolStats);
537-
538-
Stats.TotalVertexCount += PoolStats.TotalVertexCount;
539-
Stats.AllocatedVertexCount += PoolStats.AllocatedVertexCount;
540-
Stats.CommittedMemorySize += PoolStats.CommittedMemorySize;
541-
Stats.UsedMemorySize += PoolStats.UsedMemorySize;
542-
Stats.AllocationCount += PoolStats.AllocationCount;
543-
}
545+
for (const auto& it : m_VertexPools)
546+
UpdateStats(it.second);
544547
}
545548
}
546549

@@ -554,15 +557,17 @@ void ResourceManager::TransitionResourceStates(IRenderDevice* pDevice, IDeviceCo
554557
if (Info.VertexBuffers.NewState != RESOURCE_STATE_UNKNOWN)
555558
{
556559
std::lock_guard<std::mutex> Guard{m_VertexPoolsMtx};
557-
for (auto it : m_VertexPools)
560+
for (const auto& pools_it : m_VertexPools)
558561
{
559-
const auto& pPool = it.second;
560-
const auto& Desc = pPool->GetDesc();
561-
for (Uint32 elem = 0; elem < Desc.NumElements; ++elem)
562+
for (const auto& pPool : pools_it.second)
562563
{
563-
if (auto* pVertBuffer = pPool->Update(elem, pDevice, pContext))
564+
const auto& Desc = pPool->GetDesc();
565+
for (Uint32 elem = 0; elem < Desc.NumElements; ++elem)
564566
{
565-
m_Barriers.emplace_back(pVertBuffer, Info.VertexBuffers.OldState, Info.VertexBuffers.NewState, Info.VertexBuffers.Flags);
567+
if (auto* pVertBuffer = pPool->Update(elem, pDevice, pContext))
568+
{
569+
m_Barriers.emplace_back(pVertBuffer, Info.VertexBuffers.OldState, Info.VertexBuffers.NewState, Info.VertexBuffers.Flags);
570+
}
566571
}
567572
}
568573
}

0 commit comments

Comments
 (0)