From d786f52f1ff10fba42e87530933a2a4c68de49a8 Mon Sep 17 00:00:00 2001 From: antonino Date: Wed, 22 Feb 2023 17:24:57 +0100 Subject: [PATCH] zink: prevent crash when freeing If the same vertex shader is used for more than one pipeline where for some a gs is generated but not for others then the logic to free pipeline libraries might use the incorrect stage_mask and try to free a non existing gs. Reviewed-by: Mike Blumenkrantz Reviewed-by: Erik Faye-Lund Part-of: --- src/gallium/drivers/zink/zink_compiler.c | 4 ++++ src/gallium/drivers/zink/zink_program.c | 1 + src/gallium/drivers/zink/zink_types.h | 1 + 3 files changed, 6 insertions(+) diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c index c8d84ca0088..e15967f83b8 100644 --- a/src/gallium/drivers/zink/zink_compiler.c +++ b/src/gallium/drivers/zink/zink_compiler.c @@ -4726,6 +4726,10 @@ zink_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]); diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c index 3075edf2aae..fc717f8bd49 100644 --- a/src/gallium/drivers/zink/zink_program.c +++ b/src/gallium/drivers/zink/zink_program.c @@ -977,6 +977,7 @@ static struct zink_gfx_lib_cache * create_lib_cache(struct zink_gfx_program *prog, bool generated_tcs) { struct zink_gfx_lib_cache *libs = rzalloc(NULL, struct zink_gfx_lib_cache); + libs->stages_present = prog->stages_present; simple_mtx_init(&libs->lock, mtx_plain); if (generated_tcs) _mesa_set_init(&libs->libs, libs, hash_pipeline_lib_generated_tcs, equals_pipeline_lib_generated_tcs); diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index ff49bf21fe0..ee7da9a80b7 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1005,6 +1005,7 @@ struct zink_gfx_lib_cache { struct zink_shader *shaders[ZINK_GFX_SHADER_COUNT]; unsigned refcount; bool removed; //once removed from cache + uint8_t stages_present; simple_mtx_t lock; struct set libs; //zink_gfx_library_key -> VkPipeline