<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jan 4, 2015 at 8:29 PM, Connor Abbott <span dir="ltr"><<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I'd also like to rename or at least note that this is a scalar-only thing for now... otherwise,</div></blockquote><div><br></div><div>Sure, I'll add a note to the comment at the top of the file.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>Reviewed-by: Connor Abbott <<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@gmail.com</a>></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Tue, Dec 16, 2014 at 1:11 AM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">---<br>
 src/glsl/Makefile.sources   |   1 +<br>
 src/glsl/nir/nir.h          |   2 +<br>
 src/glsl/nir/nir_lower_io.c | 388 ++++++++++++++++++++++++++++++++++++++++++++<br>
 3 files changed, 391 insertions(+)<br>
 create mode 100644 src/glsl/nir/nir_lower_io.c<br>
<br>
diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources<br>
index 6230f49..53c3e98 100644<br>
--- a/src/glsl/Makefile.sources<br>
+++ b/src/glsl/Makefile.sources<br>
@@ -23,6 +23,7 @@ NIR_FILES = \<br>
        $(GLSL_SRCDIR)/nir/nir_live_variables.c \<br>
        $(GLSL_SRCDIR)/nir/nir_lower_atomics.c \<br>
        $(GLSL_SRCDIR)/nir/nir_lower_locals_to_regs.c \<br>
+       $(GLSL_SRCDIR)/nir/nir_lower_io.c \<br>
        $(GLSL_SRCDIR)/nir/nir_lower_samplers.cpp \<br>
        $(GLSL_SRCDIR)/nir/nir_lower_system_values.c \<br>
        $(GLSL_SRCDIR)/nir/nir_lower_variables.c \<br>
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h<br>
index 7d7aec7..ec9ce07 100644<br>
--- a/src/glsl/nir/nir.h<br>
+++ b/src/glsl/nir/nir.h<br>
@@ -1360,6 +1360,8 @@ void nir_split_var_copies(nir_shader *shader);<br>
<br>
 void nir_lower_locals_to_regs(nir_shader *shader);<br>
<br>
+void nir_lower_io(nir_shader *shader);<br>
+<br>
 void nir_lower_variables(nir_shader *shader);<br>
