diff options
24 files changed, 248 insertions, 319 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index eb037d081e1..4d4b486d247 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -136,6 +136,10 @@ void DRW_opengl_context_destroy(void); void DRW_opengl_context_enable(void); void DRW_opengl_context_disable(void); +/* Never use this. Only for closing blender. */ +void DRW_opengl_context_enable_ex(bool restore); +void DRW_opengl_context_disable_ex(bool restore); + void DRW_opengl_render_context_enable(void *re_gl_context); void DRW_opengl_render_context_disable(void *re_gl_context); void DRW_gawain_render_context_enable(void *re_gpu_context); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 2793410cd8e..cc4f8ec7947 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2374,21 +2374,21 @@ void DRW_opengl_context_destroy(void) } } -void DRW_opengl_context_enable(void) +void DRW_opengl_context_enable_ex(bool restore) { if (DST.gl_context != NULL) { /* IMPORTANT: We dont support immediate mode in render mode! * This shall remain in effect until immediate mode supports * multiple threads. */ BLI_ticket_mutex_lock(DST.gl_context_mutex); - if (BLI_thread_is_main()) { + if (BLI_thread_is_main() && restore) { if (!G.background) { immDeactivate(); } } WM_opengl_context_activate(DST.gl_context); GPU_context_active_set(DST.gpu_context); - if (BLI_thread_is_main()) { + if (BLI_thread_is_main() && restore) { if (!G.background) { immActivate(); } @@ -2397,7 +2397,7 @@ void DRW_opengl_context_enable(void) } } -void DRW_opengl_context_disable(void) +void DRW_opengl_context_disable_ex(bool restore) { if (DST.gl_context != NULL) { #ifdef __APPLE__ @@ -2406,7 +2406,7 @@ void DRW_opengl_context_disable(void) glFlush(); #endif - if (BLI_thread_is_main()) { + if (BLI_thread_is_main() && restore) { wm_window_reset_drawable(); } else { @@ -2418,6 +2418,16 @@ void DRW_opengl_context_disable(void) } } +void DRW_opengl_context_enable(void) +{ + DRW_opengl_context_enable_ex(true); +} + +void DRW_opengl_context_disable(void) +{ + DRW_opengl_context_disable_ex(true); +} + void DRW_opengl_render_context_enable(void *re_gl_context) { /* If thread is main you should use DRW_opengl_context_enable(). */ diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 58295ae9329..8273f3f1992 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -62,9 +62,9 @@ set(SRC intern/gpu_batch.c intern/gpu_batch_presets.c intern/gpu_batch_utils.c - intern/gpu_buffer_id.cpp intern/gpu_buffers.c intern/gpu_codegen.c + intern/gpu_context.cpp intern/gpu_debug.c intern/gpu_draw.c intern/gpu_element.c @@ -84,7 +84,6 @@ set(SRC intern/gpu_state.c intern/gpu_texture.c intern/gpu_uniformbuffer.c - intern/gpu_vertex_array_id.cpp intern/gpu_vertex_buffer.c intern/gpu_vertex_format.c intern/gpu_viewport.c @@ -113,7 +112,6 @@ set(SRC GPU_attr_binding.h GPU_basic_shader.h GPU_batch.h - GPU_buffer_id.h GPU_buffers.h GPU_common.h GPU_debug.h @@ -135,7 +133,6 @@ set(SRC GPU_state.h GPU_texture.h GPU_uniformbuffer.h - GPU_vertex_array_id.h GPU_vertex_buffer.h GPU_vertex_format.h GPU_viewport.h @@ -143,6 +140,7 @@ set(SRC intern/gpu_attr_binding_private.h intern/gpu_batch_private.h intern/gpu_codegen.h + intern/gpu_context_private.h intern/gpu_primitive_private.h intern/gpu_private.h intern/gpu_select_private.h diff --git a/source/blender/gpu/GPU_buffer_id.h b/source/blender/gpu/GPU_buffer_id.h deleted file mode 100644 index 4615e9e2c66..00000000000 --- a/source/blender/gpu/GPU_buffer_id.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2016 by Mike Erwin. - * All rights reserved. - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/gpu/GPU_buffer_id.h - * \ingroup gpu - * - * GPU buffer IDs - */ - -#ifndef __GPU_BUFFER_ID_H__ -#define __GPU_BUFFER_ID_H__ - -/* Manage GL buffer IDs in a thread-safe way - * Use these instead of glGenBuffers & its friends - * - alloc must be called from main thread - * - free can be called from any thread */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "GPU_common.h" - -GLuint GPU_buf_id_alloc(void); -void GPU_buf_id_free(GLuint buffer_id); - -#ifdef __cplusplus -} -#endif - -#endif /* __GPU_BUFFER_ID_H__ */ diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 4e264defbd4..f2c029f643e 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -254,11 +254,6 @@ void GPU_material_free(struct ListBase *gpumaterial); void GPU_materials_free(struct Main *bmain); -void GPU_material_orphans_init(void); -void GPU_material_orphans_exit(void); -/* This has to be called from a thread with an ogl context bound. */ -void GPU_material_orphans_delete(void); - struct Scene *GPU_material_scene(GPUMaterial *material); GPUMatType GPU_Material_get_type(GPUMaterial *material); struct GPUPass *GPU_material_get_pass(GPUMaterial *material); diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index e3db18f1358..1ddf801e166 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -198,11 +198,6 @@ void GPU_invalid_tex_free(void); void GPU_texture_free(GPUTexture *tex); -void GPU_texture_orphans_init(void); -void GPU_texture_orphans_exit(void); -/* This has to be called from a thread with an ogl context bound. */ -void GPU_texture_orphans_delete(void); - void GPU_texture_ref(GPUTexture *tex); void GPU_texture_bind(GPUTexture *tex, int number); void GPU_texture_unbind(GPUTexture *tex); diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index a11eefee078..9b433a37a72 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -32,12 +32,11 @@ #include "GPU_batch.h" #include "GPU_batch_presets.h" -#include "GPU_buffer_id.h" #include "GPU_matrix.h" #include "GPU_shader.h" -#include "GPU_vertex_array_id.h" #include "gpu_batch_private.h" +#include "gpu_context_private.h" #include "gpu_primitive_private.h" #include "gpu_shader_private.h" diff --git a/source/blender/gpu/intern/gpu_batch_private.h b/source/blender/gpu/intern/gpu_batch_private.h index 51040ff751a..3a05e243065 100644 --- a/source/blender/gpu/intern/gpu_batch_private.h +++ b/source/blender/gpu/intern/gpu_batch_private.h @@ -43,9 +43,6 @@ extern "C" { void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface); -void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch); -void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch); - #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/intern/gpu_buffer_id.cpp b/source/blender/gpu/intern/gpu_buffer_id.cpp deleted file mode 100644 index f3faba9c766..00000000000 --- a/source/blender/gpu/intern/gpu_buffer_id.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2016 by Mike Erwin. - * All rights reserved. - * - * Contributor(s): Blender Foundation - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/gpu/intern/gpu_buffer_id.cpp - * \ingroup gpu - * - * GPU buffer IDs - */ - -#include "GPU_buffer_id.h" - -#include <mutex> -#include <vector> - -#define ORPHAN_DEBUG 0 - -#if ORPHAN_DEBUG -# include <cstdio> -#endif - -static std::vector<GLuint> orphaned_buffer_ids; - -static std::mutex orphan_mutex; - -extern "C" { -extern int BLI_thread_is_main(void); /* Blender-specific function */ -} - -static bool thread_is_main() -{ - /* "main" here means the GL context's thread */ - return BLI_thread_is_main(); -} - -GLuint GPU_buf_id_alloc() -{ - /* delete orphaned IDs */ - orphan_mutex.lock(); - if (!orphaned_buffer_ids.empty()) { - const auto orphaned_buffer_len = (uint)orphaned_buffer_ids.size(); -#if ORPHAN_DEBUG - printf("deleting %u orphaned VBO%s\n", orphaned_buffer_len, orphaned_buffer_len == 1 ? "" : "s"); -#endif - glDeleteBuffers(orphaned_buffer_len, orphaned_buffer_ids.data()); - orphaned_buffer_ids.clear(); - } - orphan_mutex.unlock(); - - GLuint new_buffer_id = 0; - glGenBuffers(1, &new_buffer_id); - return new_buffer_id; -} - -void GPU_buf_id_free(GLuint buffer_id) -{ - if (thread_is_main()) { - glDeleteBuffers(1, &buffer_id); - } - else { - /* add this ID to the orphaned list */ - orphan_mutex.lock(); -#if ORPHAN_DEBUG - printf("orphaning VBO %u\n", buffer_id); -#endif - orphaned_buffer_ids.emplace_back(buffer_id); - orphan_mutex.unlock(); - } -} diff --git a/source/blender/gpu/intern/gpu_vertex_array_id.cpp b/source/blender/gpu/intern/gpu_context.cpp index 64f704bb107..6a42552c2fd 100644 --- a/source/blender/gpu/intern/gpu_vertex_array_id.cpp +++ b/source/blender/gpu/intern/gpu_context.cpp @@ -34,9 +34,15 @@ * - free can be called from any thread */ -#include "gpu_batch_private.h" -#include "GPU_vertex_array_id.h" +#include "BLI_assert.h" +#include "BLI_utildefines.h" + #include "GPU_context.h" +#include "GPU_framebuffer.h" + +#include "gpu_batch_private.h" +#include "gpu_context_private.h" + #include <vector> #include <string.h> #include <pthread.h> @@ -56,10 +62,19 @@ static bool thread_is_main() { #endif #endif +static std::vector<GLuint> orphaned_buffer_ids; +static std::vector<GLuint> orphaned_texture_ids; + +static std::mutex orphans_mutex; + struct GPUContext { GLuint default_vao; 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 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. */ @@ -78,22 +93,51 @@ thread_local GPUContext *active_ctx = NULL; static thread_local GPUContext *active_ctx = NULL; #endif -static void clear_orphans(GPUContext *ctx) +static void orphans_add(GPUContext *ctx, std::vector<GLuint> *orphan_list, GLuint id) { + std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex; + + mutex->lock(); + orphan_list->emplace_back(id); + mutex->unlock(); +} + +static void orphans_clear(GPUContext *ctx) +{ + BLI_assert(ctx); /* need at least an active context */ + BLI_assert(pthread_equal(pthread_self(), ctx->thread)); /* context has been activated by another thread! */ + 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(); + } + 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) { -#if TRUST_NO_ONE - /* assert(thread_is_main()); */ -#endif + /* BLI_assert(thread_is_main()); */ GPUContext *ctx = new GPUContext; glGenVertexArrays(1, &ctx->default_vao); GPU_context_active_set(ctx); @@ -103,12 +147,12 @@ GPUContext *GPU_context_create(void) /* to be called after GPU_context_active_set(ctx_to_destroy) */ void GPU_context_discard(GPUContext *ctx) { -#if TRUST_NO_ONE /* Make sure no other thread has locked it. */ - assert(ctx == active_ctx); - assert(pthread_equal(pthread_self(), ctx->thread)); - assert(ctx->orphaned_vertarray_ids.empty()); -#endif + BLI_assert(ctx == active_ctx); + BLI_assert(pthread_equal(pthread_self(), ctx->thread)); + BLI_assert(ctx->orphaned_vertarray_ids.empty()); + /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */ + BLI_assert(ctx->framebuffers.empty()); /* delete remaining vaos */ while (!ctx->batches.empty()) { /* this removes the array entry */ @@ -135,7 +179,7 @@ void GPU_context_active_set(GPUContext *ctx) } #endif if (ctx) { - clear_orphans(ctx); + orphans_clear(ctx); } active_ctx = ctx; } @@ -147,50 +191,125 @@ GPUContext *GPU_context_active_get(void) GLuint GPU_vao_default(void) { -#if TRUST_NO_ONE - assert(active_ctx); /* need at least an active context */ - assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ -#endif + 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; } GLuint GPU_vao_alloc(void) { -#if TRUST_NO_ONE - assert(active_ctx); /* need at least an active context */ - assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ -#endif - clear_orphans(active_ctx); - GLuint new_vao_id = 0; + orphans_clear(active_ctx); glGenVertexArrays(1, &new_vao_id); return new_vao_id; } -/* this can be called from multiple thread */ +GLuint GPU_fbo_alloc(void) +{ + GLuint new_fbo_id = 0; + orphans_clear(active_ctx); + glGenFramebuffers(1, &new_fbo_id); + return new_fbo_id; +} + +GLuint GPU_buf_alloc(void) +{ + GLuint new_buffer_id = 0; + orphans_clear(active_ctx); + glGenBuffers(1, &new_buffer_id); + return new_buffer_id; +} + +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) { -#if TRUST_NO_ONE - assert(ctx); -#endif + BLI_assert(ctx); if (ctx == active_ctx) { glDeleteVertexArrays(1, &vao_id); } else { - ctx->orphans_mutex.lock(); - ctx->orphaned_vertarray_ids.emplace_back(vao_id); - ctx->orphans_mutex.unlock(); + orphans_add(ctx, &ctx->orphaned_vertarray_ids, 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); + } +} + +void GPU_buf_free(GLuint buf_id) +{ + if (active_ctx) { + glDeleteBuffers(1, &buf_id); + } + else { + orphans_add(NULL, &orphaned_buffer_ids, 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); + } +} + +/* GPUBatch & GPUFrameBuffer contains respectively VAO & FBO indices + * which are not shared across contexts. So we need to keep track of + * ownership. */ + void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch) { + BLI_assert(ctx); + ctx->orphans_mutex.lock(); ctx->batches.emplace(batch); + ctx->orphans_mutex.unlock(); } void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch) { + BLI_assert(ctx); ctx->orphans_mutex.lock(); ctx->batches.erase(batch); ctx->orphans_mutex.unlock(); } + +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(); +#else + UNUSED_VARS(ctx, fb); +#endif +} + +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(); +#else + UNUSED_VARS(ctx, fb); +#endif +} diff --git a/source/blender/gpu/GPU_vertex_array_id.h b/source/blender/gpu/intern/gpu_context_private.h index ff84a290a5a..4881a892e38 100644 --- a/source/blender/gpu/GPU_vertex_array_id.h +++ b/source/blender/gpu/intern/gpu_context_private.h @@ -23,33 +23,46 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/gpu/GPU_vertex_array_id.h +/** \file blender/gpu/intern/gpu_context_private.h * \ingroup gpu * - * Manage GL vertex array IDs in a thread-safe way - * Use these instead of glGenBuffers & its friends - * - alloc must be called from a thread that is bound - * to the context that will be used for drawing with - * this vao. - * - free can be called from any thread + * This interface allow GPU to manage GL objects for mutiple context and threads. */ -#ifndef __GPU_VERTEX_ARRAY_ID_H__ -#define __GPU_VERTEX_ARRAY_ID_H__ +#ifndef __GPU_CONTEXT_PRIVATE_H__ +#define __GPU_CONTEXT_PRIVATE_H__ #ifdef __cplusplus extern "C" { #endif -#include "GPU_common.h" #include "GPU_context.h" +struct GPUFrameBuffer; + GLuint GPU_vao_default(void); + +/* These require a gl ctx bound. */ +GLuint GPU_buf_alloc(void); +GLuint GPU_tex_alloc(void); GLuint GPU_vao_alloc(void); -void GPU_vao_free(GLuint vao_id, GPUContext *); +GLuint GPU_fbo_alloc(void); + +/* These can be called any threads even without gl ctx. */ +void GPU_buf_free(GLuint buf_id); +void GPU_tex_free(GLuint tex_id); +/* These two need the ctx the id was created with. */ +void GPU_vao_free(GLuint vao_id, GPUContext *ctx); +void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx); + +void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch); +void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch); + +void gpu_context_add_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb); +void gpu_context_remove_framebuffer(GPUContext *ctx, struct GPUFrameBuffer *fb); #ifdef __cplusplus } #endif -#endif /* __GPU_VERTEX_ARRAY_ID_H__ */ +#endif /* __GPU_CONTEXT_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c index 9abfed2db05..901e09443d1 100644 --- a/source/blender/gpu/intern/gpu_element.c +++ b/source/blender/gpu/intern/gpu_element.c @@ -30,7 +30,8 @@ */ #include "GPU_element.h" -#include "GPU_buffer_id.h" + +#include "gpu_context_private.h" #include <stdlib.h> @@ -279,7 +280,7 @@ void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *builder, GPUIndexBuf *elem) #endif if (elem->vbo_id == 0) { - elem->vbo_id = GPU_buf_id_alloc(); + elem->vbo_id = GPU_buf_alloc(); } /* send data to GPU */ /* GL_ELEMENT_ARRAY_BUFFER changes the state of the last VAO bound, @@ -302,7 +303,7 @@ void GPU_indexbuf_use(GPUIndexBuf *elem) void GPU_indexbuf_discard(GPUIndexBuf *elem) { if (elem->vbo_id) { - GPU_buf_id_free(elem->vbo_id); + GPU_buf_free(elem->vbo_id); } free(elem); } diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index d28b82ac3cd..ba8dcb04269 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -42,7 +42,8 @@ #include "GPU_shader.h" #include "GPU_texture.h" -#include "intern/gpu_private.h" +#include "gpu_private.h" +#include "gpu_context_private.h" static ThreadLocal(void *) g_currentfb; @@ -69,6 +70,7 @@ typedef enum { #define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type)) struct GPUFrameBuffer { + GPUContext *ctx; GLuint object; GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT]; uint16_t dirty_flag; @@ -196,7 +198,9 @@ GPUFrameBuffer *GPU_framebuffer_create(void) static void gpu_framebuffer_init(GPUFrameBuffer *fb) { - glGenFramebuffers(1, &fb->object); + fb->object = GPU_fbo_alloc(); + fb->ctx = GPU_context_active_get(); + gpu_context_add_framebuffer(fb->ctx, fb); } void GPU_framebuffer_free(GPUFrameBuffer *fb) @@ -207,8 +211,11 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb) } } - /* This restores the framebuffer if it was bound */ - glDeleteFramebuffers(1, &fb->object); + if (fb->object != 0) { + /* This restores the framebuffer if it was bound */ + GPU_fbo_free(fb->object, fb->ctx); + gpu_context_remove_framebuffer(fb->ctx, fb); + } if (gpu_framebuffer_current_get() == fb->object) { gpu_framebuffer_current_set(0); diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index 66a467e339e..9674cf0b9f7 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -32,11 +32,10 @@ #include "UI_resources.h" #include "GPU_attr_binding.h" -#include "GPU_buffer_id.h" #include "GPU_immediate.h" -#include "GPU_vertex_array_id.h" #include "gpu_attr_binding_private.h" +#include "gpu_context_private.h" #include "gpu_primitive_private.h" #include "gpu_shader_private.h" #include "gpu_vertex_format_private.h" @@ -91,7 +90,7 @@ void immInit(void) #endif memset(&imm, 0, sizeof(Immediate)); - imm.vbo_id = GPU_buf_id_alloc(); + imm.vbo_id = GPU_buf_alloc(); glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); @@ -127,7 +126,7 @@ void immDeactivate(void) void immDestroy(void) { - GPU_buf_id_free(imm.vbo_id); + GPU_buf_free(imm.vbo_id); initialized = false; } diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index 78d4f491b66..55d0466c929 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -57,8 +57,6 @@ void GPU_init(void) gpu_extensions_init(); /* must come first */ - GPU_texture_orphans_init(); - GPU_material_orphans_init(); gpu_codegen_init(); gpu_framebuffer_module_init(); @@ -84,9 +82,6 @@ void GPU_exit(void) gpu_batch_exit(); - GPU_texture_orphans_exit(); - GPU_material_orphans_exit(); - if (G.debug & G_DEBUG_GPU) gpu_debug_exit(); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 9566f091ada..92aff91da32 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -75,9 +75,6 @@ # include "BKE_DerivedMesh.h" #endif -static ListBase g_orphaned_mat = {NULL, NULL}; -static ThreadMutex g_orphan_lock; - /* Structs */ struct GPUMaterial { @@ -175,44 +172,12 @@ void GPU_material_free(ListBase *gpumaterial) { for (LinkData *link = gpumaterial->first; link; link = link->next) { GPUMaterial *material = link->data; - - /* TODO(fclem): Check if the thread has an ogl context. */ - if (BLI_thread_is_main()) { - gpu_material_free_single(material); - MEM_freeN(material); - } - else { - BLI_mutex_lock(&g_orphan_lock); - BLI_addtail(&g_orphaned_mat, BLI_genericNodeN(material)); - BLI_mutex_unlock(&g_orphan_lock); - } + gpu_material_free_single(material); + MEM_freeN(material); } BLI_freelistN(gpumaterial); } -void GPU_material_orphans_init(void) -{ - BLI_mutex_init(&g_orphan_lock); -} - -void GPU_material_orphans_delete(void) -{ - BLI_mutex_lock(&g_orphan_lock); - LinkData *link; - while ((link = BLI_pophead(&g_orphaned_mat))) { - gpu_material_free_single((GPUMaterial *)link->data); - MEM_freeN(link->data); - MEM_freeN(link); - } - BLI_mutex_unlock(&g_orphan_lock); -} - -void GPU_material_orphans_exit(void) -{ - GPU_material_orphans_delete(); - BLI_mutex_end(&g_orphan_lock); -} - GPUBuiltin GPU_get_material_builtins(GPUMaterial *material) { return material->builtins; diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h index 996ba9c63a1..df55f7922b3 100644 --- a/source/blender/gpu/intern/gpu_private.h +++ b/source/blender/gpu/intern/gpu_private.h @@ -25,6 +25,9 @@ #ifndef __GPU_PRIVATE_H__ #define __GPU_PRIVATE_H__ +struct GPUContext; +struct GPUFrameBuffer; + /* call this before running any of the functions below */ void gpu_extensions_init(void); void gpu_extensions_exit(void); diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 1eae073d9c0..04b43d03c83 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -38,6 +38,7 @@ #include "DNA_space_types.h" #include "GPU_extensions.h" +#include "GPU_context.h" #include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_texture.h" @@ -572,6 +573,7 @@ void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader)) void GPU_shader_free(GPUShader *shader) { + BLI_assert(GPU_context_active_get() != NULL); BLI_assert(shader); if (shader->vertex) diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index 4b8413d0cc3..54c5f41bbd3 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -29,9 +29,11 @@ * GPU shader interface (C --> GLSL) */ -#include "gpu_batch_private.h" #include "GPU_shader_interface.h" -#include "GPU_vertex_array_id.h" + +#include "gpu_batch_private.h" +#include "gpu_context_private.h" + #include <stdlib.h> #include <stddef.h> #include <string.h> diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 4465136dd0f..5ac746ec9c1 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -38,22 +38,22 @@ #include "BKE_global.h" #include "GPU_batch.h" +#include "GPU_context.h" #include "GPU_debug.h" #include "GPU_draw.h" #include "GPU_extensions.h" -#include "GPU_framebuffer.h" #include "GPU_glew.h" +#include "GPU_framebuffer.h" #include "GPU_texture.h" +#include "gpu_context_private.h" + static struct GPUTextureGlobal { GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ GPUTexture *invalid_tex_2D; GPUTexture *invalid_tex_3D; } GG = {NULL, NULL, NULL}; -static ListBase g_orphaned_tex = {NULL, NULL}; -static ThreadMutex g_orphan_lock; - /* Maximum number of FBOs a texture can be attached to. */ #define GPU_TEX_MAX_FBO_ATTACHED 8 @@ -535,7 +535,7 @@ GPUTexture *GPU_texture_create_nD( gpu_texture_memory_footprint_add(tex); /* Generate Texture object */ - glGenTextures(1, &tex->bindcode); + tex->bindcode = GPU_tex_alloc(); if (!tex->bindcode) { if (err_out) @@ -668,7 +668,7 @@ static GPUTexture *GPU_texture_cube_create( gpu_texture_memory_footprint_add(tex); /* Generate Texture object */ - glGenTextures(1, &tex->bindcode); + tex->bindcode = GPU_tex_alloc(); if (!tex->bindcode) { if (err_out) @@ -752,7 +752,7 @@ GPUTexture *GPU_texture_create_buffer(GPUTextureFormat tex_format, const GLuint } /* Generate Texture object */ - glGenTextures(1, &tex->bindcode); + tex->bindcode = GPU_tex_alloc(); if (!tex->bindcode) { fprintf(stderr, "GPUTexture: texture create failed\n"); @@ -1301,17 +1301,6 @@ void GPU_texture_filters(GPUTexture *tex, GPUFilterFunction min_filter, GPUFilte glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter)); } - -static void gpu_texture_delete(GPUTexture *tex) -{ - if (tex->bindcode) - glDeleteTextures(1, &tex->bindcode); - - gpu_texture_memory_footprint_remove(tex); - - MEM_freeN(tex); -} - void GPU_texture_free(GPUTexture *tex) { tex->refcount--; @@ -1326,38 +1315,13 @@ void GPU_texture_free(GPUTexture *tex) } } - /* TODO(fclem): Check if the thread has an ogl context. */ - if (BLI_thread_is_main()) { - gpu_texture_delete(tex); - } - else { - BLI_mutex_lock(&g_orphan_lock); - BLI_addtail(&g_orphaned_tex, BLI_genericNodeN(tex)); - BLI_mutex_unlock(&g_orphan_lock); - } - } -} + if (tex->bindcode) + GPU_tex_free(tex->bindcode); -void GPU_texture_orphans_init(void) -{ - BLI_mutex_init(&g_orphan_lock); -} + gpu_texture_memory_footprint_remove(tex); -void GPU_texture_orphans_delete(void) -{ - BLI_mutex_lock(&g_orphan_lock); - LinkData *link; - while ((link = BLI_pophead(&g_orphaned_tex))) { - gpu_texture_delete((GPUTexture *)link->data); - MEM_freeN(link); + MEM_freeN(tex); } - BLI_mutex_unlock(&g_orphan_lock); -} - -void GPU_texture_orphans_exit(void) -{ - GPU_texture_orphans_delete(); - BLI_mutex_end(&g_orphan_lock); } void GPU_texture_ref(GPUTexture *tex) diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c index 1e39b2ea5b7..9b8441efd08 100644 --- a/source/blender/gpu/intern/gpu_uniformbuffer.c +++ b/source/blender/gpu/intern/gpu_uniformbuffer.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "gpu_codegen.h" +#include "gpu_context_private.h" #include "GPU_extensions.h" #include "GPU_glew.h" @@ -88,7 +89,7 @@ GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_ ubo->bindpoint = -1; /* Generate Buffer object */ - glGenBuffers(1, &ubo->bindcode); + ubo->bindcode = GPU_buf_alloc(); if (!ubo->bindcode) { if (err_out) @@ -127,7 +128,7 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou ubo->flag = GPU_UBO_FLAG_DIRTY; /* Generate Buffer object. */ - glGenBuffers(1, &ubo->buffer.bindcode); + ubo->buffer.bindcode = GPU_buf_alloc(); if (!ubo->buffer.bindcode) { if (err_out) @@ -190,7 +191,7 @@ void GPU_uniformbuffer_free(GPUUniformBuffer *ubo) gpu_uniformbuffer_dynamic_free(ubo); } - glDeleteBuffers(1, &ubo->bindcode); + GPU_buf_free(ubo->bindcode); MEM_freeN(ubo); } diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c index b25d9fc3a2c..d605378bf0e 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.c +++ b/source/blender/gpu/intern/gpu_vertex_buffer.c @@ -30,8 +30,10 @@ */ #include "GPU_vertex_buffer.h" -#include "GPU_buffer_id.h" + +#include "gpu_context_private.h" #include "gpu_vertex_format_private.h" + #include <stdlib.h> #include <string.h> @@ -88,7 +90,7 @@ void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts, const GPUVertFormat *for void GPU_vertbuf_discard(GPUVertBuf *verts) { if (verts->vbo_id) { - GPU_buf_id_free(verts->vbo_id); + GPU_buf_free(verts->vbo_id); #if VRAM_USAGE vbo_memory_usage -= GPU_vertbuf_size_get(verts); #endif @@ -117,7 +119,7 @@ void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len) #endif /* only create the buffer the 1st time */ if (verts->vbo_id == 0) { - verts->vbo_id = GPU_buf_id_alloc(); + verts->vbo_id = GPU_buf_alloc(); } /* discard previous data if any */ if (verts->data) { diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 0c7c85e0d94..f7d6561e17f 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -119,6 +119,7 @@ #include "GPU_material.h" #include "GPU_draw.h" +#include "GPU_immediate.h" #include "GPU_init_exit.h" #include "BKE_sound.h" @@ -515,9 +516,11 @@ void WM_exit_ext(bContext *C, const bool do_python) BLF_exit(); if (opengl_is_init) { + DRW_opengl_context_enable_ex(false); GPU_pass_cache_free(); - DRW_opengl_context_destroy(); GPU_exit(); + DRW_opengl_context_disable_ex(false); + DRW_opengl_context_destroy(); } #ifdef WITH_INTERNATIONAL diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index b87ae7e076c..c1006db34ef 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1921,8 +1921,6 @@ void wm_window_raise(wmWindow *win) void wm_window_swap_buffers(wmWindow *win) { - GPU_texture_orphans_delete(); /* XXX should be done elsewhere. */ - GPU_material_orphans_delete(); /* XXX Amen to that. */ GHOST_SwapWindowBuffers(win->ghostwin); } |