Mesa (master): iris: Reference the shader variant for last_vue_map as well

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Feb 19 18:54:55 UTC 2021


Module: Mesa
Branch: master
Commit: 4c4a91abe59c37aa88391e7aff30e078682ecb4c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4c4a91abe59c37aa88391e7aff30e078682ecb4c

Author: Kenneth Graunke <kenneth at whitecape.org>
Date:   Thu Feb 18 14:27:19 2021 -0800

iris: Reference the shader variant for last_vue_map as well

We call update_last_vue_map after updating the shaders, which compares
the new and old VUE maps.  Except...updating the shaders may have
dropped the last reference to the variant that ice->shaders.last_vue_map
belonged to, leading to a classic use-after-free.

Fix this by taking a reference to the variant for the last VUE stage,
so it stays around until we're done with it.

Fixes: 1afed51445c ("iris: Store a list of shader variants in the shader itself")
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4311
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9143>

---

 src/gallium/drivers/iris/iris_context.h       |  2 +-
 src/gallium/drivers/iris/iris_program.c       | 18 +++++++++++-------
 src/gallium/drivers/iris/iris_program_cache.c |  1 +
 src/gallium/drivers/iris/iris_state.c         |  9 ++++++---
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h
index 986ac0d4694..ed7affdb352 100644
--- a/src/gallium/drivers/iris/iris_context.h
+++ b/src/gallium/drivers/iris/iris_context.h
@@ -630,7 +630,7 @@ struct iris_context {
    struct {
       struct iris_uncompiled_shader *uncompiled[MESA_SHADER_STAGES];
       struct iris_compiled_shader *prog[MESA_SHADER_STAGES];
-      struct brw_vue_map *last_vue_map;
+      struct iris_compiled_shader *last_vue_shader;
       struct {
          unsigned size[4];
          unsigned entries[4];
diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c
index e0661ec2d84..9b76c78052f 100644
--- a/src/gallium/drivers/iris/iris_program.c
+++ b/src/gallium/drivers/iris/iris_program.c
@@ -1817,8 +1817,11 @@ iris_update_compiled_fs(struct iris_context *ice)
    struct iris_screen *screen = (struct iris_screen *)ice->ctx.screen;
    screen->vtbl.populate_fs_key(ice, &ish->nir->info, &key);
 
+   struct brw_vue_map *last_vue_map =
+      &brw_vue_prog_data(ice->shaders.last_vue_shader->prog_data)->vue_map;
+
    if (ish->nos & (1ull << IRIS_NOS_LAST_VUE_MAP))
-      key.input_slots_valid = ice->shaders.last_vue_map->slots_valid;
+      key.input_slots_valid = last_vue_map->slots_valid;
 
    struct iris_compiled_shader *old = ice->shaders.prog[IRIS_CACHE_FS];
    struct iris_compiled_shader *shader =
@@ -1831,7 +1834,7 @@ iris_update_compiled_fs(struct iris_context *ice)
 
    if (!shader) {
       shader = iris_compile_fs(screen, uploader, &ice->dbg,
-                               ish, &key, ice->shaders.last_vue_map);
+                               ish, &key, last_vue_map);
    }
 
    if (old != shader) {
@@ -1857,11 +1860,12 @@ iris_update_compiled_fs(struct iris_context *ice)
  */
 static void
 update_last_vue_map(struct iris_context *ice,
-                    struct brw_stage_prog_data *prog_data)
+                    struct iris_compiled_shader *shader)
 {
-   struct brw_vue_prog_data *vue_prog_data = (void *) prog_data;
+   struct brw_vue_prog_data *vue_prog_data = (void *) shader->prog_data;
    struct brw_vue_map *vue_map = &vue_prog_data->vue_map;
-   struct brw_vue_map *old_map = ice->shaders.last_vue_map;
+   struct brw_vue_map *old_map = !ice->shaders.last_vue_shader ? NULL :
+      &brw_vue_prog_data(ice->shaders.last_vue_shader->prog_data)->vue_map;
    const uint64_t changed_slots =
       (old_map ? old_map->slots_valid : 0ull) ^ vue_map->slots_valid;
 
@@ -1880,7 +1884,7 @@ update_last_vue_map(struct iris_context *ice,
       ice->state.dirty |= IRIS_DIRTY_SBE;
    }
 
-   ice->shaders.last_vue_map = &vue_prog_data->vue_map;
+   iris_shader_variant_reference(&ice->shaders.last_vue_shader, shader);
 }
 
 static void
@@ -1981,7 +1985,7 @@ iris_update_compiled_shaders(struct iris_context *ice)
    gl_shader_stage last_stage = last_vue_stage(ice);
    struct iris_compiled_shader *shader = ice->shaders.prog[last_stage];
    struct iris_uncompiled_shader *ish = ice->shaders.uncompiled[last_stage];
-   update_last_vue_map(ice, shader->prog_data);
+   update_last_vue_map(ice, shader);
    if (ice->state.streamout != shader->streamout) {
       ice->state.streamout = shader->streamout;
       ice->state.dirty |= IRIS_DIRTY_SO_DECL_LIST | IRIS_DIRTY_STREAMOUT;
diff --git a/src/gallium/drivers/iris/iris_program_cache.c b/src/gallium/drivers/iris/iris_program_cache.c
index de7fe4df67f..21465ea9473 100644
--- a/src/gallium/drivers/iris/iris_program_cache.c
+++ b/src/gallium/drivers/iris/iris_program_cache.c
@@ -281,6 +281,7 @@ iris_destroy_program_cache(struct iris_context *ice)
    for (int i = 0; i < MESA_SHADER_STAGES; i++) {
       iris_shader_variant_reference(&ice->shaders.prog[i], NULL);
    }
+   iris_shader_variant_reference(&ice->shaders.last_vue_shader, NULL);
 
    hash_table_foreach(ice->shaders.cache, entry) {
       struct iris_compiled_shader *shader = entry->data;
diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c
index 53120f4a8a0..a247dc01af1 100644
--- a/src/gallium/drivers/iris/iris_state.c
+++ b/src/gallium/drivers/iris/iris_state.c
@@ -4003,13 +4003,13 @@ iris_compute_sbe_urb_read_interval(uint64_t fs_input_slots,
 static void
 iris_emit_sbe_swiz(struct iris_batch *batch,
                    const struct iris_context *ice,
+                   const struct brw_vue_map *vue_map,
                    unsigned urb_read_offset,
                    unsigned sprite_coord_enables)
 {
    struct GENX(SF_OUTPUT_ATTRIBUTE_DETAIL) attr_overrides[16] = {};
    const struct brw_wm_prog_data *wm_prog_data = (void *)
       ice->shaders.prog[MESA_SHADER_FRAGMENT]->prog_data;
-   const struct brw_vue_map *vue_map = ice->shaders.last_vue_map;
    const struct iris_rasterizer_state *cso_rast = ice->state.cso_rast;
 
    /* XXX: this should be generated when putting programs in place */
@@ -4150,10 +4150,12 @@ iris_emit_sbe(struct iris_batch *batch, const struct iris_context *ice)
       ice->shaders.prog[MESA_SHADER_FRAGMENT]->prog_data;
    const struct shader_info *fs_info =
       iris_get_shader_info(ice, MESA_SHADER_FRAGMENT);
+   const struct brw_vue_map *last_vue_map =
+      &brw_vue_prog_data(ice->shaders.last_vue_shader->prog_data)->vue_map;
 
    unsigned urb_read_offset, urb_read_length;
    iris_compute_sbe_urb_read_interval(fs_info->inputs_read,
-                                      ice->shaders.last_vue_map,
+                                      last_vue_map,
                                       cso_rast->light_twoside,
                                       &urb_read_offset, &urb_read_length);
 
@@ -4178,7 +4180,8 @@ iris_emit_sbe(struct iris_batch *batch, const struct iris_context *ice)
 #endif
    }
 
-   iris_emit_sbe_swiz(batch, ice, urb_read_offset, sprite_coord_overrides);
+   iris_emit_sbe_swiz(batch, ice, last_vue_map, urb_read_offset,
+                      sprite_coord_overrides);
 }
 
 /* ------------------------------------------------------------------- */



More information about the mesa-commit mailing list