zink: prevent crash when freeing
authorantonino <antonino.maniscalco@collabora.com>
Wed, 22 Feb 2023 16:24:57 +0000 (17:24 +0100)
committerMarge Bot <emma+marge@anholt.net>
Wed, 29 Mar 2023 19:18:40 +0000 (19:18 +0000)
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 <michael.blumenkrantz@gmail.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21238>

src/gallium/drivers/zink/zink_compiler.c
src/gallium/drivers/zink/zink_program.c
src/gallium/drivers/zink/zink_types.h

index c8d84ca..e15967f 100644 (file)
@@ -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]);
index 3075edf..fc717f8 100644 (file)
@@ -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);
index ff49bf2..ee7da9a 100644 (file)
@@ -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