[Mesa-dev] [PATCH 3/7] nir: Add nir_load_interpolated_input lowering code.

Kenneth Graunke kenneth at whitecape.org
Mon Jul 18 20:26:33 UTC 2016


Now nir_lower_io can optionally produce load_interpolated_input
and load_barycentric_* intrinsics for fragment shader inputs.

flat inputs continue using regular load_input.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 src/compiler/nir/nir_lower_io.c | 94 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 89 insertions(+), 5 deletions(-)

diff --git a/src/compiler/nir/nir_lower_io.c b/src/compiler/nir/nir_lower_io.c
index aa8a517..e480264 100644
--- a/src/compiler/nir/nir_lower_io.c
+++ b/src/compiler/nir/nir_lower_io.c
@@ -174,12 +174,30 @@ lower_load(nir_intrinsic_instr *intrin, struct lower_io_state *state,
 {
    nir_variable *var = intrin->variables[0]->var;
    nir_variable_mode mode = var->data.mode;
+   nir_ssa_def *barycentric = NULL;
 
    nir_intrinsic_op op;
    switch (mode) {
    case nir_var_shader_in:
-      op = vertex_index ? nir_intrinsic_load_per_vertex_input :
-                          nir_intrinsic_load_input;
+      if (state->use_interpolated_input &&
+          var->data.interpolation != INTERP_MODE_FLAT) {
+         assert(vertex_index == NULL);
+
+         nir_intrinsic_op bary_op;
+         if (var->data.sample)
+            bary_op = nir_intrinsic_load_barycentric_sample;
+         else if (var->data.centroid)
+            bary_op = nir_intrinsic_load_barycentric_centroid;
+         else
+            bary_op = nir_intrinsic_load_barycentric_pixel;
+
+         barycentric = nir_load_barycentric(&state->builder, bary_op,
+                                            var->data.interpolation);
+         op = nir_intrinsic_load_interpolated_input;
+      } else {
+         op = vertex_index ? nir_intrinsic_load_per_vertex_input :
+                             nir_intrinsic_load_input;
+      }
       break;
    case nir_var_shader_out:
       op = vertex_index ? nir_intrinsic_load_per_vertex_output :
@@ -205,10 +223,15 @@ lower_load(nir_intrinsic_instr *intrin, struct lower_io_state *state,
    if (load->intrinsic == nir_intrinsic_load_uniform)
       nir_intrinsic_set_range(load, state->type_size(var->type));
 
-   if (vertex_index)
+   if (vertex_index) {
       load->src[0] = nir_src_for_ssa(vertex_index);
-
-   load->src[vertex_index ? 1 : 0] = nir_src_for_ssa(offset);
+      load->src[1] = nir_src_for_ssa(offset);
+   } else if (barycentric) {
+      load->src[0] = nir_src_for_ssa(barycentric);
+      load->src[1] = nir_src_for_ssa(offset);
+   } else {
+      load->src[0] = nir_src_for_ssa(offset);
+   }
 
    return load;
 }
@@ -288,6 +311,54 @@ lower_atomic(nir_intrinsic_instr *intrin, struct lower_io_state *state,
    return atomic;
 }
 
+static nir_intrinsic_instr *
+lower_interpolate_at(nir_intrinsic_instr *intrin, struct lower_io_state *state,
+                     nir_ssa_def *offset)
+{
+   nir_variable *var = intrin->variables[0]->var;
+
+   assert(var->data.mode == nir_var_shader_in);
+
+   nir_intrinsic_op bary_op;
+   switch (intrin->intrinsic) {
+   case nir_intrinsic_interp_var_at_centroid:
+      bary_op = nir_intrinsic_load_barycentric_centroid;
+      break;
+   case nir_intrinsic_interp_var_at_sample:
+      bary_op = nir_intrinsic_load_barycentric_at_sample;
+      break;
+   case nir_intrinsic_interp_var_at_offset:
+      bary_op = nir_intrinsic_load_barycentric_at_offset;
+      break;
+   default:
+      unreachable("Bogus interpolateAt() intrinsic.");
+   }
+
+   nir_intrinsic_instr *bary_setup =
+      nir_intrinsic_instr_create(state->mem_ctx, bary_op);
+
+   nir_ssa_dest_init(&bary_setup->instr, &bary_setup->dest, 2, 32, NULL);
+   nir_intrinsic_set_interp_mode(bary_setup, var->data.interpolation);
+
+   if (intrin->intrinsic != nir_intrinsic_interp_var_at_centroid)
+      nir_src_copy(&bary_setup->src[0], &intrin->src[0], bary_setup);
+
+   nir_builder_instr_insert(&state->builder, &bary_setup->instr);
+
+   nir_intrinsic_instr *load =
+      nir_intrinsic_instr_create(state->mem_ctx,
+                                 nir_intrinsic_load_interpolated_input);
+   load->num_components = intrin->num_components;
+
+   nir_intrinsic_set_base(load, var->data.driver_location);
+   nir_intrinsic_set_component(load, var->data.location_frac);
+
+   load->src[0] = nir_src_for_ssa(&bary_setup->dest.ssa);
+   load->src[1] = nir_src_for_ssa(offset);
+
+   return load;
+}
+
 static bool
 nir_lower_io_block(nir_block *block,
                    struct lower_io_state *state)
@@ -315,6 +386,12 @@ nir_lower_io_block(nir_block *block,
       case nir_intrinsic_var_atomic_comp_swap:
          /* We can lower the io for this nir instrinsic */
          break;
+      case nir_intrinsic_interp_var_at_centroid:
+      case nir_intrinsic_interp_var_at_sample:
+      case nir_intrinsic_interp_var_at_offset:
+         /* We can optionally lower these to load_interpolated_input */
+         if (state->use_interpolated_input)
+            break;
       default:
          /* We can't lower the io for this nir instrinsic, so skip it */
          continue;
@@ -369,6 +446,13 @@ nir_lower_io_block(nir_block *block,
          replacement = lower_atomic(intrin, state, offset);
          break;
 
+      case nir_intrinsic_interp_var_at_centroid:
+      case nir_intrinsic_interp_var_at_sample:
+      case nir_intrinsic_interp_var_at_offset:
+         assert(vertex_index == NULL);
+         replacement = lower_interpolate_at(intrin, state, offset);
+         break;
+
       default:
          break;
       }
-- 
2.9.0



More information about the mesa-dev mailing list