Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-07-19 16:48:13 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-07-19 17:13:15 +0300
commit5037dd8abdf9335e998141336d4e15f81580c491 (patch)
tree0f6a1df0db24e27c3dbef47cf858132f0b975a66 /source/blender
parent3882d0943b33c42d1dbe67d10d2432c0e7191959 (diff)
GPU: Add GC to FBOs and UBOs and centralize all GCs
GPUFrameBuffers were being free when no context was attached or in the wrong gl context. This make sure this does not happen again. You can now safely free any gl resource from any thread (well as long as it's not used anymore!).
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/draw/DRW_engine.h4
-rw-r--r--source/blender/draw/intern/draw_manager.c20
-rw-r--r--source/blender/gpu/CMakeLists.txt6
-rw-r--r--source/blender/gpu/GPU_buffer_id.h53
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/GPU_texture.h5
-rw-r--r--source/blender/gpu/intern/gpu_batch.c3
-rw-r--r--source/blender/gpu/intern/gpu_batch_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_buffer_id.cpp90
-rw-r--r--source/blender/gpu/intern/gpu_context.cpp (renamed from source/blender/gpu/intern/gpu_vertex_array_id.cpp)177
-rw-r--r--source/blender/gpu/intern/gpu_context_private.h (renamed from source/blender/gpu/GPU_vertex_array_id.h)37
-rw-r--r--source/blender/gpu/intern/gpu_element.c7
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c15
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c7
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c5
-rw-r--r--source/blender/gpu/intern/gpu_material.c39
-rw-r--r--source/blender/gpu/intern/gpu_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_shader.c2
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c6
-rw-r--r--source/blender/gpu/intern/gpu_texture.c58
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c7
-rw-r--r--source/blender/gpu/intern/gpu_vertex_buffer.c8
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c5
-rw-r--r--source/blender/windowmanager/intern/wm_window.c2
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);
}