From 338674fda9e2ef0495d184691aed5ffe605e42ea Mon Sep 17 00:00:00 2001 From: Icecream95 Date: Fri, 10 Dec 2021 23:51:06 +1300 Subject: [PATCH] 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: (cherry picked from commit c65afe541b764a75da68b6bf83aca60d72f88916) --- .pick_status.json | 2 +- src/panfrost/midgard/midgard_ra.c | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 73463f9fb38..545b2fea478 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -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 }, { diff --git a/src/panfrost/midgard/midgard_ra.c b/src/panfrost/midgard/midgard_ra.c index 28d195553e3..802d983514b 100644 --- a/src/panfrost/midgard/midgard_ra.c +++ b/src/panfrost/midgard/midgard_ra.c @@ -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)