Module: Mesa
Branch: main
Commit: 39770c6503ac44090decd88698802bb95189bb4d
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=39770c6503ac44090decd88698802bb95189bb4d

Author: antonino <[email protected]>
Date:   Tue Apr 25 12:29:35 2023 +0200

zink: fix store subsitution in `lower_pv_mode_gs_store`

Previously it was assumed that between the and the variable there was
only one deref.

To handle all cases a new function is introduced that recreates a chain
of derefs.

Fixes: 5a4083349f3 ("zink: add provoking vertex mode lowering")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22678>

---

 src/gallium/drivers/zink/zink_compiler.c | 33 +++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_compiler.c 
b/src/gallium/drivers/zink/zink_compiler.c
index d708ab1c879..41cda4b535f 100644
--- a/src/gallium/drivers/zink/zink_compiler.c
+++ b/src/gallium/drivers/zink/zink_compiler.c
@@ -426,6 +426,31 @@ lower_pv_mode_gs_ring_index(nir_builder *b,
                       nir_imm_int(b, state->ring_size));
 }
 
+/* Given the final deref of chain of derefs this function will walk up the 
chain
+ * until it finds a var deref.
+ *
+ * It will then recreate an identical chain that ends with the provided deref.
+ */
+static nir_deref_instr*
+replicate_derefs(nir_builder *b, nir_deref_instr *old, nir_deref_instr *new)
+{
+   nir_deref_instr *parent = nir_src_as_deref(old->parent);
+   switch(old->deref_type) {
+   case nir_deref_type_var:
+      return new;
+   case nir_deref_type_array:
+      assert(old->arr.index.is_ssa);
+      return nir_build_deref_array(b, replicate_derefs(b, parent, new), 
old->arr.index.ssa);
+   case nir_deref_type_struct:
+      return nir_build_deref_struct(b, replicate_derefs(b, parent, new), 
old->strct.index);
+   case nir_deref_type_array_wildcard:
+   case nir_deref_type_ptr_as_array:
+   case nir_deref_type_cast:
+      unreachable("unexpected deref type");
+   }
+   unreachable("impossible deref type");
+}
+
 static bool
 lower_pv_mode_gs_store(nir_builder *b,
                        nir_intrinsic_instr *intrin,
@@ -441,9 +466,11 @@ lower_pv_mode_gs_store(nir_builder *b,
       assert(intrin->src[1].is_ssa);
       nir_ssa_def *pos_counter = nir_load_var(b, state->pos_counter);
       nir_ssa_def *index = lower_pv_mode_gs_ring_index(b, state, pos_counter);
-      nir_store_array_var(b, state->varyings[location],
-                             index, intrin->src[1].ssa,
-                             nir_intrinsic_write_mask(intrin));
+      nir_deref_instr *varying_deref = nir_build_deref_var(b, 
state->varyings[location]);
+      nir_deref_instr *ring_deref = nir_build_deref_array(b, varying_deref, 
index);
+      // recreate the chain of deref that lead to the store.
+      nir_deref_instr *new_top_deref = replicate_derefs(b, deref, ring_deref);
+      nir_store_deref(b, new_top_deref, intrin->src[1].ssa, 
nir_intrinsic_write_mask(intrin));
       nir_instr_remove(&intrin->instr);
       return true;
    }

Reply via email to