aboutsummaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 11:46:42 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 11:05:48 -0500
commit567aaa3e88244162c083bc525f13db40cdd2cce1 (patch)
tree7beaa65b0f9e2dacc588851a9ee1a134525eb01b /src/shader_recompiler
parentfa1f6b1d7ba4f880821802f88fe48cd9d01e1f50 (diff)
nx2: lower 32-bit MATCH.ALL
Only MATCH.ALL.U64 was lowered; Nintendo Switch Sports Resort and Kirby Air Riders use the 32-bit form (MATCH.ALL P0, RZ, Rx) in compute and pixel shaders. Compare one word instead of two.
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/frontend/ampere/lower_to_maxwell.h15
1 files changed, 9 insertions, 6 deletions
diff --git a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
index 4cc2d0eb84..9a5b55033b 100644
--- a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
+++ b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
@@ -836,23 +836,26 @@ inline LoweredProgram LowerToMaxwell(std::span<const Instruction> code) {
emit(0x3828000000000000ULL | predicate | (dest + 216) | (u64{insn.words[1] + 216} << 8) |
(u64{1} << 39) | (u64{1} << 40));
break;
- case 0x3a1: { // MATCH.ALL.U64 with only the all-equal predicate retained.
+ case 0x3a1: { // MATCH.ALL (.U32, or .U64 on bit 73) with only the all-equal predicate retained.
const u32 source = insn.Bits(24, 8), target = insn.Bits(81, 3);
- if (dest != 255 || source >= 254 || (source & 1) || target >= 6 ||
- native_predicate != 7 || insn.words[1] || (insn.words[2] & ~0xe0000U) != 0x200)
+ const u32 words = insn.Bits(73, 1) ? 2 : 1;
+ if (dest != 255 || source >= 254 || (words == 2 && (source & 1)) || target >= 6 ||
+ native_predicate != 7 || insn.words[1] || (insn.words[2] & ~0xe0200U) != 0)
return fail(index, "native warp match mode");
save_predicate();
+ // Compare every lane with the lowest active one, then require all to agree.
emit(0x50d8000000070000ULL | 250 | (u64{7} << 39) | (u64{7} << 45) | (u64{1} << 48));
emit(0x5c10000000070000ULL | 251 | (u64{250} << 8) | (u64{255} << 20) | (u64{1} << 49));
emit(0x5c40000000070000ULL | 250 | (u64{250} << 8) | (u64{251} << 20) | (u64{7} << 48));
emit(0x5c30000000070000ULL | 250 | (u64{250} << 20));
- for (u32 word = 0; word < 2; ++word)
+ for (u32 word = 0; word < words; ++word)
emit(0xef10000000070000ULL | (251 + word) | (u64{source + word} << 8) |
(u64{250} << 20) | (u64{1} << 29) | (u64{31} << 34) | (u64{7} << 48));
emit(0x5b60000000070000ULL | 7 | (u64{6} << 3) | (u64{source} << 8) |
(u64{251} << 20) | (u64{7} << 39) | (u64{2} << 49));
- emit(0x5b60000000070000ULL | 7 | (u64{6} << 3) | (u64{source + 1} << 8) |
- (u64{252} << 20) | (u64{6} << 39) | (u64{2} << 49));
+ if (words == 2)
+ emit(0x5b60000000070000ULL | 7 | (u64{6} << 3) | (u64{source + 1} << 8) |
+ (u64{252} << 20) | (u64{6} << 39) | (u64{2} << 49));
emit(0x50d8000000070000ULL | 255 | (u64{6} << 39) | (u64{target} << 45));
restore_predicate();
break;