aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-30 11:57:48 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-11-01 11:05:53 -0500
commit6e38b4c8fbb653eef82864a76127f04f4da4c394 (patch)
treee4cb15451d8982d0bd74505af2d9347e87ae84e6 /src
parentd88554cedb396863929dd31439dc8d4c92b367c8 (diff)
nx2: lower REDUX.OR and REDUX.XOR
The warp reduction was lowered for SUM and unsigned MAX; Kirby Air Riders reduces with OR. Inactive lanes contribute zero, as for the sum, so OR and XOR accumulate with LOP over the same 32-lane walk.
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/frontend/ampere/lower_to_maxwell.h9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
index b59118efa3..d81f6742b1 100644
--- a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
+++ b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
@@ -860,11 +860,13 @@ inline LoweredProgram LowerToMaxwell(std::span<const Instruction> code) {
restore_predicate();
break;
}
- case 0x3c4: { // REDUX.SUM (modulo 2^32) or .MAX (unsigned) over the actual active lanes.
+ 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;
+ // OR and XOR: inactive lanes contribute zero, as for the sum. Maxwell LOP: 1 = OR, 2 = XOR.
+ const u32 logical = insn.words[2] == 0x4000 ? 1U : insn.words[2] == 0x8000 ? 2U : 0U;
if (target == ~0U || target == 255 || insn.words[1] ||
- (insn.words[2] != 0xc000 && !maximum) || native_predicate != 7)
+ (insn.words[2] != 0xc000 && !maximum && !logical) || native_predicate != 7)
return fail(index, "native warp sum mode");
emit(0x50d8000000070000ULL | 250 | (u64{7} << 39) | (u64{7} << 45) | (u64{1} << 48));
mov_imm(target, 0);
@@ -877,6 +879,9 @@ inline LoweredProgram LowerToMaxwell(std::span<const Instruction> code) {
emit(0x5c40000000070000ULL | 251 | (u64{251} << 8) | (u64{252} << 20) | (u64{7} << 48));
if (maximum) {
emit(0x5c20000000070000ULL | target | (u64{target} << 8) | (u64{251} << 20) | (u64{15} << 39));
+ } else if (logical) {
+ emit(0x5c40000000070000ULL | target | (u64{target} << 8) | (u64{251} << 20) |
+ (u64{logical} << 41) | (u64{7} << 48));
} else {
emit(0x5c10000000070000ULL | target | (u64{target} << 8) | (u64{251} << 20));
}