<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Nov 21, 2017 at 9:37 PM, 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">On 21/11/17 03:18, Jason Ekstrand wrote:<div><div class="h5"><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
On Mon, Nov 20, 2017 at 3:03 AM, Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a> <mailto:<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>><wbr>> wrote:<br>
    On 29/10/17 05:36, Jason Ekstrand wrote:<br>
<br>
        Instead of hashing each stage separately (and TES and TCS<br>
        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<br>
        it also<br>
        means we can now safely do cross-stage optimizations.<br>
        ---<br>
           src/intel/vulkan/anv_pipeline.<wbr>c | 151<br>
        +++++++++++++++++++++++++-----<wbr>----------<br>
           1 file changed, 94 insertions(+), 57 deletions(-)<br>
<br>
        diff --git a/src/intel/vulkan/anv_pipelin<wbr>e.c<br>
        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,<br>
        sizeof(stage->module->sha1));<br>
        +   _mesa_sha1_update(ctx, stage->entrypoint,<br>
        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,<br>
        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,<br>
        sizeof(stage->module->sha1));<br>
        -   _mesa_sha1_update(&ctx, stage->entrypoint,<br>
        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(&ctx<wbr>, &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,<br>
        brw_prog_key_size(stage->stage<wbr>));<br>
        +<br>
        +   anv_pipeline_hash_shader(&ctx<wbr>, stage);<br>
        +<br>
              _mesa_sha1_final(&ctx, sha1_out);<br>
           }<br>
           @@ -515,12 +550,6 @@ anv_pipeline_compile_vs(struct<br>
        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>
<br>
<br>
    This is always true now so the if can be removed. Smae goes for the<br>
    other stages. With that 5-12 are:<br>
<br>
<br>
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>
</blockquote>
<br></div></div>
Ok, no problem :)<br>
<br>
Once you push this can I temp you into reviewing this series [1]? It should be straight forward adding those passes to ANV also.<br>
<br>
[1] <a href="https://patchwork.freedesktop.org/series/34131/" rel="noreferrer" target="_blank">https://patchwork.freedesktop.<wbr>org/series/34131/</a><br></blockquote><div><br></div><div>I'd like to but I can't guarantee when.  Cross-stage optimization isn't exactly on the top of my priority list right now.  I'm trying to rework a bunch of stuff so we can finally get this modifiers stuff landed.  I do plan to take a look at it though.</div><div><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
    Reviewed-by: Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a><br>
    <mailto:<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>><wbr>><div><div class="h5"><br>
<br>
<br>
<br>
                 struct brw_vs_prog_data prog_data = {};<br>
        @@ -557,7 +586,9 @@ anv_pipeline_compile_vs(struct anv_pipeline<br>
        *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,<br>
        sizeof(prog_data),<br>
                                                  &map);<br>
        @@ -624,17 +655,6 @@ anv_pipeline_compile_tcs_tes(s<wbr>truct<br>
        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,<br>
        sizeof(tcs_sha1));<br>
        -      tes_bin = anv_pipeline_cache_search(cach<wbr>e, tes_sha1,<br>
        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<br>
        anv_pipeline *pipeline,<br>
                   unsigned code_size =<br>
        tcs_prog_data.base.base.progra<wbr>m_size;<br>
                 tcs_bin = anv_pipeline_upload_kernel(pip<wbr>eline, cache,<br>
        -                                           tcs_sha1,<br>
        sizeof(tcs_sha1),<br>
        +                                           &tcs_stage->cache_key,<br>
        +                                                   sizeof(tcs_stage->cache_key),<br>
                                                      shader_code,<br>
        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<br>
        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,<br>
        sizeof(tes_sha1),<br>
        +                                           &tes_stage->cache_key,<br>
        +                                                   sizeof(tes_stage->cache_key),<br>
                                                      shader_code,<br>
        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<br>
        *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<br>
        *pipeline,<br>
                   /* TODO: SIMD8 GS */<br>
                 const unsigned code_size =<br>
        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,<br>
        sizeof(prog_data),<br>
                                                  &map);<br>
        @@ -821,7 +839,6 @@ anv_pipeline_compile_fs(struct anv_pipeline<br>
        *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<br>
        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<br>
        *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<br>
        *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,<br>
        sizeof(prog_data),<br>
                                                  &map);<br>
        @@ -957,7 +971,7 @@ anv_pipeline_compile_cs(struct anv_pipeline<br>
        *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<br>
        *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])<wbr>;<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_CTR<wbr>L],<br>
                                                      &stages[MESA_SHADER_TESS_EVA<wbr>L]);<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_<wbr>GEOMETRY]);<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_<wbr>FRAGMENT]);<br>
                 if (result != VK_SUCCESS)<br>
<br>
<br>
</div></div></blockquote>
</blockquote></div><br></div></div>