Commit: cb7ea2ccfbb5d81083313c21d6b85a9c85db67d4
Author: Clément Foucault
Date:   Sat Aug 8 01:18:18 2020 +0200
Branches: master
https://developer.blender.org/rBcb7ea2ccfbb5d81083313c21d6b85a9c85db67d4

GPUBackend: Add new GPUBackend object to manage GL object allocations

This just set a global object responsible for allocating new objects
in a thread safe way without needing any GPUContext bound to this
thread.

This also introduce the GLContext which will contain all the GL related
functions for the current context.

# Conflicts:
#       source/blender/gpu/intern/gpu_context.cc

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

M       source/blender/gpu/intern/gpu_context.cc
M       source/blender/gpu/intern/gpu_context_private.h
M       source/blender/gpu/intern/gpu_init_exit.c
M       source/blender/gpu/opengl/gl_backend.hh
M       source/blender/gpu/opengl/gl_context.cc
M       source/blender/gpu/opengl/gl_context.hh
M       source/blender/windowmanager/intern/wm_init_exit.c

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

diff --git a/source/blender/gpu/intern/gpu_context.cc 
b/source/blender/gpu/intern/gpu_context.cc
index 9707c32cede..d9f435ce1a9 100644
--- a/source/blender/gpu/intern/gpu_context.cc
+++ b/source/blender/gpu/intern/gpu_context.cc
@@ -52,58 +52,34 @@
 #include <mutex>
 #include <vector>
 
-static std::vector<GLuint> orphaned_buffer_ids;
-static std::vector<GLuint> orphaned_texture_ids;
-
-static std::mutex orphans_mutex;
-static std::mutex main_context_mutex;
+using namespace blender::gpu;
 
 static thread_local GPUContext *active_ctx = NULL;
 
-static void orphans_add(GPUContext *ctx, std::vector<GLuint> *orphan_list, 
GLuint id)
-{
-  std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex;
+/* -------------------------------------------------------------------- */
+/** \name GPUContext methods
+ * \{ */
 
-  mutex->lock();
-  orphan_list->emplace_back(id);
-  mutex->unlock();
+GPUContext::GPUContext()
+{
+  thread_ = pthread_self();
+  is_active_ = false;
+  matrix_state = GPU_matrix_state_create();
 }
 
-static void orphans_clear(GPUContext *ctx)
+GPUContext::~GPUContext()
 {
-  /* need at least an active context */
-  BLI_assert(ctx);
-
-  /* context has been activated by another thread! */
-  BLI_assert(pthread_equal(pthread_self(), ctx->thread));
+  GPU_matrix_state_discard(matrix_state);
+}
 
-  ctx->orphans_mutex.lock();
-  if (!ctx->orphaned_vertarray_ids.empty()) {
-    uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size();
-    glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data());
-    ctx->orphaned_vertarray_ids.clear();
-  }
-  if (!ctx->orphaned_framebuffer_ids.empty()) {
-    uint orphan_len = (uint)ctx->orphaned_framebuffer_ids.size();
-    glDeleteFramebuffers(orphan_len, ctx->orphaned_framebuffer_ids.data());
-    ctx->orphaned_framebuffer_ids.clear();
-  }
+bool GPUContext::is_active_on_thread(void)
+{
+  return (this == active_ctx) && pthread_equal(pthread_self(), thread_);
+}
 
-  ctx->orphans_mutex.unlock();
+/** \} */
 
-  orphans_mutex.lock();
-  if (!orphaned_buffer_ids.empty()) {
-    uint orphan_len = (uint)orphaned_buffer_ids.size();
-    glDeleteBuffers(orphan_len, orphaned_buffer_ids.data());
-    orphaned_buffer_ids.clear();
-  }
-  if (!orphaned_texture_ids.empty()) {
-    uint orphan_len = (uint)orphaned_texture_ids.size();
-    glDeleteTextures(orphan_len, orphaned_texture_ids.data());
-    orphaned_texture_ids.clear();
-  }
-  orphans_mutex.unlock();
-}
+/* -------------------------------------------------------------------- */
 
 GPUContext *GPU_context_create(void *ghost_window)
 {
@@ -113,15 +89,7 @@ GPUContext *GPU_context_create(void *ghost_window)
   }
 
   GPUContext *ctx = gpu_backend_get()->context_alloc(ghost_window);
-  glGenVertexArrays(1, &ctx->default_vao);
-  if (ghost_window != NULL) {
-    ctx->default_framebuffer = 
GHOST_GetDefaultOpenGLFramebuffer((GHOST_WindowHandle)ghost_window);
-  }
-  else {
-    ctx->default_framebuffer = 0;
-  }
 
