Fix #138354: GPU: Race condition with SRGB builtin uniform
Multiple threads would be setting the globals `g_shader_builtin_srgb_transform` and `g_shader_builtin_srgb_is_dirty`. These are use for color management inside the builtin shaders. But the render thread could modify these values even if its shader have no use of these. The fix is to move these globals to the `gpu::Context` class. This way we remove the race condition.
This commit is contained in:
@@ -74,6 +74,10 @@ class Context {
|
||||
/** Texture pool used to recycle temporary texture (or render target) memory. */
|
||||
TexturePool *texture_pool = nullptr;
|
||||
|
||||
/** Global state to avoid setting the srgb builtin uniform for every shader bind. */
|
||||
int shader_builtin_srgb_transform = 0;
|
||||
bool shader_builtin_srgb_is_dirty = false;
|
||||
|
||||
protected:
|
||||
/** Thread on which this context is active. */
|
||||
pthread_t thread_;
|
||||
|
||||
@@ -56,7 +56,6 @@ void immBindShader(GPUShader *shader)
|
||||
|
||||
GPU_shader_bind(shader);
|
||||
GPU_matrix_bind(shader);
|
||||
Shader::set_srgb_uniform(shader);
|
||||
}
|
||||
|
||||
void immBindBuiltinProgram(eGPUBuiltinShader shader_id)
|
||||
|
||||
@@ -407,7 +407,7 @@ void GPU_shader_bind(GPUShader *gpu_shader)
|
||||
ctx->shader = shader;
|
||||
shader->bind();
|
||||
GPU_matrix_bind(gpu_shader);
|
||||
Shader::set_srgb_uniform(gpu_shader);
|
||||
Shader::set_srgb_uniform(ctx, gpu_shader);
|
||||
shader->constants.is_dirty = false;
|
||||
}
|
||||
else {
|
||||
@@ -415,8 +415,8 @@ void GPU_shader_bind(GPUShader *gpu_shader)
|
||||
shader->bind();
|
||||
shader->constants.is_dirty = false;
|
||||
}
|
||||
if (Shader::srgb_uniform_dirty_get()) {
|
||||
Shader::set_srgb_uniform(gpu_shader);
|
||||
if (ctx->shader_builtin_srgb_is_dirty) {
|
||||
Shader::set_srgb_uniform(ctx, gpu_shader);
|
||||
}
|
||||
if (GPU_matrix_dirty_get()) {
|
||||
GPU_matrix_bind(gpu_shader);
|
||||
@@ -790,28 +790,21 @@ namespace blender::gpu {
|
||||
* frame-buffer color-space.
|
||||
* \{ */
|
||||
|
||||
static int g_shader_builtin_srgb_transform = 0;
|
||||
static bool g_shader_builtin_srgb_is_dirty = false;
|
||||
|
||||
bool Shader::srgb_uniform_dirty_get()
|
||||
{
|
||||
return g_shader_builtin_srgb_is_dirty;
|
||||
}
|
||||
|
||||
void Shader::set_srgb_uniform(GPUShader *shader)
|
||||
void Shader::set_srgb_uniform(Context *ctx, GPUShader *shader)
|
||||
{
|
||||
int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SRGB_TRANSFORM);
|
||||
if (loc != -1) {
|
||||
GPU_shader_uniform_int_ex(shader, loc, 1, 1, &g_shader_builtin_srgb_transform);
|
||||
GPU_shader_uniform_int_ex(shader, loc, 1, 1, &ctx->shader_builtin_srgb_transform);
|
||||
}
|
||||
g_shader_builtin_srgb_is_dirty = false;
|
||||
ctx->shader_builtin_srgb_is_dirty = false;
|
||||
}
|
||||
|
||||
void Shader::set_framebuffer_srgb_target(int use_srgb_to_linear)
|
||||
{
|
||||
if (g_shader_builtin_srgb_transform != use_srgb_to_linear) {
|
||||
g_shader_builtin_srgb_transform = use_srgb_to_linear;
|
||||
g_shader_builtin_srgb_is_dirty = true;
|
||||
Context *ctx = Context::get();
|
||||
if (ctx->shader_builtin_srgb_transform != use_srgb_to_linear) {
|
||||
ctx->shader_builtin_srgb_transform = use_srgb_to_linear;
|
||||
ctx->shader_builtin_srgb_is_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,8 +131,7 @@ class Shader {
|
||||
return parent_shader_;
|
||||
}
|
||||
|
||||
static bool srgb_uniform_dirty_get();
|
||||
static void set_srgb_uniform(GPUShader *shader);
|
||||
static void set_srgb_uniform(Context *ctx, GPUShader *shader);
|
||||
static void set_framebuffer_srgb_target(int use_srgb_to_linear);
|
||||
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user