From cb7ea2ccfbb5d81083313c21d6b85a9c85db67d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Sat, 8 Aug 2020 01:18:18 +0200 Subject: 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 --- source/blender/gpu/intern/gpu_context.cc | 178 +++++++++---------------------- 1 file changed, 52 insertions(+), 126 deletions(-) (limited to 'source/blender/gpu/intern/gpu_context.cc') 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 #include -static std::vector orphaned_buffer_ids; -static std::vector 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 *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(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(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(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(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(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(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(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(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(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(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) -- cgit v1.2.3