[PATCH 20/21] etnaviv: nir: avoid multiple uniform src for alu ops

Philipp Zabel p.zabel at pengutronix.de
Tue Jun 5 14:38:44 UTC 2018


From: Michael Tretter <m.tretter at pengutronix.de>

The hardware does not allow two different uniform registers to be used
as sources in the same ALU instruction. Emit mov instructions to
temporary registers for all but one uniform register in this case.

Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
---
 src/gallium/drivers/etnaviv/etnaviv_nir.c | 36 +++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_nir.c b/src/gallium/drivers/etnaviv/etnaviv_nir.c
index 988b4bd62b6e..36ec21fbd623 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_nir.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_nir.c
@@ -942,6 +942,41 @@ etna_add_mov_for_uniform_output(nir_shader *shader)
    }
 }
 
+/* Accessing two different uniforms from one alu instruction is illegal.
+ * Insert a mov for all but one uniform before alu instructions.
+ */
+static void
+etna_fix_alu_uniform_src(nir_shader *shader)
+{
+   nir_foreach_function(function, shader) {
+      nir_foreach_block(block, function->impl) {
+         nir_foreach_instr_safe(instr, block) {
+            if (instr->type != nir_instr_type_alu)
+               continue;
+            nir_alu_instr *alu = nir_instr_as_alu(instr);
+
+            unsigned i;
+            bool needs_fixup = false;
+
+            for (i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {
+               nir_src *src = &alu->src[i].src;
+               if (!src->is_ssa || !nir_src_is_dynamically_uniform(*src))
+                  continue;
+
+               /* FIXME The fixup unnecessarily fixes instructions where the
+                * same uniform is used twice, which is allowed.
+                */
+               if (needs_fixup) {
+                  insert_mov(&alu->instr, src, shader);
+               } else
+                  needs_fixup = true;
+            }
+         }
+      }
+      nir_metadata_preserve(function->impl, nir_metadata_block_index);
+   }
+}
+
 /* Remove input_load and output_store intrinsics after global register
  * allocation. After the SSA destinations are replaced, these contain no useful
  * information anymore.
@@ -1024,6 +1059,7 @@ etna_optimize_nir(struct etna_shader *shader,
 
    NIR_PASS_V(s, nir_convert_from_ssa, true);
    NIR_PASS_V(s, etna_fixup_tex);
+   NIR_PASS_V(s, etna_fix_alu_uniform_src);
    NIR_PASS_V(s, etna_add_mov_for_uniform_output);
    NIR_PASS_V(s, etna_assign_registers);
    NIR_PASS_V(s, etna_remove_io_intrinsics);
-- 
2.17.1



More information about the etnaviv mailing list