panfrost: ensure sample_mask is written before color

The ATEST instruction needs sample_mask as an input, but if the
shader writes to color before sample_mask we could emit them
in the wrong order. Fix this in pan_nir_lower_zs_store by
deferring the color write until after the sample_mask write.

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Benjamin Lee <benjamin.lee@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32879>
This commit is contained in:
Eric R. Smith 2025-01-03 19:20:54 -04:00 committed by Marge Bot
parent 115eb1d5f3
commit 03a1a5009f

View file

@ -108,6 +108,8 @@ pan_nir_lower_zs_store(nir_shader *nir)
nir_foreach_function_impl(impl, nir) {
nir_intrinsic_instr *stores[3] = {NULL};
nir_intrinsic_instr *last_mask_store = NULL;
nir_block *mask_block = NULL;
unsigned writeout = 0;
nir_foreach_block(block, impl) {
@ -130,14 +132,17 @@ pan_nir_lower_zs_store(nir_shader *nir)
assert(!stores[2]); /* there should be only 1 source for dual blending */
stores[2] = intr;
writeout |= PAN_WRITEOUT_2;
} else if (sem.location == FRAG_RESULT_SAMPLE_MASK) {
last_mask_store = intr;
mask_block = intr->instr.block;
}
}
}
if (!writeout)
if (!writeout && !last_mask_store)
continue;
nir_block *common_block = NULL;
nir_block *common_block = mask_block;
/* Ensure all stores are in the same block */
for (unsigned i = 0; i < ARRAY_SIZE(stores); ++i) {
@ -152,6 +157,28 @@ pan_nir_lower_zs_store(nir_shader *nir)
common_block = block;
}
/* move data stores in the common block to after the last mask store */
if (last_mask_store) {
nir_cursor insert_point = nir_after_instr(&last_mask_store->instr);
nir_foreach_instr_safe(instr, mask_block) {
if (instr->type != nir_instr_type_intrinsic)
continue;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
/* stop when we've reached the last store to mask */
if (intr == last_mask_store)
break;
if (intr->intrinsic != nir_intrinsic_store_output)
continue;
nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
if (sem.location >= FRAG_RESULT_DATA0 &&
sem.location <= FRAG_RESULT_DATA7) {
nir_instr_move(insert_point, instr);
insert_point = nir_after_instr(instr);
}
}
}
bool replaced = false;
nir_foreach_block(block, impl) {