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!).
This commit is contained in:
Clément Foucault 2018-07-19 15:48:13 +02:00
parent 3882d0943b
commit 5037dd8abd
Notes: blender-bot 2023-02-14 07:39:44 +01:00
Referenced by issue #55695, Crash due to GPU memory leak when tweaking shader and light settings with Eevee
24 changed files with 250 additions and 321 deletions

View File

@ -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);

View File

@ -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(). */

View File

@ -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

View File

@ -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__ */

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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();
}
}

View File

@ -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
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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>

View File

@ -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,40 +1315,15 @@ 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);
gpu_texture_memory_footprint_remove(tex);
MEM_freeN(tex);
}
}
void GPU_texture_orphans_init(void)
{
BLI_mutex_init(&g_orphan_lock);
}
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);
}
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)
{
tex->refcount++;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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

View File

@ -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);
}