nir: Add a way to identify per-primitive variables
authorCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Thu, 29 Apr 2021 18:51:57 +0000 (11:51 -0700)
committerMarge Bot <eric+marge@anholt.net>
Sat, 28 Aug 2021 03:56:42 +0000 (03:56 +0000)
Per-primitive is similar to per-vertex attributes, but applies to all
fragments of the primitive without any interpolation involved.

Because they are regular input and outputs, keep track in shader_info
of which I/O is per-primitive so we can distinguish them after deref
lowering.  These fields can be used combined with the regular
`inputs_read`, `outputs_written` and `outputs_read`.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10600>

src/compiler/nir/nir.h
src/compiler/nir/nir_gather_info.c
src/compiler/nir/nir_lower_io.c
src/compiler/nir/nir_print.c
src/compiler/shader_info.h

index b71b74c..07688b5 100644 (file)
@@ -495,6 +495,12 @@ typedef struct nir_variable {
       unsigned per_view:1;
 
       /**
+       * Whether the variable is per-primitive.
+       * Can be use by Mesh Shader outputs and corresponding Fragment Shader inputs.
+       */
+      unsigned per_primitive:1;
+
+      /**
        * \brief Layout qualifier for gl_FragDepth. See nir_depth_layout.
        *
        * This is not equal to \c ir_depth_layout_none if and only if this
index e4f858f..9472f89 100644 (file)
@@ -910,4 +910,27 @@ nir_shader_gather_info(nir_shader *shader, nir_function_impl *entrypoint)
        */
       shader->info.fs.uses_sample_shading = true;
    }
+
+   shader->info.per_primitive_outputs = 0;
+   if (shader->info.stage == MESA_SHADER_MESH) {
+      nir_foreach_shader_out_variable(var, shader) {
+         if (var->data.per_primitive) {
+            assert(nir_is_arrayed_io(var, shader->info.stage));
+            const unsigned slots =
+               glsl_count_attribute_slots(glsl_get_array_element(var->type), false);
+            shader->info.per_primitive_outputs |= BITFIELD64_RANGE(var->data.location, slots);
+         }
+      }
+   }
+
+   shader->info.per_primitive_inputs = 0;
+   if (shader->info.stage == MESA_SHADER_FRAGMENT) {
+      nir_foreach_shader_in_variable(var, shader) {
+         if (var->data.per_primitive) {
+            const unsigned slots =
+               glsl_count_attribute_slots(var->type, false);
+            shader->info.per_primitive_inputs |= BITFIELD64_RANGE(var->data.location, slots);
+         }
+      }
+   }
 }
index f5651d4..71bd31c 100644 (file)
@@ -255,7 +255,8 @@ emit_load(struct lower_io_state *state,
    case nir_var_shader_in:
       if (nir->info.stage == MESA_SHADER_FRAGMENT &&
           nir->options->use_interpolated_input_intrinsics &&
-          var->data.interpolation != INTERP_MODE_FLAT) {
+          var->data.interpolation != INTERP_MODE_FLAT &&
+          !var->data.per_primitive) {
          if (var->data.interpolation == INTERP_MODE_EXPLICIT) {
             assert(array_index != NULL);
             op = nir_intrinsic_load_input_vertex;
index b42a21b..f8736b7 100644 (file)
@@ -489,8 +489,9 @@ print_var_decl(nir_variable *var, print_state *state)
    const char *const patch = (var->data.patch) ? "patch " : "";
    const char *const inv = (var->data.invariant) ? "invariant " : "";
    const char *const per_view = (var->data.per_view) ? "per_view " : "";
-   fprintf(fp, "%s%s%s%s%s%s %s ",
-           cent, samp, patch, inv, per_view,
+   const char *const per_primitive = (var->data.per_primitive) ? "per_primitive " : "";
+   fprintf(fp, "%s%s%s%s%s%s%s %s ",
+           cent, samp, patch, inv, per_view, per_primitive,
            get_variable_mode_str(var->data.mode, false),
            glsl_interp_mode_name(var->data.interpolation));
 
index 6794f3d..b1a5d05 100644 (file)
@@ -154,6 +154,12 @@ typedef struct shader_info {
    /* Which system values are actually read */
    BITSET_DECLARE(system_values_read, SYSTEM_VALUE_MAX);
 
+   /* Which I/O is per-primitive, for read/written information combine with
+    * the fields above.
+    */
+   uint64_t per_primitive_inputs;
+   uint64_t per_primitive_outputs;
+
    /* Which 16-bit inputs and outputs are used corresponding to
     * VARYING_SLOT_VARn_16BIT.
     */