.vertex_id_zero_based = true,
.lower_extract_byte = true,
.lower_extract_word = true,
- .lower_all_io_to_elements = true,
.lower_helper_invocation = true,
.lower_bitfield_insert_to_shifts = true,
.lower_bitfield_extract_to_shifts = true,
.vertex_id_zero_based = false,
.lower_extract_byte = true,
.lower_extract_word = true,
- .lower_all_io_to_elements = true,
.lower_helper_invocation = true,
.lower_bitfield_insert_to_shifts = true,
.lower_bitfield_extract_to_shifts = true,
}
void
+ir3_nir_lower_io_to_temporaries(nir_shader *s)
+{
+ /* Outputs consumed by the VPC, VS inputs, and FS outputs are all handled
+ * by the hardware pre-loading registers at the beginning and then reading
+ * them at the end, so we can't access them indirectly except through
+ * normal register-indirect accesses, and therefore ir3 doesn't support
+ * indirect accesses on those. Other i/o is lowered in ir3_nir_lower_tess,
+ * and indirects work just fine for those. GS outputs may be consumed by
+ * VPC, but have their own lowering in ir3_nir_lower_gs() which does
+ * something similar to nir_lower_io_to_temporaries so we shouldn't need
+ * to lower them.
+ *
+ * Note: this might be a little inefficient for VS or TES outputs which are
+ * when the next stage isn't an FS, but it probably don't make sense to
+ * depend on the next stage before variant creation.
+ *
+ * TODO: for gallium, mesa/st also does some redundant lowering, including
+ * running this pass for GS inputs/outputs which we don't want but not
+ * including TES outputs or FS inputs which we do need. We should probably
+ * stop doing that once we're sure all drivers are doing their own
+ * indirect i/o lowering.
+ */
+ bool lower_input = s->info.stage == MESA_SHADER_VERTEX || s->info.stage == MESA_SHADER_FRAGMENT;
+ bool lower_output = s->info.stage != MESA_SHADER_TESS_CTRL && s->info.stage != MESA_SHADER_GEOMETRY;
+ if (lower_input || lower_output) {
+ NIR_PASS_V(s, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(s),
+ lower_output, lower_input);
+
+ /* nir_lower_io_to_temporaries() creates global variables and copy
+ * instructions which need to be cleaned up.
+ */
+ NIR_PASS_V(s, nir_split_var_copies);
+ NIR_PASS_V(s, nir_lower_var_copies);
+ NIR_PASS_V(s, nir_lower_global_vars_to_local);
+ }
+}
+
+void
ir3_finalize_nir(struct ir3_compiler *compiler, nir_shader *s)
{
struct nir_lower_tex_options tex_options = {
if (s->info.stage == MESA_SHADER_GEOMETRY)
NIR_PASS_V(s, ir3_nir_lower_gs);
- NIR_PASS_V(s, nir_lower_io_arrays_to_elements_no_indirects, false);
-
NIR_PASS_V(s, nir_lower_amul, ir3_glsl_type_size);
OPT_V(s, nir_lower_regs_to_ssa);
NIR_PASS_V(nir, nir_propagate_invariant);
- NIR_PASS_V(nir, nir_lower_io_to_temporaries, nir_shader_get_entrypoint(nir), true, true);
-
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
NIR_PASS_V(nir, nir_split_var_copies);
NIR_PASS_V(nir, nir_lower_var_copies);
NIR_PASS_V(nir, nir_opt_copy_prop_vars);
NIR_PASS_V(nir, nir_opt_combine_stores, nir_var_all);
- /* ir3 doesn't support indirect input/output */
- /* TODO: We shouldn't perform this lowering pass on gl_TessLevelInner
- * and gl_TessLevelOuter. Since the tess levels are actually stored in
- * a global BO, they can be directly accessed via stg and ldg.
- * nir_lower_indirect_derefs will instead generate a big if-ladder which
- * isn't *incorrect* but is much less efficient. */
- NIR_PASS_V(nir, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out, UINT32_MAX);
-
- NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false);
-
NIR_PASS_V(nir, nir_lower_is_helper_invocation);
NIR_PASS_V(nir, nir_lower_system_values);
});
}
+ /* This needs to happen before multiview lowering which rewrites store
+ * instructions of the position variable, so that we can just rewrite one
+ * store at the end instead of having to rewrite every store specified by
+ * the user.
+ */
+ ir3_nir_lower_io_to_temporaries(nir);
+
if (nir->info.stage == MESA_SHADER_VERTEX && multiview_mask) {
tu_nir_lower_multiview(nir, multiview_mask,
&shader->multi_pos_output, dev);