[Bf-blender-cvs] [1c672f3d1da] master: Fix T103433: Ensure Metal memory allocator is safe for multi-threaded allocation. Resolves crash when baking indirect lighting.

Jason Fielder noreply at git.blender.org
Mon Jan 23 17:45:57 CET 2023


Commit: 1c672f3d1dae4f79d327c0fd38c440f3bf23d35c
Author: Jason Fielder
Date:   Mon Jan 23 17:40:44 2023 +0100
Branches: master
https://developer.blender.org/rB1c672f3d1dae4f79d327c0fd38c440f3bf23d35c

Fix T103433: Ensure Metal memory allocator is safe for multi-threaded allocation. Resolves crash when baking indirect lighting.

Also applies correct texture usage flag to light bake texture.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem, jbakker

Maniphest Tasks: T96261, T103433

Differential Revision: https://developer.blender.org/D17018

===================================================================

M	source/blender/draw/engines/eevee/eevee_lightcache.c
M	source/blender/gpu/metal/mtl_memory.hh
M	source/blender/gpu/metal/mtl_memory.mm

===================================================================

diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index eead1a39ea2..b3b4b5a6dec 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -716,7 +716,8 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
                                                     lbake->irr_size[1],
                                                     lbake->irr_size[2],
                                                     IRRADIANCE_FORMAT,
-                                                    GPU_TEXTURE_USAGE_SHADER_READ,
+                                                    GPU_TEXTURE_USAGE_SHADER_READ |
+                                                        GPU_TEXTURE_USAGE_ATTACHMENT,
                                                     DRW_TEX_FILTER,
                                                     NULL);
 
diff --git a/source/blender/gpu/metal/mtl_memory.hh b/source/blender/gpu/metal/mtl_memory.hh
index bd354376b12..cce5edeafef 100644
--- a/source/blender/gpu/metal/mtl_memory.hh
+++ b/source/blender/gpu/metal/mtl_memory.hh
@@ -339,10 +339,10 @@ class MTLSafeFreeList {
 class MTLBufferPool {
 
  private:
+#if MTL_DEBUG_MEMORY_STATISTICS == 1
   /* Memory statistics. */
-  int64_t total_allocation_bytes_ = 0;
+  std::atomic<int64_t> total_allocation_bytes_;
 
-#if MTL_DEBUG_MEMORY_STATISTICS == 1
   /* Debug statistics. */
   std::atomic<int> per_frame_allocation_count_;
   std::atomic<int64_t> allocations_in_pool_;
@@ -368,10 +368,14 @@ class MTLBufferPool {
    * - A size-ordered list (MultiSet) of allocated buffers is kept per MTLResourceOptions
    *   permutation. This allows efficient lookup for buffers of a given requested size.
    * - MTLBufferHandle wraps a gpu::MTLBuffer pointer to achieve easy size-based sorting
-   *   via CompareMTLBuffer. */
+   *   via CompareMTLBuffer.
+   *
+   * NOTE: buffer_pool_lock_ guards against concurrent access to the memory allocator. This
+   * can occur during light baking or rendering operations. */
   using MTLBufferPoolOrderedList = std::multiset<MTLBufferHandle, CompareMTLBuffer>;
   using MTLBufferResourceOptions = uint64_t;
 
+  std::mutex buffer_pool_lock_;
   blender::Map<MTLBufferResourceOptions, MTLBufferPoolOrderedList *> buffer_pools_;
   blender::Vector<gpu::MTLBuffer *> allocations_;
 
diff --git a/source/blender/gpu/metal/mtl_memory.mm b/source/blender/gpu/metal/mtl_memory.mm
index a7717bfef89..101dee2794e 100644
--- a/source/blender/gpu/metal/mtl_memory.mm
+++ b/source/blender/gpu/metal/mtl_memory.mm
@@ -25,6 +25,7 @@ void MTLBufferPool::init(id<MTLDevice> mtl_device)
 
 #if MTL_DEBUG_MEMORY_STATISTICS == 1
     /* Debug statistics. */
+    total_allocation_bytes_ = 0;
     per_frame_allocation_count_ = 0;
     allocations_in_pool_ = 0;
     buffers_in_pool_ = 0;
@@ -43,7 +44,7 @@ MTLBufferPool::~MTLBufferPool()
 
 void MTLBufferPool::free()
 {
-
+  buffer_pool_lock_.lock();
   for (auto buffer : allocations_) {
     BLI_assert(buffer);
     delete buffer;
@@ -55,6 +56,7 @@ void MTLBufferPool::free()
     delete buffer_pool;
   }
   buffer_pools_.clear();
+  buffer_pool_lock_.unlock();
 }
 
 gpu::MTLBuffer *MTLBufferPool::allocate(uint64_t size, bool cpu_visible)
@@ -96,6 +98,8 @@ gpu::MTLBuffer *MTLBufferPool::allocate_aligned(uint64_t size,
 
   /* Check if we have a suitable buffer */
   gpu::MTLBuffer *new_buffer = nullptr;
+  buffer_pool_lock_.lock();
+
   std::multiset<MTLBufferHandle, CompareMTLBuffer> **pool_search = buffer_pools_.lookup_ptr(
       (uint64_t)options);
 
@@ -142,7 +146,9 @@ gpu::MTLBuffer *MTLBufferPool::allocate_aligned(uint64_t size,
 
     /* Track allocation in context. */
     allocations_.append(new_buffer);
+#if MTL_DEBUG_MEMORY_STATISTICS == 1
     total_allocation_bytes_ += aligned_alloc_size;
+#endif
   }
   else {
     /* Re-use suitable buffer. */
@@ -165,6 +171,9 @@ gpu::MTLBuffer *MTLBufferPool::allocate_aligned(uint64_t size,
   per_frame_allocation_count_++;
 #endif
 
+  /* Release lock. */
+  buffer_pool_lock_.unlock();
+
   return new_buffer;
 }
 
@@ -209,8 +218,11 @@ void MTLBufferPool::update_memory_pools()
 {
   /* Ensure thread-safe access to `completed_safelist_queue_`, which contains
    * the list of MTLSafeFreeList's whose buffers are ready to be
-   * re-inserted into the Memory Manager pools. */
+   * re-inserted into the Memory Manager pools.
+   * we also need to lock access to general buffer pools, to ensure allocations
+   * are not simultaneously happening on background threads. */
   safelist_lock_.lock();
+  buffer_pool_lock_.lock();
 
 #if MTL_DEBUG_MEMORY_STATISTICS == 1
   int num_buffers_added = 0;
@@ -302,6 +314,7 @@ void MTLBufferPool::update_memory_pools()
 
   /* Clear safe pools list */
   completed_safelist_queue_.clear();
+  buffer_pool_lock_.unlock();
   safelist_lock_.unlock();
 }



More information about the Bf-blender-cvs mailing list