-  ctx->matrix_state = GPU_matrix_state_create();
   GPU_context_active_set(ctx);
   return ctx;
 }
@@ -129,21 +97,6 @@ GPUContext *GPU_context_create(void *ghost_window)
 /* to be called after GPU_context_active_set(ctx_to_destroy) */
 void GPU_context_discard(GPUContext *ctx)
 {
-  /* Make sure no other thread has locked it. */
-  BLI_assert(ctx == active_ctx);
-  BLI_assert(pthread_equal(pthread_self(), ctx->thread));
-  BLI_assert(ctx->orphaned_vertarray_ids.empty());
-#ifdef DEBUG
-  /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */
-  BLI_assert(ctx->framebuffers.empty());
-#endif
-  /* delete remaining vaos */
-  while (!ctx->batches.empty()) {
-    /* this removes the array entry */
-    GPU_batch_vao_cache_clear(*ctx->batches.begin());
-  }
-  GPU_matrix_state_discard(ctx->matrix_state);
-  glDeleteVertexArrays(1, &ctx->default_vao);
   delete ctx;
   active_ctx = NULL;
 }
@@ -151,22 +104,15 @@ void GPU_context_discard(GPUContext *ctx)
 /* ctx can be NULL */
 void GPU_context_active_set(GPUContext *ctx)
 {
-#if TRUST_NO_ONE
   if (active_ctx) {
-    active_ctx->thread_is_used = false;
+    active_ctx->deactivate();
   }
-  /* Make sure no other context is already bound to this thread. */
-  if (ctx) {
-    /* Make sure no other thread has locked it. */
-    assert(ctx->thread_is_used == false);
-    ctx->thread = pthread_self();
-    ctx->thread_is_used = true;
-  }
-#endif
+
+  active_ctx = ctx;
+
   if (ctx) {
-    orphans_clear(ctx);
+    ctx->activate();
   }
-  active_ctx = ctx;
 }
 
 GPUContext *GPU_context_active_get(void)
@@ -177,23 +123,18 @@ GPUContext *GPU_context_active_get(void)
 GLuint GPU_vao_default(void)
 {
   BLI_assert(active_ctx); /* need at least an active context */
-  BLI_assert(pthread_equal(
-      pthread_self(), active_ctx->thread)); /* context has been activated by 
another thread! */
-  return active_ctx->default_vao;
+  return static_cast<GLContext *>(active_ctx)->default_vao_;
 }
 
 GLuint GPU_framebuffer_default(void)
 {
   BLI_assert(active_ctx); /* need at least an active context */
-  BLI_assert(pthread_equal(
-      pthread_self(), active_ctx->thread)); /* context has been activated by 
another thread! */
-  return active_ctx->default_framebuffer;
+  return static_cast<GLContext *>(active_ctx)->default_framebuffer_;
 }
 
 GLuint GPU_vao_alloc(void)
 {
   GLuint new_vao_id = 0;
-  orphans_clear(active_ctx);
   glGenVertexArrays(1, &new_vao_id);
   return new_vao_id;
 }
@@ -201,7 +142,6 @@ GLuint GPU_vao_alloc(void)
 GLuint GPU_fbo_alloc(void)
 {
   GLuint new_fbo_id = 0;
-  orphans_clear(active_ctx);
   glGenFramebuffers(1, &new_fbo_id);
   return new_fbo_id;
 }
@@ -209,7 +149,6 @@ GLuint GPU_fbo_alloc(void)
 GLuint GPU_buf_alloc(void)
 {
   GLuint new_buffer_id = 0;
-  orphans_clear(active_ctx);
   glGenBuffers(1, &new_buffer_id);
   return new_buffer_id;
 }
