Fix crash with OpenGL rendering in multiple threads on macOS.
On macOS we must always go through BLI_thread_local_get/set(). Differential Revision: https://developer.blender.org/D3470
This commit is contained in:
Submodule release/scripts/addons updated: ebd058d7a6...c88411ff77
@@ -42,7 +42,9 @@
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_texture.h"
|
||||
|
||||
static ThreadLocal(GLuint) g_currentfb;
|
||||
#include "intern/gpu_private.h"
|
||||
|
||||
static ThreadLocal(void*) g_currentfb;
|
||||
|
||||
typedef enum {
|
||||
GPU_FB_DEPTH_ATTACHMENT = 0,
|
||||
@@ -163,6 +165,26 @@ static void gpu_print_framebuffer_error(GLenum status, char err_out[256])
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_framebuffer_module_init(void)
|
||||
{
|
||||
BLI_thread_local_create(g_currentfb);
|
||||
}
|
||||
|
||||
void gpu_framebuffer_module_exit(void)
|
||||
{
|
||||
BLI_thread_local_delete(g_currentfb);
|
||||
}
|
||||
|
||||
static uint gpu_framebuffer_current_get()
|
||||
{
|
||||
return GET_UINT_FROM_POINTER(BLI_thread_local_get(g_currentfb));
|
||||
}
|
||||
|
||||
static void gpu_framebuffer_current_set(uint object)
|
||||
{
|
||||
BLI_thread_local_set(g_currentfb, SET_UINT_IN_POINTER(object));
|
||||
}
|
||||
|
||||
/* GPUFrameBuffer */
|
||||
|
||||
GPUFrameBuffer *GPU_framebuffer_create(void)
|
||||
@@ -188,8 +210,8 @@ void GPU_framebuffer_free(GPUFrameBuffer *fb)
|
||||
/* This restores the framebuffer if it was bound */
|
||||
glDeleteFramebuffers(1, &fb->object);
|
||||
|
||||
if (g_currentfb == fb->object) {
|
||||
g_currentfb = 0;
|
||||
if (gpu_framebuffer_current_get() == fb->object) {
|
||||
gpu_framebuffer_current_set(0);
|
||||
}
|
||||
|
||||
MEM_freeN(fb);
|
||||
@@ -341,7 +363,7 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb)
|
||||
GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT];
|
||||
int numslots = 0;
|
||||
|
||||
BLI_assert(g_currentfb == fb->object);
|
||||
BLI_assert(gpu_framebuffer_current_get() == fb->object);
|
||||
|
||||
/* Update attachments */
|
||||
for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) {
|
||||
@@ -385,10 +407,10 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
|
||||
if (fb->object == 0)
|
||||
gpu_framebuffer_init(fb);
|
||||
|
||||
if (g_currentfb != fb->object)
|
||||
if (gpu_framebuffer_current_get() != fb->object)
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
|
||||
|
||||
g_currentfb = fb->object;
|
||||
gpu_framebuffer_current_set(fb->object);
|
||||
|
||||
if (fb->dirty_flag != 0)
|
||||
gpu_framebuffer_update_attachments(fb);
|
||||
@@ -409,20 +431,20 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
|
||||
|
||||
void GPU_framebuffer_restore(void)
|
||||
{
|
||||
if (g_currentfb != 0) {
|
||||
if (gpu_framebuffer_current_get() != 0) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
g_currentfb = 0;
|
||||
gpu_framebuffer_current_set(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
|
||||
{
|
||||
return (fb->object == g_currentfb) && (fb->object != 0);
|
||||
return (fb->object == gpu_framebuffer_current_get()) && (fb->object != 0);
|
||||
}
|
||||
|
||||
unsigned int GPU_framebuffer_current_get(void)
|
||||
{
|
||||
return g_currentfb;
|
||||
return gpu_framebuffer_current_get();
|
||||
}
|
||||
|
||||
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
|
||||
@@ -513,7 +535,7 @@ void GPU_framebuffer_blit(
|
||||
{
|
||||
BLI_assert(blit_buffers != 0);
|
||||
|
||||
GLuint prev_fb = g_currentfb;
|
||||
GLuint prev_fb = gpu_framebuffer_current_get();
|
||||
|
||||
/* Framebuffers must be up to date. This simplify this function. */
|
||||
if (fb_read->dirty_flag != 0 || fb_read->object == 0) {
|
||||
@@ -573,7 +595,7 @@ void GPU_framebuffer_blit(
|
||||
}
|
||||
else {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, prev_fb);
|
||||
g_currentfb = prev_fb;
|
||||
gpu_framebuffer_current_set(prev_fb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,13 +608,13 @@ void GPU_framebuffer_recursive_downsample(
|
||||
void (*callback)(void *userData, int level), void *userData)
|
||||
{
|
||||
/* Framebuffer must be up to date and bound. This simplify this function. */
|
||||
if (g_currentfb != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
|
||||
if (gpu_framebuffer_current_get() != fb->object || fb->dirty_flag != 0 || fb->object == 0) {
|
||||
GPU_framebuffer_bind(fb);
|
||||
}
|
||||
/* HACK: We make the framebuffer appear not bound in order to
|
||||
* not trigger any error in GPU_texture_bind(). */
|
||||
GLuint prev_fb = g_currentfb;
|
||||
g_currentfb = 0;
|
||||
GLuint prev_fb = gpu_framebuffer_current_get();
|
||||
gpu_framebuffer_current_set(0);
|
||||
|
||||
int i;
|
||||
int current_dim[2] = {fb->width, fb->height};
|
||||
@@ -640,7 +662,7 @@ void GPU_framebuffer_recursive_downsample(
|
||||
}
|
||||
}
|
||||
|
||||
g_currentfb = prev_fb;
|
||||
gpu_framebuffer_current_set(prev_fb);
|
||||
}
|
||||
|
||||
/* GPUOffScreen */
|
||||
|
||||
@@ -60,6 +60,7 @@ void GPU_init(void)
|
||||
GPU_texture_orphans_init();
|
||||
GPU_material_orphans_init();
|
||||
gpu_codegen_init();
|
||||
gpu_framebuffer_module_init();
|
||||
|
||||
if (G.debug & G_DEBUG_GPU)
|
||||
gpu_debug_init();
|
||||
@@ -89,6 +90,7 @@ void GPU_exit(void)
|
||||
if (G.debug & G_DEBUG_GPU)
|
||||
gpu_debug_exit();
|
||||
|
||||
gpu_framebuffer_module_exit();
|
||||
gpu_codegen_exit();
|
||||
|
||||
gpu_extensions_exit(); /* must come last */
|
||||
|
||||
@@ -33,4 +33,8 @@ void gpu_extensions_exit(void);
|
||||
void gpu_debug_init(void);
|
||||
void gpu_debug_exit(void);
|
||||
|
||||
/* gpu_framebuffer.c */
|
||||
void gpu_framebuffer_module_init(void);
|
||||
void gpu_framebuffer_module_exit(void);
|
||||
|
||||
#endif /* __GPU_PRIVATE_H__ */
|
||||
|
||||
Reference in New Issue
Block a user