nir: lower interp_deref_at_vertex to load_input_vertex
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 27 Jan 2020 10:34:00 +0000 (11:34 +0100)
committerMarge Bot <eric+marge@anholt.net>
Wed, 29 Jan 2020 09:49:50 +0000 (09:49 +0000)
This introduces a new NIR intrinsic for loading inputs at a specific
vertex index.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3578>

src/compiler/nir/nir_divergence_analysis.c
src/compiler/nir/nir_intrinsics.py
src/compiler/nir/nir_lower_io.c

index f0c8bfad7b2632bbd9d67233a17a007b737ac648..bfa12d1a57d1fb940fd684f7d094439f305f0f38 100644 (file)
@@ -125,6 +125,11 @@ visit_intrinsic(bool *divergent, nir_intrinsic_instr *instr,
       else
          is_divergent = true;
       break;
+   case nir_intrinsic_load_input_vertex:
+      is_divergent = divergent[instr->src[1].ssa->index];
+      assert(stage == MESA_SHADER_FRAGMENT);
+      is_divergent |= !(options & nir_divergence_single_prim_per_subgroup);
+      break;
    case nir_intrinsic_load_output:
       assert(stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_FRAGMENT);
       is_divergent = divergent[instr->src[0].ssa->index];
@@ -264,6 +269,7 @@ visit_intrinsic(bool *divergent, nir_intrinsic_instr *instr,
    case nir_intrinsic_load_barycentric_pixel:
    case nir_intrinsic_load_barycentric_centroid:
    case nir_intrinsic_load_barycentric_sample:
+   case nir_intrinsic_load_barycentric_model:
    case nir_intrinsic_load_barycentric_at_sample:
    case nir_intrinsic_load_barycentric_at_offset:
    case nir_intrinsic_interp_deref_at_offset:
index 6ebc76eb88bac283686633388b5ed3f86ef16f93..292933bd06578c65e0c965bf4fb8cdabb9b95e22 100644 (file)
@@ -726,6 +726,8 @@ load("uniform", 1, [BASE, RANGE, TYPE], [CAN_ELIMINATE, CAN_REORDER])
 load("ubo", 2, [ACCESS, ALIGN_MUL, ALIGN_OFFSET], flags=[CAN_ELIMINATE, CAN_REORDER])
 # src[] = { offset }.
 load("input", 1, [BASE, COMPONENT, TYPE], [CAN_ELIMINATE, CAN_REORDER])
+# src[] = { vertex_id, offset }.
+load("input_vertex", 2, [BASE, COMPONENT, TYPE], [CAN_ELIMINATE, CAN_REORDER])
 # src[] = { vertex, offset }.
 load("per_vertex_input", 2, [BASE, COMPONENT], [CAN_ELIMINATE, CAN_REORDER])
 # src[] = { barycoord, offset }.
index f10022936d0b65d7fd2fc6d007c955d6c68115f3..780d76748bea37922807d7ca6bec1906951beda0 100644 (file)
@@ -245,20 +245,25 @@ emit_load(struct lower_io_state *state,
       if (nir->info.stage == MESA_SHADER_FRAGMENT &&
           nir->options->use_interpolated_input_intrinsics &&
           var->data.interpolation != INTERP_MODE_FLAT) {
-         assert(vertex_index == NULL);
-
-         nir_intrinsic_op bary_op;
-         if (var->data.sample ||
-             (state->options & nir_lower_io_force_sample_interpolation))
-            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;
+         if (var->data.interpolation == INTERP_MODE_EXPLICIT) {
+            assert(vertex_index != NULL);
+            op = nir_intrinsic_load_input_vertex;
+         } else {
+            assert(vertex_index == NULL);
+
+            nir_intrinsic_op bary_op;
+            if (var->data.sample ||
+                (state->options & nir_lower_io_force_sample_interpolation))
+               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;
@@ -291,6 +296,7 @@ emit_load(struct lower_io_state *state,
                               state->type_size(var->type, var->data.bindless));
 
    if (load->intrinsic == nir_intrinsic_load_input ||
+       load->intrinsic == nir_intrinsic_load_input_vertex ||
        load->intrinsic == nir_intrinsic_load_uniform)
       nir_intrinsic_set_type(load, type);
 
@@ -489,9 +495,20 @@ lower_interpolate_at(nir_intrinsic_instr *intrin, struct lower_io_state *state,
    nir_builder *b = &state->builder;
    assert(var->data.mode == nir_var_shader_in);
 
-   /* Ignore interpolateAt() for flat variables - flat is flat. */
-   if (var->data.interpolation == INTERP_MODE_FLAT)
-      return lower_load(intrin, state, NULL, var, offset, component, type);
+   /* Ignore interpolateAt() for flat variables - flat is flat. Lower
+    * interpolateAtVertex() for explicit variables.
+    */
+   if (var->data.interpolation == INTERP_MODE_FLAT ||
+       var->data.interpolation == INTERP_MODE_EXPLICIT) {
+      nir_ssa_def *vertex_index = NULL;
+
+      if (var->data.interpolation == INTERP_MODE_EXPLICIT) {
+         assert(intrin->intrinsic == nir_intrinsic_interp_deref_at_vertex);
+         vertex_index = intrin->src[1].ssa;
+      }
+
+      return lower_load(intrin, state, vertex_index, var, offset, component, type);
+   }
 
    /* None of the supported APIs allow interpolation on 64-bit things */
    assert(intrin->dest.is_ssa && intrin->dest.ssa.bit_size <= 32);