<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, May 29, 2016 at 3:38 PM, Jordan Justen <span dir="ltr"><<a href="mailto:jordan.l.justen@intel.com" target="_blank">jordan.l.justen@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">We add a lowering pass for nir intrinsics. This pass can replace nir<br>
intrinsics with driver specific nir lower code.<br>
<br>
We lower the gl_LocalInvocationIndex intrinsic based on a uniform<br>
which is loaded with a thread specific ID.<br>
<br>
We also lower the gl_LocalInvocationID based on<br>
gl_LocalInvocationIndex.<br>
<br>
v2:<br>
 * Create variable during lowering pass. (Ken)<br>
<br>
v3:<br>
 * Don't create a variable, but instead just insert an intrisic call<br>
   to load a uniform from the allocated location. (Jason)<br>
<br>
Signed-off-by: Jordan Justen <<a href="mailto:jordan.l.justen@intel.com">jordan.l.justen@intel.com</a>><br>
---<br>
 src/mesa/drivers/dri/i965/Makefile.sources     |   1 +<br>
 src/mesa/drivers/dri/i965/brw_nir.h            |   2 +<br>
 src/mesa/drivers/dri/i965/brw_nir_intrinsics.c | 177 +++++++++++++++++++++++++<br>
 3 files changed, 180 insertions(+)<br>
 create mode 100644 src/mesa/drivers/dri/i965/brw_nir_intrinsics.c<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources<br>
index d8711ed..f448551 100644<br>
--- a/src/mesa/drivers/dri/i965/Makefile.sources<br>
+++ b/src/mesa/drivers/dri/i965/Makefile.sources<br>
@@ -46,6 +46,7 @@ i965_compiler_FILES = \<br>
        brw_nir.c \<br>
        brw_nir_analyze_boolean_resolves.c \<br>
        brw_nir_attribute_workarounds.c \<br>
+       brw_nir_intrinsics.c \<br>
        brw_nir_opt_peephole_ffma.c \<br>
        brw_packed_float.c \<br>
        brw_predicated_break.cpp \<br>
diff --git a/src/mesa/drivers/dri/i965/brw_nir.h b/src/mesa/drivers/dri/i965/brw_nir.h<br>
index 409e49a..74c354f 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_nir.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_nir.h<br>
@@ -91,6 +91,8 @@ void brw_nir_analyze_boolean_resolves(nir_shader *nir);<br>
 nir_shader *brw_preprocess_nir(const struct brw_compiler *compiler,<br>
                                nir_shader *nir);<br>
