nir/lower_subgroups: generalize vote lowering

We currently have code to lower quad votes to a ballot. The same idea works for
subgroup votes. Generalize the quad vote code and use it to lower
vote_all/vote_eq for backends setting a new lower_vote option.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@intel.com>
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40074>
This commit is contained in:
Alyssa Rosenzweig 2026-02-19 21:57:38 -05:00 committed by Marge Bot
parent f8f80c3700
commit 8a450fb0ff
2 changed files with 17 additions and 12 deletions

View file

@ -5787,6 +5787,7 @@ typedef struct nir_lower_subgroups_options {
uint8_t ballot_bit_size;
uint8_t ballot_components;
bool lower_to_scalar : 1;
bool lower_vote : 1;
bool lower_vote_trivial : 1;
bool lower_vote_feq : 1;
bool lower_vote_ieq : 1;

View file

@ -980,15 +980,19 @@ build_subgroup_gt_mask(nir_builder *b,
}
static nir_def *
build_quad_vote_any(nir_builder *b, nir_def *src,
const nir_lower_subgroups_options *options)
build_vote(nir_builder *b, nir_def *src,
const nir_lower_subgroups_options *options,
unsigned cluster_size, bool all)
{
nir_def *ballot = nir_ballot(b, options->ballot_components,
options->ballot_bit_size,
src);
nir_def *mask = build_cluster_mask(b, 4, options);
all ? nir_inot(b, src) : src);
if (cluster_size) {
nir_def *mask = build_cluster_mask(b, cluster_size, options);
ballot = nir_iand(b, ballot, mask);
}
return nir_ine_imm(b, nir_iand(b, ballot, mask), 0);
return all ? nir_ieq_imm(b, ballot, 0) : nir_ine_imm(b, ballot, 0);
}
static nir_def *
@ -1088,8 +1092,12 @@ lower_subgroups_instr(nir_builder *b, nir_instr *instr, void *_options)
switch (intrin->intrinsic) {
case nir_intrinsic_vote_any:
case nir_intrinsic_vote_all:
if (options->lower_vote_trivial)
if (options->lower_vote_trivial) {
return intrin->src[0].ssa;
} else if (options->lower_vote) {
return build_vote(b, intrin->src[0].ssa, options, 0,
intrin->intrinsic == nir_intrinsic_vote_all);
}
break;
case nir_intrinsic_vote_feq:
@ -1337,14 +1345,10 @@ lower_subgroups_instr(nir_builder *b, nir_instr *instr, void *_options)
break;
case nir_intrinsic_quad_vote_any:
if (options->lower_quad_vote)
return build_quad_vote_any(b, intrin->src[0].ssa, options);
break;
case nir_intrinsic_quad_vote_all:
if (options->lower_quad_vote) {
nir_def *not_src = nir_inot(b, intrin->src[0].ssa);
nir_def *any_not = build_quad_vote_any(b, not_src, options);
return nir_inot(b, any_not);
return build_vote(b, intrin->src[0].ssa, options, 4,
intrin->intrinsic == nir_intrinsic_quad_vote_all);
}
break;