[Mesa-dev] [PATCH 1/7] nir: Add new intrinsics for fragment shader input interpolation.

Jason Ekstrand jason at jlekstrand.net
Tue Jul 19 19:54:43 UTC 2016


On Mon, Jul 18, 2016 at 1:26 PM, Kenneth Graunke <kenneth at whitecape.org>
wrote:

> Backends can normally handle shader inputs solely by looking at
> load_input intrinsics, and ignore the nir_variables in nir->inputs.
>
> One exception is fragment shader inputs.  load_input doesn't capture
> the necessary interpolation information - flat, smooth, noperspective
> mode, and centroid, sample, or pixel for the location.  This means
> that backends have to interpolate based on the nir_variables, then
> associate those with the load_input intrinsics (say, by storing a
> map of which variables are at which locations).
>
> With GL_ARB_enhanced_layouts, we're going to have multiple varyings
> packed into a single vec4 location.  The intrinsics make this easy:
> simply load N components from location <loc, component>.  However,
> working with variables and correlating the two is very awkward; we'd
> much rather have intrinsics capture all the necessary information.
>
> Fragment shader input interpolation typically works by producing a
> set of barycentric coordinates, then using those to do a linear
> interpolation between the values at the triangle's corners.
>
> We represent this by introducing five new load_barycentric_* intrinsics:
>
> - load_barycentric_pixel     (ordinary variable)
> - load_barycentric_centroid  (centroid qualified variable)
> - load_barycentric_sample    (sample qualified variable)
> - load_barycentric_at_sample (ARB_gpu_shader5's interpolateAtSample())
> - load_barycentric_at_offset (ARB_gpu_shader5's interpolateAtOffset())
>
> Each of these take the interpolation mode (smooth or noperspective only)
> as a const_index, and produce a vec2.  The last two also take a sample
> or offset source.
>
> We then introduce a new load_interpolated_input intrinsic, which
> is like a normal load_input intrinsic, but with an additional
> barycentric coordinate source.
>
> The intention is that flat inputs will still use regular load_input
> intrinsics.  This makes them distinguishable from normal inputs that
> need fancy interpolation, while also providing all the necessary data.
>
> This nicely unifies regular inputs and interpolateAt functions.
> Qualifiers and variables become irrelevant; there are just
> load_barycentric intrinsics that determine the interpolation.
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/compiler/nir/nir.h            |  6 ++++++
>  src/compiler/nir/nir_builder.h    | 11 +++++++++++
>  src/compiler/nir/nir_intrinsics.h | 24 ++++++++++++++++++++++++
>  src/compiler/nir/nir_lower_io.c   |  1 +
>  src/compiler/nir/nir_print.c      |  1 +
>  5 files changed, 43 insertions(+)
>
> diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> index c5d3b6b..ac11998 100644
> --- a/src/compiler/nir/nir.h
> +++ b/src/compiler/nir/nir.h
> @@ -992,6 +992,11 @@ typedef enum {
>      */
>     NIR_INTRINSIC_COMPONENT = 8,
>
> +   /**
> +    * Interpolation mode (only meaningful for FS inputs).
> +    */
> +   NIR_INTRINSIC_INTERP_MODE = 9,
> +
>     NIR_INTRINSIC_NUM_INDEX_FLAGS,
>
>  } nir_intrinsic_index_flag;
> @@ -1059,6 +1064,7 @@ INTRINSIC_IDX_ACCESSORS(range, RANGE, unsigned)
>  INTRINSIC_IDX_ACCESSORS(desc_set, DESC_SET, unsigned)
>  INTRINSIC_IDX_ACCESSORS(binding, BINDING, unsigned)
>  INTRINSIC_IDX_ACCESSORS(component, COMPONENT, unsigned)
> +INTRINSIC_IDX_ACCESSORS(interp_mode, INTERP_MODE, unsigned)
>
>  /**
>   * \group texture information
> diff --git a/src/compiler/nir/nir_builder.h
> b/src/compiler/nir/nir_builder.h
> index 09cdf72..435582a 100644
> --- a/src/compiler/nir/nir_builder.h
> +++ b/src/compiler/nir/nir_builder.h
> @@ -458,6 +458,17 @@ nir_load_system_value(nir_builder *build,
> nir_intrinsic_op op, int index)
>     return &load->dest.ssa;
>  }
>
> +static inline nir_ssa_def *
> +nir_load_barycentric(nir_builder *build, nir_intrinsic_op op,
> +                     unsigned interp_mode)
> +{
> +   nir_intrinsic_instr *bary = nir_intrinsic_instr_create(build->shader,
> op);
> +   nir_ssa_dest_init(&bary->instr, &bary->dest, 2, 32, NULL);
> +   nir_intrinsic_set_interp_mode(bary, interp_mode);
> +   nir_builder_instr_insert(build, &bary->instr);
> +   return &bary->dest.ssa;
> +}
> +
>  static inline void
>  nir_jump(nir_builder *build, nir_jump_type jump_type)
>  {
> diff --git a/src/compiler/nir/nir_intrinsics.h
> b/src/compiler/nir/nir_intrinsics.h
> index 2f74555..29917e3 100644
> --- a/src/compiler/nir/nir_intrinsics.h
> +++ b/src/compiler/nir/nir_intrinsics.h
> @@ -306,6 +306,27 @@ SYSTEM_VALUE(num_work_groups, 3, 0, xx, xx, xx)
>  SYSTEM_VALUE(helper_invocation, 1, 0, xx, xx, xx)
>  SYSTEM_VALUE(channel_num, 1, 0, xx, xx, xx)
>
> +/**
> + * Barycentric coordinate intrinsics.
> + *
> + * These set up the barycentric coordinates for a particular
> interpolation.
> + * The first three are for the simple cases: pixel, centroid, or
> per-sample
> + * (at gl_SampleID).  The next two handle interpolating at a specified
> + * sample location, or interpolating with a vec2 offset,
>

Could you please document what goes in the INTERP_MODE index.


> + *
> + * The vec2 value produced by these intrinsics is intended for use as the
> + * barycoord source of a load_interpolated_input intrinsic.
> + */
> +SYSTEM_VALUE(barycentric_pixel, 2, 1, INTERP_MODE, xx, xx)
> +SYSTEM_VALUE(barycentric_centroid, 2, 1, INTERP_MODE, xx, xx)
> +SYSTEM_VALUE(barycentric_sample, 2, 1, INTERP_MODE, xx, xx)
>

I'm not sure what I think about using SYSTEM_VALUE here.  The macros serve
as helpers, yes, but also as lables for what the intrinsic is.  Maybe we
just need a new BARYCENTRIC helper that can be used for all 5.


> +/* src[] = { sample_id }.  const_index[] = { interp_mode } */
> +INTRINSIC(load_barycentric_at_sample, 1, ARR(1), true, 2, 0, 1,
> INTERP_MODE,
> +          xx, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
> +/* src[] = { offset.xy }.  const_index[] = { interp_mode } */
> +INTRINSIC(load_barycentric_at_offset, 1, ARR(2), true, 2, 0, 1,
> INTERP_MODE,
> +          xx, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
> +
>  /*
>   * Load operations pull data from some piece of GPU memory.  All load
>   * operations operate in terms of offsets into some piece of theoretical
> @@ -339,6 +360,9 @@ LOAD(ubo, 2, 0, xx, xx, xx,
> NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REOR
>  LOAD(input, 1, 2, BASE, COMPONENT, xx, NIR_INTRINSIC_CAN_ELIMINATE |
> NIR_INTRINSIC_CAN_REORDER)
>  /* src[] = { vertex, offset }. const_index[] = { base, component } */
>  LOAD(per_vertex_input, 2, 2, BASE, COMPONENT, xx,
> NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
> +/* src[] = { barycoord, offset }. const_index[] = { base, component } */
> +LOAD(interpolated_input, 2, 2, BASE, COMPONENT, xx,
> NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
> +
>  /* src[] = { buffer_index, offset }. No const_index */
>  LOAD(ssbo, 2, 0, xx, xx, xx, NIR_INTRINSIC_CAN_ELIMINATE)
>  /* src[] = { offset }. const_index[] = { base, component } */
> diff --git a/src/compiler/nir/nir_lower_io.c
> b/src/compiler/nir/nir_lower_io.c
> index 71d2432..b05a73f 100644
> --- a/src/compiler/nir/nir_lower_io.c
> +++ b/src/compiler/nir/nir_lower_io.c
> @@ -436,6 +436,7 @@ nir_get_io_offset_src(nir_intrinsic_instr *instr)
>     case nir_intrinsic_load_ssbo:
>     case nir_intrinsic_load_per_vertex_input:
>     case nir_intrinsic_load_per_vertex_output:
> +   case nir_intrinsic_load_interpolated_input:
>     case nir_intrinsic_store_output:
>        return &instr->src[1];
>     case nir_intrinsic_store_ssbo:
> diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
> index a3380e6..3beb70a 100644
> --- a/src/compiler/nir/nir_print.c
> +++ b/src/compiler/nir/nir_print.c
> @@ -571,6 +571,7 @@ print_intrinsic_instr(nir_intrinsic_instr *instr,
> print_state *state)
>        [NIR_INTRINSIC_DESC_SET] = "desc-set",
>        [NIR_INTRINSIC_BINDING] = "binding",
>        [NIR_INTRINSIC_COMPONENT] = "component",
> +      [NIR_INTRINSIC_INTERP_MODE] = "interp_mode",
>     };
>     for (unsigned idx = 1; idx < NIR_INTRINSIC_NUM_INDEX_FLAGS; idx++) {
>        if (!info->index_map[idx])
> --
> 2.9.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160719/b8f4d21d/attachment-0001.html>


More information about the mesa-dev mailing list