ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
60.9k stars 10.28k forks source link

imgui_impl_metal: resource leak when using thread-local GImGui #7419

Open anszom opened 7 months ago

anszom commented 7 months ago

Version/Branch of Dear ImGui:

git commit 9a5da23, but the code is the same on master

Back-ends:

imgui_impl_metal.cpp + custom platform backend

Compiler, OS:

macOS + Clang 14

Full config/build information:

No response

Details:

My Issue/Question:

I'm using multiple ImGui contexts within a single application, with a thread_local GImGui pointer, as described in imgui.cpp:

struct ImGuiContext;
extern thread_local ImGuiContext* GImGui_tls;
#define GImGui GImGui_tls

I'm observing a significant memory leak with the Metal backend. I've traced it down to the buffers allocated in dequeueReusableBufferOfLength:device:. The asynchronous callback responsible for releasing the buffers is running on a thread without any ImGui context active, therefore the buffers are never released.

I suggest the following changes to fix the problem.

diff --git a/3rdparty/imgui/imgui_impl_metal.mm b/3rdparty/imgui/imgui_impl_metal.mm
index 23870f37..1206187a 100644
--- a/3rdparty/imgui/imgui_impl_metal.mm
+++ b/3rdparty/imgui/imgui_impl_metal.mm
@@ -310,17 +310,14 @@ void ImGui_ImplMetal_RenderDrawData(ImDrawData* drawData, id<MTLCommandBuffer> c
         indexBufferOffset += (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
     }

+    __block MetalContext* SharedMetalContext = bd->SharedMetalContext;
     [commandBuffer addCompletedHandler:^(id<MTLCommandBuffer>)
     {
         dispatch_async(dispatch_get_main_queue(), ^{
-            ImGui_ImplMetal_Data* bd = ImGui_ImplMetal_GetBackendData();
-            if (bd != nullptr)
+            @synchronized(SharedMetalContext.bufferCache)
             {
-                @synchronized(bd->SharedMetalContext.bufferCache)
-                {
-                    [bd->SharedMetalContext.bufferCache addObject:vertexBuffer];
-                    [bd->SharedMetalContext.bufferCache addObject:indexBuffer];
-                }
+                [SharedMetalContext.bufferCache addObject:vertexBuffer];
+                [SharedMetalContext.bufferCache addObject:indexBuffer];
             }
         });
     }];

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

ocornut commented 7 months ago

Hello, please note that I haven't checked yet as objC is entirely foreign to me, but could this be related to #7393 and #6528 ?

anszom commented 7 months ago

My experience with osx is quite limited, but I think these issues are not directly related.