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