summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir/nir_intrinsics.h
diff options
context:
space:
mode:
authorKenneth Graunke <[email protected]>2016-07-12 01:46:43 -0700
committerKenneth Graunke <[email protected]>2016-07-20 11:00:45 -0700
commit249646247996d9950584bbd34067a27b8b704a6f (patch)
treebd929d55db4e767ee66ba7e66d04485c2c6b131a /src/compiler/nir/nir_intrinsics.h
parente614062e548ae58f51082c2cf984c3141cf01ec9 (diff)
nir: Add new intrinsics for fragment shader input interpolation.
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. v2: Document the interp_mode const_index value, define a new BARYCENTRIC() helper rather than using SYSTEM_VALUE() for some of them (requested by Jason Ekstrand). Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Chris Forbes <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/compiler/nir/nir_intrinsics.h')
-rw-r--r--src/compiler/nir/nir_intrinsics.h32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/compiler/nir/nir_intrinsics.h b/src/compiler/nir/nir_intrinsics.h
index 2f74555ee48..cf2ddc8ac72 100644
--- a/src/compiler/nir/nir_intrinsics.h
+++ b/src/compiler/nir/nir_intrinsics.h
@@ -306,6 +306,35 @@ 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,
+ *
+ * The interp_mode index should be either the INTERP_MODE_SMOOTH or
+ * INTERP_MODE_NOPERSPECTIVE enum values.
+ *
+ * The vec2 value produced by these intrinsics is intended for use as the
+ * barycoord source of a load_interpolated_input intrinsic.
+ */
+
+#define BARYCENTRIC(name, sources, source_components) \
+ INTRINSIC(load_barycentric_##name, sources, ARR(source_components), \
+ true, 2, 0, 1, INTERP_MODE, xx, xx, \
+ NIR_INTRINSIC_CAN_ELIMINATE | NIR_INTRINSIC_CAN_REORDER)
+
+/* no sources. const_index[] = { interp_mode } */
+BARYCENTRIC(pixel, 0, 0)
+BARYCENTRIC(centroid, 0, 0)
+BARYCENTRIC(sample, 0, 0)
+/* src[] = { sample_id }. const_index[] = { interp_mode } */
+BARYCENTRIC(at_sample, 1, 1)
+/* src[] = { offset.xy }. const_index[] = { interp_mode } */
+BARYCENTRIC(at_offset, 1, 2)
+
/*
* 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 +368,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 } */