nak: Fix divergence test for redux availability

nak's divergence differs slightly from nir's divergence. Fix the test to
match what the backend will use, since we need to allocate a ureg.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13964
Fixes: 295373f29f ("nak: Implement nir_intrinsic_reduce with REDUX")
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37585>
This commit is contained in:
Mel Henning 2025-09-25 17:07:39 -04:00 committed by Marge Bot
parent bb3e401cca
commit 094804131e
3 changed files with 44 additions and 1 deletions

View file

@ -498,3 +498,36 @@ nak_nir_lower_cf(nir_shader *nir)
return progress;
}
bool
nak_block_is_divergent(const nir_block *block)
{
const nir_cf_node* node = &block->cf_node;
while (node) {
switch (node->type) {
case nir_cf_node_if: {
nir_if *nif = nir_cf_node_as_if(node);
if (nir_src_is_divergent(&nif->condition))
return true;
break;
}
case nir_cf_node_loop: {
nir_loop *loop = nir_cf_node_as_loop(node);
if (nir_loop_is_divergent(loop))
return true;
break;
}
case nir_cf_node_block: {
nir_block *block = nir_cf_node_as_block(node);
if (block->divergent)
return true;
break;
}
case nir_cf_node_function:
break;
}
node = node->parent;
}
return false;
}

View file

@ -229,7 +229,7 @@ nak_nir_lower_scan_reduce_intrin(nir_builder *b,
nir_op_infos[red_op].output_type != nir_type_float &&
intrin->src[0].ssa->bit_size == 32 &&
cluster_size == 32 &&
!intrin->instr.block->divergent) {
!nak_block_is_divergent(intrin->instr.block)) {
/* TODO: We could probably also use REDUX for the non-uniform case if we
* were allowed to write uregs from non-uniform control flow.
*/

View file

@ -343,6 +343,16 @@ bool nak_nir_add_barriers(nir_shader *nir, const struct nak_compiler *nak);
bool nak_nir_lower_cf(nir_shader *nir);
bool nak_nir_lower_cmat(nir_shader *shader, const struct nak_compiler *nak);
/**
* Check if, for nak's purposes, a block is divergent
*
* Note that this differs from block->divergent because in nir's terms, the
* start block of a loop with divergent continues can be non-divergent but nak
* will always consider this divergent. This matters because nak does not allow
* writing uregs from these blocks.
*/
bool nak_block_is_divergent(const nir_block *block);
void nak_optimize_nir(nir_shader *nir, const struct nak_compiler *nak);
#ifdef __cplusplus