From e8ce53a33d5c4e2e5d007f0c9de05f113cc413df Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 15 Feb 2024 08:59:13 -0500 Subject: [PATCH] zink: promote gpl libs freeing during shader destroy out of prog loop now that zink_gfx_lib_cache::stages_present exists (and is correct), this value can be used directly to effect cache eviction instead of depending on the prog->stages_present value, which may not even be the same prog that owns a given zink_gfx_lib_cache instance this fixes the case where a shader used in multiple progs with differing shader masks would never have all its gpl pipelines freed fixes leaks with caselist: KHR-Single-GL46.arrays_of_arrays_gl.InteractionUniformBuffers1 KHR-Single-GL46.subgroups.quad.framebuffer.subgroupquadbroadcast_3_float_vertex Fixes: d786f52f1ff ("zink: prevent crash when freeing") Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_compiler.c | 25 +++++++++++------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index 99310cf6f17..303c7a22e86 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -5764,20 +5764,6 @@ zink_gfx_shader_free(struct zink_screen *screen, struct zink_shader *shader) } } - while (util_dynarray_contains(&shader->pipeline_libs, struct zink_gfx_lib_cache*)) { - struct zink_gfx_lib_cache *libs = util_dynarray_pop(&shader->pipeline_libs, struct zink_gfx_lib_cache*); - //this condition is equivalent to verifying that, for each bit stages_present_i in stages_present, - //stages_present_i implies libs->stages_present_i - if ((stages_present & ~(libs->stages_present & stages_present)) != 0) - continue; - if (!libs->removed) { - libs->removed = true; - simple_mtx_lock(&screen->pipeline_libs_lock[idx]); - _mesa_set_remove_key(&screen->pipeline_libs[idx], libs); - simple_mtx_unlock(&screen->pipeline_libs_lock[idx]); - } - zink_gfx_lib_cache_unref(screen, libs); - } if (stage == MESA_SHADER_FRAGMENT || !shader->non_fs.is_generated) { prog->shaders[stage] = NULL; prog->stages_remaining &= ~BITFIELD_BIT(stage); @@ -5793,6 +5779,17 @@ zink_gfx_shader_free(struct zink_screen *screen, struct zink_shader *shader) } zink_gfx_program_reference(screen, &prog, NULL); } + while (util_dynarray_contains(&shader->pipeline_libs, struct zink_gfx_lib_cache*)) { + struct zink_gfx_lib_cache *libs = util_dynarray_pop(&shader->pipeline_libs, struct zink_gfx_lib_cache*); + if (!libs->removed) { + libs->removed = true; + unsigned idx = zink_program_cache_stages(libs->stages_present); + simple_mtx_lock(&screen->pipeline_libs_lock[idx]); + _mesa_set_remove_key(&screen->pipeline_libs[idx], libs); + simple_mtx_unlock(&screen->pipeline_libs_lock[idx]); + } + zink_gfx_lib_cache_unref(screen, libs); + } if (shader->info.stage == MESA_SHADER_TESS_EVAL && shader->non_fs.generated_tcs) { /* automatically destroy generated tcs shaders when tes is destroyed */