zink: add locking for program caches
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Tue, 20 Sep 2022 18:23:14 +0000 (14:23 -0400)
committerMarge Bot <emma+marge@anholt.net>
Fri, 23 Sep 2022 17:02:11 +0000 (17:02 +0000)
these are context-based, so destroying them from another context needs locks

locks are not currently able to be contended

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18689>

src/gallium/drivers/zink/zink_compiler.c
src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_draw.cpp
src/gallium/drivers/zink/zink_program.c
src/gallium/drivers/zink/zink_types.h

index b2170c7..ebd63ab 100644 (file)
@@ -3248,11 +3248,14 @@ zink_shader_free(struct zink_context *ctx, struct zink_shader *shader)
          unsigned stages_present = prog->stages_present;
          if (prog->shaders[MESA_SHADER_TESS_CTRL] && prog->shaders[MESA_SHADER_TESS_CTRL]->is_generated)
             stages_present &= ~BITFIELD_BIT(MESA_SHADER_TESS_CTRL);
-         struct hash_table *ht = &ctx->program_cache[zink_program_cache_stages(stages_present)];
+         unsigned idx = zink_program_cache_stages(stages_present);
+         struct hash_table *ht = &ctx->program_cache[idx];
+         simple_mtx_lock(&ctx->program_lock[idx]);
          struct hash_entry *he = _mesa_hash_table_search(ht, prog->shaders);
          assert(he);
          _mesa_hash_table_remove(ht, he);
          prog->base.removed = true;
+         simple_mtx_unlock(&ctx->program_lock[idx]);
       }
       if (stage != MESA_SHADER_TESS_CTRL || !shader->is_generated) {
          prog->shaders[stage] = NULL;
index 29d4854..86e7597 100644 (file)
@@ -97,10 +97,12 @@ zink_context_destroy(struct pipe_context *pctx)
    }
 
    for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_cache); i++) {
+      simple_mtx_lock((&ctx->program_lock[i]));
       hash_table_foreach(&ctx->program_cache[i], entry) {
          struct zink_program *pg = entry->data;
          pg->removed = true;
       }
+      simple_mtx_unlock((&ctx->program_lock[i]));
    }
 
    if (ctx->blitter)
@@ -158,6 +160,8 @@ zink_context_destroy(struct pipe_context *pctx)
    slab_destroy_child(&ctx->transfer_pool);
    for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_cache); i++)
       _mesa_hash_table_clear(&ctx->program_cache[i], NULL);
+   for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
+      simple_mtx_destroy(&ctx->program_lock[i]);
    _mesa_hash_table_destroy(ctx->render_pass_cache, NULL);
    slab_destroy_child(&ctx->transfer_pool_unsync);
 
index 96808bc..5a40053 100644 (file)
@@ -1112,6 +1112,8 @@ zink_init_draw_functions(struct zink_context *ctx, struct zink_screen *screen)
    _mesa_hash_table_init(&ctx->program_cache[5], ctx, hash_gfx_program<5>, equals_gfx_program<5>);
    _mesa_hash_table_init(&ctx->program_cache[6], ctx, hash_gfx_program<6>, equals_gfx_program<6>);
    _mesa_hash_table_init(&ctx->program_cache[7], ctx, hash_gfx_program<7>, equals_gfx_program<7>);
+   for (unsigned i = 0; i < ARRAY_SIZE(ctx->program_lock); i++)
+      simple_mtx_init(&ctx->program_lock[i], mtx_plain);
 }
 
 void
index 01094f7..16cc6b2 100644 (file)
@@ -414,6 +414,7 @@ zink_gfx_program_update(struct zink_context *ctx)
    if (ctx->gfx_dirty) {
       struct zink_gfx_program *prog = NULL;
 
+      simple_mtx_lock(&ctx->program_lock[zink_program_cache_stages(ctx->shader_stages)]);
       struct hash_table *ht = &ctx->program_cache[zink_program_cache_stages(ctx->shader_stages)];
       const uint32_t hash = ctx->gfx_hash;
       struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ht, hash, ctx->gfx_stages);
@@ -432,6 +433,7 @@ zink_gfx_program_update(struct zink_context *ctx)
          _mesa_hash_table_insert_pre_hashed(ht, hash, prog->shaders, prog);
          generate_gfx_program_modules(ctx, zink_screen(ctx->base.screen), prog, &ctx->gfx_pipeline_state);
       }
+      simple_mtx_unlock(&ctx->program_lock[zink_program_cache_stages(ctx->shader_stages)]);
       if (prog && prog != ctx->curr_program)
          zink_batch_reference_program(&ctx->batch, &prog->base);
       if (ctx->curr_program)
index b063856..64d38e0 100644 (file)
@@ -1398,6 +1398,7 @@ struct zink_context {
     * thus only 3 stages need to be considered, giving 2^3 = 8 program caches.
     */
    struct hash_table program_cache[8];
+   simple_mtx_t program_lock[8];
    uint32_t gfx_hash;
    struct zink_gfx_program *curr_program;
    struct set gfx_inputs;