Mesa (main): radeonsi: store shader variants in an array

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri May 13 15:08:34 UTC 2022


Module: Mesa
Branch: main
Commit: d4e4aa997a656cff73be281ecece350cbc730b1b
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d4e4aa997a656cff73be281ecece350cbc730b1b

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Date:   Mon May  2 11:15:44 2022 +0200

radeonsi: store shader variants in an array

Instead of storing them in a linked list, put them in an array
in si_shader_selector. The keys are also stored separatly, to
avoid pointer chasing when searching a variant in si_shader_select_with_key.

This main point here is to simplify the code by storing everything
in the selector instead of splitting the list storage between the selector
and the shaders; this shouldn't affect performance in a meaningful way.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16273>

---

 src/gallium/drivers/radeonsi/si_shader.h          |  7 +--
 src/gallium/drivers/radeonsi/si_state_shaders.cpp | 64 +++++++++++++----------
 2 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/si_shader.h b/src/gallium/drivers/radeonsi/si_shader.h
index 24fdd4dc046..a7417461e00 100644
--- a/src/gallium/drivers/radeonsi/si_shader.h
+++ b/src/gallium/drivers/radeonsi/si_shader.h
@@ -473,8 +473,10 @@ struct si_shader_selector {
    gl_shader_stage stage;
 
    simple_mtx_t mutex;
-   struct si_shader *first_variant; /* immutable after the first variant */
-   struct si_shader *last_variant;  /* mutable */
+   union si_shader_key *keys;
+   unsigned variants_count;
+   unsigned variants_max_count;
+   struct si_shader **variants;
 
    /* The compiled NIR shader without a prolog and/or epilog (not
     * uploaded to a buffer object).
@@ -817,7 +819,6 @@ struct si_shader {
 
    struct si_shader_selector *selector;
    struct si_shader_selector *previous_stage_sel; /* for refcounting */
-   struct si_shader *next_variant;
 
    struct si_shader_part *prolog;
    struct si_shader *previous_stage; /* for GFX9 */
diff --git a/src/gallium/drivers/radeonsi/si_state_shaders.cpp b/src/gallium/drivers/radeonsi/si_state_shaders.cpp
index 31405624489..4ad3d8ca0e4 100644
--- a/src/gallium/drivers/radeonsi/si_state_shaders.cpp
+++ b/src/gallium/drivers/radeonsi/si_state_shaders.cpp
@@ -2559,7 +2559,7 @@ static int si_shader_select_with_key(struct si_context *sctx, struct si_shader_c
    struct si_shader_selector *sel = state->cso;
    struct si_shader_selector *previous_stage_sel = NULL;
    struct si_shader *current = state->current;
-   struct si_shader *iter, *shader = NULL;
+   struct si_shader *shader = NULL;
    const SHADER_KEY_TYPE *zeroed_key = (SHADER_KEY_TYPE*)&zeroed;
 
    /* "opt" must be the last field and "inlined_uniform_values" must be the last field inside opt.
@@ -2620,10 +2620,13 @@ current_not_ready:
    const int max_inline_uniforms_variants = 5;
 
    /* Find the shader variant. */
-   for (iter = sel->first_variant; iter; iter = iter->next_variant) {
-      const SHADER_KEY_TYPE *iter_key = (const SHADER_KEY_TYPE *)&iter->key;
+   const unsigned cnt = sel->variants_count;
+   for (unsigned i = 0; i < cnt; i++) {
+      const SHADER_KEY_TYPE *iter_key = (const SHADER_KEY_TYPE *)&sel->keys[i];
 
       if (memcmp(iter_key, key, key_size_no_uniforms) == 0) {
+         struct si_shader *iter = sel->variants[i];
+
          /* Check the inlined uniform values separately, and count
           * the number of variants based on them.
           */
@@ -2662,7 +2665,7 @@ current_not_ready:
             return -1; /* skip the draw call */
          }
 
-         state->current = iter;
+         state->current = sel->variants[i];
          return 0;
       }
    }
@@ -2747,6 +2750,14 @@ current_not_ready:
       }
    }
 
+   if (sel->variants_count == sel->variants_max_count) {
+      sel->variants_max_count += 2;
+      sel->variants = (struct si_shader**)
+         realloc(sel->variants, sel->variants_max_count * sizeof(struct si_shader*));
+      sel->keys = (union si_shader_key*)
+         realloc(sel->keys, sel->variants_max_count * sizeof(union si_shader_key));
+   }
+
    /* Keep the reference to the 1st shader of merged shaders, so that
     * Gallium can't destroy it before we destroy the 2nd shader.
     *
@@ -2771,13 +2782,9 @@ current_not_ready:
 
       /* Add only after the ready fence was reset, to guard against a
        * race with si_bind_XX_shader. */
-      if (!sel->last_variant) {
-         sel->first_variant = shader;
-         sel->last_variant = shader;
-      } else {
-         sel->last_variant->next_variant = shader;
-         sel->last_variant = shader;
-      }
+      sel->variants[sel->variants_count] = shader;
+      sel->keys[sel->variants_count] = shader->key;
+      sel->variants_count++;
 
       /* Use the default (unoptimized) shader for now. */
       key = use_local_key_copy(key, &local_key, key_size);
@@ -2793,13 +2800,9 @@ current_not_ready:
    /* Reset the fence before adding to the variant list. */
    util_queue_fence_reset(&shader->ready);
 
