Mesa (main): nouveau/nir: Move FS output stores to the end of the last block.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 29 23:13:23 UTC 2022


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

Author: Emma Anholt <emma at anholt.net>
Date:   Wed Apr 20 16:30:37 2022 -0700

nouveau/nir: Move FS output stores to the end of the last block.

The nir_move/sink caused instructions to sink interleaved into the output
stores at the end of the shader.  nouveau's RA doesn't track liveness of
FS outputs in registers after the export instruction, so they could end up
overwritten.  To work around it, after normal NIR move/sink, move the
output stores back to the end of the shader.

Fixes: b1fa2068b8e8 ("nouveau/nir: Enable nir_opt_move/sink.")

Reviewed-by: M Henning <drawoc at darkrefraction.com>
Reviewed-by: Karol Herbst <kherbst at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15949>

---

 .../drivers/nouveau/codegen/nv50_ir_from_nir.cpp   | 34 +++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
index 7abd83d3a56..6d9ba1ccca5 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
@@ -1034,7 +1034,6 @@ bool Converter::assignSlots() {
       int slot = var->data.location;
       uint16_t slots = calcSlots(type, prog->getType(), nir->info, true, var);
       uint32_t vary = var->data.driver_location;
-
       assert(vary + slots <= PIPE_MAX_SHADER_INPUTS);
 
       switch(prog->getType()) {
@@ -3122,6 +3121,36 @@ Converter::visit(nir_tex_instr *insn)
    return true;
 }
 
+/* nouveau's RA doesn't track the liveness of exported registers in the fragment
+ * shader, so we need all the store_outputs to appear at the end of the shader
+ * with no other instructions that might generate a temp value in between them.
+ */
+static void
+nv_nir_move_stores_to_end(nir_shader *s)
+{
+   nir_function_impl *impl = nir_shader_get_entrypoint(s);
+   nir_block *block = nir_impl_last_block(impl);
+   nir_instr *first_store = NULL;
+
+   nir_foreach_instr_safe(instr, block) {
+      if (instr == first_store)
+         break;
+      if (instr->type != nir_instr_type_intrinsic)
+         continue;
+      nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+      if (intrin->intrinsic == nir_intrinsic_store_output) {
+         nir_instr_remove(instr);
+         nir_instr_insert(nir_after_block(block), instr);
+
+         if (!first_store)
+            first_store = instr;
+      }
+   }
+   nir_metadata_preserve(impl,
+                         nir_metadata_block_index |
+                         nir_metadata_dominance);
+}
+
 bool
 Converter::run()
 {
@@ -3191,6 +3220,9 @@ Converter::run()
    NIR_PASS_V(nir, nir_opt_sink, move_options);
    NIR_PASS_V(nir, nir_opt_move, move_options);
 
+   if (nir->info.stage == MESA_SHADER_FRAGMENT)
+      NIR_PASS_V(nir, nv_nir_move_stores_to_end);
+
    NIR_PASS_V(nir, nir_lower_bool_to_int32);
    NIR_PASS_V(nir, nir_convert_from_ssa, true);
 



More information about the mesa-commit mailing list