diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index b7ff1ae04a0..bff821bd9bc 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -297,6 +297,8 @@ panfrost_create_shader_state( struct panfrost_device *dev = pan_device(pctx->screen); so->base = *cso; + simple_mtx_init(&so->lock, mtx_plain); + /* Token deep copy to prevent memory corruption */ if (cso->type == PIPE_SHADER_IR_TGSI) @@ -339,6 +341,8 @@ panfrost_delete_shader_state( panfrost_bo_unreference(shader_state->linkage.bo); } + simple_mtx_destroy(&cso->lock); + free(cso->variants); free(so); } @@ -451,6 +455,8 @@ panfrost_bind_shader_state( signed variant = -1; struct panfrost_shader_variants *variants = (struct panfrost_shader_variants *) hwcso; + simple_mtx_lock(&variants->lock); + for (unsigned i = 0; i < variants->variant_count; ++i) { if (panfrost_variant_matches(ctx, &variants->variants[i], type)) { variant = i; @@ -528,6 +534,11 @@ panfrost_bind_shader_state( update_so_info(&shader_state->stream_output, shader_state->info.outputs_written); } + + /* TODO: it would be more efficient to release the lock before + * compiling instead of after, but that can race if thread A compiles a + * variant while thread B searches for that same variant */ + simple_mtx_unlock(&variants->lock); } static void * diff --git a/src/gallium/drivers/panfrost/pan_context.h b/src/gallium/drivers/panfrost/pan_context.h index 7e49c2c4faf..98394c1bcf8 100644 --- a/src/gallium/drivers/panfrost/pan_context.h +++ b/src/gallium/drivers/panfrost/pan_context.h @@ -44,6 +44,7 @@ #include "pipe/p_state.h" #include "util/u_blitter.h" #include "util/hash_table.h" +#include "util/simple_mtx.h" #include "midgard/midgard_compile.h" #include "compiler/shader_enums.h" @@ -286,6 +287,9 @@ struct panfrost_shader_variants { struct pipe_compute_state cbase; }; + /** Lock for the variants array */ + simple_mtx_t lock; + struct panfrost_shader_state *variants; unsigned variant_space;