<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Nov 20, 2017 at 3:03 AM, Timothy Arceri <span dir="ltr"><<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
<br>
On 29/10/17 05:36, Jason Ekstrand wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Instead of hashing each stage separately (and TES and TCS together), we<br>
hash the entire pipeline.  This means we'll get fewer cache hits if<br>
they, for instance, re-use the same VS over and over again but it also<br>
means we can now safely do cross-stage optimizations.<br>
---<br>
  src/intel/vulkan/anv_pipeline.<wbr>c | 151 +++++++++++++++++++++++++-----<wbr>----------<br>
  1 file changed, 94 insertions(+), 57 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_pipelin<wbr>e.c b/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
index 0ebc90b..e6c4955 100644<br>
--- a/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
+++ b/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
@@ -367,35 +367,70 @@ struct anv_pipeline_stage {<br>
     const VkSpecializationInfo *spec_info;<br>
       union brw_any_prog_key key;<br>
+<br>
+   struct {<br>
+      gl_shader_stage stage;<br>
+      unsigned char sha1[20];<br>
+   } cache_key;<br>
  };<br>
    static void<br>
-anv_pipeline_hash_shader(stru<wbr>ct anv_pipeline *pipeline,<br>
-                         struct anv_pipeline_stage *stage,<br>
-                         unsigned char *sha1_out)<br>
+anv_pipeline_hash_shader(stru<wbr>ct mesa_sha1 *ctx,<br>
+                         struct anv_pipeline_stage *stage)<br>
  {<br>
-   struct mesa_sha1 ctx;<br>
+   _mesa_sha1_update(ctx, &stage->stage, sizeof(stage->stage));<br>
+   _mesa_sha1_update(ctx, stage->module->sha1, sizeof(stage->module->sha1));<br>
+   _mesa_sha1_update(ctx, stage->entrypoint, strlen(stage->entrypoint));<br>
+   _mesa_sha1_update(ctx, &stage->stage, sizeof(stage->stage));<br>
+   if (stage->spec_info) {<br>
+      _mesa_sha1_update(ctx, stage->spec_info->pMapEntries,<br>
+                        stage->spec_info->mapEntryCoun<wbr>t *<br>
+                        sizeof(*stage->spec_info->pMap<wbr>Entries));<br>
+      _mesa_sha1_update(ctx, stage->spec_info->pData,<br>
+                        stage->spec_info->dataSize);<br>
+   }<br>
+   _mesa_sha1_update(ctx, &stage->key, brw_prog_key_size(stage->stage<wbr>));<br>
+}<br>
  +static void<br>
