summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIcecream95 <ixn@disroot.org>2021-12-10 23:51:06 +1300
committerDylan Baker <dylan.c.baker@intel.com>2022-05-10 21:23:14 -0700
commit5b82328bbdb2ac179a7507f6ea1332da7c5139c6 (patch)
treec20881a6c587cfa43ffc75ab9759f5a2e07a9205
parent7c24f4fbc9148a3810d48cadcd99d3c69992408f (diff)
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 c65afe541b764a75da68b6bf83aca60d72f88916)
-rw-r--r--.pick_status.json2
-rw-r--r--src/panfrost/midgard/midgard_ra.c28
2 files changed, 23 insertions, 7 deletions
diff --git a/.pick_status.json b/.pick_status.json
index 2ad46bb2382..14e5dd73fe5 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -652,7 +652,7 @@
"description": "pan/mdg: Fix multiple spilt writes in the same bundle",
"nominated": true,
"nomination_type": 0,
- "resolution": 0,
+ "resolution": 1,
"main_sha": null,
"because_sha": null
},
diff --git a/src/panfrost/midgard/midgard_ra.c b/src/panfrost/midgard/midgard_ra.c
index dea96086948..d493f4219e3 100644
--- a/src/panfrost/midgard/midgard_ra.c
+++ b/src/panfrost/midgard/midgard_ra.c
@@ -922,6 +922,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) {
@@ -944,17 +949,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;
@@ -966,7 +973,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;
@@ -981,9 +988,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);
@@ -991,6 +1004,9 @@ mir_spill_register(
mir_insert_instruction_after_scheduled(ctx, block, ins, mv);
}
+
+ last_id = bundle;
+ last_spill_index = ins->dest;
}
if (!is_special)