diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 15:44:48 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-28 15:44:48 -0400 |
| commit | 82a5b520bc6dc4a77acca9b3ddd0bc577ada5676 (patch) | |
| tree | e78d56756d7aa7b4ac4407b4c62fb205ac713529 | |
| parent | 934ad3b97c12e1d40cf4e1f6094c756873b6af82 (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.
| -rw-r--r-- | src/shader_recompiler/frontend/ampere/lower_to_maxwell.h | 12 |
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; |
