On Mon, Jul 18, 2016 at 1:26 PM, Kenneth Graunke <kenn...@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 <kenn...@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@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev