summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2017-06-14 18:35:22 +0200
committerPhilipp Zabel <p.zabel@pengutronix.de>2018-06-05 16:26:24 +0200
commite5cd92413edd2adb4dd1d3d20377c734dd395f69 (patch)
tree3c7cd18d290eb5426b95c6a35d15bf3296c8073d
parent92df44881750b03f3d95ead40920caea63963b53 (diff)
downloadmesa-e5cd92413edd2adb4dd1d3d20377c734dd395f69.tar.gz
mesa-e5cd92413edd2adb4dd1d3d20377c734dd395f69.tar.xz
etnaviv: nir: hardwire position location
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@pengutronix.de> Signed-off-by: Michael Tretter <m.tretter@pengutronix.de>
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_nir.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/gallium/drivers/etnaviv/etnaviv_nir.c b/src/gallium/drivers/etnaviv/etnaviv_nir.c
index 1ddfbb8189..3b29ea9a0e 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);