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

Author: Mike Blumenkrantz <[email protected]>
Date:   Tue Jun 30 09:57:19 2020 -0400

zink: start using per-stage flags for new shaders, refcount shader modules

we don't want to recompile shaders if we don't have to, so we can set bitflags
upon receiving new shader states and then compile only the stages that have
changed while refcounting the unchanged stages

Reviewed-by: Erik Faye-Lund <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5970>

---

 src/gallium/drivers/zink/zink_context.c  |  2 --
 src/gallium/drivers/zink/zink_context.h  |  2 +-
 src/gallium/drivers/zink/zink_draw.c     |  4 +--
 src/gallium/drivers/zink/zink_pipeline.c |  2 +-
 src/gallium/drivers/zink/zink_program.c  | 50 ++++++++++++++++++++++++++++----
 src/gallium/drivers/zink/zink_program.h  |  7 ++++-
 6 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_context.c 
b/src/gallium/drivers/zink/zink_context.c
index 9098765bb9c..c5ec154cf3c 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -1178,8 +1178,6 @@ zink_context_create(struct pipe_screen *pscreen, void 
*priv, unsigned flags)
    if (!ctx->dummy_buffer)
       goto fail;
 
-   ctx->dirty_program = true;
-
    /* start the first batch */
    zink_start_batch(ctx, zink_curr_batch(ctx));
 
diff --git a/src/gallium/drivers/zink/zink_context.h 
b/src/gallium/drivers/zink/zink_context.h
index b403bc92a85..a9c3b718cee 100644
--- a/src/gallium/drivers/zink/zink_context.h
+++ b/src/gallium/drivers/zink/zink_context.h
@@ -95,7 +95,7 @@ struct zink_context {
    struct hash_table *program_cache;
    struct zink_gfx_program *curr_program;
 
-   unsigned dirty_program : 1;
+   unsigned dirty_shader_stages : 6; /* mask of changed shader stages */
 
    struct hash_table *render_pass_cache;
 
diff --git a/src/gallium/drivers/zink/zink_draw.c 
b/src/gallium/drivers/zink/zink_draw.c
index 79e61ccb52b..9ce51ea0bee 100644
--- a/src/gallium/drivers/zink/zink_draw.c
+++ b/src/gallium/drivers/zink/zink_draw.c
@@ -160,7 +160,7 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct 
zink_context *ctx)
 static struct zink_gfx_program *
 get_gfx_program(struct zink_context *ctx)
 {
-   if (ctx->dirty_program) {
+   if (ctx->dirty_shader_stages) {
       struct hash_entry *entry = _mesa_hash_table_search(ctx->program_cache,
                                                          ctx->gfx_stages);
       if (!entry) {
@@ -171,7 +171,7 @@ get_gfx_program(struct zink_context *ctx)
             return NULL;
       }
       ctx->curr_program = entry->data;
-      ctx->dirty_program = false;
+      ctx->dirty_shader_stages = 0;
    }
 
    assert(ctx->curr_program);
diff --git a/src/gallium/drivers/zink/zink_pipeline.c 
b/src/gallium/drivers/zink/zink_pipeline.c
index af38c84aeaf..637e880eb3c 100644
--- a/src/gallium/drivers/zink/zink_pipeline.c
+++ b/src/gallium/drivers/zink/zink_pipeline.c
@@ -149,7 +149,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
       VkPipelineShaderStageCreateInfo stage = {};
       stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
       stage.stage = zink_shader_stage(i);
-      stage.module = prog->stages[i];
+      stage.module = prog->stages[i]->shader;
       stage.pName = "main";
       shader_stages[num_stages++] = stage;
    }
diff --git a/src/gallium/drivers/zink/zink_program.c 
b/src/gallium/drivers/zink/zink_program.c
index ee735a810d2..f6b3acdc84d 100644
--- a/src/gallium/drivers/zink/zink_program.c
+++ b/src/gallium/drivers/zink/zink_program.c
@@ -45,6 +45,12 @@ debug_describe_zink_gfx_program(char *buf, const struct 
zink_gfx_program *ptr)
    sprintf(buf, "zink_gfx_program");
 }
 