+anv_pipeline_hash_graphics(st<wbr>ruct anv_pipeline *pipeline,<br>
+                           struct anv_pipeline_stage *stages,<br>
+                           unsigned char *sha1_out)<br>
+{<br>
+   struct mesa_sha1 ctx;<br>
     _mesa_sha1_init(&ctx);<br>
-   if (stage->stage != MESA_SHADER_COMPUTE) {<br>
-      _mesa_sha1_update(&ctx, &pipeline->subpass->view_mask,<br>
-                        sizeof(pipeline->subpass->view<wbr>_mask));<br>
-   }<br>
+<br>
+   _mesa_sha1_update(&ctx, &pipeline->subpass->view_mask,<br>
+                     sizeof(pipeline->subpass->vie<wbr>w_mask));<br>
+<br>
     if (pipeline->layout) {<br>
        _mesa_sha1_update(&ctx, pipeline->layout->sha1,<br>
                          sizeof(pipeline->layout->sha1)<wbr>);<br>
     }<br>
-   _mesa_sha1_update(&ctx, stage->module->sha1, sizeof(stage->module->sha1));<br>
-   _mesa_sha1_update(&ctx, stage->entrypoint, strlen(stage->entrypoint));<br>
-   _mesa_sha1_update(&ctx, &stage->stage, sizeof(stage->stage));<br>
-   if (stage->spec_info) {<br>
-      _mesa_sha1_update(&ctx, stage->spec_info->pMapEntries,<br>
-                        stage->spec_info->mapEntryCoun<wbr>t *<br>
-                        sizeof(*stage->spec_info->pMap<wbr>Entries));<br>
-      _mesa_sha1_update(&ctx, stage->spec_info->pData,<br>
-                        stage->spec_info->dataSize);<br>
+<br>
+   for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {<br>
+      if (stages[s].entrypoint)<br>
+         anv_pipeline_hash_shader(&<wbr>ctx, &stages[s]);<br>
+   }<br>
+<br>
+   _mesa_sha1_final(&ctx, sha1_out);<br>
+}<br>
+<br>
+static void<br>
+anv_pipeline_hash_compute(str<wbr>uct anv_pipeline *pipeline,<br>
+                          struct anv_pipeline_stage *stage,<br>
+                          unsigned char *sha1_out)<br>
+{<br>
+   struct mesa_sha1 ctx;<br>
+   _mesa_sha1_init(&ctx);<br>
+<br>
+   if (pipeline->layout) {<br>
+      _mesa_sha1_update(&ctx, pipeline->layout->sha1,<br>
+                        sizeof(pipeline->layout->sha1)<wbr>);<br>
     }<br>
-   _mesa_sha1_update(&ctx, &stage->key, brw_prog_key_size(stage->stage<wbr>));<br>
+<br>
+   anv_pipeline_hash_shader(&<wbr>ctx, stage);<br>
+<br>
     _mesa_sha1_final(&ctx, sha1_out);<br>
  }<br>
  @@ -515,12 +550,6 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,<br>
     const struct brw_compiler *compiler =<br>
        pipeline->device->instance->ph<wbr>ysicalDevice.compiler;<br>
     struct anv_shader_bin *bin = NULL;<br>
-   unsigned char sha1[20];<br>
-<br>
-   if (cache) {<br>
-      anv_pipeline_hash_shader(pipel<wbr>ine, stage, sha1);<br>
-      bin = anv_pipeline_cache_search(cach<wbr>e, sha1, 20);<br>
-   }<br>
       if (bin == NULL) {<br>
</blockquote>
<br></div></div>
This is always true now so the if can be removed. Smae goes for the other stages. With that 5-12 are:<br></blockquote><div><br></div><div>True, and it does get removed by the end of the series.  I just didn't remove it here because I didn't want to permute these functions any more than needed and blow up indentation.  I was trying to be nice to the reviewers. :-)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Reviewed-by: Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>><div class="HOEnZb"><div class="h5"><br>
<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
        struct brw_vs_prog_data prog_data = {};<br>
@@ -557,7 +586,9 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,<br>
        }<br>
          unsigned code_size = prog_data.base.base.program_si<wbr>ze;<br>
-      bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache, sha1, 20,<br>
+      bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache,<br>
+                                       &stage->cache_key,<br>
+                                       sizeof(stage->cache_key),<br>
                                         shader_code, code_size,<br>
                                         &prog_data.base.base, sizeof(prog_data),<br>
                                         &map);<br>
