Mesa (main): zink: add a compiler pass to split xfb block outputs
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Jul 15 17:48:36 UTC 2022
Module: Mesa
Branch: main
Commit: bd2eaaeb7debeef417fe3d9fd04fbd5df4e11ed7
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=bd2eaaeb7debeef417fe3d9fd04fbd5df4e11ed7
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Thu Jul 7 14:09:52 2022 -0400
zink: add a compiler pass to split xfb block outputs
this splits all the members of a struct into separate variables to
improve xfb inlining and reduce the number of locations consumed by
xfb outputs, reducing the chances of running out of shader outputs
Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17404>
---
src/gallium/drivers/zink/zink_compiler.c | 73 ++++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c
index 1ae03ab3c07..2fafe487a1c 100644
--- a/src/gallium/drivers/zink/zink_compiler.c
+++ b/src/gallium/drivers/zink/zink_compiler.c
@@ -1835,6 +1835,76 @@ lower_64bit_vars(nir_shader *shader)
return progress;
}
+static bool
+split_blocks(nir_shader *nir)
+{
+ bool progress = false;
+ bool changed = true;
+ do {
+ progress = false;
+ nir_foreach_shader_out_variable(var, nir) {
+ const struct glsl_type *base_type = glsl_without_array(var->type);
+ nir_variable *members[32]; //can't have more than this without breaking NIR
+ if (!glsl_type_is_struct(base_type))
+ continue;
+ /* TODO: arrays? */
+ if (!glsl_type_is_struct(var->type) || glsl_get_length(var->type) == 1)
+ continue;
+ if (glsl_count_attribute_slots(var->type, false) == 1)
+ continue;
+ unsigned offset = 0;
+ for (unsigned i = 0; i < glsl_get_length(var->type); i++) {
+ members[i] = nir_variable_clone(var, nir);
+ members[i]->type = glsl_get_struct_field(var->type, i);
+ members[i]->name = (void*)glsl_get_struct_elem_name(var->type, i);
+ members[i]->data.location += offset;
+ offset += glsl_count_attribute_slots(members[i]->type, false);
+ nir_shader_add_variable(nir, members[i]);
+ }
+ nir_foreach_function(function, nir) {
+ bool func_progress = false;
+ if (!function->impl)
+ continue;
+ nir_builder b;
+ nir_builder_init(&b, function->impl);
+ nir_foreach_block(block, function->impl) {
+ nir_foreach_instr_safe(instr, block) {
+ switch (instr->type) {
+ case nir_instr_type_deref: {
+ nir_deref_instr *deref = nir_instr_as_deref(instr);
+ if (!(deref->modes & nir_var_shader_out))
+ continue;
+ if (nir_deref_instr_get_variable(deref) != var)
+ continue;
+ if (deref->deref_type != nir_deref_type_struct)
+ continue;
+ nir_deref_instr *parent = nir_deref_instr_parent(deref);
+ if (parent->deref_type != nir_deref_type_var)
+ continue;
+ deref->modes = nir_var_shader_temp;
+ parent->modes = nir_var_shader_temp;
+ b.cursor = nir_before_instr(instr);
+ nir_ssa_def *dest = &nir_build_deref_var(&b, members[deref->strct.index])->dest.ssa;
+ nir_ssa_def_rewrite_uses_after(&deref->dest.ssa, dest, &deref->instr);
+ nir_instr_remove(&deref->instr);
+ func_progress = true;
+ break;
+ }
+ default: break;
+ }
+ }
+ }
+ if (func_progress)
+ nir_metadata_preserve(function->impl, nir_metadata_none);
+ }
+ var->data.mode = nir_var_shader_temp;
+ changed = true;
+ progress = true;
+ }
+ } while (progress);
+ return changed;
+}
+
static void
zink_shader_dump(void *words, size_t size, const char *file)
{
@@ -2879,6 +2949,9 @@ zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,
NIR_PASS_V(nir, nir_lower_subgroups, &subgroup_options);
}
+ if (so_info && so_info->num_outputs)
+ NIR_PASS_V(nir, split_blocks);
+
optimize_nir(nir, NULL);
NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
NIR_PASS_V(nir, nir_lower_discard_if);
More information about the mesa-commit
mailing list