@@ -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
216263RefCntAutoPtr<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+
347395ITexture* 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