nir: add array lowering function that assumes there are no indirects
authorTimothy Arceri <tarceri@itsqueeze.com>
Wed, 15 Nov 2017 03:28:01 +0000 (14:28 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Mon, 4 Dec 2017 01:52:18 +0000 (12:52 +1100)
The gallium glsl->nir pass currently lowers away all indirects on both inputs
and outputs. This fuction allows us to lower vs inputs and fs outputs and also
lower things one stage at a time as we don't need to worry about indirects
on the other side of the shaders interface.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/compiler/nir/nir.h
src/compiler/nir/nir_lower_io_arrays_to_elements.c

index 83858afe1485868a5af72a9cfcdd1bbbbc34b41e..189c17d16251d8f5557a09940029dcc200adde81 100644 (file)
@@ -2496,6 +2496,7 @@ bool nir_lower_load_const_to_scalar(nir_shader *shader);
 bool nir_lower_read_invocation_to_scalar(nir_shader *shader);
 bool nir_lower_phis_to_scalar(nir_shader *shader);
 void nir_lower_io_arrays_to_elements(nir_shader *producer, nir_shader *consumer);
+void nir_lower_io_arrays_to_elements_no_indirects(nir_shader *shader);
 void nir_lower_io_to_scalar(nir_shader *shader, nir_variable_mode mask);
 void nir_lower_io_to_scalar_early(nir_shader *shader, nir_variable_mode mask);
 
index 94b93e3ec91ed655749ec42e21c30f4a5ba6a7ed..c785e22b0eabce2190e184bd6c51b39293dae864 100644 (file)
@@ -35,6 +35,9 @@ static unsigned
 get_io_offset(nir_builder *b, nir_deref_var *deref, nir_variable *var,
               unsigned *element_index)
 {
+   bool vs_in = (b->shader->info.stage == MESA_SHADER_VERTEX) &&
+                (var->data.mode == nir_var_shader_in);
+
    nir_deref *tail = &deref->deref;
 
    /* For per-vertex input arrays (i.e. geometry shader inputs), skip the
@@ -52,7 +55,7 @@ get_io_offset(nir_builder *b, nir_deref_var *deref, nir_variable *var,
          nir_deref_array *deref_array = nir_deref_as_array(tail);
          assert(deref_array->deref_array_type != nir_deref_array_type_indirect);
 
-         unsigned size = glsl_count_attribute_slots(tail->type, false);
+         unsigned size = glsl_count_attribute_slots(tail->type, vs_in);
          offset += size * deref_array->base_offset;
 
          unsigned num_elements = glsl_type_is_array(tail->type) ?
@@ -339,6 +342,45 @@ lower_io_arrays_to_elements(nir_shader *shader, nir_variable_mode mask,
    }
 }
 
+void
+nir_lower_io_arrays_to_elements_no_indirects(nir_shader *shader)
+{
+   struct hash_table *split_inputs =
+      _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+                              _mesa_key_pointer_equal);
+   struct hash_table *split_outputs =
+      _mesa_hash_table_create(NULL, _mesa_hash_pointer,
+                              _mesa_key_pointer_equal);
+
+   uint64_t indirects[4] = {0}, patch_indirects[4] = {0};
+
+   lower_io_arrays_to_elements(shader, nir_var_shader_out, indirects,
+                               patch_indirects, split_outputs);
+
+   lower_io_arrays_to_elements(shader, nir_var_shader_in, indirects,
+                               patch_indirects, split_inputs);
+
+   /* Remove old input from the shaders inputs list */
+   struct hash_entry *entry;
+   hash_table_foreach(split_inputs, entry) {
+      nir_variable *var = (nir_variable *) entry->key;
+      exec_node_remove(&var->node);
+
+      free(entry->data);
+   }
+
+   /* Remove old output from the shaders outputs list */
+   hash_table_foreach(split_outputs, entry) {
+      nir_variable *var = (nir_variable *) entry->key;
+      exec_node_remove(&var->node);
+
+      free(entry->data);
+   }
+
+   _mesa_hash_table_destroy(split_inputs, NULL);
+   _mesa_hash_table_destroy(split_outputs, NULL);
+}
+
 void
 nir_lower_io_arrays_to_elements(nir_shader *producer, nir_shader *consumer)
 {