aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 11:57:50 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 11:08:07 -0500
commitb52f29993f4a9b18b153860fb3da8ef7db73eaf2 (patch)
tree4f1304dfcab909fcb3996c5f6988bd465645214c /src
parent572c89d7134691a36395cd469dc89b4ae0924fc1 (diff)
nx2: lower CSMTEST as a false test
Kirby Air Riders' vertex-side shaders run CSMTEST, a test of shading-mode state Eden does not model, then exit early when it holds ("CSMTEST.A. FCSM_TR P0; @P0 EXIT"); another discards its result. Set its predicate outputs to false, so these shaders run through instead of being rejected.
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/frontend/ampere/lower_to_maxwell.h12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
index a982312ae9..a7800bdea1 100644
--- a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
+++ b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
@@ -860,6 +860,18 @@ inline LoweredProgram LowerToMaxwell(std::span<const Instruction> code) {
restore_predicate();
break;
}
+ case 0x80d: { // CSMTEST: a test of shading-mode state Eden does not model, taken as false.
+ // Kirby Air Riders' vertex-side shaders run "CSMTEST.A.FCSM_TR P0" then "@P0 EXIT":
+ // never leave early. Outputs of PT discard the result.
+ const u32 first = insn.Bits(81, 3), second = insn.Bits(84, 3);
+ if (insn.Bits(87, 4) != 7 || insn.Bits(16, 16))
+ return fail(index, "native CSM test mode");
+ for (const u32 target : {first, second})
+ if (target != 7)
+ emit(0x5090000000000000ULL | predicate | (u64{target} << 3) | 7 | (u64{7} << 12) |
+ (u64{1} << 15) | (u64{7} << 29) | (u64{7} << 39));
+ break;
+ }
case 0x3c4: { // REDUX.SUM (modulo 2^32), .MAX (unsigned), .OR or .XOR over the actual active lanes.
const u32 source = insn.Bits(24, 8), target = uniform_register(static_cast<u32>(dest));
const bool maximum = insn.words[2] == 0x14000;