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: d786f52f1f ("zink: prevent crash when freeing")

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27358>
This commit is contained in:
Mike Blumenkrantz
2024-02-15 08:59:13 -05:00
parent 36e7350e0b
commit e8ce53a33d

View File

@@ -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 */