Repository navigation
perf(shader): choose the fma NaN result only when the result is NaN - #2279
Merged
adriadam10 merged 1 commit intoOct 10, 2026
Merged
Conversation
boykopovar#2083 chooses the NaN result of the f32 fma family on the bits: the first NaN source, quieted in IEEE mode, with the addend skipped when the product is infinity times zero, and 0xffc00000 otherwise. The selection and the infinity-times-zero test ran for every fma, but a NaN source always gives a NaN result, so for any other result they return it unchanged. FPNanResultFma32 carries the result and the three sources, with the IEEE mode as a flag. The SPIR-V emitter makes the selection, including the infinity-times-zero test, in a branch taken only for a NaN result, and the SRT evaluator computes it exactly. Add, sub and mul keep the inline selects: with two sources a branch costs more than it saves.
9 tasks done
This was referenced Oct 10, 2026
Collaborator
|
Checked on Linux (RADV wave64 and CI's lavapipe): |
9 tasks done
oneandonlydean
added a commit
that referenced
this pull request
Oct 10, 2026
#2279 made agc_driver_f32_arithmetic_nan fail on NVIDIA (Windows): v_fmamk_f32 returns a quiet NaN where the signalling one is expected (lane 1 no float mode v_fmamk_f32 is 0x7fc12345, expected 0x7f812345), 5/5 runs on main and 5/5 passing with #2279 reverted. CI's Windows job skips the AGC execution tests, so it did not show there. v_fma_legacy was rewritten as a split multiply and add after #2279; it keeps that and gets back the invalid-product argument it passed before. Fixes #2581
oneandonlydean
added a commit
that referenced
this pull request
Oct 10, 2026
revert(shader): undo #2279's fma NaN result selection
SleglJan
pushed a commit
to SleglJan/AnyPS5
that referenced
this pull request
Oct 10, 2026
…-result-guard perf(shader): choose the fma NaN result only when the result is NaN
SleglJan
pushed a commit
to SleglJan/AnyPS5
that referenced
this pull request
Oct 10, 2026
boykopovar#2279 made agc_driver_f32_arithmetic_nan fail on NVIDIA (Windows): v_fmamk_f32 returns a quiet NaN where the signalling one is expected (lane 1 no float mode v_fmamk_f32 is 0x7fc12345, expected 0x7f812345), 5/5 runs on main and 5/5 passing with boykopovar#2279 reverted. CI's Windows job skips the AGC execution tests, so it did not show there. v_fma_legacy was rewritten as a split multiply and add after boykopovar#2279; it keeps that and gets back the invalid-product argument it passed before. Fixes boykopovar#2581
SleglJan
pushed a commit
to SleglJan/AnyPS5
that referenced
this pull request
Oct 10, 2026
revert(shader): undo boykopovar#2279's fma NaN result selection
9 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Follow-up to #2083.
nanResultF32chooses the NaN result ofv_add/sub/mul_f32and of the f32 fma family (v_fma/fmac/fmamk/fmaak_f32,v_fma_mix_f32with f32 sources) on the bits: the first NaN source, quieted in IEEE mode, and0xffc00000when no source is a NaN; for the fma family the addend is skipped when the product is infinity times zero. That selection and the infinity-times-zero test run for every op, but a NaN source always gives a NaN result, so for any result that isn't a NaN they return the result unchanged.For the fma family:
FPNanResultFma32(result, lhs, rhs, addend), with the IEEE mode as its flag.nanResultF32emits it for three sources, soinvalidProductF32moves into the emitter.MaskedSelectEliminatortreats it as lane-local likeFPFma32.Add, sub and mul keep #2083's inline selects. With two sources the selection is cheap, and the branch costs more than it saves on NVIDIA: with the same branch for all four, a dependent chain of 1024
v_add_f32went from 8.87 to 12.09 ms (best of 4 alternated runs) andv_mul_f32showed no clear gain, whilev_fma_f32went from 25.5 to 19.1 ms.Results are bit-identical.
Tested
Windows 11, MinGW-w64 GCC 15.2.0 (WinLibs r7), Release,
ANYPS5_ENABLE_SPIRV_TOOLS=ON,mainat d70b899. GPU tests on an NVIDIA GeForce RTX 4060 Laptop GPU (591.86, subgroup 32) and on lavapipe (Mesa 26.2.4 for Windows,GALLIUM_OVERRIDE_CPU_CAPS=avx).agc_driver_f32_arithmetic_nan(feat(shader): choose f32 arithmetic NaN results on the bits #2083's rows measured on hardware, with signaling and quiet payloads, infinity times zero with a NaN addend, IEEE=0 and IEEE=1) passes on both devices, as doagc_driver_f32_denormal_flush,agc_driver_f32_output_modifier,agc_driver_f32_min_max_nan,vector_fused_multiply_add,vector_mad_legacy,agc_shader_memoryandagc_masked_select.New
vector_fma_nan_result:v_fma_f32andv_fmac_f32emit oneFPNanResultFma32with the IEEE flag of the float mode,v_add_f32none; the SRT evaluator keeps a number result, picks the first NaN source, quiets it in IEEE mode, skips the NaN addend of infinity times zero and keeps it for infinity times infinity.Negative checks, each reverted:
agc_driver_f32_arithmetic_nanfails on both devices (lane 10 no float mode v_fma_f32 is 0x7fc00003, expected 0xffc00000).lane 0 IEEE=1 v_fma_f32 is 0x7f812345, expected 0x7fc12345).vector_fma_nan_resultfails (a NaN addend of an invalid product is not ignored).Full ctest after
cmake --build buildand--target libs, serial,--timeout 120, RTX 4060: 490 pass, 2 skip (agc_driver_storage_cache_budget,guest_video_out_wqhd_detection_no_vulkan), 19 fail. The 19 are relinker tests: during the run Windows Defender quarantined the freshly builtbuild/core/relinker/relinker.exe(and, as on perf(shader): skip the tiny product check that a constant factor settles #2020, an executabletls_function_coveragewrites), so every relinker test after it failed to start it ([WinError 225] ... contains a virus or potentially unwanted software). The relinker's build contains no recompiler sources.Per op in
FLOAT_MODE0xc0 on the RTX 4060 (pipeline statistics of a compute program with a dependent chain of 8 ops, not committed):v_fma_f32goes from 38 to 41 instructions and from 33 to 30 registers, since the selection stays in the branch;v_add_f32(14) andv_mul_f32(30) are unchanged. Without any NaN selectionv_fma_f32would be 25.Throughput on the RTX 4060, not committed: a dependent chain of 1024 ops on registers, 65535 workgroups of 32, timed per dispatch including submit and wait, main and this branch alternated over 4 runs (best / run medians):
FLOAT_MODE0xc0v_fma_f32v_add_f32v_mul_f32v_add_f32andv_mul_f32compile to the same code on both; their spread is this laptop's run-to-run variation. Without any NaN selectionv_fma_f32takes 16.7 ms. The outputs are bit-identical (same checksum).Touches
TranslationContext.hppandOperandAccess.cppnext to #2035 (quietNan64), in other declarations and functions.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)