nir/linker: pack varyings with different interpolation qualifier
authorQiang Yu <yuq825@gmail.com>
Wed, 25 Aug 2021 06:07:50 +0000 (14:07 +0800)
committerMarge Bot <eric+marge@anholt.net>
Thu, 9 Sep 2021 06:00:58 +0000 (06:00 +0000)
Driver like radeonsi load varying in a scalar manner, so prefer to pack
varying with different interpolation qualifier into same slot to save
space.

But driver like panfrost/bifrost can load varying in vector manner,
so prefer to pack varying with same interpolation qualifier.

Driver can add interpolation qualifiers which are able to be
packed into same varying slot to pack_varying_options nir option.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12537>

src/compiler/nir/nir.h
src/compiler/nir/nir_linking_helpers.c

index a58c136..33cc82e 100644 (file)
@@ -3416,6 +3416,16 @@ typedef enum {
    nir_divergence_multiple_workgroup_per_compute_subgroup = (1 << 5),
 } nir_divergence_options;
 
+typedef enum {
+   nir_pack_varying_interp_mode_none          = (1 << 0),
+   nir_pack_varying_interp_mode_smooth        = (1 << 1),
+   nir_pack_varying_interp_mode_flat          = (1 << 2),
+   nir_pack_varying_interp_mode_noperspective = (1 << 3),
+   nir_pack_varying_interp_loc_sample         = (1 << 16),
+   nir_pack_varying_interp_loc_centroid       = (1 << 17),
+   nir_pack_varying_interp_loc_center         = (1 << 18),
+} nir_pack_varying_options;
+
 /** An instruction filtering callback
  *
  * Returns true if the instruction should be processed and false otherwise.
@@ -3777,6 +3787,13 @@ typedef struct nir_shader_compiler_options {
    nir_lower_int64_options lower_int64_options;
    nir_lower_doubles_options lower_doubles_options;
    nir_divergence_options divergence_analysis_options;
+
+   /**
+    * Support pack varyings with different interpolation location
+    * (center, centroid, sample) and mode (flat, noperspective, smooth)
+    * into same slot.
+    */
+   nir_pack_varying_options pack_varying_options;
 } nir_shader_compiler_options;
 
 typedef struct nir_shader {
index be4144a..2c2c342 100644 (file)
@@ -670,12 +670,60 @@ gather_varying_component_info(nir_shader *producer, nir_shader *consumer,
    }
 }
 
+static bool
+allow_pack_interp_type(nir_pack_varying_options options, int type)
+{
+   int sel;
+
+   switch (type) {
+   case INTERP_MODE_NONE:
+      sel = nir_pack_varying_interp_mode_none;
+      break;
+   case INTERP_MODE_SMOOTH:
+      sel = nir_pack_varying_interp_mode_smooth;
+      break;
+   case INTERP_MODE_FLAT:
+      sel = nir_pack_varying_interp_mode_flat;
+      break;
+   case INTERP_MODE_NOPERSPECTIVE:
+      sel = nir_pack_varying_interp_mode_noperspective;
+      break;
+   default:
+      return false;
+   }
+
+   return options & sel;
+}
+
+static bool
+allow_pack_interp_loc(nir_pack_varying_options options, int loc)
+{
+   int sel;
+
+   switch (loc) {
+   case INTERPOLATE_LOC_SAMPLE:
+      sel = nir_pack_varying_interp_loc_sample;
+      break;
+   case INTERPOLATE_LOC_CENTROID:
+      sel = nir_pack_varying_interp_loc_centroid;
+      break;
+   case INTERPOLATE_LOC_CENTER:
+      sel = nir_pack_varying_interp_loc_center;
+      break;
+   default:
+      return false;
+   }
+
+   return options & sel;
+}
+
 static void
 assign_remap_locations(struct varying_loc (*remap)[4],
                        struct assigned_comps *assigned_comps,
                        struct varying_component *info,
                        unsigned *cursor, unsigned *comp,
-                       unsigned max_location)
+                       unsigned max_location,
+                       nir_pack_varying_options options)
 {
    unsigned tmp_cursor = *cursor;
    unsigned tmp_comp = *comp;
@@ -683,21 +731,28 @@ assign_remap_locations(struct varying_loc (*remap)[4],
    for (; tmp_cursor < max_location; tmp_cursor++) {
 
       if (assigned_comps[tmp_cursor].comps) {
-         /* We can only pack varyings with matching interpolation types,
-          * interpolation loc must match also.
-          * TODO: i965 can handle interpolation locations that don't match,
-          * but the radeonsi nir backend handles everything as vec4s and so
-          * expects this to be the same for all components. We could make this
-          * check driver specfific or drop it if NIR ever become the only
-          * radeonsi backend.
-          * TODO2: The radeonsi comment above is not true. Only "flat" is per
-          * vec4 (128-bit granularity), all other interpolation qualifiers are
-          * per component (16-bit granularity for float16, 32-bit granularity
-          * otherwise). Each vec4 (128 bits) must be either vec4 or f16vec8.
+         /* We can only pack varyings with matching precision. */
+         if (assigned_comps[tmp_cursor].is_mediump != info->is_mediump) {
+            tmp_comp = 0;
+            continue;
+         }
+
+         /* We can only pack varyings with matching interpolation type
+          * if driver does not support it.
+          */
+         if (assigned_comps[tmp_cursor].interp_type != info->interp_type &&
+             (!allow_pack_interp_type(options, assigned_comps[tmp_cursor].interp_type) ||
+              !allow_pack_interp_type(options, info->interp_type))) {
+            tmp_comp = 0;
+            continue;
+         }
+
+         /* We can only pack varyings with matching interpolation location
+          * if driver does not support it.
           */
-         if (assigned_comps[tmp_cursor].interp_type != info->interp_type ||
-             assigned_comps[tmp_cursor].interp_loc != info->interp_loc ||
-             assigned_comps[tmp_cursor].is_mediump != info->is_mediump) {
+         if (assigned_comps[tmp_cursor].interp_loc != info->interp_loc &&
+             (!allow_pack_interp_loc(options, assigned_comps[tmp_cursor].interp_loc) ||
+              !allow_pack_interp_loc(options, info->interp_loc))) {
             tmp_comp = 0;
             continue;
          }
@@ -764,6 +819,8 @@ compact_components(nir_shader *producer, nir_shader *consumer,
    qsort(varying_comp_info, varying_comp_info_size,
          sizeof(struct varying_component), cmp_varying_component);
 
+   nir_pack_varying_options options = consumer->options->pack_varying_options;
+
    unsigned cursor = 0;
    unsigned comp = 0;
 
@@ -783,10 +840,12 @@ compact_components(nir_shader *producer, nir_shader *consumer,
          }
 
          assign_remap_locations(remap, assigned_comps, info,
-                                &cursor, &comp, MAX_VARYINGS_INCL_PATCH);
+                                &cursor, &comp, MAX_VARYINGS_INCL_PATCH,
+                                options);
       } else {
          assign_remap_locations(remap, assigned_comps, info,
-                                &cursor, &comp, MAX_VARYING);
+                                &cursor, &comp, MAX_VARYING,
+                                options);
 
          /* Check if we failed to assign a remap location. This can happen if
           * for example there are a bunch of unmovable components with
@@ -799,7 +858,8 @@ compact_components(nir_shader *producer, nir_shader *consumer,
             cursor = 0;
             comp = 0;
             assign_remap_locations(remap, assigned_comps, info,
-                                   &cursor, &comp, MAX_VARYING);
+                                   &cursor, &comp, MAX_VARYING,
+                                   options);
          }
       }
    }