[Mesa-dev] [PATCH 01/15] nir: add array lowering function that assumes there are no indirects

Nicolai Hähnle nhaehnle at gmail.com
Wed Nov 29 11:14:37 UTC 2017


On 22.11.2017 11:29, Timothy Arceri wrote:
> 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.

There is a check for var->data.location vs. VARYING_SLOT_VAR0 in 
lower_io_arrays_to_elements that I believe needs to be adjusted for VS 
inputs and FS outputs.

Apart from that this looks good to me.

Cheers,
Nicolai


> ---
>   src/compiler/nir/nir.h                             |  1 +
>   src/compiler/nir/nir_lower_io_arrays_to_elements.c | 44 +++++++++++++++++++++-
>   2 files changed, 44 insertions(+), 1 deletion(-)
> 
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index 5832c05680..97f38e7c73 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -2478,20 +2478,21 @@ bool nir_lower_constant_initializers(nir_shader *shader,
>   
>   bool nir_move_vec_src_uses_to_dest(nir_shader *shader);
>   bool nir_lower_vec_to_movs(nir_shader *shader);
>   void nir_lower_alpha_test(nir_shader *shader, enum compare_func func,
>                             bool alpha_to_one);
>   bool nir_lower_alu_to_scalar(nir_shader *shader);
>   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);
>   
>   bool nir_lower_samplers(nir_shader *shader,
>                           const struct gl_shader_program *shader_program);
>   bool nir_lower_samplers_as_deref(nir_shader *shader,
>                                    const struct gl_shader_program *shader_program);
>   
>   typedef struct nir_lower_subgroups_options {
>      uint8_t subgroup_size;
> diff --git a/src/compiler/nir/nir_lower_io_arrays_to_elements.c b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
> index c41f300edb..29076bf79b 100644
> --- a/src/compiler/nir/nir_lower_io_arrays_to_elements.c
> +++ b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
> @@ -28,38 +28,41 @@
>    *
>    * Split arrays/matrices with direct indexing into individual elements. This
>    * will allow optimisation passes to better clean up unused elements.
>    *
>    */
>   
>   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
>       * outermost array index.  Process the rest normally.
>       */
>      if (nir_is_per_vertex_io(var, b->shader->info.stage)) {
>         tail = tail->child;
>      }
>   
>      unsigned offset = 0;
>      while (tail->child != NULL) {
>         tail = tail->child;
>   
>         if (tail->deref_type == nir_deref_type_array) {
>            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) ?
>               glsl_get_aoa_size(tail->type) : 1;
>   
>            num_elements *= glsl_type_is_matrix(glsl_without_array(tail->type)) ?
>               glsl_get_matrix_columns(glsl_without_array(tail->type)) : 1;
>   
>            *element_index += num_elements * deref_array->base_offset;
>         } else if (tail->deref_type == nir_deref_type_struct) {
> @@ -324,20 +327,59 @@ lower_io_arrays_to_elements(nir_shader *shader, nir_variable_mode mask,
>                     break;
>                  default:
>                     break;
>                  }
>               }
>            }
>         }
>      }
>   }
>   
> +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)
>   {
>      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);
>   
> 


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list