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.
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 {
}
}
+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;
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;
}
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;
}
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
cursor = 0;
comp = 0;
assign_remap_locations(remap, assigned_comps, info,
- &cursor, &comp, MAX_VARYING);
+ &cursor, &comp, MAX_VARYING,
+ options);
}
}
}