[Bf-blender-cvs] [359d98423e1] master: Metal: Fix memory leaks.

Jason Fielder noreply at git.blender.org
Thu Dec 8 23:12:48 CET 2022


Commit: 359d98423e17eb62b03b65666734fd97ecd04318
Author: Jason Fielder
Date:   Thu Dec 8 23:08:49 2022 +0100
Branches: master
https://developer.blender.org/rB359d98423e17eb62b03b65666734fd97ecd04318

Metal: Fix memory leaks.

Fix a number of small memory leaks in the Metal backend. Unreleased blit
shader objects and temporary textures addressed. Static memory manager
modified to defer creation until use. Added reference count tracker to
shared memory manager across contexts, such that cached memory allocations
will be released if all contexts are destroyed and re-initialized.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem
Differential Revision: https://developer.blender.org/D16415

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

M	source/blender/gpu/metal/mtl_backend.mm
M	source/blender/gpu/metal/mtl_batch.mm
M	source/blender/gpu/metal/mtl_command_buffer.mm
M	source/blender/gpu/metal/mtl_context.hh
M	source/blender/gpu/metal/mtl_context.mm
M	source/blender/gpu/metal/mtl_index_buffer.mm
M	source/blender/gpu/metal/mtl_memory.mm
M	source/blender/gpu/metal/mtl_query.mm
M	source/blender/gpu/metal/mtl_texture.hh
M	source/blender/gpu/metal/mtl_texture.mm
M	source/blender/gpu/metal/mtl_uniform_buffer.mm
M	source/blender/gpu/metal/mtl_vertex_buffer.mm

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

diff --git a/source/blender/gpu/metal/mtl_backend.mm b/source/blender/gpu/metal/mtl_backend.mm
index 9d482558939..e6bd8456605 100644
--- a/source/blender/gpu/metal/mtl_backend.mm
+++ b/source/blender/gpu/metal/mtl_backend.mm
@@ -144,15 +144,15 @@ void MTLBackend::render_step()
    * is also thread-safe. */
 
   /* Flush any MTLSafeFreeLists which have previously been released by any MTLContext. */
-  MTLContext::get_global_memory_manager().update_memory_pools();
+  MTLContext::get_global_memory_manager()->update_memory_pools();
 
   /* End existing MTLSafeFreeList and begin new list --
    * Buffers wont `free` until all associated in-flight command buffers have completed.
    * Decrement final reference count for ensuring the previous list is certainly
    * released. */
   MTLSafeFreeList *cmd_free_buffer_list =
-      MTLContext::get_global_memory_manager().get_current_safe_list();
-  MTLContext::get_global_memory_manager().begin_new_safe_list();
+      MTLContext::get_global_memory_manager()->get_current_safe_list();
+  MTLContext::get_global_memory_manager()->begin_new_safe_list();
   cmd_free_buffer_list->decrement_reference();
 }
 
