[Mesa-dev] [RFCv3 08/11] gallium/auxiliary: introduce nir_emulate

Rob Clark robdclark at gmail.com
Mon Feb 1 16:54:58 UTC 2016


On Mon, Feb 1, 2016 at 11:42 AM, Connor Abbott <cwabbott0 at gmail.com> wrote:
> This doesn't really seem to be following NIR's convention/style of
> having separate passes/files for each thing that needs to be lowered.
> This might've made sense for TGSI, where there was a lot of
> boilerplate that each thing needed since TGSI isn't designed for doing
> transforms on it, but with NIR it doesn't. Also, this isn't really any
> more TGSI-specific than the other stuff that you've already put in
> src/compiler/nir. So instead, in src/compiler/nir you would have
> something like:

Yeah, nir_emulate (and tgsi_emulate on which it's based) is kinda misc
grab-bag of things too small to otherwise be their own thing.  We
could split them into separate passes..  it was kind of arbitrary to
just lump them all together like tgsi_emulate did.

> - nir_lower_passthrough_edgeflags
> - nir_lower_clamp_color_outputs
> - nir_force_persample_interp
>
> Unfortunately, it doesn't quite fit with the whole "nir_lower_noun"
> convention, but oh well...

If I split these up, I'll probably just inline the last one in
mesa/st, since it is a bit overkill to make this it's own object file:


      nir_foreach_variable(var, &shader->inputs) {
         var->data.sample = true;
      }

;-)

BR,
-R