<br>
 void nir_lower_variables_scalar(nir_shader *shader, bool lower_globals,<br>
diff --git a/src/glsl/nir/nir_lower_io.c b/src/glsl/nir/nir_lower_io.c<br>
new file mode 100644<br>
index 0000000..a3b8186<br>
--- /dev/null<br>
+++ b/src/glsl/nir/nir_lower_io.c<br>
@@ -0,0 +1,388 @@<br>
+/*<br>
+ * Copyright © 2014 Intel Corporation<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ *<br>
+ * Authors:<br>
+ *    Connor Abbott (<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@gmail.com</a>)<br>
+ *    Jason Ekstrand (<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>)<br>
+ *<br>
+ */<br>
+<br>
+/*<br>
+ * This lowering pass converts references to input/output variables with<br>
+ * loads/stores to actual input/output intrinsics.<br>
+ */<br>
+<br>
+#include "nir.h"<br>
+<br>
+struct lower_io_state {<br>
+   void *mem_ctx;<br>
+};<br>
+<br>
+static unsigned<br>
+type_size(const struct glsl_type *type)<br>
+{<br>
+   unsigned int size, i;<br>
+<br>
+   switch (glsl_get_base_type(type)) {<br>
+   case GLSL_TYPE_UINT:<br>
+   case GLSL_TYPE_INT:<br>
+   case GLSL_TYPE_FLOAT:<br>
+   case GLSL_TYPE_BOOL:<br>
+      return glsl_get_components(type);<br>
+   case GLSL_TYPE_ARRAY:<br>
+      return type_size(glsl_get_array_element(type)) * glsl_get_length(type);<br>
+   case GLSL_TYPE_STRUCT:<br>
+      size = 0;<br>
+      for (i = 0; i < glsl_get_length(type); i++) {<br>
+         size += type_size(glsl_get_struct_field(type, i));<br>
+      }<br>
+      return size;<br>
+   case GLSL_TYPE_SAMPLER:<br>
+      return 0;<br>
+   case GLSL_TYPE_ATOMIC_UINT:<br>
+      return 0;<br>
+   case GLSL_TYPE_INTERFACE:<br>
+      return 0;<br>
+   case GLSL_TYPE_IMAGE:<br>
+      return 0;<br>
+   case GLSL_TYPE_VOID:<br>
+   case GLSL_TYPE_ERROR:<br>
+      unreachable("not reached");<br>
+   }<br>
+<br>
+   return 0;<br>
+}<br>
+<br>
+static void<br>
+assign_var_locations(struct hash_table *ht, unsigned *size)<br>
+{<br>
+   unsigned location = 0;<br>
+<br>
+   struct hash_entry *entry;<br>
+   hash_table_foreach(ht, entry) {<br>
+      nir_variable *var = (nir_variable *) entry->data;<br>
+<br>
+      /*<br>
+       * UBO's have their own address spaces, so don't count them towards the<br>
+       * number of global uniforms<br>
+       */<br>
+      if (var->data.mode == nir_var_uniform && var->interface_type != NULL)<br>
+         continue;<br>
+<br>
+      var->data.driver_location = location;<br>
+      location += type_size(var->type);<br>
+   }<br>
+<br>
+   *size = location;<br>
+}<br>
+<br>
+static void<br>
+assign_var_locations_shader(nir_shader *shader)<br>
+{<br>
+   assign_var_locations(shader->inputs, &shader->num_inputs);<br>
+   assign_var_locations(shader->outputs, &shader->num_outputs);<br>
+   assign_var_locations(shader->uniforms, &shader->num_uniforms);<br>
+}<br>
+<br>
+static bool<br>
+deref_has_indirect(nir_deref_var *deref)<br>
+{<br>
+   for (nir_deref *tail = deref->deref.child; tail; tail = tail->child) {<br>
+      if (tail->deref_type == nir_deref_type_array) {<br>
+         nir_deref_array *arr = nir_deref_as_array(tail);<br>
+         if (arr->deref_array_type == nir_deref_array_type_indirect)<br>
+            return true;<br>
+      }<br>
+   }<br>
+<br>
+   return false;<br>
+}<br>
+<br>
+static unsigned<br>
+get_io_offset(nir_deref_var *deref, nir_instr *instr, nir_src *indirect,<br>
+              struct lower_io_state *state)<br>
+{<br>
+   bool found_indirect = false;<br>
+   unsigned base_offset = 0;<br>
+<br>
+   nir_deref *tail = &deref->deref;<br>
+   while (tail->child != NULL) {<br>
+      const struct glsl_type *parent_type = tail->type;<br>
+      tail = tail->child;<br>
+<br>
+      if (tail->deref_type == nir_deref_type_array) {<br>
+         nir_deref_array *deref_array = nir_deref_as_array(tail);<br>
+         unsigned size = type_size(tail->type);<br>
+<br>
+         base_offset += size * deref_array->base_offset;<br>
+<br>
+         if (deref_array->deref_array_type == nir_deref_array_type_indirect) {<br>
+            nir_load_const_instr *load_const =<br>
+               nir_load_const_instr_create(state->mem_ctx);<br>
+            load_const->num_components = 1;<br>
+            load_const->value.u[0] = size;<br>
+            load_const->dest.is_ssa = true;<br>
+            nir_ssa_def_init(&load_const->instr, &load_const->dest.ssa,<br>
+                             1, NULL);<br>
+            nir_instr_insert_before(instr, &load_const->instr);<br>
+<br>
+            nir_alu_instr *mul = nir_alu_instr_create(state->mem_ctx,<br>
+                                                      nir_op_imul);<br>
+            mul->src[0].src.is_ssa = true;<br>
+            mul->src[0].src.ssa = &load_const->dest.ssa;<br>
+            mul->src[1].src = nir_src_copy(deref_array->indirect,<br>
+                                           state->mem_ctx);<br>
+            mul->dest.write_mask = 1;<br>
+            mul->dest.dest.is_ssa = true;<br>
+            nir_ssa_def_init(&mul->instr, &mul->dest.dest.ssa, 1, NULL);<br>
+            nir_instr_insert_before(instr, &mul->instr);<br>
+<br>
+            if (found_indirect) {<br>
+               nir_alu_instr *add = nir_alu_instr_create(state->mem_ctx,<br>
+                                                         nir_op_iadd);<br>
+               add->src[0].src = *indirect;<br>
+               add->src[1].src.is_ssa = true;<br>
+               add->src[1].src.ssa = &mul->dest.dest.ssa;<br>
+               add->dest.write_mask = 1;<br>
+               add->dest.dest.is_ssa = true;<br>
+               nir_ssa_def_init(&add->instr, &add->dest.dest.ssa, 1, NULL);<br>
+               nir_instr_insert_before(instr, &add->instr);<br>
+<br>
+               indirect->is_ssa = true;<br>
+               indirect->ssa = &add->dest.dest.ssa;<br>
+            } else {<br>
+               indirect->is_ssa = true;<br>
+               indirect->ssa = &mul->dest.dest.ssa;<br>
+               found_indirect = true;<br>
+            }<br>
+         }<br>
+      } else if (tail->deref_type == nir_deref_type_struct) {<br>
+         nir_deref_struct *deref_struct = nir_deref_as_struct(tail);<br>
+<br>
+         for (unsigned i = 0; i < deref_struct->index; i++)<br>
+            base_offset += type_size(glsl_get_struct_field(parent_type, i));<br>
+      }<br>
+   }<br>
+<br>
+   return base_offset;<br>
+}<br>
+<br>
+static nir_intrinsic_op<br>
+get_load_op(nir_variable_mode mode, bool indirect, unsigned num_components)<br>
+{<br>
+   if (indirect) {<br>
+      switch (mode) {<br>
+      case nir_var_shader_in:<br>
+         switch (num_components) {<br>
+         case 1: return nir_intrinsic_load_input_vec1_indirect;<br>
+         case 2: return nir_intrinsic_load_input_vec2_indirect;<br>
+         case 3: return nir_intrinsic_load_input_vec3_indirect;<br>
+         case 4: return nir_intrinsic_load_input_vec4_indirect;<br>
+         default: unreachable("Invalid number of components"); break;<br>
+         }<br>
+         break;<br>
+<br>
+      case nir_var_uniform:<br>
+         switch (num_components) {<br>
+         case 1: return nir_intrinsic_load_uniform_vec1_indirect;<br>
+         case 2: return nir_intrinsic_load_uniform_vec2_indirect;<br>
+         case 3: return nir_intrinsic_load_uniform_vec3_indirect;<br>
+         case 4: return nir_intrinsic_load_uniform_vec4_indirect;<br>
+         default: unreachable("Invalid number of components"); break;<br>
+         }<br>
+         break;<br>
+<br>
+      default:<br>
+         unreachable("Invalid input type");<br>
+         break;<br>
+      }<br>
+   } else {<br>
+      switch (mode) {<br>
+      case nir_var_shader_in:<br>
+         switch (num_components) {<br>
+         case 1: return nir_intrinsic_load_input_vec1;<br>
+         case 2: return nir_intrinsic_load_input_vec2;<br>
+         case 3: return nir_intrinsic_load_input_vec3;<br>
+         case 4: return nir_intrinsic_load_input_vec4;<br>
+         default: unreachable("Invalid number of components"); break;<br>
+         }<br>
+         break;<br>
+<br>
+      case nir_var_uniform:<br>
+         switch (num_components) {<br>
+         case 1: return nir_intrinsic_load_uniform_vec1;<br>
+         case 2: return nir_intrinsic_load_uniform_vec2;<br>
+         case 3: return nir_intrinsic_load_uniform_vec3;<br>
+         case 4: return nir_intrinsic_load_uniform_vec4;<br>
+         default: unreachable("Invalid number of components"); break;<br>
+         }<br>
+         break;<br>
+<br>
+      default:<br>
+         unreachable("Invalid input type");<br>
+         break;<br>
+      }<br>
+   }<br>
+<br>
+   return nir_intrinsic_load_input_vec1;<br>
+}<br>
+<br>
+static bool<br>
+nir_lower_io_block(nir_block *block, void *void_state)<br>
+{<br>
+   struct lower_io_state *state = void_state;<br>
+<br>
+   nir_foreach_instr_safe(block, instr) {<br>
+      if (instr->type != nir_instr_type_intrinsic)<br>
+         continue;<br>
+<br>
+      nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);<br>
+<br>
+      switch (intrin->intrinsic) {<br>
+      case nir_intrinsic_load_var_vec1:<br>
+      case nir_intrinsic_load_var_vec2:<br>
+      case nir_intrinsic_load_var_vec3:<br>
+      case nir_intrinsic_load_var_vec4: {<br>
+         nir_variable_mode mode = intrin->variables[0]->var->data.mode;<br>
+         if (mode != nir_var_shader_in && mode != nir_var_uniform)<br>
+            continue;<br>
+<br>
+         bool has_indirect = deref_has_indirect(intrin->variables[0]);<br>
+         unsigned num_components =<br>
+            nir_intrinsic_infos[intrin->intrinsic].dest_components;<br>
+<br>
+         nir_intrinsic_op load_op = get_load_op(mode, has_indirect,<br>
+                                                num_components);<br>
+         nir_intrinsic_instr *load = nir_intrinsic_instr_create(state->mem_ctx,<br>
+                                                                load_op);<br>
+<br>
+         nir_src indirect;<br>
+         unsigned offset = get_io_offset(intrin->variables[0],<br>
+                                         &intrin->instr, &indirect, state);<br>
+         offset += intrin->variables[0]->var->data.driver_location;<br>
+<br>
+         load->const_index[0] = offset;<br>
+         load->const_index[1] = 1;<br>
+<br>
+         if (has_indirect)<br>
+            load->src[0] = indirect;<br>
+<br>
+         if (intrin->dest.is_ssa) {<br>
+            load->dest.is_ssa = true;<br>
+            nir_ssa_def_init(&load->instr, &load->dest.ssa,<br>
+                             num_components, NULL);<br>
+<br>
+            nir_src new_src = {<br>
+               .is_ssa = true,<br>
+               .ssa = &load->dest.ssa,<br>
+            };<br>
+<br>
+            nir_ssa_def_rewrite_uses(&intrin->dest.ssa, new_src,<br>
+                                     state->mem_ctx);<br>
+         } else {<br>
+            load->dest = nir_dest_copy(intrin->dest, state->mem_ctx);<br>
+         }<br>
+<br>
+         nir_instr_insert_before(&intrin->instr, &load->instr);<br>
+         nir_instr_remove(&intrin->instr);<br>
+         break;<br>
+      }<br>
+<br>
+      case nir_intrinsic_store_var_vec1:<br>
+      case nir_intrinsic_store_var_vec2:<br>
+      case nir_intrinsic_store_var_vec3:<br>
+      case nir_intrinsic_store_var_vec4: {<br>
+         if (intrin->variables[0]->var->data.mode != nir_var_shader_out)<br>
+            continue;<br>
+<br>
+         bool has_indirect = deref_has_indirect(intrin->variables[0]);<br>
+         unsigned num_components =<br>
+            nir_intrinsic_infos[intrin->intrinsic].src_components[0];<br>
+<br>
+         nir_intrinsic_op store_op;<br>
+         if (has_indirect) {<br>
+            switch (num_components) {<br>
+            case 1: store_op = nir_intrinsic_store_output_vec1_indirect; break;<br>
+            case 2: store_op = nir_intrinsic_store_output_vec2_indirect; break;<br>
+            case 3: store_op = nir_intrinsic_store_output_vec3_indirect; break;<br>
+            case 4: store_op = nir_intrinsic_store_output_vec4_indirect; break;<br>
+            default: unreachable("Invalid number of components"); break;<br>
+            }<br>
+         } else {<br>
+            switch (num_components) {<br>
+            case 1: store_op = nir_intrinsic_store_output_vec1; break;<br>
+            case 2: store_op = nir_intrinsic_store_output_vec2; break;<br>
+            case 3: store_op = nir_intrinsic_store_output_vec3; break;<br>
+            case 4: store_op = nir_intrinsic_store_output_vec4; break;<br>
+            default: unreachable("Invalid number of components"); break;<br>
+            }<br>
+         }<br>
+<br>
+         nir_intrinsic_instr *store = nir_intrinsic_instr_create(state->mem_ctx,<br>
+                                                                 store_op);<br>
+<br>
+         nir_src indirect;<br>
+         unsigned offset = get_io_offset(intrin->variables[0],<br>
+                                         &intrin->instr, &indirect, state);<br>
+         offset += intrin->variables[0]->var->data.driver_location;<br>
+<br>
+         store->const_index[0] = offset;<br>
+         store->const_index[1] = 1;<br>
+<br>
+         store->src[0] = nir_src_copy(intrin->src[0], state->mem_ctx);<br>
+<br>
+         if (has_indirect)<br>
+            store->src[1] = indirect;<br>
+<br>
+         nir_instr_insert_before(&intrin->instr, &store->instr);<br>
+         nir_instr_remove(&intrin->instr);<br>
+         break;<br>
+      }<br>
+<br>
+      default:<br>
+         break;<br>
+      }<br>
+   }<br>
+<br>
+   return true;<br>
+}<br>
+<br>
+static void<br>
+nir_lower_io_impl(nir_function_impl *impl)<br>
+{<br>
+   struct lower_io_state state;<br>
+<br>
+   state.mem_ctx = ralloc_parent(impl);<br>
+<br>
+   nir_foreach_block(impl, nir_lower_io_block, &state);<br>
+}<br>
+<br>
+void<br>
+nir_lower_io(nir_shader *shader)<br>
+{<br>
+   assign_var_locations_shader(shader);<br>
+<br>
+   nir_foreach_overload(shader, overload) {<br>
+      if (overload->impl)<br>
+         nir_lower_io_impl(overload->impl);<br>
+   }<br>
+}<br>
</div></div><span class="HOEnZb"><font color="#888888"><span><font color="#888888">--<br>
2.2.0<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></font></span></blockquote></div><br></div>
</blockquote></div><br></div></div>