pan/mdg: Fix multiple spilt writes in the same bundle

If two instructions in a single bundle both write to a spilt
destination, then we need to reuse the fill and spill instructions,
otherwise the value will be overwritten.

This and the rest of this set of Midgard bug fixes were found from a
vertex shader in Firefox WebRender that is used when a video is
clipped, for example by setting the border-radius CSS property.

CC: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16382>
(cherry picked from commit c65afe541b)
This commit is contained in:
Icecream95 2021-12-10 23:51:06 +13:00 committed by Dylan Baker
parent 3a957eb909
commit 338674fda9
2 changed files with 23 additions and 7 deletions

View file

@ -580,7 +580,7 @@
"description": "pan/mdg: Fix multiple spilt writes in the same bundle",
"nominated": true,
"nomination_type": 0,
"resolution": 0,
"resolution": 1,
"because_sha": null
},
{

View file

@ -884,6 +884,11 @@ mir_spill_register(
if (is_special_w)
spill_slot = spill_index++;
unsigned last_id = ~0;
unsigned last_fill = ~0;
unsigned last_spill_index = ~0;
midgard_instruction *last_spill = NULL;
mir_foreach_block(ctx, _block) {
midgard_block *block = (midgard_block *) _block;
mir_foreach_instr_in_block_safe(block, ins) {
@ -906,17 +911,19 @@ mir_spill_register(
mir_insert_instruction_after_scheduled(ctx, block, ins, st);
} else {
unsigned dest = spill_index++;
unsigned bundle = ins->bundle_id;
unsigned dest = (bundle == last_id)? last_spill_index : spill_index++;
unsigned bytemask = mir_bytemask(ins);
unsigned write_mask = mir_from_bytemask(mir_round_bytemask_up(
bytemask, 32), 32);
if (write_count > 1 && bytemask != 0xFFFF) {
if (write_count > 1 && bytemask != 0xFFFF && bundle != last_fill) {
midgard_instruction read =
v_load_store_scratch(dest, spill_slot, false, 0xF);
mir_insert_instruction_before_scheduled(ctx, block, ins, read);
write_mask = 0xF;
last_fill = bundle;
}
ins->dest = dest;
@ -928,7 +935,7 @@ mir_spill_register(
* of the spilt instruction need to be direct */
midgard_instruction *it = ins;
while ((it = list_first_entry(&it->link, midgard_instruction, link))
&& (it->bundle_id == ins->bundle_id)) {
&& (it->bundle_id == bundle)) {
if (!mir_has_arg(it, spill_node)) continue;
@ -943,9 +950,15 @@ mir_spill_register(
if (move)
dest = spill_index++;
midgard_instruction st =
v_load_store_scratch(dest, spill_slot, true, write_mask);
mir_insert_instruction_after_scheduled(ctx, block, ins, st);
if (last_id == bundle) {
last_spill->mask |= write_mask;
u_foreach_bit(c, write_mask)
last_spill->swizzle[0][c] = c;
} else {
midgard_instruction st =
v_load_store_scratch(dest, spill_slot, true, write_mask);
last_spill = mir_insert_instruction_after_scheduled(ctx, block, ins, st);
}
if (move) {
midgard_instruction mv = v_mov(ins->dest, dest);
@ -953,6 +966,9 @@ mir_spill_register(
mir_insert_instruction_after_scheduled(ctx, block, ins, mv);
}
last_id = bundle;
last_spill_index = ins->dest;
}
if (!is_special)