@@ -624,17 +655,6 @@ anv_pipeline_compile_tcs_tes(s<wbr>truct anv_pipeline *pipeline,<br>
        pipeline->device->instance->ph<wbr>ysicalDevice.compiler;<br>
     struct anv_shader_bin *tcs_bin = NULL;<br>
     struct anv_shader_bin *tes_bin = NULL;<br>
-   unsigned char tcs_sha1[40];<br>
-   unsigned char tes_sha1[40];<br>
-<br>
-   if (cache) {<br>
-      anv_pipeline_hash_shader(pipel<wbr>ine, tcs_stage, tcs_sha1);<br>
-      anv_pipeline_hash_shader(pipel<wbr>ine, tes_stage, tes_sha1);<br>
-      memcpy(&tcs_sha1[20], tes_sha1, 20);<br>
-      memcpy(&tes_sha1[20], tcs_sha1, 20);<br>
-      tcs_bin = anv_pipeline_cache_search(cach<wbr>e, tcs_sha1, sizeof(tcs_sha1));<br>
-      tes_bin = anv_pipeline_cache_search(cach<wbr>e, tes_sha1, sizeof(tes_sha1));<br>
-   }<br>
       if (tcs_bin == NULL || tes_bin == NULL) {<br>
        struct brw_tcs_prog_data tcs_prog_data = {};<br>
@@ -705,7 +725,8 @@ anv_pipeline_compile_tcs_tes(s<wbr>truct anv_pipeline *pipeline,<br>
          unsigned code_size = tcs_prog_data.base.base.progra<wbr>m_size;<br>
        tcs_bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache,<br>
-                                           tcs_sha1, sizeof(tcs_sha1),<br>
+                                           &tcs_stage->cache_key,<br>
+                                           sizeof(tcs_stage->cache_key),<br>
                                             shader_code, code_size,<br>
                                             &tcs_prog_data.base.base,<br>
                                             sizeof(tcs_prog_data),<br>
@@ -726,7 +747,8 @@ anv_pipeline_compile_tcs_tes(s<wbr>truct anv_pipeline *pipeline,<br>
          code_size = tes_prog_data.base.base.progra<wbr>m_size;<br>
        tes_bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache,<br>
-                                           tes_sha1, sizeof(tes_sha1),<br>
+                                           &tes_stage->cache_key,<br>
+                                           sizeof(tes_stage->cache_key),<br>
                                             shader_code, code_size,<br>
                                             &tes_prog_data.base.base,<br>
                                             sizeof(tes_prog_data),<br>
@@ -753,12 +775,6 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,<br>
     const struct brw_compiler *compiler =<br>
        pipeline->device->instance->ph<wbr>ysicalDevice.compiler;<br>
     struct anv_shader_bin *bin = NULL;<br>
-   unsigned char sha1[20];<br>
-<br>
-   if (cache) {<br>
-      anv_pipeline_hash_shader(pipel<wbr>ine, stage, sha1);<br>
-      bin = anv_pipeline_cache_search(cach<wbr>e, sha1, 20);<br>
-   }<br>
       if (bin == NULL) {<br>
        struct brw_gs_prog_data prog_data = {};<br>
@@ -796,7 +812,9 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,<br>
          /* TODO: SIMD8 GS */<br>
        const unsigned code_size = prog_data.base.base.program_si<wbr>ze;<br>
-      bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache, sha1, 20,<br>
+      bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache,<br>
+                                       &stage->cache_key,<br>
+                                       sizeof(stage->cache_key),<br>
                                         shader_code, code_size,<br>
                                         &prog_data.base.base, sizeof(prog_data),<br>
                                         &map);<br>
@@ -821,7 +839,6 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,<br>
     const struct brw_compiler *compiler =<br>
        pipeline->device->instance->ph<wbr>ysicalDevice.compiler;<br>
     struct anv_shader_bin *bin = NULL;<br>
-   unsigned char sha1[20];<br>
       /* TODO: we could set this to 0 based on the information in nir_shader, but<br>
      * we need this before we call spirv_to_nir.<br>
@@ -830,11 +847,6 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,<br>
        &anv_pipeline_get_last_vue_pro<wbr>g_data(pipeline)->vue_map;<br>
     stage->key.wm.input_slots_val<wbr>id = vue_map->slots_valid;<br>
  -   if (cache) {<br>
-      anv_pipeline_hash_shader(pipel<wbr>ine, stage, sha1);<br>
-      bin = anv_pipeline_cache_search(cach<wbr>e, sha1, 20);<br>
-   }<br>
-<br>
     if (bin == NULL) {<br>
        struct brw_wm_prog_data prog_data = {};<br>
        struct anv_pipeline_binding surface_to_descriptor[256];<br>
@@ -916,7 +928,9 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,<br>
        }<br>
          unsigned code_size = prog_data.base.program_size;<br>
-      bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache, sha1, 20,<br>
+      bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache,<br>
+                                       &stage->cache_key,<br>
+                                       sizeof(stage->cache_key),<br>
                                         shader_code, code_size,<br>
                                         &prog_data.base, sizeof(prog_data),<br>
                                         &map);<br>
@@ -957,7 +971,7 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,<br>
     unsigned char sha1[20];<br>
       if (cache) {<br>
-      anv_pipeline_hash_shader(pipel<wbr>ine, &stage, sha1);<br>
+      anv_pipeline_hash_compute(pipe<wbr>line, &stage, sha1);<br>
        bin = anv_pipeline_cache_search(cach<wbr>e, sha1, 20);<br>
     }<br>
  @@ -1299,27 +1313,50 @@ anv_pipeline_init(struct anv_pipeline *pipeline,<br>
        }<br>
     }<br>
  -   if (stages[MESA_SHADER_VERTEX].en<wbr>trypoint) {<br>
+   if (cache) {<br>
+      unsigned char sha1[20];<br>
+      anv_pipeline_hash_graphics(pip<wbr>eline, stages, sha1);<br>
+<br>
+      for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {<br>
+         if (!stages[s].entrypoint)<br>
+            continue;<br>
+<br>
+         stages[s].cache_key.stage = s;<br>
+         memcpy(stages[s].cache_key.sh<wbr>a1, sha1, sizeof(sha1));<br>
+<br>
+         struct anv_shader_bin *bin =<br>
+            anv_pipeline_cache_search(cach<wbr>e, &stages[s].cache_key,<br>
+                                      sizeof(stages[s].cache_key));<br>
+         if (bin)<br>
+            anv_pipeline_add_compiled_stag<wbr>e(pipeline, s, bin);<br>
+      }<br>
+   }<br>
+<br>
+   if (stages[MESA_SHADER_VERTEX].en<wbr>trypoint &&<br>
+       !pipeline->shaders[MESA_SHADE<wbr>R_VERTEX]) {<br>
        result = anv_pipeline_compile_vs(pipeli<wbr>ne, cache,<br>
                                         &stages[MESA_SHADER_VERTEX]);<br>
        if (result != VK_SUCCESS)<br>
           goto compile_fail;<br>
     }<br>
  -   if (stages[MESA_SHADER_TESS_EVAL]<wbr>.entrypoint) {<br>
+   if (stages[MESA_SHADER_TESS_EVAL]<wbr>.entrypoint &&<br>
+       !pipeline->shaders[MESA_SHADE<wbr>R_TESS_EVAL]) {<br>
        anv_pipeline_compile_tcs_tes(p<wbr>ipeline, cache,<br>
                                     &stages[MESA_SHADER_TESS_<wbr>CTRL],<br>
                                     &stages[MESA_SHADER_TESS_<wbr>EVAL]);<br>
     }<br>
  -   if (stages[MESA_SHADER_GEOMETRY].<wbr>entrypoint) {<br>
+   if (stages[MESA_SHADER_GEOMETRY].<wbr>entrypoint &&<br>
+       !pipeline->shaders[MESA_SHADE<wbr>R_GEOMETRY]) {<br>
        result = anv_pipeline_compile_gs(pipeli<wbr>ne, cache,<br>
                                         &stages[MESA_SHADER_GEOMETRY]<wbr>);<br>
        if (result != VK_SUCCESS)<br>
           goto compile_fail;<br>
     }<br>
  -   if (stages[MESA_SHADER_FRAGMENT].<wbr>entrypoint) {<br>
+   if (stages[MESA_SHADER_FRAGMENT].<wbr>entrypoint &&<br>
+       !pipeline->shaders[MESA_SHADE<wbr>R_FRAGMENT]) {<br>
        result = anv_pipeline_compile_fs(pipeli<wbr>ne, cache,<br>
                                         &stages[MESA_SHADER_FRAGMENT]<wbr>);<br>
        if (result != VK_SUCCESS)<br>
<br>
</blockquote>
</div></div></blockquote></div><br></div></div>