+static void
+debug_describe_zink_shader_module(char *buf, const struct zink_shader_module 
*ptr)
+{
+   sprintf(buf, "zink_shader_module");
+}
+
 static VkDescriptorSetLayout
 create_desc_set_layout(VkDevice dev,
                        struct zink_shader *stages[ZINK_SHADER_COUNT],
@@ -107,15 +113,47 @@ create_pipeline_layout(VkDevice dev, 
VkDescriptorSetLayout dsl)
    return layout;
 }
 
+static void
+zink_destroy_shader_module(struct zink_screen *screen, struct 
zink_shader_module *zm)
+{
+   vkDestroyShaderModule(screen->dev, zm->shader, NULL);
+   free(zm);
+}
+
+static inline void
+zink_shader_module_reference(struct zink_screen *screen,
+                           struct zink_shader_module **dst,
+                           struct zink_shader_module *src)
+{
+   struct zink_shader_module *old_dst = dst ? *dst : NULL;
+
+   if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, 
&src->reference,
+                                
(debug_reference_descriptor)debug_describe_zink_shader_module))
+      zink_destroy_shader_module(screen, old_dst);
+   if (dst) *dst = src;
+}
+
 static void
 update_shader_modules(struct zink_context *ctx, struct zink_shader 
*stages[ZINK_SHADER_COUNT], struct zink_gfx_program *prog)
 {
+   struct zink_shader *dirty[ZINK_SHADER_COUNT] = {NULL};
+
+   unsigned dirty_shader_stages = ctx->dirty_shader_stages;
+   while (dirty_shader_stages) {
+      unsigned type = u_bit_scan(&dirty_shader_stages);
+      dirty[type] = stages[type];
+   }
    for (int i = 0; i < ZINK_SHADER_COUNT; ++i) {
-      if (stages[i]) {
-         prog->stages[i] = zink_shader_compile(zink_screen(ctx->base.screen), 
stages[i]);
-         prog->shaders[i] = stages[i];
-      }
+      if (dirty[i]) {
+         prog->stages[i] = CALLOC_STRUCT(zink_shader_module);
+         assert(prog->stages[i]);
+         pipe_reference_init(&prog->stages[i]->reference, 1);
+         prog->stages[i]->shader = 
zink_shader_compile(zink_screen(ctx->base.screen), stages[i]);
+      } else if (stages[i]) /* reuse existing shader module */
+         zink_shader_module_reference(zink_screen(ctx->base.screen), 
&prog->stages[i], ctx->curr_program->stages[i]);
+      prog->shaders[i] = stages[i];
    }
+   ctx->dirty_shader_stages = 0;
 }
 
 static uint32_t
@@ -204,7 +242,7 @@ zink_destroy_gfx_program(struct zink_screen *screen,
       if (prog->shaders[i])
          gfx_program_remove_shader(prog, prog->shaders[i]);
       if (prog->stages[i])
-         vkDestroyShaderModule(screen->dev, prog->stages[i], NULL);
+         zink_shader_module_reference(screen, &prog->stages[i], NULL);
    }
 
    /* unref all used render-passes */
@@ -323,7 +361,7 @@ bind_stage(struct zink_context *ctx, enum pipe_shader_type 
stage,
 {
    assert(stage < PIPE_SHADER_COMPUTE);
    ctx->gfx_stages[stage] = shader;
-   ctx->dirty_program = true;
+   ctx->dirty_shader_stages |= 1 << stage;
 }
 
 static void
diff --git a/src/gallium/drivers/zink/zink_program.h 
b/src/gallium/drivers/zink/zink_program.h
index 1d4aaa0cfdc..c82d409d673 100644
--- a/src/gallium/drivers/zink/zink_program.h
+++ b/src/gallium/drivers/zink/zink_program.h
@@ -38,10 +38,15 @@ struct zink_gfx_pipeline_state;
 struct hash_table;
 struct set;
 
+struct zink_shader_module {
+   struct pipe_reference reference;
+   VkShaderModule shader;
+};
+
 struct zink_gfx_program {
    struct pipe_reference reference;
 
-   VkShaderModule stages[ZINK_SHADER_COUNT]; // compute stage doesn't belong 
here
+   struct zink_shader_module *stages[ZINK_SHADER_COUNT]; // compute stage 
doesn't belong here
    struct zink_shader *shaders[ZINK_SHADER_COUNT];
    VkDescriptorSetLayout dsl;
    VkPipelineLayout layout;

_______________________________________________
mesa-commit mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to