Mesa (main): zink: handle shader key variants that have nonseamless cubemaps

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 7 14:47:38 UTC 2022


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Mon Mar 21 14:48:19 2022 -0400

zink: handle shader key variants that have nonseamless cubemaps

this is just the program-based handling, which means finding the right
variant and/or creating new ones based on matching a 32bit mask indicating
which textures must be rewritten

Reviewed-by: Erik Faye-Lund <erik.faye-lund at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15536>

---

 src/gallium/drivers/zink/zink_program.c     | 90 +++++++++++++++++------------
 src/gallium/drivers/zink/zink_program.h     |  5 +-
 src/gallium/drivers/zink/zink_shader_keys.h |  1 +
 3 files changed, 56 insertions(+), 40 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c
index a72c881d97c..95b0f39cba4 100644
--- a/src/gallium/drivers/zink/zink_program.c
+++ b/src/gallium/drivers/zink/zink_program.c
@@ -69,16 +69,20 @@ debug_describe_zink_compute_program(char *buf, const struct zink_compute_program
 static bool
 shader_key_matches(const struct zink_shader_module *zm, const struct zink_shader_key *key, unsigned num_uniforms)
 {
-   if (zm->key_size != key->size || zm->num_uniforms != num_uniforms)
+   if (zm->key_size != key->size || zm->num_uniforms != num_uniforms || zm->has_nonseamless != !!key->base.nonseamless_cube_mask)
       return false;
+   const uint32_t nonseamless_size = zm->has_nonseamless ? sizeof(uint32_t) : 0;
    return !memcmp(zm->key, key, zm->key_size) &&
-          (!num_uniforms || !memcmp(zm->key + zm->key_size, key->base.inlined_uniform_values, zm->num_uniforms * sizeof(uint32_t)));
+          (!nonseamless_size || !memcmp(zm->key + zm->key_size, &key->base.nonseamless_cube_mask, nonseamless_size)) &&
+          (!num_uniforms || !memcmp(zm->key + zm->key_size + nonseamless_size,
+                                    key->base.inlined_uniform_values, zm->num_uniforms * sizeof(uint32_t)));
 }
 
 static uint32_t
 shader_module_hash(const struct zink_shader_module *zm)
 {
-   unsigned key_size = zm->key_size + zm->num_uniforms * sizeof(uint32_t);
+   const uint32_t nonseamless_size = zm->has_nonseamless ? sizeof(uint32_t) : 0;
+   unsigned key_size = zm->key_size + nonseamless_size + zm->num_uniforms * sizeof(uint32_t);
    return _mesa_hash_data(zm->key, key_size);
 }
 
@@ -91,7 +95,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
    enum pipe_shader_type pstage = pipe_shader_type_from_mesa(stage);
    VkShaderModule mod;
    struct zink_shader_module *zm = NULL;
-   unsigned inline_size = 0;
+   unsigned inline_size = 0, nonseamless_size = 0;
    struct zink_shader_key *key = &state->shader_keys.key[pstage];
 
    if (ctx && zs->nir->info.num_inlinable_uniforms &&
@@ -101,9 +105,11 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
       else
          key->inline_uniforms = false;
    }
+   if (key->base.nonseamless_cube_mask)
+      nonseamless_size = sizeof(uint32_t);
 
    struct zink_shader_module *iter, *next;
-   LIST_FOR_EACH_ENTRY_SAFE(iter, next, &prog->shader_cache[pstage][!!inline_size], list) {
+   LIST_FOR_EACH_ENTRY_SAFE(iter, next, &prog->shader_cache[pstage][!!nonseamless_size][!!inline_size], list) {
       if (!shader_key_matches(iter, key, inline_size))
          continue;
       list_delinit(&iter->list);
@@ -112,7 +118,7 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
    }
 
    if (!zm) {
-      zm = malloc(sizeof(struct zink_shader_module) + key->size + inline_size * sizeof(uint32_t));
+      zm = malloc(sizeof(struct zink_shader_module) + key->size + nonseamless_size + inline_size * sizeof(uint32_t));
       if (!zm) {
          return NULL;
       }
@@ -137,17 +143,22 @@ get_shader_module_for_stage(struct zink_context *ctx, struct zink_screen *screen
          zm->key_size = 0;
          memset(zm->key, 0, key->size);
       }
+      if (nonseamless_size) {
+         /* nonseamless mask gets added to base key if it exists */
+         memcpy(zm->key + key->size, &key->base.nonseamless_cube_mask, nonseamless_size);
+      }
+      zm->has_nonseamless = !!nonseamless_size;
       if (inline_size)
-         memcpy(zm->key + key->size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
+         memcpy(zm->key + key->size + nonseamless_size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
       if (zs->is_generated)
          zm->hash = zink_get_tcs_key(ctx)->patch_vertices;
       else
          zm->hash = shader_module_hash(zm);
-      zm->default_variant = !inline_size && list_is_empty(&prog->shader_cache[pstage][0]);
+      zm->default_variant = !inline_size && list_is_empty(&prog->shader_cache[pstage][0][0]);
       if (inline_size)
          prog->inlined_variant_count[pstage]++;
    }
-   list_add(&zm->list, &prog->shader_cache[pstage][!!inline_size]);
+   list_add(&zm->list, &prog->shader_cache[pstage][!!nonseamless_size][!!inline_size]);
    return zm;
 }
 
@@ -258,19 +269,6 @@ zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog)
    update_gfx_shader_modules(ctx, zink_screen(ctx->base.screen), prog, ctx->dirty_shader_stages & prog->stages_present, &ctx->gfx_pipeline_state);
 }
 
-static bool
-uniforms_match(const struct zink_shader_module *zm, uint32_t *uniforms, unsigned num_uniforms)
-{
-   assert(zm->num_uniforms == num_uniforms);
-   return !memcmp(zm->key, uniforms, zm->num_uniforms * sizeof(uint32_t));
-}
-
-static uint32_t
-cs_module_hash(const struct zink_shader_module *zm)
-{
-   return _mesa_hash_data(zm->key, zm->num_uniforms * sizeof(uint32_t));
-}
-
 static void
 update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *comp)
 {
@@ -278,7 +276,7 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
    struct zink_shader *zs = comp->shader;
    VkShaderModule mod;
    struct zink_shader_module *zm = NULL;
-   unsigned inline_size = 0;
+   unsigned inline_size = 0, nonseamless_size = 0;
    struct zink_shader_key *key = &ctx->compute_pipeline_state.key;
 
    if (ctx && zs->nir->info.num_inlinable_uniforms &&
@@ -288,11 +286,13 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
       else
          key->inline_uniforms = false;
    }
+   if (key->base.nonseamless_cube_mask)
+      nonseamless_size = sizeof(uint32_t);
 
-   if (inline_size) {
+   if (inline_size || nonseamless_size) {
       struct zink_shader_module *iter, *next;
-      LIST_FOR_EACH_ENTRY_SAFE(iter, next, &comp->shader_cache, list) {
-         if (!uniforms_match(iter, key->base.inlined_uniform_values, inline_size))
+      LIST_FOR_EACH_ENTRY_SAFE(iter, next, &comp->shader_cache[!!nonseamless_size], list) {
+         if (!shader_key_matches(iter, key, inline_size))
             continue;
          list_delinit(&iter->list);
          zm = iter;
@@ -303,7 +303,7 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
    }
 
    if (!zm) {
-      zm = malloc(sizeof(struct zink_shader_module) + inline_size * sizeof(uint32_t));
+      zm = malloc(sizeof(struct zink_shader_module) + nonseamless_size + inline_size * sizeof(uint32_t));
       if (!zm) {
          return;
       }
@@ -316,14 +316,19 @@ update_cs_shader_module(struct zink_context *ctx, struct zink_compute_program *c
       list_inithead(&zm->list);
       zm->num_uniforms = inline_size;
       zm->key_size = 0;
-      assert(inline_size);
-      memcpy(zm->key, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
-      zm->hash = cs_module_hash(zm);
+      zm->has_nonseamless = !!nonseamless_size;
+      assert(nonseamless_size || inline_size);
+      if (nonseamless_size)
+         memcpy(zm->key, &key->base.nonseamless_cube_mask, nonseamless_size);
+      if (inline_size)
+         memcpy(zm->key + nonseamless_size, key->base.inlined_uniform_values, inline_size * sizeof(uint32_t));
+      zm->hash = shader_module_hash(zm);
       zm->default_variant = false;
-      comp->inlined_variant_count++;
+      if (inline_size)
+         comp->inlined_variant_count++;
    }
-   if (zm->num_uniforms)
-      list_add(&zm->list, &comp->shader_cache);
+   if (zm->num_uniforms || nonseamless_size)
+      list_add(&zm->list, &comp->shader_cache[!!nonseamless_size]);
    if (comp->curr == zm)
       return;
    ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash;
@@ -417,8 +422,10 @@ zink_create_gfx_program(struct zink_context *ctx,
    pipe_reference_init(&prog->base.reference, 1);
 
    for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
-      list_inithead(&prog->shader_cache[i][0]);
-      list_inithead(&prog->shader_cache[i][1]);
+      list_inithead(&prog->shader_cache[i][0][0]);
+      list_inithead(&prog->shader_cache[i][0][1]);
+      list_inithead(&prog->shader_cache[i][1][0]);
+      list_inithead(&prog->shader_cache[i][1][1]);
       if (stages[i]) {
          prog->shaders[i] = stages[i];
          prog->stages_present |= BITFIELD_BIT(i);
@@ -530,7 +537,8 @@ zink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader
    assert(comp->module);
    comp->module->shader = zink_shader_compile(screen, shader, shader->nir, NULL);
    assert(comp->module->shader);
-   list_inithead(&comp->shader_cache);
+   list_inithead(&comp->shader_cache[0]);
+   list_inithead(&comp->shader_cache[1]);
 
    comp->pipelines = _mesa_hash_table_create(NULL, NULL,
                                              equals_compute_pipeline_state);
@@ -666,8 +674,10 @@ zink_destroy_gfx_program(struct zink_context *ctx,
          _mesa_set_remove_key(prog->shaders[i]->programs, prog);
          prog->shaders[i] = NULL;
       }
-      destroy_shader_cache(screen, &prog->shader_cache[i][0]);
-      destroy_shader_cache(screen, &prog->shader_cache[i][1]);
+      destroy_shader_cache(screen, &prog->shader_cache[i][0][0]);
+      destroy_shader_cache(screen, &prog->shader_cache[i][0][1]);
+      destroy_shader_cache(screen, &prog->shader_cache[i][1][0]);
+      destroy_shader_cache(screen, &prog->shader_cache[i][1][1]);
       ralloc_free(prog->nir[i]);
    }
 
@@ -709,6 +719,8 @@ zink_destroy_compute_program(struct zink_context *ctx,
 
    if (comp->shader)
       _mesa_set_remove_key(comp->shader->programs, comp);
+   destroy_shader_cache(screen, &comp->shader_cache[0]);
+   destroy_shader_cache(screen, &comp->shader_cache[1]);
 
    hash_table_foreach(comp->pipelines, entry) {
       struct compute_pipeline_cache_entry *pc_entry = entry->data;
@@ -899,6 +911,8 @@ bind_stage(struct zink_context *ctx, enum pipe_shader_type stage,
          ctx->compute_pipeline_state.module_hash = ctx->curr_compute->curr->hash;
          ctx->compute_pipeline_state.module = ctx->curr_compute->curr->shader;
          ctx->compute_pipeline_state.final_hash ^= ctx->compute_pipeline_state.module_hash;
+         if (ctx->compute_pipeline_state.key.base.nonseamless_cube_mask)
+            ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_COMPUTE);
       } else if (!shader)
          ctx->curr_compute = NULL;
       ctx->compute_stage = shader;
diff --git a/src/gallium/drivers/zink/zink_program.h b/src/gallium/drivers/zink/zink_program.h
index 20b99c0e691..775919af331 100644
--- a/src/gallium/drivers/zink/zink_program.h
+++ b/src/gallium/drivers/zink/zink_program.h
@@ -68,6 +68,7 @@ struct zink_shader_module {
    VkShaderModule shader;
    uint32_t hash;
    bool default_variant;
+   bool has_nonseamless;
    uint8_t num_uniforms;
    uint8_t key_size;
    uint8_t key[0]; /* | key | uniforms | */
@@ -104,7 +105,7 @@ struct zink_gfx_program {
 
    struct zink_shader *last_vertex_stage;
 
-   struct list_head shader_cache[ZINK_SHADER_COUNT][2]; //normal, inline uniforms
+   struct list_head shader_cache[ZINK_SHADER_COUNT][2][2]; //normal, nonseamless cubes, inline uniforms
    unsigned inlined_variant_count[ZINK_SHADER_COUNT];
 
    struct zink_shader *shaders[ZINK_SHADER_COUNT];
@@ -119,7 +120,7 @@ struct zink_compute_program {
    struct zink_shader_module *curr;
 
    struct zink_shader_module *module; //base
-   struct list_head shader_cache; //inline uniforms
+   struct list_head shader_cache[2]; //nonseamless cubes, inline uniforms
    unsigned inlined_variant_count;
 
    struct zink_shader *shader;
diff --git a/src/gallium/drivers/zink/zink_shader_keys.h b/src/gallium/drivers/zink/zink_shader_keys.h
index 0857d63b734..531a729416a 100644
--- a/src/gallium/drivers/zink/zink_shader_keys.h
+++ b/src/gallium/drivers/zink/zink_shader_keys.h
@@ -68,6 +68,7 @@ struct zink_tcs_key {
 };
 
 struct zink_shader_key_base {
+   uint32_t nonseamless_cube_mask;
    uint32_t inlined_uniform_values[MAX_INLINABLE_UNIFORMS];
 };
 



More information about the mesa-commit mailing list