Mesa (main): zink: optimize shader recalc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jul 20 00:04:42 UTC 2021


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Fri May 14 18:33:15 2021 -0400

zink: optimize shader recalc

now we only have to loop over the changed shaders that exist for the
program, and we can avoid a lot of hashing operations by reusing stored
hash values where possible

Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11962>

---

 src/gallium/drivers/zink/zink_program.c | 54 ++++++++++++++-------------------
 src/gallium/drivers/zink/zink_program.h |  1 +
 2 files changed, 23 insertions(+), 32 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c
index e5e736c72df..2d6f462b4fa 100644
--- a/src/gallium/drivers/zink/zink_program.c
+++ b/src/gallium/drivers/zink/zink_program.c
@@ -274,40 +274,30 @@ destroy_shader_cache(struct zink_screen *screen, struct hash_table *sc)
 }
 
 static void
-update_shader_modules(struct zink_context *ctx, struct zink_shader *stages[ZINK_SHADER_COUNT], struct zink_gfx_program *prog, bool disallow_reuse)
+update_shader_modules(struct zink_context *ctx, struct zink_gfx_program *prog)
 {
-   struct zink_shader *dirty[ZINK_SHADER_COUNT] = {NULL};
-
-   unsigned gfx_bits = u_bit_consecutive(PIPE_SHADER_VERTEX, 5);
-   unsigned dirty_shader_stages = ctx->dirty_shader_stages & gfx_bits;
-   if (!dirty_shader_stages)
-      return;
-   /* we need to map pipe_shader_type -> gl_shader_stage so we can ensure that we're compiling
-    * the shaders in pipeline order and have builtin input/output locations match up after being compacted
-    */
-   while (dirty_shader_stages) {
-      unsigned type = u_bit_scan(&dirty_shader_stages);
-      dirty[tgsi_processor_to_shader_stage(type)] = stages[type];
+   bool hash_changed = false;
+   bool default_variants = true;
+   bool first = !!prog->modules[PIPE_SHADER_VERTEX];
+   u_foreach_bit(pstage, ctx->dirty_shader_stages & prog->stages_present) {
+      assert(prog->shaders[pstage]);
+      struct zink_shader_module *zm = get_shader_module_for_stage(ctx, prog->shaders[pstage], prog);
+      if (prog->modules[pstage] != zm)
+         hash_changed = true;
+      default_variants &= zm->default_variant;
+      prog->modules[pstage] = zm;
+      ctx->gfx_pipeline_state.modules[pstage] = zm->shader;
    }
 
-   for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
-      /* we need to iterate over the stages in pipeline-order here */
-      enum pipe_shader_type type = pipe_shader_type_from_mesa(i);
-      assert(type < ZINK_SHADER_COUNT);
-      if (dirty[i] || (stages[type] && !prog->modules[type])) {
-         struct zink_shader_module *zm;
-         zm = get_shader_module_for_stage(ctx, dirty[i] ? dirty[i] : stages[type], prog);
-         prog->modules[type] = zm;
-         ctx->gfx_pipeline_state.combined_dirty |= zm->shader != ctx->gfx_pipeline_state.modules[type];
-         ctx->gfx_pipeline_state.modules[type] = zm->shader;
-      } else if (!stages[type]) {
-         ctx->gfx_pipeline_state.combined_dirty |= ctx->gfx_pipeline_state.modules[type] != VK_NULL_HANDLE;
-         ctx->gfx_pipeline_state.modules[type] = VK_NULL_HANDLE;
-      }
+   if (hash_changed) {
+      if (default_variants && !first)
+         prog->last_variant_hash = prog->default_variant_hash;
+      else
+         prog->last_variant_hash = _mesa_hash_data(ctx->gfx_pipeline_state.modules, sizeof(ctx->gfx_pipeline_state.modules));
+      ctx->gfx_pipeline_state.combined_dirty = true;
    }
-   ctx->gfx_pipeline_state.module_hash = _mesa_hash_data(ctx->gfx_pipeline_state.modules, sizeof(ctx->gfx_pipeline_state.modules));
-   unsigned clean = u_bit_consecutive(PIPE_SHADER_VERTEX, 5);
-   ctx->dirty_shader_stages &= ~clean;
+   ctx->gfx_pipeline_state.module_hash = prog->last_variant_hash;
+   ctx->dirty_shader_stages &= ~u_bit_consecutive(PIPE_SHADER_VERTEX, 5);
 }
 
 static uint32_t
@@ -350,7 +340,7 @@ equals_gfx_pipeline_state(const void *a, const void *b)
 void
 zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog)
 {
-   update_shader_modules(ctx, ctx->gfx_stages, prog, true);
+   update_shader_modules(ctx, prog);
 }
 
 VkPipelineLayout
@@ -446,7 +436,7 @@ zink_create_gfx_program(struct zink_context *ctx,
    ctx->dirty_shader_stages |= prog->stages_present;
    assign_io(prog, prog->shaders);
 
-   update_shader_modules(ctx, prog->shaders, prog, false);
+   update_shader_modules(ctx, prog);
    prog->default_variant_hash = ctx->gfx_pipeline_state.module_hash;
 
    for (int i = 0; i < ARRAY_SIZE(prog->pipelines); ++i) {
diff --git a/src/gallium/drivers/zink/zink_program.h b/src/gallium/drivers/zink/zink_program.h
index be4cd6cb68f..eb77c828ec3 100644
--- a/src/gallium/drivers/zink/zink_program.h
+++ b/src/gallium/drivers/zink/zink_program.h
@@ -102,6 +102,7 @@ struct zink_gfx_program {
    struct zink_shader *shaders[ZINK_SHADER_COUNT];
    struct hash_table *pipelines[11]; // number of draw modes we support
    uint32_t default_variant_hash;
+   uint32_t last_variant_hash;
 };
 
 struct zink_compute_program {



More information about the mesa-commit mailing list