diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-08-08 02:18:18 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-08-08 02:30:33 +0300 |
commit | cb7ea2ccfbb5d81083313c21d6b85a9c85db67d4 (patch) | |
tree | af7baa1dc3438da8f349bd38c2a65f9caad50bf3 /source/blender/gpu/intern | |
parent | 1dd737759639c63d3279be774202585de778dac5 (diff) |
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
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_context.cc | 178 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_context_private.h | 49 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_init_exit.c | 2 |
3 files changed, 75 insertions, 154 deletions
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 - struct GPUMatrixState *matrix_state; - std::vector<GLuint> orphaned_vertarray_ids; - std::vector<GLuint> orphaned_framebuffer_ids; - std::mutex orphans_mutex; /* todo: try spinlock instead */ -# if TRUST_NO_ONE - pthread_t thread; /* Thread on which this context is active. */ - bool thread_is_used; -# endif - - GPUContext() - { -# if TRUST_NO_ONE - thread_is_used = false; -# endif - current_fbo = 0; - }; - - virtual ~GPUContext(){}; + public: + /** State managment */ + GPUFrameBuffer *current_fbo = NULL; + GPUMatrixState *matrix_state = NULL; + + protected: + /** Thread on which this context is active. */ + pthread_t thread_; + bool is_active_; + + public: + GPUContext(); + virtual ~GPUContext(); + + virtual void activate(void) = 0; + virtual void deactivate(void) = 0; + + bool is_active_on_thread(void); + + MEM_CXX_CLASS_ALLOC_FUNCS("GPUContext") }; #endif diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index 462a1d395c2..ba0da95eb9d 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -93,8 +93,6 @@ void GPU_exit(void) gpu_extensions_exit(); gpu_platform_exit(); /* must come last */ - GPU_backend_exit(); - initialized = false; } |