-   if (!sel->last_variant) {
-      sel->first_variant = shader;
-      sel->last_variant = shader;
-   } else {
-      sel->last_variant->next_variant = shader;
-      sel->last_variant = shader;
-   }
+   sel->variants[sel->variants_count] = shader;
+   sel->keys[sel->variants_count] = shader->key;
+   sel->variants_count++;
 
    simple_mtx_unlock(&sel->mutex);
 
@@ -3092,6 +3095,11 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
    sel->screen = sscreen;
    sel->compiler_ctx_state.debug = sctx->debug;
    sel->compiler_ctx_state.is_debug_context = sctx->is_debug;
+   sel->variants_max_count = 2;
+   sel->keys = (union si_shader_key *)
+      realloc(NULL, sel->variants_max_count * sizeof(union si_shader_key));
+   sel->variants = (struct si_shader **)
+      realloc(NULL, sel->variants_max_count * sizeof(struct si_shader *));
 
    if (state->type == PIPE_SHADER_IR_TGSI) {
       sel->nir = tgsi_to_nir(state->tokens, ctx->screen, true);
@@ -3292,7 +3300,7 @@ static void si_bind_vs_shader(struct pipe_context *ctx, void *state)
       return;
 
    sctx->shader.vs.cso = sel;
-   sctx->shader.vs.current = sel ? sel->first_variant : NULL;
+   sctx->shader.vs.current = (sel && sel->variants_count) ? sel->variants[0] : NULL;
    sctx->num_vs_blit_sgprs = sel ? sel->info.base.vs.blit_sgprs_amd : 0;
    sctx->vs_uses_draw_id = sel ? sel->info.uses_drawid : false;
    sctx->fixed_func_tcs_shader.key.ge.mono.u.ff_tcs_inputs_to_copy = sel ? sel->info.outputs_written : 0;
@@ -3381,7 +3389,7 @@ static void si_bind_gs_shader(struct pipe_context *ctx, void *state)
       return;
 
    sctx->shader.gs.cso = sel;
-   sctx->shader.gs.current = sel ? sel->first_variant : NULL;
+   sctx->shader.gs.current = (sel && sel->variants_count) ? sel->variants[0] : NULL;
    sctx->ia_multi_vgt_param_key.u.uses_gs = sel != NULL;
 
    si_update_common_shader_state(sctx, sel, PIPE_SHADER_GEOMETRY);
@@ -3412,7 +3420,7 @@ static void si_bind_tcs_shader(struct pipe_context *ctx, void *state)
       return;
 
    sctx->shader.tcs.cso = sel;
-   sctx->shader.tcs.current = sel ? sel->first_variant : NULL;
+   sctx->shader.tcs.current = (sel && sel->variants_count) ? sel->variants[0] : NULL;
    sctx->shader.tcs.key.ge.part.tcs.epilog.invoc0_tess_factors_are_def =
       sel ? sel->info.tessfactors_are_def_in_all_invocs : 0;
    si_update_tess_uses_prim_id(sctx);
@@ -3435,7 +3443,7 @@ static void si_bind_tes_shader(struct pipe_context *ctx, void *state)
       return;
 
    sctx->shader.tes.cso = sel;
-   sctx->shader.tes.current = sel ? sel->first_variant : NULL;
+   sctx->shader.tes.current = (sel && sel->variants_count) ? sel->variants[0] : NULL;
    sctx->ia_multi_vgt_param_key.u.uses_tess = sel != NULL;
    si_update_tess_uses_prim_id(sctx);
 
@@ -3509,7 +3517,7 @@ static void si_bind_ps_shader(struct pipe_context *ctx, void *state)
       return;
 
    sctx->shader.ps.cso = sel;
-   sctx->shader.ps.current = sel ? sel->first_variant : NULL;
+   sctx->shader.ps.current = (sel && sel->variants_count) ? sel->variants[0] : NULL;
 
    si_update_common_shader_state(sctx, sel, PIPE_SHADER_FRAGMENT);
    if (sel) {
@@ -3614,7 +3622,6 @@ static void si_destroy_shader_selector(struct pipe_context *ctx, void *cso)
 {
    struct si_context *sctx = (struct si_context *)ctx;
    struct si_shader_selector *sel = (struct si_shader_selector *)cso;
-   struct si_shader *p = sel->first_variant, *c;
    enum pipe_shader_type type = pipe_shader_type_from_mesa(sel->stage);
 
    util_queue_drop_job(&sctx->screen->shader_compiler_queue, &sel->ready);
@@ -3624,10 +3631,8 @@ static void si_destroy_shader_selector(struct pipe_context *ctx, void *cso)
       sctx->shaders[type].current = NULL;
    }
 
-   while (p) {
-      c = p->next_variant;
-      si_delete_shader(sctx, p);
-      p = c;
+   for (unsigned i = 0; i < sel->variants_count; i++) {
+      si_delete_shader(sctx, sel->variants[i]);
    }
 
    if (sel->main_shader_part)
@@ -3639,6 +3644,9 @@ static void si_destroy_shader_selector(struct pipe_context *ctx, void *cso)
    if (sel->main_shader_part_ngg)
       si_delete_shader(sctx, sel->main_shader_part_ngg);
 
+   free(sel->keys);
+   free(sel->variants);
+
    util_queue_fence_destroy(&sel->ready);
    simple_mtx_destroy(&sel->mutex);
    ralloc_free(sel->nir);



More information about the mesa-commit mailing list