nir: add tess patch support to nir_remove_unused_varyings()
authorTimothy Arceri <tarceri@itsqueeze.com>
Mon, 30 Oct 2017 04:11:10 +0000 (15:11 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Thu, 2 Nov 2017 21:58:39 +0000 (08:58 +1100)
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/compiler/nir/nir_linking_helpers.c

index 54ba1c85e58c8b3fb77edd1794902074817bfbe5..4d709c1b3c54bb82dba2669db59f5dc9356bcb82 100644 (file)
 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;
 }