<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 18, 2016 at 1:26 PM, Kenneth Graunke <span dir="ltr"><<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Backends can normally handle shader inputs solely by looking at<br>
load_input intrinsics, and ignore the nir_variables in nir->inputs.<br>
<br>
One exception is fragment shader inputs.  load_input doesn't capture<br>
the necessary interpolation information - flat, smooth, noperspective<br>
mode, and centroid, sample, or pixel for the location.  This means<br>
that backends have to interpolate based on the nir_variables, then<br>
associate those with the load_input intrinsics (say, by storing a<br>
map of which variables are at which locations).<br>
<br>
With GL_ARB_enhanced_layouts, we're going to have multiple varyings<br>
packed into a single vec4 location.  The intrinsics make this easy:<br>
simply load N components from location <loc, component>.  However,<br>
working with variables and correlating the two is very awkward; we'd<br>
much rather have intrinsics capture all the necessary information.<br>
<br>
Fragment shader input interpolation typically works by producing a<br>
set of barycentric coordinates, then using those to do a linear<br>
interpolation between the values at the triangle's corners.<br>
<br>
We represent this by introducing five new load_barycentric_* intrinsics:<br>
<br>
- load_barycentric_pixel     (ordinary variable)<br>
- load_barycentric_centroid  (centroid qualified variable)<br>
- load_barycentric_sample    (sample qualified variable)<br>
- load_barycentric_at_sample (ARB_gpu_shader5's interpolateAtSample())<br>
- load_barycentric_at_offset (ARB_gpu_shader5's interpolateAtOffset())<br>
<br>
Each of these take the interpolation mode (smooth or noperspective only)<br>
as a const_index, and produce a vec2.  The last two also take a sample<br>
or offset source.<br>
<br>
We then introduce a new load_interpolated_input intrinsic, which<br>
is like a normal load_input intrinsic, but with an additional<br>
barycentric coordinate source.<br>
<br>
The intention is that flat inputs will still use regular load_input<br>
intrinsics.  This makes them distinguishable from normal inputs that<br>
need fancy interpolation, while also providing all the necessary data.<br>
<br>
This nicely unifies regular inputs and interpolateAt functions.<br>
Qualifiers and variables become irrelevant; there are just<br>
load_barycentric intrinsics that determine the interpolation.<br>
<br>
Signed-off-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
---<br>
 src/compiler/nir/nir.h            |  6 ++++++<br>
 src/compiler/nir/nir_builder.h    | 11 +++++++++++<br>
 src/compiler/nir/nir_intrinsics.h | 24 ++++++++++++++++++++++++<br>
 src/compiler/nir/nir_lower_io.c   |  1 +<br>
 src/compiler/nir/nir_print.c      |  1 +<br>
 5 files changed, 43 insertions(+)<br>
<br>
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h<br>
index c5d3b6b..ac11998 100644<br>
--- a/src/compiler/nir/nir.h<br>
+++ b/src/compiler/nir/nir.h<br>
@@ -992,6 +992,11 @@ typedef enum {<br>
     */<br>
    NIR_INTRINSIC_COMPONENT = 8,<br>
<br>
+   /**<br>
+    * Interpolation mode (only meaningful for FS inputs).<br>
+    */<br>
+   NIR_INTRINSIC_INTERP_MODE = 9,<br>
+<br>
    NIR_INTRINSIC_NUM_INDEX_FLAGS,<br>
<br>
 } nir_intrinsic_index_flag;<br>
@@ -1059,6 +1064,7 @@ INTRINSIC_IDX_ACCESSORS(range, RANGE, unsigned)<br>
 INTRINSIC_IDX_ACCESSORS(desc_set, DESC_SET, unsigned)<br>
 INTRINSIC_IDX_ACCESSORS(binding, BINDING, unsigned)<br>
 INTRINSIC_IDX_ACCESSORS(component, COMPONENT, unsigned)<br>
+INTRINSIC_IDX_ACCESSORS(interp_mode, INTERP_MODE, unsigned)<br>
<br>
 /**<br>
  * \group texture information<br>
diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h<br>
index 09cdf72..435582a 100644<br>
--- a/src/compiler/nir/nir_builder.h<br>
+++ b/src/compiler/nir/nir_builder.h<br>
@@ -458,6 +458,17 @@ nir_load_system_value(nir_builder *build, nir_intrinsic_op op, int index)<br>
    return &load->dest.ssa;<br>
 }<br>
<br>
+static inline nir_ssa_def *<br>
+nir_load_barycentric(nir_builder *build, nir_intrinsic_op op,<br>
+                     unsigned interp_mode)<br>
+{<br>
+   nir_intrinsic_instr *bary = nir_intrinsic_instr_create(build->shader, op);<br>
+   nir_ssa_dest_init(&bary->instr, &bary->dest, 2, 32, NULL);<br>
+   nir_intrinsic_set_interp_mode(bary, interp_mode);<br>
+   nir_builder_instr_insert(build, &bary->instr);<br>
+   return &bary->dest.ssa;<br>
+}<br>
+<br>
 static inline void<br>
 nir_jump(nir_builder *build, nir_jump_type jump_type)<br>
 {<br>
diff --git a/src/compiler/nir/nir_intrinsics.h b/src/compiler/nir/nir_intrinsics.h<br>
index 2f74555..29917e3 100644<br>
--- a/src/compiler/nir/nir_intrinsics.h<br>
+++ b/src/compiler/nir/nir_intrinsics.h<br>
@@ -306,6 +306,27 @@ SYSTEM_VALUE(num_work_groups, 3, 0, xx, xx, xx)<br>
 SYSTEM_VALUE(helper_invocation, 1, 0, xx, xx, xx)<br>
 SYSTEM_VALUE(channel_num, 1, 0, xx, xx, xx)<br>
<br>
+/**<br>
+ * Barycentric coordinate intrinsics.<br>
+ *<br>
+ * These set up the barycentric coordinates for a particular interpolation.<br>
+ * The first three are for the simple cases: pixel, centroid, or per-sample<br>
+ * (at gl_SampleID).  The next two handle interpolating at a specified<br>
+ * sample location, or interpolating with a vec2 offset,<br></blockquote><div><br></div><div>Could you please document what goes in the INTERP_MODE index.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ *<br>
+ * The vec2 value produced by these intrinsics is intended for use as the<br>
+ * barycoord source of a load_interpolated_input intrinsic.<br>
+ */<br>
+SYSTEM_VALUE(barycentric_pixel, 2, 1, INTERP_MODE, xx, xx)<br>
+SYSTEM_VALUE(barycentric_centroid, 2, 1, INTERP_MODE, xx, xx)<br>
+SYSTEM_VALUE(barycentric_sample, 2, 1, INTERP_MODE, xx, xx)<br></blockquote><div><br></div><div>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.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+/* src[] = { sample_id }.  const_index[] = { interp_mode } */<br>
+INTRINSIC(load_barycentric_at_sample, 1, ARR(1), true, 2, 0, 1, INTERP_MODE,<br>
+          xx, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)<br>
+/* src[] = { offset.xy }.  const_index[] = { interp_mode } */<br>
+INTRINSIC(load_barycentric_at_offset, 1, ARR(2), true, 2, 0, 1, INTERP_MODE,<br>
+          xx, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)<br>
+<br>
 /*<br>
  * Load operations pull data from some piece of GPU memory.  All load<br>
  * operations operate in terms of offsets into some piece of theoretical<br>
@@ -339,6 +360,9 @@ LOAD(ubo, 2, 0, xx, xx, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REOR<br>
 LOAD(input, 1, 2, BASE, COMPONENT, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)<br>
 /* src[] = { vertex, offset }. const_index[] = { base, component } */<br>
 LOAD(per_vertex_input, 2, 2, BASE, COMPONENT, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)<br>
+/* src[] = { barycoord, offset }. const_index[] = { base, component } */<br>
+LOAD(interpolated_input, 2, 2, BASE, COMPONENT, xx, NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)<br>
+<br>
 /* src[] = { buffer_index, offset }. No const_index */<br>
 LOAD(ssbo, 2, 0, xx, xx, xx, NIR_INTRINSIC_CAN_ELIMINATE)<br>
 /* src[] = { offset }. const_index[] = { base, component } */<br>
diff --git a/src/compiler/nir/nir_lower_io.c b/src/compiler/nir/nir_lower_io.c<br>
index 71d2432..b05a73f 100644<br>
--- a/src/compiler/nir/nir_lower_io.c<br>
+++ b/src/compiler/nir/nir_lower_io.c<br>
@@ -436,6 +436,7 @@ nir_get_io_offset_src(nir_intrinsic_instr *instr)<br>
    case nir_intrinsic_load_ssbo:<br>
    case nir_intrinsic_load_per_vertex_input:<br>
    case nir_intrinsic_load_per_vertex_output:<br>
+   case nir_intrinsic_load_interpolated_input:<br>
    case nir_intrinsic_store_output:<br>
       return &instr->src[1];<br>
    case nir_intrinsic_store_ssbo:<br>
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c<br>
index a3380e6..3beb70a 100644<br>
--- a/src/compiler/nir/nir_print.c<br>
+++ b/src/compiler/nir/nir_print.c<br>
@@ -571,6 +571,7 @@ print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state)<br>
       [NIR_INTRINSIC_DESC_SET] = "desc-set",<br>
       [NIR_INTRINSIC_BINDING] = "binding",<br>
       [NIR_INTRINSIC_COMPONENT] = "component",<br>
+      [NIR_INTRINSIC_INTERP_MODE] = "interp_mode",<br>
    };<br>
    for (unsigned idx = 1; idx < NIR_INTRINSIC_NUM_INDEX_FLAGS; idx++) {<br>
       if (!info->index_map[idx])<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.9.0<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>