Mesa (master): anv/pipeline: Hash the entire pipeline in one go

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Aug 2 17:29:34 UTC 2018


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

Author: Jason Ekstrand <jason.ekstrand at intel.com>
Date:   Thu Oct 26 19:24:28 2017 -0700

anv/pipeline: Hash the entire pipeline in one go

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.

Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>

---

 src/intel/vulkan/anv_pipeline.c | 147 +++++++++++++++++++++++++---------------
 1 file changed, 94 insertions(+), 53 deletions(-)

diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index f1a43a3bfc..3033acbe95 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -400,34 +400,67 @@ 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_layout *layout,
-                         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_init(&ctx);
-   if (stage->stage != MESA_SHADER_COMPUTE) {
-      _mesa_sha1_update(&ctx, &pipeline->subpass->view_mask,
-                        sizeof(pipeline->subpass->view_mask));
-   }
-   if (layout)
-      _mesa_sha1_update(&ctx, layout->sha1, sizeof(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));
+   _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,
+      _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,
+      _mesa_sha1_update(ctx, stage->spec_info->pData,
                         stage->spec_info->dataSize);
    }
-   _mesa_sha1_update(&ctx, &stage->key, brw_prog_key_size(stage->stage));
+   _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_layout *layout,
+                           struct anv_pipeline_stage *stages,
+                           unsigned char *sha1_out)
+{
+   struct mesa_sha1 ctx;
+   _mesa_sha1_init(&ctx);
+
+   _mesa_sha1_update(&ctx, &pipeline->subpass->view_mask,
+                     sizeof(pipeline->subpass->view_mask));
+
+   if (layout)
+      _mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
+
+   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_layout *layout,
+                          struct anv_pipeline_stage *stage,
+                          unsigned char *sha1_out)
+{
+   struct mesa_sha1 ctx;
+   _mesa_sha1_init(&ctx);
+
+   if (layout)
+      _mesa_sha1_update(&ctx, layout->sha1, sizeof(layout->sha1));
+
+   anv_pipeline_hash_shader(&ctx, stage);
+
    _mesa_sha1_final(&ctx, sha1_out);
 }
 
@@ -532,10 +565,6 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
 
    ANV_FROM_HANDLE(anv_pipeline_layout, layout, info->layout);
 
-   unsigned char sha1[20];
-   anv_pipeline_hash_shader(pipeline, layout, stage, sha1);
-   bin = anv_device_search_for_kernel(pipeline->device, cache, sha1, 20);
-
    if (bin == NULL) {
       struct brw_vs_prog_data prog_data = {};
       struct anv_pipeline_binding surface_to_descriptor[256];
@@ -571,7 +600,9 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
       }
 
       unsigned code_size = prog_data.base.base.program_size;
-      bin = anv_device_upload_kernel(pipeline->device, cache, sha1, 20,
+      bin = anv_device_upload_kernel(pipeline->device, cache,
+                                     &stage->cache_key,
+                                     sizeof(stage->cache_key),
                                      shader_code, code_size,
                                      nir->constant_data,
                                      nir->constant_data_size,
@@ -644,18 +675,6 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
 
    ANV_FROM_HANDLE(anv_pipeline_layout, layout, info->layout);
 
-   unsigned char tcs_sha1[40];
-   unsigned char tes_sha1[40];
-   anv_pipeline_hash_shader(pipeline, layout, tcs_stage, tcs_sha1);
-   anv_pipeline_hash_shader(pipeline, layout, tes_stage, tes_sha1);
-   memcpy(&tcs_sha1[20], tes_sha1, 20);
-   memcpy(&tes_sha1[20], tcs_sha1, 20);
-
-   tcs_bin = anv_device_search_for_kernel(pipeline->device, cache,
-                                          tcs_sha1, sizeof(tcs_sha1));
-   tes_bin = anv_device_search_for_kernel(pipeline->device, cache,
-                                          tes_sha1, sizeof(tes_sha1));
-
    if (tcs_bin == NULL || tes_bin == NULL) {
       struct brw_tcs_prog_data tcs_prog_data = {};
       struct brw_tes_prog_data tes_prog_data = {};
@@ -725,7 +744,8 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
 
       unsigned code_size = tcs_prog_data.base.base.program_size;
       tcs_bin = anv_device_upload_kernel(pipeline->device, cache,
-                                         tcs_sha1, sizeof(tcs_sha1),
+                                         &tcs_stage->cache_key,
+                                         sizeof(tcs_stage->cache_key),
                                          shader_code, code_size,
                                          tcs_nir->constant_data,
                                          tcs_nir->constant_data_size,
@@ -748,7 +768,8 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline,
 
       code_size = tes_prog_data.base.base.program_size;
       tes_bin = anv_device_upload_kernel(pipeline->device, cache,
-                                         tes_sha1, sizeof(tes_sha1),
+                                         &tes_stage->cache_key,
+                                         sizeof(tes_stage->cache_key),
                                          shader_code, code_size,
                                          tes_nir->constant_data,
                                          tes_nir->constant_data_size,
@@ -781,10 +802,6 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
 
    ANV_FROM_HANDLE(anv_pipeline_layout, layout, info->layout);
 
-   unsigned char sha1[20];
-   anv_pipeline_hash_shader(pipeline, layout, stage, sha1);
-   bin = anv_device_search_for_kernel(pipeline->device, cache, sha1, 20);
-
    if (bin == NULL) {
       struct brw_gs_prog_data prog_data = {};
       struct anv_pipeline_binding surface_to_descriptor[256];
@@ -821,7 +838,9 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
 
       /* TODO: SIMD8 GS */
       const unsigned code_size = prog_data.base.base.program_size;
-      bin = anv_device_upload_kernel(pipeline->device, cache, sha1, 20,
+      bin = anv_device_upload_kernel(pipeline->device, cache,
+                                     &stage->cache_key,
+                                     sizeof(stage->cache_key),
                                      shader_code, code_size,
                                      nir->constant_data,
                                      nir->constant_data_size,
@@ -859,10 +878,6 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
 
    ANV_FROM_HANDLE(anv_pipeline_layout, layout, info->layout);
 
-   unsigned char sha1[20];
-   anv_pipeline_hash_shader(pipeline, layout, stage, sha1);
-   bin = anv_device_search_for_kernel(pipeline->device, cache, sha1, 20);
-
    if (bin == NULL) {
       struct brw_wm_prog_data prog_data = {};
       struct anv_pipeline_binding surface_to_descriptor[256];
@@ -981,7 +996,9 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
       }
 
       unsigned code_size = prog_data.base.program_size;
-      bin = anv_device_upload_kernel(pipeline->device, cache, sha1, 20,
+      bin = anv_device_upload_kernel(pipeline->device, cache,
+                                     &stage->cache_key,
+                                     sizeof(stage->cache_key),
                                      shader_code, code_size,
                                      nir->constant_data,
                                      nir->constant_data_size,
@@ -1025,7 +1042,7 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,
    ANV_FROM_HANDLE(anv_pipeline_layout, layout, info->layout);
 
    unsigned char sha1[20];
-   anv_pipeline_hash_shader(pipeline, layout, &stage, sha1);
+   anv_pipeline_hash_compute(pipeline, layout, &stage, sha1);
    bin = anv_device_search_for_kernel(pipeline->device, cache, sha1, 20);
 
    if (bin == NULL) {
@@ -1384,14 +1401,36 @@ anv_pipeline_init(struct anv_pipeline *pipeline,
 
    assert(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT);
 
-   if (stages[MESA_SHADER_VERTEX].entrypoint) {
+   ANV_FROM_HANDLE(anv_pipeline_layout, layout, pCreateInfo->layout);
+
+   unsigned char sha1[20];
+   anv_pipeline_hash_graphics(pipeline, layout, 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_device_search_for_kernel(pipeline->device, 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, pCreateInfo,
                                        &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]) {
       result = anv_pipeline_compile_tcs_tes(pipeline, cache, pCreateInfo,
                                             &stages[MESA_SHADER_TESS_CTRL],
                                             &stages[MESA_SHADER_TESS_EVAL]);
@@ -1399,14 +1438,16 @@ anv_pipeline_init(struct anv_pipeline *pipeline,
          goto compile_fail;
    }
 
-   if (stages[MESA_SHADER_GEOMETRY].entrypoint) {
+   if (stages[MESA_SHADER_GEOMETRY].entrypoint &&
+       !pipeline->shaders[MESA_SHADER_GEOMETRY]) {
       result = anv_pipeline_compile_gs(pipeline, cache, pCreateInfo,
                                        &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, pCreateInfo,
                                        &stages[MESA_SHADER_FRAGMENT]);
       if (result != VK_SUCCESS)




More information about the mesa-commit mailing list