[Mesa-dev] [PATCH] nir: add tess patch support to nir_remove_unused_varyings()

Timothy Arceri tarceri at itsqueeze.com
Wed Oct 25 08:06:41 UTC 2017


Shader-db results BDW:

total instructions in shared programs: 13276247 -> 13275395 (-0.01%)
instructions in affected programs: 29407 -> 28555 (-2.90%)
helped: 71
HURT: 0

total cycles in shared programs: 539866300 -> 539861882 (-0.00%)
cycles in affected programs: 127518 -> 123100 (-3.46%)
helped: 71
HURT: 1

These are all Shadow of Mordor shaders.
---
 src/compiler/nir/nir_linking_helpers.c | 61 +++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 19 deletions(-)

diff --git a/src/compiler/nir/nir_linking_helpers.c b/src/compiler/nir/nir_linking_helpers.c
index 54ba1c85e58..4d709c1b3c5 100644
--- a/src/compiler/nir/nir_linking_helpers.c
+++ b/src/compiler/nir/nir_linking_helpers.c
@@ -37,10 +37,12 @@
 static uint64_t
 get_variable_io_mask(nir_variable *var, gl_shader_stage stage)
 {
-   /* TODO: add support for tess patches */
-   if (var->data.patch || var->data.location < 0)
+   if (var->data.location < 0)
       return 0;
 
+   unsigned location = var->data.patch ?
+      var->data.location - VARYING_SLOT_PATCH0 : var->data.location;
+
    assert(var->data.mode == nir_var_shader_in ||
           var->data.mode == nir_var_shader_out ||
           var->data.mode == nir_var_system_value);
@@ -53,11 +55,11 @@ get_variable_io_mask(nir_variable *var, gl_shader_stage stage)
    }
 
    unsigned slots = glsl_count_attribute_slots(type, false);
-   return ((1ull << slots) - 1) << var->data.location;
+   return ((1ull << slots) - 1) << location;
 }
 
 static void
-tcs_add_output_reads(nir_shader *shader, uint64_t *read)
+tcs_add_output_reads(nir_shader *shader, uint64_t *read, uint64_t *patches_read)
 {
    nir_foreach_function(function, shader) {
       if (function->impl) {
@@ -73,9 +75,15 @@ tcs_add_output_reads(nir_shader *shader, uint64_t *read)
                    nir_var_shader_out) {
 
                   nir_variable *var = intrin_instr->variables[0]->var;
-                  read[var->data.location_frac] |=
-                     get_variable_io_mask(intrin_instr->variables[0]->var,
-                                          shader->info.stage);
+                  if (var->data.patch) {
+                     patches_read[var->data.location_frac] |=
+                        get_variable_io_mask(intrin_instr->variables[0]->var,
+                                             shader->info.stage);
+                  } else {
+                     read[var->data.location_frac] |=
+                        get_variable_io_mask(intrin_instr->variables[0]->var,
+                                             shader->info.stage);
+                  }
                }
             }
          }
@@ -85,14 +93,17 @@ tcs_add_output_reads(nir_shader *shader, uint64_t *read)
 
 static bool
 remove_unused_io_vars(nir_shader *shader, struct exec_list *var_list,
-                      uint64_t *used_by_other_stage)
+                      uint64_t *used_by_other_stage,
+                      uint64_t *used_by_other_stage_patches)
 {
    bool progress = false;
+   uint64_t *used;
 
    nir_foreach_variable_safe(var, var_list) {
-      /* TODO: add patch support */
       if (var->data.patch)
-         continue;
+         used = used_by_other_stage_patches;
+      else
+         used = used_by_other_stage;
 
       if (var->data.location < VARYING_SLOT_VAR0 && var->data.location >= 0)
          continue;
@@ -100,7 +111,7 @@ remove_unused_io_vars(nir_shader *shader, struct exec_list *var_list,
       if (var->data.always_active_io)
          continue;
 
-      uint64_t other_stage = used_by_other_stage[var->data.location_frac];
+      uint64_t other_stage = used[var->data.location_frac];
 
       if (!(other_stage & get_variable_io_mask(var, shader->info.stage))) {
          /* This one is invalid, make it a global variable instead */
@@ -124,15 +135,26 @@ nir_remove_unused_varyings(nir_shader *producer, nir_shader *consumer)
    assert(consumer->info.stage != MESA_SHADER_VERTEX);
 
    uint64_t read[4] = { 0 }, written[4] = { 0 };
+   uint64_t patches_read[4] = { 0 }, patches_written[4] = { 0 };
 
    nir_foreach_variable(var, &producer->outputs) {
-      written[var->data.location_frac] |=
-         get_variable_io_mask(var, producer->info.stage);
+      if (var->data.patch) {
+         patches_written[var->data.location_frac] |=
+            get_variable_io_mask(var, producer->info.stage);
+      } else {
+         written[var->data.location_frac] |=
+            get_variable_io_mask(var, producer->info.stage);
+      }
    }
 
    nir_foreach_variable(var, &consumer->inputs) {
-      read[var->data.location_frac] |=
-         get_variable_io_mask(var, consumer->info.stage);
+      if (var->data.patch) {
+         patches_read[var->data.location_frac] |=
+            get_variable_io_mask(var, consumer->info.stage);
+      } else {
+         read[var->data.location_frac] |=
+            get_variable_io_mask(var, consumer->info.stage);
+      }
    }
 
    /* Each TCS invocation can read data written by other TCS invocations,
@@ -140,13 +162,14 @@ nir_remove_unused_varyings(nir_shader *producer, nir_shader *consumer)
     * sure they are not read by the TCS before demoting them to globals.
     */
    if (producer->info.stage == MESA_SHADER_TESS_CTRL)
-      tcs_add_output_reads(producer, read);
+      tcs_add_output_reads(producer, read, patches_read);
 
    bool progress = false;
-   progress = remove_unused_io_vars(producer, &producer->outputs, read);
+   progress = remove_unused_io_vars(producer, &producer->outputs, read,
+                                    patches_read);
 
-   progress =
-      remove_unused_io_vars(consumer, &consumer->inputs, written) || progress;
+   progress = remove_unused_io_vars(consumer, &consumer->inputs, written,
+                                    patches_written) || progress;
 
    return progress;
 }
-- 
2.13.6



More information about the mesa-dev mailing list