3030// / \file
3131// / Defines Diligent::ResourceManager class implementing GLTF resource manager.
3232
33- #include < mutex >
33+ #include < shared_mutex >
3434#include < vector>
3535#include < unordered_map>
3636#include < atomic>
@@ -100,10 +100,6 @@ class ResourceManager final : public ObjectBase<IObject>
100100 {
101101 return Elements != rhs.Elements ;
102102 }
103- explicit operator bool () const
104- {
105- return Elements.empty ();
106- }
107103
108104 struct Hasher
109105 {
@@ -178,16 +174,25 @@ class ResourceManager final : public ObjectBase<IObject>
178174 // / If the texture atlas for the given format does not exist and if the default
179175 // / atlas description allows creating new atlases (Desc.Type != Diligent::RESOURCE_DIM_UNDEFINED),
180176 // / new atlas will be added. Otherwise, the function will return null.
177+ // /
178+ // / The function is thread-safe and can be called from multiple threads simultaneously and
179+ // / in parallel with other thread-safe class methods.
181180 RefCntAutoPtr<ITextureAtlasSuballocation> AllocateTextureSpace (TEXTURE_FORMAT Fmt,
182181 Uint32 Width,
183182 Uint32 Height,
184183 const char * CacheId = nullptr ,
185184 IObject* pUserData = nullptr );
186185
187186 // / Finds texture allocation in the texture atlas that matches the specified cache ID.
187+ // /
188+ // / The function is thread-safe and can be called from multiple threads simultaneously and
189+ // / in parallel with other thread-safe class methods.
188190 RefCntAutoPtr<ITextureAtlasSuballocation> FindTextureAllocation (const char * CacheId);
189191
190192 // / Allocates indices in the index buffer.
193+ // /
194+ // / The function is thread-safe and can be called from multiple threads simultaneously and
195+ // / in parallel with other thread-safe class methods.
191196 RefCntAutoPtr<IBufferSuballocation> AllocateIndices (Uint32 Size, Uint32 Alignment = 4 );
192197
193198 // / Allocates vertices in the vertex pool that matches the specified layout.
@@ -205,35 +210,65 @@ class ResourceManager final : public ObjectBase<IObject>
205210 // / If no pull exists for the given key and the default
206211 // / pool description does not allow creating new pools
207212 // / (VertexCount == 0), the function returns null.
213+ // /
214+ // / The function is thread-safe and can be called from multiple threads simultaneously and
215+ // / in parallel with other thread-safe class methods.
208216 RefCntAutoPtr<IVertexPoolAllocation> AllocateVertices (const VertexLayoutKey& LayoutKey, Uint32 VertexCount);
209217
210218
211219 // / Returns the combined texture atlas version, i.e. the sum of the texture versions of all
212220 // / atlases.
221+ // /
222+ // / The function is thread-safe and can be called from multiple threads simultaneously and
223+ // / in parallel with other thread-safe class methods.
213224 Uint32 GetTextureVersion () const ;
214225
215226 // / Returns the index buffer version.
227+ // /
228+ // / The function is thread-safe and can be called from multiple threads simultaneously and
229+ // / in parallel with other thread-safe class methods.
216230 Uint32 GetIndexBufferVersion () const ;
217231
218232 // / Returns the combined vertex pool version, i.e. the sum all vertex pool versions.
233+ // /
234+ // / The function is thread-safe and can be called from multiple threads simultaneously and
235+ // / in parallel with other thread-safe class methods.
219236 Uint32 GetVertexPoolsVersion () const ;
220237
221238 // / Updates the index buffer, if necessary.
239+ // /
240+ // / The function is not thread-safe, but can be called in parallel
241+ // / with other thread-safe class methods.
222242 IBuffer* UpdateIndexBuffer (IRenderDevice* pDevice, IDeviceContext* pContext, Uint32 Index = 0 );
223243
224244 // / Updates all index buffers.
245+ // /
246+ // / The function is not thread-safe, but can be called in parallel
247+ // / with other thread-safe class methods.
225248 void UpdateIndexBuffers (IRenderDevice* pDevice, IDeviceContext* pContext);
226249
227250 // / Returns the number of index buffers.
251+ // /
252+ // / The function is thread-safe and can be called from multiple threads simultaneously and
253+ // / in parallel with other thread-safe class methods.
228254 size_t GetIndexBufferCount () const ;
229255
230256 // / Returns the index allocator index.
257+ // /
258+ // / The function is thread-safe and can be called from multiple threads simultaneously and
259+ // / in parallel with other thread-safe class methods.
231260 Uint32 GetIndexAllocatorIndex (IBufferSuballocator* pAllocator) const ;
232261
233262 // / Updates the vertex buffers, if necessary.
263+ // /
264+ // / The function is not thread-safe, but can be called in parallel
265+ // / with other thread-safe class methods.
234266 void UpdateVertexBuffers (IRenderDevice* pDevice, IDeviceContext* pContext);
235267
236268 // / Returns a pointer to the index buffer.
269+ // /
270+ // / The function is thread-safe and can be called from multiple threads simultaneously and
271+ // / in parallel with other thread-safe class methods.
237272 IBuffer* GetIndexBuffer (Uint32 Index = 0 ) const ;
238273
239274 // / Returns a pointer to the vertex pool for the given key and index.
@@ -242,54 +277,94 @@ class ResourceManager final : public ObjectBase<IObject>
242277 // / If multiple vertex pools with the same key may exist,
243278 // / an application can use the GetVertexPools() method to
244279 // / get all pools for the given key.
280+ // /
281+ // / The function is thread-safe and can be called from multiple threads simultaneously and
282+ // / in parallel with other thread-safe class methods.
245283 IVertexPool* GetVertexPool (const VertexLayoutKey& Key, Uint32 Index = 0 );
246284
247285 // / Returns the number of vertex pools for the given key.
286+ // /
287+ // / The function is thread-safe and can be called from multiple threads simultaneously and
288+ // / in parallel with other thread-safe class methods.
248289 size_t GetVertexPoolCount (const VertexLayoutKey& Key) const ;
249290
250291 // / Returns all vertex pools for the given key.
292+ // /
293+ // / The function is thread-safe and can be called from multiple threads simultaneously and
294+ // / in parallel with other thread-safe class methods.
251295 std::vector<IVertexPool*> GetVertexPools (const VertexLayoutKey& Key) const ;
252296
253297 // / Returns index of the vertex pool with the give key.
254298 // / If the pool does not exist, InvalidIndex (0xFFFFFFFF) is returned.
299+ // /
300+ // / The function is thread-safe and can be called from multiple threads simultaneously and
301+ // / in parallel with other thread-safe class methods.
255302 Uint32 GetVertexPoolIndex (const VertexLayoutKey& Key, IVertexPool* pPool) const ;
256303
257304 // / Updates the atlas texture for the given format.
258305 // / If the atlas does not exist, null is returned.
306+ // /
307+ // / The function is not thread-safe, but can be called in parallel
308+ // / with other thread-safe class methods.
259309 ITexture* UpdateTexture (TEXTURE_FORMAT Fmt, IRenderDevice* pDevice, IDeviceContext* pContext);
260310
261311 // / Updates all atlas textures.
312+ // /
313+ // / The function is not thread-safe, but can be called in parallel
314+ // / with other thread-safe class methods.
262315 void UpdateTextures (IRenderDevice* pDevice, IDeviceContext* pContext);
263316
264317 // / Returns the atlas texture for the given format.
265318 // / If the atlas does not exist, null is returned.
319+ // /
320+ // / The function is thread-safe and can be called from multiple threads simultaneously and
321+ // / in parallel with other thread-safe class methods.
266322 ITexture* GetTexture (TEXTURE_FORMAT Fmt) const ;
267323
268324 // / Updates all vertex buffers, index buffer and atlas textures.
269325 // /
270326 // / This method is equivalent to calling UpdateIndexBuffer(),
271327 // / UpdateVertexBuffers() and UpdateTextures().
328+ // /
329+ // / The function is not thread-safe, but can be called in parallel
330+ // / with other thread-safe class methods.
272331 void UpdateAllResources (IRenderDevice* pDevice, IDeviceContext* pContext);
273332
333+ // / Returns the texture atlas description for the given format.
274334 // NB: can't return reference here!
335+ // /
336+ // / The function is thread-safe and can be called from multiple threads simultaneously and
337+ // / in parallel with other thread-safe class methods.
275338 TextureDesc GetAtlasDesc (TEXTURE_FORMAT Fmt);
276339
277340 // / Returns the texture atlas allocation alignment for the given format.
341+ // /
342+ // / The function is thread-safe and can be called from multiple threads simultaneously and
343+ // / in parallel with other thread-safe class methods.
278344 Uint32 GetAllocationAlignment (TEXTURE_FORMAT Fmt, Uint32 Width, Uint32 Height);
279345
280346 // / Returns the index buffer usage stats.
347+ // /
348+ // / The function is thread-safe and can be called from multiple threads simultaneously and
349+ // / in parallel with other thread-safe class methods.
281350 BufferSuballocatorUsageStats GetIndexBufferUsageStats ();
282351
283352 // / Returns the texture atlas usage stats.
284353
285354 // / If `fmt` is not Diligent::TEX_FORMAT_UNKNOWN, returns the stats for the atlas matching the specified format.
286355 // / Otherwise, returns the net usage stats for all atlases.
356+ // /
357+ // / The function is thread-safe and can be called from multiple threads simultaneously and
358+ // / in parallel with other thread-safe class methods.
287359 DynamicTextureAtlasUsageStats GetAtlasUsageStats (TEXTURE_FORMAT Fmt = TEX_FORMAT_UNKNOWN);
288360
289361 // / Returns the vertex pool usage stats.
290362
291363 // / If the key is not equal the default key, returns the stats for the vertex pool matching the key.
292364 // / Otherwise, returns the net usage stats for all pools.
365+ // /
366+ // / The function is thread-safe and can be called from multiple threads simultaneously and
367+ // / in parallel with other thread-safe class methods.
293368 VertexPoolUsageStats GetVertexPoolUsageStats (const VertexLayoutKey& Key = VertexLayoutKey{});
294369
295370 // / Parameters of the TransitionResourceStates() method.
@@ -362,10 +437,13 @@ class ResourceManager final : public ObjectBase<IObject>
362437 // / \param[in] pContext - Pointer to the device context.
363438 // / \param[in] Info - Resource state transition info, see Diligent::ResourceManager::TransitionResourceStatesInfo.
364439 // /
365- // / \remarks This function is thread-safe.
440+ // / This function is not thread-safe, but can be called in parallel with other thread-safe class methods .
366441 void TransitionResourceStates (IRenderDevice* pDevice, IDeviceContext* pContext, const TransitionResourceStatesInfo& Info);
367442
368443 // / Returns the formats of the allocated texture atlases.
444+ // /
445+ // / The function is thread-safe and can be called from multiple threads simultaneously and
446+ // / in parallel with other thread-safe class methods.
369447 std::vector<TEXTURE_FORMAT> GetAllocatedAtlasFormats () const ;
370448
371449private:
@@ -390,21 +468,24 @@ class ResourceManager final : public ObjectBase<IObject>
390468
391469 const BufferSuballocatorCreateInfo m_IndexAllocatorCI;
392470
393- mutable std::mutex m_IndexAllocatorsMtx;
471+ mutable std::shared_mutex m_IndexAllocatorsMtx;
394472 std::vector<RefCntAutoPtr<IBufferSuballocator>> m_IndexAllocators;
395473
396474 std::unordered_map<VertexLayoutKey, VertexPoolCreateInfoX, VertexLayoutKey::Hasher> m_VertexPoolCIs;
397475
398476 using VertexPoolsHashMapType = std::unordered_map<VertexLayoutKey, std::vector<RefCntAutoPtr<IVertexPool>>, VertexLayoutKey::Hasher>;
399- mutable std::mutex m_VertexPoolsMtx;
400- VertexPoolsHashMapType m_VertexPools;
477+ mutable std::shared_mutex m_VertexPoolsMtx;
478+ VertexPoolsHashMapType m_VertexPools;
401479
402480 using AtlasesHashMapType = std::unordered_map<TEXTURE_FORMAT, RefCntAutoPtr<IDynamicTextureAtlas>, std::hash<Uint32>>;
403- mutable std::mutex m_AtlasesMtx;
404- AtlasesHashMapType m_Atlases;
481+ mutable std::shared_mutex m_AtlasesMtx;
482+ AtlasesHashMapType m_Atlases;
483+
484+ std::vector<IDynamicTextureAtlas*> m_TmpAtlasList;
485+ std::vector<IVertexPool*> m_TmpVertexPoolList;
405486
406487 using TexAllocationsHashMapType = std::unordered_map<std::string, RefCntWeakPtr<ITextureAtlasSuballocation>>;
407- std::mutex m_TexAllocationsMtx;
488+ std::shared_mutex m_TexAllocationsMtx;
408489 TexAllocationsHashMapType m_TexAllocations;
409490
410491 std::vector<StateTransitionDesc> m_Barriers;
0 commit comments