<br>
+bool brw_nir_lower_intrinsics(nir_shader *nir,<br>
+                              struct brw_stage_prog_data *prog_data);<br>
 void brw_nir_lower_vs_inputs(nir_shader *nir,<br>
                              const struct brw_device_info *devinfo,<br>
                              bool is_scalar,<br>
diff --git a/src/mesa/drivers/dri/i965/brw_nir_intrinsics.c b/src/mesa/drivers/dri/i965/brw_nir_intrinsics.c<br>
new file mode 100644<br>
index 0000000..02816e7<br>
--- /dev/null<br>
+++ b/src/mesa/drivers/dri/i965/brw_nir_intrinsics.c<br>
@@ -0,0 +1,177 @@<br>
+/*<br>
+ * Copyright (c) 2016 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>
+<br>
+#include "brw_nir.h"<br>
+#include "compiler/nir/nir_builder.h"<br>
+<br>
+struct lower_intrinsics_state {<br>
+   nir_shader *nir;<br>
+   union {<br>
+      struct brw_stage_prog_data *prog_data;<br>
+      struct brw_cs_prog_data *cs_prog_data;<br>
+   };<br>
+   nir_function_impl *impl;<br>
+   bool progress;<br>
+   nir_builder builder;<br>
+   bool cs_thread_id_used;<br>
+};<br>
+<br>
+static int<br>
+get_cs_local_id_uniform_index(struct lower_intrinsics_state *state)<br>
+{<br>
+   assert(state->cs_prog_data->thread_local_id_index >= 0);<br>
+   state->cs_thread_id_used = true;<br>
+   return state->cs_prog_data->thread_local_id_index;<br></blockquote><div><br></div><div>Maybe create the actual load_uniform intrinsic here?  It doesn't much matter given that it's called exactly once.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+}<br>
+<br>
+static bool<br>
+lower_cs_intrinsics_convert_block(struct lower_intrinsics_state *state,<br>
+                                  nir_block *block)<br>
+{<br>
+   bool progress = false;<br>
+   nir_builder *b = &state->builder;<br>
+   nir_shader *nir = state->nir;<br>
+<br>
+   nir_foreach_instr_safe(instr, block) {<br>
+      if (instr->type != nir_instr_type_intrinsic)<br>
+         continue;<br>
+<br>
+      nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(instr);<br>
+<br>
+      b->cursor = nir_after_instr(&intrinsic->instr);<br>
+<br>
+      nir_ssa_def *sysval;<br>
+      switch (intrinsic->intrinsic) {<br>
+      case nir_intrinsic_load_local_invocation_index: {<br>
+         assert(nir->stage == MESA_SHADER_COMPUTE);<br>
+         /* We construct the local invocation index from:<br>
+          *<br>
+          *    gl_LocalInvocationIndex =<br>
+          *       cs_thread_local_id + channel_num;<br>
+          */<br>
+         nir_intrinsic_instr *load;<br>
+         load = nir_intrinsic_instr_create(nir, nir_intrinsic_load_uniform);<br>
+         load->num_components = 1;<br>
+         load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));<br>
+         nir_ssa_dest_init(&load->instr, &load->dest, 1, 32, NULL);<br>
+         int id_index = get_cs_local_id_uniform_index(state);<br>
+         nir_intrinsic_set_base(load, id_index * sizeof(uint32_t));<br>
+         nir_intrinsic_set_range(load, sizeof(uint32_t));<br>
+         nir_builder_instr_insert(b, &load->instr);<br>
+         nir_ssa_def *id_val = &load->dest.ssa;<br>
+<br>
+         nir_ssa_def *channel =<br>
+            nir_load_system_value(b, nir_intrinsic_load_channel_num, 0);<br>
+         sysval = nir_iadd(b, channel, id_val);<br>
+         break;<br>
+      }<br>
+<br>
+      case nir_intrinsic_load_local_invocation_id: {<br>
+         assert(nir->stage == MESA_SHADER_COMPUTE);<br>
+         /* We lower gl_LocalInvocationID from gl_LocalInvocationIndex based<br>
+          * on this formula:<br>
+          *<br>
+          *    gl_LocalInvocationID.x =<br>
+          *       gl_LocalInvocationIndex % gl_WorkGroupSize.x;<br>
+          *    gl_LocalInvocationID.y =<br>
+          *       (gl_LocalInvocationIndex / gl_WorkGroupSize.x) %<br>
+          *       gl_WorkGroupSize.y;<br>
+          *    gl_LocalInvocationID.z =<br>
+          *       (gl_LocalInvocationIndex /<br>
+          *        (gl_WorkGroupSize.x * gl_WorkGroupSize.y)) %<br>
+          *       gl_WorkGroupSize.z;<br>
+          */<br>
+         unsigned *size = nir->info.cs.local_size;<br>
+<br>
+         nir_ssa_def *local_index =<br>
+            nir_load_system_value(b, nir_intrinsic_load_local_invocation_index, 0);<br>
+<br>
+         nir_const_value uvec3;<br>
+         uvec3.u32[0] = 1;<br>
+         uvec3.u32[1] = size[0];<br>
+         uvec3.u32[2] = size[0] * size[1];<br>
+         nir_ssa_def *div_val = nir_build_imm(b, 3, 32, uvec3);<br>
+         uvec3.u32[0] = size[0];<br>
+         uvec3.u32[1] = size[1];<br>
+         uvec3.u32[2] = size[2];<br>
+         nir_ssa_def *mod_val = nir_build_imm(b, 3, 32, uvec3);<br>
+<br>
+         sysval = nir_imod(b, nir_idiv(b, local_index, div_val), mod_val);<br>
+         break;<br>
+      }<br>
+<br>
+      default:<br>
+         continue;<br>
+      }<br>
+<br>
+      nir_ssa_def_rewrite_uses(&intrinsic->dest.ssa, nir_src_for_ssa(sysval));<br>
+      nir_instr_remove(&intrinsic->instr);<br>
+<br>
+      state->progress = true;<br>
+   }<br>
+<br>
+   return progress;<br>
+}<br>
+<br>
+static void<br>
+lower_cs_intrinsics_convert_impl(struct lower_intrinsics_state *state)<br>
+{<br>
+   nir_builder_init(&state->builder, state->impl);<br>
+<br>
+   nir_foreach_block(block, state->impl) {<br>
+      lower_cs_intrinsics_convert_block(state, block);<br>
+   }<br>
+<br>
+   nir_metadata_preserve(state->impl,<br>
+                         nir_metadata_block_index | nir_metadata_dominance);<br>
+}<br>
+<br>
+bool<br>
+brw_nir_lower_intrinsics(nir_shader *nir, struct brw_stage_prog_data *prog_data)<br>
+{<br>
+   /* Currently we only lower intrinsics for compute shaders */<br>
+   if (nir->stage != MESA_SHADER_COMPUTE)<br>
+      return false;<br>
+<br>
+   bool progress = false;<br>
+   struct lower_intrinsics_state state;<br>
+   memset(&state, 0, sizeof(state));<br>
+   state.nir = nir;<br>
+   state.prog_data = prog_data;<br>
+<br>
+   do {<br>
+      state.progress = false;<br>
+      nir_foreach_function(function, nir) {<br>
+         if (function->impl) {<br>
+            state.impl = function->impl;<br>
+            lower_cs_intrinsics_convert_impl(&state);<br>
+         }<br>
+      }<br>
+      progress |= state.progress;<br>
+   } while (state.progress);<br>
+<br>
+   if (nir->stage == MESA_SHADER_COMPUTE && !state.cs_thread_id_used)<br>
+      state.cs_prog_data->thread_local_id_index = -1;<br>
+<br>
+   return progress;<br>
+}<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.8.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>