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) { 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) -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev