[PATCH 06/21] etnaviv: nir: hardwire position location

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


The temporary input/output register 0 is reserved for position in the
fragment shader. Hardwire it to 0 and start other input/output variables
at 1. The intrinsic input load and output store base corresponds to the
temporary register number.

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

diff --git a/src/gallium/drivers/etnaviv/etnaviv_nir.c b/src/gallium/drivers/etnaviv/etnaviv_nir.c
index 1ddfbb818922..3b29ea9a0e76 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_nir.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_nir.c
@@ -81,6 +81,81 @@ etna_optimize_loop(nir_shader *s)
    } while (progress);
 }
 
+/* The temporary PS input/output register 0 is reserved for the position */
+static void
+etna_hardwire_io_position(nir_shader *shader)
+{
+   bool fixup_needed = false;
+   int pos_in = -1, pos_out = -1;
+   int max_in = 0, max_out = 0;
+
+   if (shader->info.stage != MESA_SHADER_FRAGMENT)
+      return;
+
+   nir_foreach_variable(var, &shader->inputs) {
+      if (var->data.location == VARYING_SLOT_POS) {
+         pos_in = var->data.driver_location;
+      } else {
+         max_in = MAX2(max_in, var->data.driver_location);
+         if (var->data.driver_location == 0)
+            fixup_needed = true;
+      }
+   }
+   nir_foreach_variable(var, &shader->outputs) {
+      if (var->data.location == FRAG_RESULT_DEPTH) {
+         pos_out = var->data.driver_location;
+      } else {
+         max_out = MAX2(max_out, var->data.driver_location);
+         if (var->data.driver_location == 0)
+            fixup_needed = true;
+      }
+   }
+
+   fixup_needed |= (pos_in > 0) || (pos_out > 0);
+   if (!fixup_needed)
+      return;
+
+   if (pos_in == -1)
+      pos_in = max_in + 1;
+   if (pos_out == -1)
+      pos_out = max_out + 1;
+
+   nir_foreach_variable(var, &shader->inputs) {
+      if (var->data.location == VARYING_SLOT_POS)
+         var->data.driver_location = 0;
+      else if (var->data.driver_location < pos_in)
+         var->data.driver_location++;
+   }
+   nir_foreach_variable(var, &shader->outputs) {
+      if (var->data.location == FRAG_RESULT_DEPTH)
+         var->data.driver_location = 0;
+      else if (var->data.driver_location < pos_out)
+         var->data.driver_location++;
+   }
+
+   nir_foreach_function(function, shader) {
+      nir_foreach_block(block, function->impl) {
+         nir_foreach_instr(instr, block) {
+            if (instr->type != nir_instr_type_intrinsic)
+               continue;
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+            unsigned pos;
+            if (intr->intrinsic == nir_intrinsic_load_input)
+               pos = pos_in;
+            else if (intr->intrinsic == nir_intrinsic_store_output)
+               pos = pos_out;
+            else
+               continue;
+            unsigned base = nir_intrinsic_base(intr);
+            if (base <= pos)
+               nir_intrinsic_set_base(intr, (base == pos) ? 0 : (base + 1));
+         }
+      }
+      nir_metadata_preserve(function->impl,
+                            nir_metadata_block_index | nir_metadata_dominance);
+   }
+}
+
 /* Move const loads, input load intrinsics, and uniform load intrinsics to the
  * beginning of the function implementation.
  *
@@ -545,6 +620,7 @@ etna_optimize_nir(struct etna_shader *shader,
    NIR_PASS_V(s, nir_opt_global_to_local);
    NIR_PASS_V(s, nir_lower_regs_to_ssa);
    NIR_PASS_V(s, etna_move_load_intrinsics);
+   NIR_PASS_V(s, etna_hardwire_io_position);
 
    etna_optimize_loop(s);
 
-- 
2.17.1



More information about the etnaviv mailing list