zink: cache programs
authorErik Faye-Lund <erik.faye-lund@collabora.com>
Tue, 26 Mar 2019 12:52:09 +0000 (13:52 +0100)
committerErik Faye-Lund <erik.faye-lund@collabora.com>
Mon, 28 Oct 2019 08:51:44 +0000 (08:51 +0000)
Acked-by: Jordan Justen <jordan.l.justen@intel.com>
src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_context.h

index de77575ac9f07e763fb1e4ba06ddcfdfbe8e7b4a..dd2d8d418225173f450a509e9db126279c1f0f5e 100644 (file)
@@ -257,12 +257,20 @@ zink_create_vs_state(struct pipe_context *pctx,
    return zink_compile_nir(zink_screen(pctx->screen), nir);
 }
 
+static void
+bind_stage(struct zink_context *ctx, enum pipe_shader_type stage,
+           struct zink_shader *shader)
+{
+   assert(stage < PIPE_SHADER_COMPUTE);
+   ctx->gfx_stages[stage] = shader;
+   ctx->dirty |= ZINK_DIRTY_PROGRAM;
+}
+
 static void
 zink_bind_vs_state(struct pipe_context *pctx,
                    void *cso)
 {
-   struct zink_context *ctx = zink_context(pctx);
-   ctx->gfx_stages[PIPE_SHADER_VERTEX] = cso;
+   bind_stage(zink_context(pctx), PIPE_SHADER_VERTEX, cso);
 }
 
 static void
@@ -289,8 +297,7 @@ static void
 zink_bind_fs_state(struct pipe_context *pctx,
                    void *cso)
 {
-   struct zink_context *ctx = zink_context(pctx);
-   ctx->gfx_stages[PIPE_SHADER_FRAGMENT] = cso;
+   bind_stage(zink_context(pctx), PIPE_SHADER_FRAGMENT, cso);
 }
 
 static void
@@ -770,6 +777,40 @@ begin_render_pass(struct zink_cmdbuf *cmdbuf, struct zink_render_pass *rp,
    vkCmdBeginRenderPass(cmdbuf->cmdbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
 }
 
+static uint32_t
+hash_gfx_program(const void *key)
+{
+   return _mesa_hash_data(key, sizeof(struct zink_shader *) * (PIPE_SHADER_TYPES - 1));
+}
+
+static bool
+equals_gfx_program(const void *a, const void *b)
+{
+   return memcmp(a, b, sizeof(struct zink_shader *) * (PIPE_SHADER_TYPES - 1)) == 0;
+}
+
+static struct zink_gfx_program *
+get_gfx_program(struct zink_context *ctx)
+{
+   if (ctx->dirty & ZINK_DIRTY_PROGRAM) {
+      struct hash_entry *entry = _mesa_hash_table_search(ctx->program_cache,
+                                                         ctx->gfx_stages);
+      if (!entry) {
+         struct zink_gfx_program *prog;
+         prog = zink_create_gfx_program(zink_screen(ctx->base.screen)->dev,
+                                                     ctx->gfx_stages);
+         entry = _mesa_hash_table_insert(ctx->program_cache, prog->stages, prog);
+         if (!entry)
+            return NULL;
+      }
+      ctx->curr_program = entry->data;
+      ctx->dirty &= ~ZINK_DIRTY_PROGRAM;
+   }
+
+   assert(ctx->curr_program);
+   return ctx->curr_program;
+}
+
 static void
 zink_draw_vbo(struct pipe_context *pctx,
               const struct pipe_draw_info *dinfo)
@@ -788,8 +829,7 @@ zink_draw_vbo(struct pipe_context *pctx,
       return;
    }
 
-   struct zink_gfx_program *gfx_program = zink_create_gfx_program(screen->dev,
-                                                                  ctx->gfx_stages);
+   struct zink_gfx_program *gfx_program = get_gfx_program(ctx);
    if (!gfx_program)
       return;
 
@@ -1217,6 +1257,12 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
 
    vkGetDeviceQueue(screen->dev, screen->gfx_queue, 0, &ctx->queue);
 
+   ctx->program_cache = _mesa_hash_table_create(NULL, hash_gfx_program, equals_gfx_program);
+   if (!ctx->program_cache)
+      goto fail;
+
+   ctx->dirty = ZINK_DIRTY_PROGRAM;
+
    return &ctx->base;
 
 fail:
index 81aeb337e7f20d3626f2d4322385471d54d33144..a0016ce81f323b642614b096515010f73a55fcbf 100644 (file)
 
 struct blitter_context;
 struct primconvert_context;
-struct zink_resource;
 
-struct zink_vertex_elements_state;
-struct zink_rasterizer_state;
 struct zink_blend_state;
 struct zink_depth_stencil_alpha_state;
+struct zink_gfx_program;
+struct zink_rasterizer_state;
+struct zink_resource;
+struct zink_vertex_elements_state;
 
 struct zink_sampler_view {
    struct pipe_sampler_view base;
@@ -54,6 +55,8 @@ zink_sampler_view(struct pipe_sampler_view *pview)
    return (struct zink_sampler_view *)pview;
 }
 
+#define ZINK_DIRTY_PROGRAM (1 << 0)
+
 struct zink_context {
    struct pipe_context base;
    struct slab_child_pool transfer_pool;
@@ -71,6 +74,9 @@ struct zink_context {
 
    struct zink_shader *gfx_stages[PIPE_SHADER_TYPES - 1];
    struct zink_gfx_pipeline_state gfx_pipeline_state;
+   struct hash_table *program_cache;
+   struct zink_gfx_program *curr_program;
+   unsigned dirty;
 
    struct primconvert_context *primconvert;