V2: fix matrix support, non-array matrices were being skipped in v1
---
src/compiler/Makefile.sources | 1 +
src/compiler/nir/meson.build | 1 +
src/compiler/nir/nir.h | 1 +
src/compiler/nir/nir_lower_io_arrays_to_elements.c | 373
+++++++++++++++++++++
4 files changed, 376 insertions(+)
create mode 100644 src/compiler/nir/nir_lower_io_arrays_to_elements.c
diff --git a/src/compiler/Makefile.sources
b/src/compiler/Makefile.sources
index 2ab8e163a2..c5094b7f19 100644
--- a/src/compiler/Makefile.sources
+++ b/src/compiler/Makefile.sources
@@ -219,20 +219,21 @@ NIR_FILES = \
nir/nir_lower_double_ops.c \
nir/nir_lower_drawpixels.c \
nir/nir_lower_global_vars_to_local.c \
nir/nir_lower_gs_intrinsics.c \
nir/nir_lower_load_const_to_scalar.c \
nir/nir_lower_locals_to_regs.c \
nir/nir_lower_idiv.c \
nir/nir_lower_indirect_derefs.c \
nir/nir_lower_int64.c \
nir/nir_lower_io.c \
+ nir/nir_lower_io_arrays_to_elements.c \
nir/nir_lower_io_to_temporaries.c \
nir/nir_lower_io_to_scalar.c \
nir/nir_lower_io_types.c \
nir/nir_lower_passthrough_edgeflags.c \
nir/nir_lower_patch_vertices.c \
nir/nir_lower_phis_to_scalar.c \
nir/nir_lower_regs_to_ssa.c \
nir/nir_lower_returns.c \
nir/nir_lower_samplers.c \
nir/nir_lower_samplers_as_deref.c \
diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
index e5c8326aa0..b61a07773d 100644
--- a/src/compiler/nir/meson.build
+++ b/src/compiler/nir/meson.build
@@ -107,20 +107,21 @@ files_libnir = files(
'nir_lower_double_ops.c',
'nir_lower_drawpixels.c',
'nir_lower_global_vars_to_local.c',
'nir_lower_gs_intrinsics.c',
'nir_lower_load_const_to_scalar.c',
'nir_lower_locals_to_regs.c',
'nir_lower_idiv.c',
'nir_lower_indirect_derefs.c',
'nir_lower_int64.c',
'nir_lower_io.c',
+ 'nir_lower_io_arrays_to_elements.c',
'nir_lower_io_to_temporaries.c',
'nir_lower_io_to_scalar.c',
'nir_lower_io_types.c',
'nir_lower_passthrough_edgeflags.c',
'nir_lower_patch_vertices.c',
'nir_lower_phis_to_scalar.c',
'nir_lower_regs_to_ssa.c',
'nir_lower_returns.c',
'nir_lower_samplers.c',
'nir_lower_samplers_as_deref.c',
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index f46f614711..c62af4afb9 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2475,20 +2475,21 @@ bool
nir_lower_constant_initializers(nir_shader *shader,
nir_variable_mode modes);
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_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
new file mode 100644
index 0000000000..c41f300edb
--- /dev/null
+++ b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright © 2017 Timothy Arceri
+ *
+ * Permission is hereby granted, free of charge, to any person
obtaining a
+ * copy of this software and associated documentation files (the
"Software"),
+ * to deal in the Software without restriction, including without
limitation
+ * the rights to use, copy, modify, merge, publish, distribute,
sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including
the next
+ * paragraph) shall be included in all copies or substantial portions
of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "nir.h"
+#include "nir_builder.h"
+
+/** @file nir_lower_io_arrays_to_elements.c
+ *
+ * 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)
+{
+ 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);
+ 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) {
+ /* TODO: we could also add struct splitting support to this
pass */
+ break;