>
> On Sun, Jan 31, 2016 at 3:16 PM, Rob Clark <robdclark at gmail.com> wrote:
>> From: Rob Clark <robclark at freedesktop.org>
>>
>> NIR equivalent of tgsi_emulate
>>
>> Signed-off-by: Rob Clark <robclark at freedesktop.org>
>> ---
>>  src/gallium/auxiliary/Makefile.sources  |   2 +
>>  src/gallium/auxiliary/nir/nir_emulate.c | 177 ++++++++++++++++++++++++++++++++
>>  src/gallium/auxiliary/nir/nir_emulate.h |  34 ++++++
>>  3 files changed, 213 insertions(+)
>>  create mode 100644 src/gallium/auxiliary/nir/nir_emulate.c
>>  create mode 100644 src/gallium/auxiliary/nir/nir_emulate.h
>>
>> diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources
>> index 6f50f71..c32cfdf 100644
>> --- a/src/gallium/auxiliary/Makefile.sources
>> +++ b/src/gallium/auxiliary/Makefile.sources
>> @@ -311,6 +311,8 @@ C_SOURCES := \
>>         util/u_video.h
>>
>>  NIR_SOURCES := \
>> +       nir/nir_emulate.c \
>> +       nir/nir_emulate.h \
>>         nir/tgsi_to_nir.c \
>>         nir/tgsi_to_nir.h
>>
>> diff --git a/src/gallium/auxiliary/nir/nir_emulate.c b/src/gallium/auxiliary/nir/nir_emulate.c
>> new file mode 100644
>> index 0000000..af1d3bc
>> --- /dev/null
>> +++ b/src/gallium/auxiliary/nir/nir_emulate.c
>> @@ -0,0 +1,177 @@
>> +/*
>> + * Copyright © 2015 Red Hat
>> + *
>> + * 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/nir_emulate.h"
>> +
>> +#include "compiler/nir/nir_builder.h"
>> +
>> +typedef struct {
>> +   nir_shader *shader;
>> +   nir_builder b;
>> +   unsigned flags;
>> +   /* for TGSI_EMU_PASSTHROUGH_EDGEFLAG: */
>> +   struct {
>> +      bool emitted;
>> +      nir_variable *in, *out;
>> +   } edgeflag;
>> +} emu_state;
>> +
>> +static nir_variable *
>> +create_edgeflag_var(nir_shader *shader, bool output)
>> +{
>> +   nir_variable_mode mode = output ? nir_var_shader_out : nir_var_shader_in;
>> +   nir_variable *var = nir_variable_create(shader, mode, glsl_vec4_type(),
>> +                                           output ? "edgeflag_out" : "edgeflag_in");
>> +   var->data.location = output ? VARYING_SLOT_EDGE : VERT_ATTRIB_EDGEFLAG;
>> +   return var;
>> +}
>> +
>> +static bool
>> +is_color_output(emu_state *state, nir_variable *out)
>> +{
>> +   switch (state->shader->stage) {
>> +   case MESA_SHADER_VERTEX:
>> +   case MESA_SHADER_GEOMETRY:
>> +      switch (out->data.location) {
>> +      case VARYING_SLOT_COL0:
>> +      case VARYING_SLOT_COL1:
>> +      case VARYING_SLOT_BFC0:
>> +      case VARYING_SLOT_BFC1:
>> +         return true;
>> +      default:
>> +         return false;
>> +      }
>> +      break;
>> +   case MESA_SHADER_FRAGMENT:
>> +      switch (out->data.location) {
>> +      case FRAG_RESULT_COLOR:
>> +         return true;
>> +      default:
>> +         return false;
>> +      }
>> +      break;
>> +   default:
>> +      return false;
>> +   }
>> +}
>> +
>> +static void
>> +emu_intrinsic(emu_state *state, nir_intrinsic_instr *intr)
>> +{
>> +   nir_variable *out;
>> +   nir_builder *b = &state->b;
>> +   nir_ssa_def *s;
>> +
>> +   assert(state->flags & TGSI_EMU_CLAMP_COLOR_OUTPUTS);
>> +
>> +   if (intr->intrinsic != nir_intrinsic_store_var)
>> +      return;
>> +
>> +   out = intr->variables[0]->var;
>> +
>> +   if (out->data.mode != nir_var_shader_out)
>> +      return;
>> +
>> +   /* NOTE: 'out' can be null for types larger than vec4,
>> +    * but these will never be color out's so we can ignore
>> +    */
>> +
>> +   if (out && is_color_output(state, out)) {
>> +      b->cursor = nir_before_instr(&intr->instr);
>> +      s = nir_ssa_for_src(b, intr->src[0], intr->num_components);
>> +      s = nir_fsat(b, s);
>> +      nir_instr_rewrite_src(&intr->instr, &intr->src[0], nir_src_for_ssa(s));
>> +   }
>> +}
>> +
>> +static void
>> +passthrough_edgeflags(emu_state *state, nir_block *block)
>> +{
>> +   nir_builder *b = &state->b;
>> +   nir_ssa_def *def;
>> +
>> +   if (!state->edgeflag.in)
>> +      state->edgeflag.in = create_edgeflag_var(state->shader, false);
>> +
>> +   if (!state->edgeflag.out)
>> +      state->edgeflag.out = create_edgeflag_var(state->shader, true);
>> +
>> +   b->cursor = nir_before_block(block);
>> +
>> +   def = nir_load_var(b, state->edgeflag.in);
>> +   nir_store_var(b, state->edgeflag.out, def, 0xf);
>> +}
>> +
>> +static bool
>> +emu_block(nir_block *block, void *_state)
>> +{
>> +   emu_state *state = _state;
>> +
>> +   /* we should hit the first block first.. */
>> +   if ((state->flags & TGSI_EMU_PASSTHROUGH_EDGEFLAG) &&
>> +       !state->edgeflag.emitted) {
>> +      passthrough_edgeflags(state, block);
>> +      state->edgeflag.emitted = true;
>> +   }
>> +
>> +   /* early return if we don't need per-instruction lowering: */
>> +   if (!(state->flags & TGSI_EMU_CLAMP_COLOR_OUTPUTS))
>> +      return false;
>> +
>> +   nir_foreach_instr_safe(block, instr) {
>> +      if (instr->type == nir_instr_type_intrinsic)
>> +         emu_intrinsic(state, nir_instr_as_intrinsic(instr));
>> +   }
>> +
>> +   return true;
>> +}
>> +static void
>> +emu_impl(emu_state *state, nir_function_impl *impl)
>> +{
>> +   nir_builder_init(&state->b, impl);
>> +
>> +   nir_foreach_block(impl, emu_block, state);
>> +   nir_metadata_preserve(impl, nir_metadata_block_index |
>> +                               nir_metadata_dominance);
>> +}
>> +
>> +void nir_emulate(nir_shader *shader, unsigned flags)
>> +{
>> +   emu_state state = {
>> +      .shader = shader,
>> +      .flags = flags,
>> +   };
>> +
>> +   assert(flags != 0);
>> +
>> +   if (flags & TGSI_EMU_FORCE_PERSAMPLE_INTERP) {
>> +      nir_foreach_variable(var, &shader->inputs) {
>> +         var->data.sample = true;
>> +      }
>> +   }
>> +
>> +   nir_foreach_function(shader, function) {
>> +      if (function->impl)
>> +         emu_impl(&state, function->impl);
>> +   }
>> +}
>> diff --git a/src/gallium/auxiliary/nir/nir_emulate.h b/src/gallium/auxiliary/nir/nir_emulate.h
>> new file mode 100644
>> index 0000000..9f56620
>> --- /dev/null
>> +++ b/src/gallium/auxiliary/nir/nir_emulate.h
>> @@ -0,0 +1,34 @@
>> +/*
>> + * Copyright © 2015 Red Hat
>> + *
>> + * 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.
>> + */
>> +
>> +#ifndef _NIR_EMULATE_H_
>> +#define _NIR_EMULATE_H_
>> +
>> +#include "tgsi/tgsi_emulate.h"  /* for now share TGSI_EMU_x flags */
>> +
>> +#include "compiler/nir/nir.h"
>> +
>> +
>> +void nir_emulate(nir_shader *shader, unsigned flags);
>> +
>> +#endif /* _NIR_EMULATE_H_ */
>> --
>> 2.5.0
>>


More information about the mesa-dev mailing list