zink: cache those pipelines
authorErik Faye-Lund <erik.faye-lund@collabora.com>
Tue, 26 Mar 2019 14:20:17 +0000 (15:20 +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_program.c
src/gallium/drivers/zink/zink_program.h

index c1e5e94..30ac725 100644 (file)
@@ -835,9 +835,8 @@ zink_draw_vbo(struct pipe_context *pctx,
 
    ctx->gfx_pipeline_state.primitive_topology = zink_primitive_topology(dinfo->mode);
 
-   VkPipeline pipeline = zink_create_gfx_pipeline(screen->dev,
-                                                  gfx_program,
-                                                  &ctx->gfx_pipeline_state);
+   VkPipeline pipeline = zink_get_gfx_pipeline(screen->dev, gfx_program,
+                                               &ctx->gfx_pipeline_state);
 
    bool depth_bias = false;
    switch (u_reduced_prim(dinfo->mode)) {
@@ -965,8 +964,6 @@ zink_draw_vbo(struct pipe_context *pctx,
 
    zink_end_cmdbuf(ctx, cmdbuf);
 
-   vkDestroyPipeline(screen->dev, pipeline, NULL);
-
    if (dinfo->index_size > 0 && dinfo->has_user_indices)
       pipe_resource_reference(&index_buffer, NULL);
 }
index 0fe94e7..ed890b9 100644 (file)
@@ -25,7 +25,9 @@
 
 #include "zink_compiler.h"
 #include "zink_context.h"
+#include "zink_screen.h"
 
+#include "util/hash_table.h"
 #include "util/u_debug.h"
 #include "util/u_memory.h"
 
@@ -89,15 +91,30 @@ create_pipeline_layout(VkDevice dev, VkDescriptorSetLayout dsl)
    return layout;
 }
 
+static uint32_t
+hash_gfx_pipeline_state(const void *key)
+{
+   return _mesa_hash_data(key, sizeof(struct zink_gfx_pipeline_state));
+}
+
+static bool
+equals_gfx_pipeline_state(const void *a, const void *b)
+{
+   return memcmp(a, b, sizeof(struct zink_gfx_pipeline_state)) == 0;
+}
+
 struct zink_gfx_program *
 zink_create_gfx_program(VkDevice dev,
                         struct zink_shader *stages[PIPE_SHADER_TYPES - 1])
 {
    struct zink_gfx_program *prog = CALLOC_STRUCT(zink_gfx_program);
-   if (!prog) {
-      debug_printf("failed to allocate gfx-program\n");
+   if (!prog)
+      goto fail;
+
+   prog->pipelines = _mesa_hash_table_create(NULL, hash_gfx_pipeline_state,
+                                             equals_gfx_pipeline_state);
+   if (!prog->pipelines)
       goto fail;
-   }
 
    for (int i = 0; i < PIPE_SHADER_TYPES - 1; ++i)
       prog->stages[i] = stages[i];
@@ -130,3 +147,33 @@ zink_destroy_gfx_program(VkDevice dev, struct zink_gfx_program *prog)
    FREE(prog);
 }
 
+struct pipeline_cache_entry {
+   struct zink_gfx_pipeline_state state;
+   VkPipeline pipeline;
+};
+
+VkPipeline
+zink_get_gfx_pipeline(VkDevice dev, struct zink_gfx_program *prog,
+                      struct zink_gfx_pipeline_state *state)
+{
+   /* TODO: use pre-hashed versions to save some time (can re-hash only when
+      state changes) */
+   struct hash_entry *entry = _mesa_hash_table_search(prog->pipelines, state);
+   if (!entry) {
+      VkPipeline pipeline = zink_create_gfx_pipeline(dev, prog, state);
+      if (pipeline == VK_NULL_HANDLE)
+         return VK_NULL_HANDLE;
+
+      struct pipeline_cache_entry *pc_entry = CALLOC_STRUCT(pipeline_cache_entry);
+      if (!pc_entry)
+         return NULL;
+
+      memcpy(&pc_entry->state, state, sizeof(*state));
+      pc_entry->pipeline = pipeline;
+
+      entry = _mesa_hash_table_insert(prog->pipelines, &pc_entry->state, pc_entry);
+      assert(entry);
+   }
+
+   return ((struct pipeline_cache_entry *)(entry->data))->pipeline;
+}
index ed540fd..275cafa 100644 (file)
@@ -36,6 +36,7 @@ struct zink_gfx_program {
    struct zink_shader *stages[PIPE_SHADER_TYPES - 1]; // compute stage doesn't belong here
    VkDescriptorSetLayout dsl;
    VkPipelineLayout layout;
+   struct hash_table *pipelines;
 };
 
 struct zink_gfx_program *
@@ -45,4 +46,8 @@ zink_create_gfx_program(VkDevice dev,
 void
 zink_destroy_gfx_program(VkDevice dev, struct zink_gfx_program *);
 
+VkPipeline
+zink_get_gfx_pipeline(VkDevice dev, struct zink_gfx_program *prog,
+                      struct zink_gfx_pipeline_state *state);
+
 #endif