@@ -217,51 +156,32 @@ GLuint GPU_buf_alloc(void)
 GLuint GPU_tex_alloc(void)
 {
   GLuint new_texture_id = 0;
-  orphans_clear(active_ctx);
   glGenTextures(1, &new_texture_id);
   return new_texture_id;
 }
 
 void GPU_vao_free(GLuint vao_id, GPUContext *ctx)
 {
-  BLI_assert(ctx);
-  if (ctx == active_ctx) {
-    glDeleteVertexArrays(1, &vao_id);
-  }
-  else {
-    orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id);
-  }
+  static_cast<GLContext *>(ctx)->vao_free(vao_id);
 }
 
 void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx)
 {
-  BLI_assert(ctx);
-  if (ctx == active_ctx) {
-    glDeleteFramebuffers(1, &fbo_id);
-  }
-  else {
-    orphans_add(ctx, &ctx->orphaned_framebuffer_ids, fbo_id);
-  }
+  static_cast<GLContext *>(ctx)->fbo_free(fbo_id);
 }
 
 void GPU_buf_free(GLuint buf_id)
 {
-  if (active_ctx) {
-    glDeleteBuffers(1, &buf_id);
-  }
-  else {
-    orphans_add(NULL, &orphaned_buffer_ids, buf_id);
-  }
+  /* TODO avoid using backend */
+  GPUBackend *backend = gpu_backend_get();
+  static_cast<GLBackend *>(backend)->buf_free(buf_id);
 }
 
 void GPU_tex_free(GLuint tex_id)
 {
-  if (active_ctx) {
-    glDeleteTextures(1, &tex_id);
-  }
-  else {
-    orphans_add(NULL, &orphaned_texture_ids, tex_id);
-  }
+  /* TODO avoid using backend */
+  GPUBackend *backend = gpu_backend_get();
+  static_cast<GLBackend *>(backend)->tex_free(tex_id);
 }
 
 /* GPUBatch & GPUFrameBuffer contains respectively VAO & FBO indices
@@ -271,26 +191,20 @@ void GPU_tex_free(GLuint tex_id)
 void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch)
 {
   BLI_assert(ctx);
-  ctx->orphans_mutex.lock();
-  ctx->batches.emplace(batch);
-  ctx->orphans_mutex.unlock();
+  static_cast<GLContext *>(ctx)->batch_register(batch);
 }
 
 void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch)
 {
   BLI_assert(ctx);
-  ctx->orphans_mutex.lock();
-  ctx->batches.erase(batch);
-  ctx->orphans_mutex.unlock();
+  static_cast<GLContext *>(ctx)->batch_unregister(batch);
 }
 
 void gpu_context_add_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb)
 {
 #ifdef DEBUG
   BLI_assert(ctx);
-  ctx->orphans_mutex.lock();
-  ctx->framebuffers.emplace(fb);
-  ctx->orphans_mutex.unlock();
+  static_cast<GLContext *>(ctx)->framebuffer_register(fb);
 #else
   UNUSED_VARS(ctx, fb);
 #endif
@@ -300,9 +214,7 @@ void gpu_context_remove_framebuffer(GPUContext *ctx, 
GPUFrameBuffer *fb)
 {
 #ifdef DEBUG
   BLI_assert(ctx);
-  ctx->orphans_mutex.lock();
-  ctx->framebuffers.erase(fb);
-  ctx->orphans_mutex.unlock();
+  static_cast<GLContext *>(ctx)->framebuffer_unregister(fb);
 #else
   UNUSED_VARS(ctx, fb);
 #endif
@@ -324,6 +236,14 @@ struct GPUMatrixState 
*gpu_context_active_matrix_state_get()
   return active_ctx->matrix_state;
 }
 
+/* -------------------------------------------------------------------- */
+/** \name Main context global mutex
+ *
+ * Used to avoid crash on some old drivers.
+ * \{ */
+
+static std::mutex main_context_mutex;
+
 void GPU_context_main_lock(void)
 {
   main_context_mutex.lock();
@@ -334,6 +254,8 @@ void GPU_context_main_unlock(void)
   main_context_mutex.unlock();
 }
 
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Backend selection
  * \{ */
@@ -358,7 +280,11 @@ void GPU_backend_init(eGPUBackendType backend_type)
 
 void GPU_backend_exit(void)
 {
-  delete g_backend;
+  if (g_backend) {
+    /* TODO assert no resource left. Currently UI textures are still not freed 
in their context
+     * correctly. */
+    delete g_backend;
+  }
 }
 
 GPUBackend *gpu_backend_get(void)
diff --git a/source/blender/gpu/intern/gpu_context_private.h 
b/source/blender/gpu/intern/gpu_context_private.h
index 374a05bc25f..37bf110665f 100644
--- a/source/blender/gpu/intern/gpu_context_private.h
+++ b/source/blender/gpu/intern/gpu_context_private.h
@@ -25,6 +25,8 @@
 
 #pragma once
 
+#include "MEM_guardedalloc.h"
+
 #include "GPU_context.h"
 
 /* TODO cleanup this ifdef */
@@ -37,34 +39,29 @@
 #  include <vector>
 
 struct GPUFrameBuffer;
+struct GPUMatrixState;
 
 struct GPUContext {
-  GLuint default_vao;
-  GLuint default_framebuffer;
-  GPUFrameBuffer *current_fbo;
-  std::unordered_set<GPUBatch *> batches; /* Batches that have VAOs from this 
context */
-#  ifdef DEBUG
-  std::unordered_set<GPUFrameBuffer *>
-      framebuffers; /* Framebuffers that have FBO from this context */
-#  endif
- 

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to