[Bf-blender-cvs] [1cf465bbc33] master: Fix GPU backend deleting resources without an active context

Brecht Van Lommel noreply at git.blender.org
Fri Jul 15 16:31:13 CEST 2022


Commit: 1cf465bbc3312ae8eac3e1ae573b716e0fad92cf
Author: Brecht Van Lommel
Date:   Fri Jul 15 12:44:35 2022 +0200
Branches: master
https://developer.blender.org/rB1cf465bbc3312ae8eac3e1ae573b716e0fad92cf

Fix GPU backend deleting resources without an active context

This causes an assert with libepoxy, but was wrong already regardless.

Refactor logic to work as follows:
* GPU_exit() deletes backend resources
* Destroy UI GPU resources with the context active
* Call GPU_backend_exit() after deleting the context

Ref D15291

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

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

M	source/blender/gpu/GPU_context.h
M	source/blender/gpu/intern/gpu_backend.hh
M	source/blender/gpu/intern/gpu_context.cc
M	source/blender/gpu/intern/gpu_init_exit.c
M	source/blender/gpu/intern/gpu_private.h
M	source/blender/gpu/metal/mtl_backend.hh
M	source/blender/gpu/opengl/gl_backend.hh
M	source/blender/gpu/tests/gpu_testing.cc
M	source/blender/windowmanager/intern/wm_init_exit.c

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

diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h
index b04a4422baa..c81296093a1 100644
--- a/source/blender/gpu/GPU_context.h
+++ b/source/blender/gpu/GPU_context.h
@@ -17,8 +17,11 @@
 extern "C" {
 #endif
 
+/* GPU backends abstract the differences between different APIs. These must be
+ * initialized before creating contexts, and deleted after the last context is
+ * discarded. GPU_context_create automatically initializes a backend if none
+ * exists yet. */
 bool GPU_backend_init_once(void);
-void GPU_backend_init(eGPUBackendType backend);
 void GPU_backend_exit(void);
 bool GPU_backend_supported(eGPUBackendType type);
 
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh
index 6e07e6c3229..d2890efee72 100644
--- a/source/blender/gpu/intern/gpu_backend.hh
+++ b/source/blender/gpu/intern/gpu_backend.hh
@@ -30,6 +30,7 @@ class VertBuf;
 class GPUBackend {
  public:
   virtual ~GPUBackend() = default;
+  virtual void delete_resources() = 0;
 
   static GPUBackend *get();
 
diff --git a/source/blender/gpu/intern/gpu_context.cc b/source/blender/gpu/intern/gpu_context.cc
index d3b208dc6f6..9b0670da8cb 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -27,6 +27,7 @@
 #include "gpu_batch_private.hh"
 #include "gpu_context_private.hh"
 #include "gpu_matrix_private.h"
+#include "gpu_private.h"
 
 #ifdef WITH_OPENGL_BACKEND
 #  include "gl_backend.hh"
@@ -213,20 +214,17 @@ bool GPU_backend_supported(eGPUBackendType type)
 
 bool GPU_backend_init_once()
 {
-  if (GPUBackend::get() == nullptr) {
-    if (!GPU_backend_supported(GPU_BACKEND_OPENGL)) {
-      return false;
-    }
-    /* TODO: move where it make sense. */
-    GPU_backend_init(GPU_BACKEND_OPENGL);
+  if (GPUBackend::get() != nullptr) {
+    return true;
   }
-  return true;
-}
 
-void GPU_backend_init(eGPUBackendType backend_type)
-{
-  BLI_assert(g_backend == nullptr);
-  BLI_assert(GPU_backend_supported(backend_type));
+  const eGPUBackendType backend_type = GPU_BACKEND_OPENGL;
+  if (!GPU_backend_supported(backend_type)) {
+    return false;
+  }
+
+  static std::mutex backend_init_mutex;
+  std::scoped_lock lock(backend_init_mutex);
 
   switch (backend_type) {
 #ifdef WITH_OPENGL_BACKEND
@@ -243,12 +241,19 @@ void GPU_backend_init(eGPUBackendType backend_type)
       BLI_assert(0);
       break;
   }
+
+  return true;
+}
+
+void gpu_backend_delete_resources()
+{
+  BLI_assert(backend);
+  g_backend->delete_resources();
 }
 
 void GPU_backend_exit()
 {
-  /* TODO: assert no resource left. Currently UI textures are still not freed in their context
-   * correctly. */
+  /* TODO: assert no resource left. */
   delete g_backend;
   g_backend = nullptr;
 }
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
index 062614fb5cb..34b355eefaf 100644
--- a/source/blender/gpu/intern/gpu_init_exit.c
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -55,6 +55,8 @@ void GPU_exit(void)
   gpu_shader_dependency_exit();
   gpu_shader_create_info_exit();
 
+  gpu_backend_delete_resources();
+
   initialized = false;
 }
 
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
index a8ee5187d98..0e293302086 100644
--- a/source/blender/gpu/intern/gpu_private.h
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -10,6 +10,10 @@
 extern "C" {
 #endif
 
+/* gpu_backend.cc */
+
+void gpu_backend_delete_resources(void);
+
 /* gpu_pbvh.c */
 
 void gpu_pbvh_init(void);
diff --git a/source/blender/gpu/metal/mtl_backend.hh b/source/blender/gpu/metal/mtl_backend.hh
index 7228a5f7596..3e09408e43e 100644
--- a/source/blender/gpu/metal/mtl_backend.hh
+++ b/source/blender/gpu/metal/mtl_backend.hh
@@ -40,6 +40,11 @@ class MTLBackend : public GPUBackend {
     MTLBackend::platform_exit();
   }
 
+  void delete_resources()
+  {
+    /* Delete any resources with context active. */
+  }
+
   static bool metal_is_supported();
   static MTLBackend *get()
   {
diff --git a/source/blender/gpu/opengl/gl_backend.hh b/source/blender/gpu/opengl/gl_backend.hh
index 29249111294..e425b87afe8 100644
--- a/source/blender/gpu/opengl/gl_backend.hh
+++ b/source/blender/gpu/opengl/gl_backend.hh
@@ -42,11 +42,15 @@ class GLBackend : public GPUBackend {
   }
   ~GLBackend()
   {
-    GLTexture::samplers_free();
-
     GLBackend::platform_exit();
   }
 
+  void delete_resources() override
+  {
+    /* Delete any resources with context active. */
+    GLTexture::samplers_free();
+  }
+
   static GLBackend *get()
   {
     return static_cast<GLBackend *>(GPUBackend::get());
diff --git a/source/blender/gpu/tests/gpu_testing.cc b/source/blender/gpu/tests/gpu_testing.cc
index 4e93e062b50..5a2ad893360 100644
--- a/source/blender/gpu/tests/gpu_testing.cc
+++ b/source/blender/gpu/tests/gpu_testing.cc
@@ -17,6 +17,7 @@ void GPUTest::SetUp()
   GHOST_GLSettings glSettings = {0};
   CLG_init();
   ghost_system = GHOST_CreateSystem();
+  GPU_backend_init_once();
   ghost_context = GHOST_CreateOpenGLContext(ghost_system, glSettings);
   GHOST_ActivateOpenGLContext(ghost_context);
   context = GPU_context_create(nullptr);
@@ -26,9 +27,9 @@ void GPUTest::SetUp()
 void GPUTest::TearDown()
 {
   GPU_exit();
-  GPU_backend_exit();
   GPU_context_discard(context);
   GHOST_DisposeOpenGLContext(ghost_system, ghost_context);
+  GPU_backend_exit();
   GHOST_DisposeSystem(ghost_system);
   CLG_exit();
 }
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index b9bb1d88819..7324abfd096 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -576,14 +576,6 @@ void WM_exit_ex(bContext *C, const bool do_python)
 
   BLF_exit();
 
-  if (opengl_is_init) {
-    DRW_opengl_context_enable_ex(false);
-    GPU_pass_cache_free();
-    GPU_exit();
-    DRW_opengl_context_disable_ex(false);
-    DRW_opengl_context_destroy();
-  }
-
   BLT_lang_free();
 
   ANIM_keyingset_infos_exit();
@@ -608,13 +600,25 @@ void WM_exit_ex(bContext *C, const bool do_python)
 
   ED_file_exit(); /* for fsmenu */
 
-  UI_exit();
+  /* Delete GPU resources and context. The UI also uses GPU resources and so
+   * is also deleted with the context active. */
+  if (opengl_is_init) {
+    DRW_opengl_context_enable_ex(false);
+    UI_exit();
+    GPU_pass_cache_free();
+    GPU_exit();
+    DRW_opengl_context_disable_ex(false);
+    DRW_opengl_context_destroy();
+  }
+  else {
+    UI_exit();
+  }
+  GPU_backend_exit();
+
   BKE_blender_userdef_data_free(&U, false);
 
   RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */
 
-  GPU_backend_exit();
-
   wm_ghost_exit();
 
   CTX_free(C);



More information about the Bf-blender-cvs mailing list