diff --git a/source/blender/gpu/metal/mtl_batch.mm b/source/blender/gpu/metal/mtl_batch.mm
index 1ef43a71feb..ab2c8f3e79f 100644
--- a/source/blender/gpu/metal/mtl_batch.mm
+++ b/source/blender/gpu/metal/mtl_batch.mm
@@ -943,7 +943,7 @@ id<MTLBuffer> MTLBatch::get_emulated_toplogy_buffer(GPUPrimType &in_out_prim_typ
     /* Allocate buffer. */
     uint32_t buffer_bytes = output_IB_elems * 4;
     BLI_assert(buffer_bytes > 0);
-    this->emulated_topology_buffer_ = MTLContext::get_global_memory_manager().allocate(
+    this->emulated_topology_buffer_ = MTLContext::get_global_memory_manager()->allocate(
         buffer_bytes, true);
 
     /* Populate. */
diff --git a/source/blender/gpu/metal/mtl_command_buffer.mm b/source/blender/gpu/metal/mtl_command_buffer.mm
index 327f2c0086d..8ff0f7aa2ca 100644
--- a/source/blender/gpu/metal/mtl_command_buffer.mm
+++ b/source/blender/gpu/metal/mtl_command_buffer.mm
@@ -115,7 +115,7 @@ bool MTLCommandBufferManager::submit(bool wait)
    * This ensures that in-use resources are not prematurely de-referenced and returned to the
    * available buffer pool while they are in-use by the GPU. */
   MTLSafeFreeList *cmd_free_buffer_list =
-      MTLContext::get_global_memory_manager().get_current_safe_list();
+      MTLContext::get_global_memory_manager()->get_current_safe_list();
   BLI_assert(cmd_free_buffer_list);
   cmd_free_buffer_list->increment_reference();
 
diff --git a/source/blender/gpu/metal/mtl_context.hh b/source/blender/gpu/metal/mtl_context.hh
index 39474eeb6fa..aa0a01b11d9 100644
--- a/source/blender/gpu/metal/mtl_context.hh
+++ b/source/blender/gpu/metal/mtl_context.hh
@@ -28,6 +28,7 @@
 #include <Cocoa/Cocoa.h>
 #include <Metal/Metal.h>
 #include <QuartzCore/QuartzCore.h>
+#include <mutex>
 
 @class CAMetalLayer;
 @class MTLCommandQueue;
@@ -310,6 +311,12 @@ struct MTLContextTextureUtils {
       GPU_shader_free(fullscreen_blit_shader);
     }
 
+    /* Free depth 2D Update shaders */
+    for (auto item : depth_2d_update_shaders.items()) {
+      GPU_shader_free(item.value);
+    }
+    depth_2d_update_shaders.clear();
+
     /* Free Read shader maps */
     free_cached_pso_map(texture_1d_read_compute_psos);
     free_cached_pso_map(texture_1d_read_compute_psos);
@@ -599,7 +606,9 @@ class MTLContext : public Context {
 
   /* Memory Management. */
   MTLScratchBufferManager memory_manager;
-  static MTLBufferPool global_memory_manager;
+  static std::mutex global_memory_manager_reflock;
+  static int global_memory_manager_refcount;
+  static MTLBufferPool *global_memory_manager;
 
   /* CommandBuffer managers. */
   MTLCommandBufferManager main_command_buffer;
@@ -780,8 +789,34 @@ class MTLContext : public Context {
     return this->memory_manager;
   }
 
-  static MTLBufferPool &get_global_memory_manager()
+  static void global_memory_manager_acquire_ref()
+  {
+    MTLContext::global_memory_manager_reflock.lock();
+    if (MTLContext::global_memory_manager == nullptr) {
+      BLI_assert(MTLContext::global_memory_manager_refcount == 0);
+      MTLContext::global_memory_manager = new MTLBufferPool();
+    }
+    MTLContext::global_memory_manager_refcount++;
+    MTLContext::global_memory_manager_reflock.unlock();
+  }
+
+  static void global_memory_manager_release_ref()
+  {
+    MTLContext::global_memory_manager_reflock.lock();
+    MTLContext::global_memory_manager_refcount--;
+    BLI_assert(MTLContext::global_memory_manager_refcount >= 0);
+    BLI_assert(MTLContext::global_memory_manager != nullptr);
+
+    if (MTLContext::global_memory_manager_refcount <= 0) {
+      delete MTLContext::global_memory_manager;
+      MTLContext::global_memory_manager = nullptr;
+    }
+    MTLContext::global_memory_manager_reflock.unlock();
+  }
+
+  static MTLBufferPool *get_global_memory_manager()
   {
+    BLI_assert(MTLContext::global_memory_manager != nullptr);
     return MTLContext::global_memory_manager;
   }
 
diff --git a/source/blender/gpu/metal/mtl_context.mm b/source/blender/gpu/metal/mtl_context.mm
index 50576379f0d..b20a0f7faa8 100644
--- a/source/blender/gpu/metal/mtl_context.mm
+++ b/source/blender/gpu/metal/mtl_context.mm
@@ -35,7 +35,9 @@ using namespace blender::gpu;
 namespace blender::gpu {
 
 /* Global memory manager. */
-MTLBufferPool MTLContext::global_memory_manager;
+std::mutex MTLContext::global_memory_manager_reflock;
+int MTLContext::global_memory_manager_refcount = 0;
+MTLBufferPool *MTLContext::global_memory_manager = nullptr;
 
 /* Swap-chain and latency management. */
 std::atomic<int> MTLContext::max_drawables_in_flight = 0;
@@ -207,7 +209,8 @@ MTLContext::MTLContext(void *ghost_window, void *ghost_context)
   this->imm = new MTLImmediate(this);
 
   /* Ensure global memory manager is initialized. */
-  MTLContext::global_memory_manager.init(this->device);
+  MTLContext::global_memory_manager_acquire_ref();
+  MTLContext::get_global_memory_manager()->init(this->device);
 
   /* Initialize texture read/update structures. */
   this->get_texture_utils().init();
@@ -239,6 +242,16 @@ MTLContext::~MTLContext()
     }
   }
 
+  /* Release context textures. */
+  if (default_fbo_gputexture_) {
+    GPU_texture_free(wrap(static_cast<Texture *>(default_fbo_gputexture_)));
+    default_fbo_gputexture_ = nullptr;
+  }
+  if (default_fbo_mtltexture_) {
+    [default_fbo_mtltexture_ release];
+    default_fbo_mtltexture_ = nil;
+  }
+
   /* Release Memory Manager */
   this->get_scratchbuffer_manager().free();
 
@@ -283,6 +296,9 @@ MTLContext::~MTLContext()
     [null_attribute_buffer_ release];
   }
 
+  /* Release memory manager reference. */
+  MTLContext::global_memory_manager_release_ref();
+
   /* Free Metal objects. */
   if (this->queue) {
     [this->queue release];
@@ -1291,8 +1307,8 @@ void MTLContext::ensure_texture_bindings(
                                        size;
 
           /* Allocate buffer to store encoded sampler arguments. */
-          encoder_buffer = MTLContext::get_global_memory_manager().allocate(aligned_alloc_size,
-                                                                            true);
+          encoder_buffer = MTLContext::get_global_memory_manager()->allocate(aligned_alloc_size,
+                                                                             true);
           BLI_assert(encoder_buffer);
           BLI_assert(encoder_buffer->get_metal_buffer());
           [argument_encoder setArgumentBuffer:encoder_buffer->get_metal_buffer() offset:0];
@@ -1687,7 +1703,7 @@ void present(MTLRenderPassDescriptor *blit_descriptor,
 
   /* Ensure freed buffers have usage tracked against active CommandBuffer submissions. */
   MTLSafeFreeList *cmd_free_buffer_list =
-      MTLContext::get_global_memory_manager().get_current_safe_list();
+      MTLContext::get_global_memory_manager()->get_current_safe_list();
   BLI_assert(cmd_free_buffer_list);
 
   id<MTLCommandBuffer> cmd_buffer_ref = cmdbuf;
diff --git a/source/blender/gpu/metal/mtl_index_buffer.mm b/source/blender/gpu/metal/mtl_index_buffer.mm
index 9712dce7b40..c32f9299d02 100644
--- a/source/blender/gpu/metal/mtl_index_buffer.mm
+++ b/source/blender/gpu/metal/mtl_index_buffer.mm
@@ -98,7 +98,7 @@ void MTLIndexBuf::upload_data()
       MTL_LOG_WARNING("[Metal] Warning! Trying to allocate index buffer with size=0 bytes\n");
     }
     else {
-      ibo_ = MTLContext::get_global_memory_manager().allocate_with_data(alloc_size_, true, data_);
+      ibo_ = MTLContext::get_global_memory_manager()->allocate_with_data(alloc_size_, true, data_);
       BLI_assert(ibo_);
       ibo_->set_label(@"Index Buffer");
     }
@@ -340,7 +340,7 @@ id<MTLBuffer> MTLIndexBuf::get_index_buffer(GPUPrimType &in_out_primitive_type,
         BLI_assert(max_possible_verts > 0);
 
         /* Allocate new buffer. */
-        optimized_ibo_ = MTLContext::get_global_memory_manager().allocate(
+        optimized_ibo_ = MTLContext::get_global_memory_manager()->allocate(
             max_possible_verts *
                 ((index_type_ == GPU_INDEX_U16) ? sizeof(uint16_t) : sizeof(uint32_t)),
             true);
@@ -350,7 +350,7 @@ id<MTLBuffer> MTLIndexBuf::get_index_buffer(GPUPrimType &in_out_primitive_type,
           Span<uint16_t> orig_data(static_cast<const uint16_t *>(ibo_->get_host_ptr()),
                                    this->index_len_);
           MutableSpan<uint16_t> output_data(
-              static_cast<uint16_t *>(optimized_ibo_->get_host_ptr()), this->index_len_);
+              static_cast<uint16_t *>(optimized_ibo_->get_host_ptr()), max_possible_verts);
           emulated_v_count = populate_emulated_tri_fan_buf<uint16_t>(
               orig_data, output_data, this->index_len_);
         }
@@ -358,7 +358,7 @@ id<MTLBuffer> MTLIndexBuf::get_index_buffer(GPUPrimType &in_out_primitive_type,
           Span<uint32_t> orig_data(static_cast<const uint32_t *>(ibo_->get_host_ptr()),
                                    this->index_len_);
           MutableSpan<uint32_t> output_data(
-              static_cast<uint32_t *>(optimized_ibo_->get_host_ptr()), this->index_len_);


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list