On 29/10/17 05:36, Jason Ekstrand wrote:
Instead of hashing each stage separately (and TES and TCS together), we
hash the entire pipeline.  This means we'll get fewer cache hits if
they, for instance, re-use the same VS over and over again but it also
means we can now safely do cross-stage optimizations.
---
  src/intel/vulkan/anv_pipeline.c | 151 +++++++++++++++++++++++++---------------
  1 file changed, 94 insertions(+), 57 deletions(-)

diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index 0ebc90b..e6c4955 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -367,35 +367,70 @@ struct anv_pipeline_stage {
     const VkSpecializationInfo *spec_info;
union brw_any_prog_key key;
+
+   struct {
+      gl_shader_stage stage;
+      unsigned char sha1[20];
+   } cache_key;
  };
static void
-anv_pipeline_hash_shader(struct anv_pipeline *pipeline,
-                         struct anv_pipeline_stage *stage,
-                         unsigned char *sha1_out)
+anv_pipeline_hash_shader(struct mesa_sha1 *ctx,
+                         struct anv_pipeline_stage *stage)
  {
-   struct mesa_sha1 ctx;
+   _mesa_sha1_update(ctx, &stage->stage, sizeof(stage->stage));
+   _mesa_sha1_update(ctx, stage->module->sha1, sizeof(stage->module->sha1));
+   _mesa_sha1_update(ctx, stage->entrypoint, strlen(stage->entrypoint));
+   _mesa_sha1_update(ctx, &stage->stage, sizeof(stage->stage));
+   if (stage->spec_info) {
+      _mesa_sha1_update(ctx, stage->spec_info->pMapEntries,
+                        stage->spec_info->mapEntryCount *
+                        sizeof(*stage->spec_info->pMapEntries));
+      _mesa_sha1_update(ctx, stage->spec_info->pData,
+                        stage->spec_info->dataSize);
+   }
+   _mesa_sha1_update(ctx, &stage->key, brw_prog_key_size(stage->stage));
+}
+static void
+anv_pipeline_hash_graphics(struct anv_pipeline *pipeline,
+                           struct anv_pipeline_stage *stages,
+                           unsigned char *sha1_out)
+{
+   struct mesa_sha1 ctx;
     _mesa_sha1_init(&ctx);
-   if (stage->stage != MESA_SHADER_COMPUTE) {
-      _mesa_sha1_update(&ctx, &pipeline->subpass->view_mask,
-                        sizeof(pipeline->subpass->view_mask));
-   }
+
+   _mesa_sha1_update(&ctx, &pipeline->subpass->view_mask,
+                     sizeof(pipeline->subpass->view_mask));
+
     if (pipeline->layout) {
        _mesa_sha1_update(&ctx, pipeline->layout->sha1,
                          sizeof(pipeline->layout->sha1));
     }
-   _mesa_sha1_update(&ctx, stage->module->sha1, sizeof(stage->module->sha1));
-   _mesa_sha1_update(&ctx, stage->entrypoint, strlen(stage->entrypoint));
-   _mesa_sha1_update(&ctx, &stage->stage, sizeof(stage->stage));
-   if (stage->spec_info) {
-      _mesa_sha1_update(&ctx, stage->spec_info->pMapEntries,
-                        stage->spec_info->mapEntryCount *
-                        sizeof(*stage->spec_info->pMapEntries));
-      _mesa_sha1_update(&ctx, stage->spec_info->pData,
-                        stage->spec_info->dataSize);
+
+   for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {
+      if (stages[s].entrypoint)
+         anv_pipeline_hash_shader(&ctx, &stages[s]);
+   }
+
+   _mesa_sha1_final(&ctx, sha1_out);
+}
+
+static void
+anv_pipeline_hash_compute(struct anv_pipeline *pipeline,
+                          struct anv_pipeline_stage *stage,
+                          unsigned char *sha1_out)
+{
+   struct mesa_sha1 ctx;
+   _mesa_sha1_init(&ctx);
+
+   if (pipeline->layout) {
+      _mesa_sha1_update(&ctx, pipeline->layout->sha1,
+                        sizeof(pipeline->layout->sha1));
     }
-   _mesa_sha1_update(&ctx, &stage->key, brw_prog_key_size(stage->stage));
+
+   anv_pipeline_hash_shader(&ctx, stage);
+
     _mesa_sha1_final(&ctx, sha1_out);
  }
@@ -515,12 +550,6 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
     const struct brw_compiler *compiler =
        pipeline->device->instance->physicalDevice.compiler;
     struct anv_shader_bin *bin = NULL;
-   unsigned char sha1[20];
-
-   if (cache) {
-      anv_pipeline_hash_shader(pipeline, stage, sha1);
-      bin = anv_pipeline_cache_search(cache, sha1, 20);
-   }
if (bin == NULL) {

This is always true now so the if can be removed. Smae goes for the other stages. With that 5-12 are:

Reviewed-by: Timothy Arceri <tarc...@itsqueeze.com>


        struct brw_vs_prog_data prog_data = {};
@@ -557,7 +586,9 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
        }
unsigned code_size = prog_data.base.base.program_size;
-      bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+      bin = anv_pipeline_upload_kernel(pipeline, cache,
+                                       &stage->cache_key,
+                                       sizeof(stage->cache_key),
                                         shader_code, code_size,
                                         &prog_data.base.base, 
sizeof(prog_data),
                                         &map);
@@ -624,17 +655,6 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
        pipeline->device->instance->physicalDevice.compiler;
     struct anv_shader_bin *tcs_bin = NULL;
     struct anv_shader_bin *tes_bin = NULL;
-   unsigned char tcs_sha1[40];
-   unsigned char tes_sha1[40];
-
-   if (cache) {
-      anv_pipeline_hash_shader(pipeline, tcs_stage, tcs_sha1);
-      anv_pipeline_hash_shader(pipeline, tes_stage, tes_sha1);
-      memcpy(&tcs_sha1[20], tes_sha1, 20);
-      memcpy(&tes_sha1[20], tcs_sha1, 20);
-      tcs_bin = anv_pipeline_cache_search(cache, tcs_sha1, sizeof(tcs_sha1));
-      tes_bin = anv_pipeline_cache_search(cache, tes_sha1, sizeof(tes_sha1));
-   }
if (tcs_bin == NULL || tes_bin == NULL) {
        struct brw_tcs_prog_data tcs_prog_data = {};
@@ -705,7 +725,8 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
unsigned code_size = tcs_prog_data.base.base.program_size;
        tcs_bin = anv_pipeline_upload_kernel(pipeline, cache,
-                                           tcs_sha1, sizeof(tcs_sha1),
+                                           &tcs_stage->cache_key,
+                                           sizeof(tcs_stage->cache_key),
                                             shader_code, code_size,
                                             &tcs_prog_data.base.base,
                                             sizeof(tcs_prog_data),
@@ -726,7 +747,8 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
code_size = tes_prog_data.base.base.program_size;
        tes_bin = anv_pipeline_upload_kernel(pipeline, cache,
-                                           tes_sha1, sizeof(tes_sha1),
+                                           &tes_stage->cache_key,
+                                           sizeof(tes_stage->cache_key),
                                             shader_code, code_size,
                                             &tes_prog_data.base.base,
                                             sizeof(tes_prog_data),
@@ -753,12 +775,6 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
     const struct brw_compiler *compiler =
        pipeline->device->instance->physicalDevice.compiler;
     struct anv_shader_bin *bin = NULL;
-   unsigned char sha1[20];
-
-   if (cache) {
-      anv_pipeline_hash_shader(pipeline, stage, sha1);
-      bin = anv_pipeline_cache_search(cache, sha1, 20);
-   }
if (bin == NULL) {
        struct brw_gs_prog_data prog_data = {};
@@ -796,7 +812,9 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
/* TODO: SIMD8 GS */
        const unsigned code_size = prog_data.base.base.program_size;
-      bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+      bin = anv_pipeline_upload_kernel(pipeline, cache,
+                                       &stage->cache_key,
+                                       sizeof(stage->cache_key),
                                         shader_code, code_size,
                                         &prog_data.base.base, 
sizeof(prog_data),
                                         &map);
@@ -821,7 +839,6 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
     const struct brw_compiler *compiler =
        pipeline->device->instance->physicalDevice.compiler;
     struct anv_shader_bin *bin = NULL;
-   unsigned char sha1[20];
/* TODO: we could set this to 0 based on the information in nir_shader, but
      * we need this before we call spirv_to_nir.
@@ -830,11 +847,6 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
        &anv_pipeline_get_last_vue_prog_data(pipeline)->vue_map;
     stage->key.wm.input_slots_valid = vue_map->slots_valid;
- if (cache) {
-      anv_pipeline_hash_shader(pipeline, stage, sha1);
-      bin = anv_pipeline_cache_search(cache, sha1, 20);
-   }
-
     if (bin == NULL) {
        struct brw_wm_prog_data prog_data = {};
        struct anv_pipeline_binding surface_to_descriptor[256];
@@ -916,7 +928,9 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
        }
unsigned code_size = prog_data.base.program_size;
-      bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+      bin = anv_pipeline_upload_kernel(pipeline, cache,
+                                       &stage->cache_key,
+                                       sizeof(stage->cache_key),
                                         shader_code, code_size,
                                         &prog_data.base, sizeof(prog_data),
                                         &map);
@@ -957,7 +971,7 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,
     unsigned char sha1[20];
if (cache) {
-      anv_pipeline_hash_shader(pipeline, &stage, sha1);
+      anv_pipeline_hash_compute(pipeline, &stage, sha1);
        bin = anv_pipeline_cache_search(cache, sha1, 20);
     }
@@ -1299,27 +1313,50 @@ anv_pipeline_init(struct anv_pipeline *pipeline,
        }
     }
- if (stages[MESA_SHADER_VERTEX].entrypoint) {
+   if (cache) {
+      unsigned char sha1[20];
+      anv_pipeline_hash_graphics(pipeline, stages, sha1);
+
+      for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {
+         if (!stages[s].entrypoint)
+            continue;
+
+         stages[s].cache_key.stage = s;
+         memcpy(stages[s].cache_key.sha1, sha1, sizeof(sha1));
+
+         struct anv_shader_bin *bin =
+            anv_pipeline_cache_search(cache, &stages[s].cache_key,
+                                      sizeof(stages[s].cache_key));
+         if (bin)
+            anv_pipeline_add_compiled_stage(pipeline, s, bin);
+      }
+   }
+
+   if (stages[MESA_SHADER_VERTEX].entrypoint &&
+       !pipeline->shaders[MESA_SHADER_VERTEX]) {
        result = anv_pipeline_compile_vs(pipeline, cache,
                                         &stages[MESA_SHADER_VERTEX]);
        if (result != VK_SUCCESS)
           goto compile_fail;
     }
- if (stages[MESA_SHADER_TESS_EVAL].entrypoint) {
+   if (stages[MESA_SHADER_TESS_EVAL].entrypoint &&
+       !pipeline->shaders[MESA_SHADER_TESS_EVAL]) {
        anv_pipeline_compile_tcs_tes(pipeline, cache,
                                     &stages[MESA_SHADER_TESS_CTRL],
                                     &stages[MESA_SHADER_TESS_EVAL]);
     }
- if (stages[MESA_SHADER_GEOMETRY].entrypoint) {
+   if (stages[MESA_SHADER_GEOMETRY].entrypoint &&
+       !pipeline->shaders[MESA_SHADER_GEOMETRY]) {
        result = anv_pipeline_compile_gs(pipeline, cache,
                                         &stages[MESA_SHADER_GEOMETRY]);
        if (result != VK_SUCCESS)
           goto compile_fail;
     }
- if (stages[MESA_SHADER_FRAGMENT].entrypoint) {
+   if (stages[MESA_SHADER_FRAGMENT].entrypoint &&
+       !pipeline->shaders[MESA_SHADER_FRAGMENT]) {
        result = anv_pipeline_compile_fs(pipeline, cache,
                                         &stages[MESA_SHADER_FRAGMENT]);
        if (result != VK_SUCCESS)

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to