aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 15:44:48 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 15:44:48 -0400
commit82a5b520bc6dc4a77acca9b3ddd0bc577ada5676 (patch)
treee78d56756d7aa7b4ac4407b4c62fb205ac713529 /src
parent934ad3b97c12e1d40cf4e1f6094c756873b6af82 (diff)
Switch 2 shaders: MUFU.SIN/COS take turns, Eden's Maxwell MUFU radians
SM70+ removed RRO: compilers multiply the angle by 1/2pi (FMUL.RZ by 0.15915494) and MUFU.SIN/COS compute sin/cos(2pi x). Eden's Maxwell MUFU computes sin/cos of radians (its RRO is a plain move), so every lowered sine and cosine used the wrong angle (wind animation, rotations, the ocean FFT twiddles). Scale the operand by 2pi first.
Diffstat (limited to 'src')
-rw-r--r--src/shader_recompiler/frontend/ampere/lower_to_maxwell.h12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
index 1390951ef5..365efa1118 100644
--- a/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
+++ b/src/shader_recompiler/frontend/ampere/lower_to_maxwell.h
@@ -1732,16 +1732,26 @@ inline LoweredProgram LowerToMaxwell(std::span<const Instruction> code) {
case 0x308: case 0xb08: { // MUFU
const u32 operation = insn.Bits(74, 6);
if (operation > 8 || operation == 6 || operation == 7 || insn.Bits(80, 12)) return fail(index, "native MUFU mode");
+ // SM70+ MUFU.COS/SIN take the angle in turns (compilers multiply by 1/2pi first);
+ // Eden's Maxwell MUFU takes radians (its RRO is a plain move), so scale by 2pi.
+ const bool turns = operation == 0 || operation == 1;
+ const auto to_radians = [&](u32 source) {
+ emit(0x1e00000000000000ULL | predicate | 250 | (u64{source} << 8) |
+ (u64{0x40c90fdbU} << 20));
+ return 250U;
+ };
if (insn.Bits(73, 1)) {
if (opcode != 0x308 || insn.Bits(60, 2) > 1)
return fail(index, "native half special-function source");
emit(0x5ca8000000000000ULL | predicate | 250 | (u64{2} << 8) | (u64{1} << 10) |
(u64{insn.Bits(32, 8)} << 20) | (u64{insn.Bits(60, 1)} << 41) |
(u64{insn.Bits(63, 1)} << 45) | (u64{insn.Bits(62, 1)} << 49));
+ if (turns) to_radians(250);
emit(0x5080000000000000ULL | predicate | 250 | (u64{250} << 8) | (u64{operation} << 20));
emit(base(0x5ca8000000000000ULL) | (u64{1} << 8) | (u64{2} << 10) | (u64{250} << 20));
} else {
- const u32 src = operand(1);
+ u32 src = operand(1);
+ if (turns) src = to_radians(src);
emit(base(0x5080000000000000ULL) | (u64{src} << 8) | (u64{operation} << 20));
}
break;