Skip to content

perf(shader): reuse normal-product NaN predicates - #16147

Open
Filip722 wants to merge 1 commit into
boykopovar:mainfrom
Filip722:perf/reuse-mul-nan-query-20261105
Open

Filip722 wants to merge 1 commit into
boykopovar:mainfrom
Filip722:perf/reuse-mul-nan-query-20261105

Conversation

@Filip722

@Filip722 Filip722 commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

What

Multiplication by a normal finite constant preserves its input's NaN classification once the existing source repair is applied. Later operations still recompute that classification from the repaired product, adding redundant GPU work.

  • Recognize the matching integer NaN query around a source-guarded normal-constant product and reuse its existing input predicate.
  • Preserve the multiply, payload repair and all other observers; reject exceptional factors, mismatched inputs and nonzero instruction flags.
  • Extend existing IR and arithmetic execution regressions with quieting, exceptional factors and a multiplication chain.

For a NaN input, the selected raw or quieted source remains NaN. For every other input, a normal finite nonzero factor cannot create an invalid zero-times-infinity product; overflow, underflow and denormal flushing cannot create NaN. The direct multiply and matching guard are required. This retains the existing normal-factor source repair and its payload behavior. Integer NaN checks remain in use.

The overlap tool could not merge #12324 for its shared-file comparison. Manual comparison found only its disjoint metadata replaced(info.exec) addition at the end of Eliminate; it does not implement this rule and creates no dependency.

Tested

Matched main/candidate Radeon checks cover arithmetic NaN payloads, quieting, add/multiply denormal modes, constant comparisons and denormal flushing, with the actual Khronos validation layer loaded and no new validation errors or skipped fixtures. The focused IR regression fails on main and passes with this change.

Sons of Sparta, same saved camp, 1920x1080 requested/render extent, journal enabled, immediate presentation, exact arithmetic and optimized GPL/LTO. The predeclared primary is GPU timestamped command-span milliseconds per delivered present over whole 1s intervals inside first-present+50..110s. Two separate prospective studies:

Study Main ms/present Change ms/present Paired reduction, 95% t CI
Fixed six-pair screen 10.081290 10.042350 0.386%, [0.234%, 0.538%]
One fresh four-pair confirmation 10.061245 10.035089 0.260%, [0.146%, 0.374%]

All 20 timed runs are valid, with none excluded or replaced. These are run-level pairs, not independent frames. This is a small command-span efficiency result while gameplay remains near 60 FPS; energy, uncapped FPS and a stutter improvement were not established. Frame tails and every valid slow run are retained.

Complete timing-only evidence, protocols, all full trace_digest.py outputs and hash/reproduction verifier. Both arms used the same disclosed minimal readiness/screenshot-request hook; private cost probes were disabled. Game data, shaders and screenshots remain private.

The required original 12s detailed-trace summaries from the first predeclared pair follow. These captures end before the primary 60s windows used above; all 20 full original traces and frame benches are in the linked bundle.

Main:

{"commit":"0eba5db30d8a","dirty":true,"env":{"APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_BENCH":"1","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"524288","APS5_TRACE_SECONDS":"30:12","APS5_TRACE_SUMMARY_EVERY":"1"},"gpu":"AMD Radeon 760M (RADV PHOENIX)","driver":"radv Mesa 25.0.7-2+deb13u1","os":"Linux 7.2.12-x64v3-xanmod1","cpu":"AMD Ryzen 5 7640HS w/ Radeon 760M Graphics","cpu_threads":12,"memory_mib":23820,"title_id":"PPSA28997","title":"God of War Sons of Sparta","content_version":"01.008.001","resolution":"1920x1080","window":{"spec":"seconds 30:12","first_present":1458,"ms":12011.993},"presents":720,"frame_ms":{"p50":16.684,"p90":16.692,"p99":16.701,"max":16.708},"gpu_busy_ms_per_present":9.978,"worker_busy_pct":{"queue worker 0x0":65.056},"top_phases_ms_per_frame":{"VideoOut.Flip":16.653,"VideoOut.Flip.vblank_wait":14.832,"Driver.Packet":10.775,"Driver.Packet.draw":8.955,"Driver.Draw":8.923,"Driver.Draw.device_setup":3.329,"Graphics.Draw":3.291,"Driver.Draw.draw_enqueued":2.985},"trace_dropped":false,"trace":"aps5-trace-0eba5db30d8a-2970427.json.gz"}

Change:

{"commit":"9c518277b4e2","dirty":true,"env":{"APS5_NO_PAD_INPUT":"1","APS5_PAD_INPUT_FILE":"<path>","APS5_TRACE_BENCH":"1","APS5_TRACE_DIR":"<path>","APS5_TRACE_EVENTS":"524288","APS5_TRACE_SECONDS":"30:12","APS5_TRACE_SUMMARY_EVERY":"1"},"gpu":"AMD Radeon 760M (RADV PHOENIX)","driver":"radv Mesa 25.0.7-2+deb13u1","os":"Linux 7.2.12-x64v3-xanmod1","cpu":"AMD Ryzen 5 7640HS w/ Radeon 760M Graphics","cpu_threads":12,"memory_mib":23820,"title_id":"PPSA28997","title":"God of War Sons of Sparta","content_version":"01.008.001","resolution":"1920x1080","window":{"spec":"seconds 30:12","first_present":1460,"ms":12011.999},"presents":720,"frame_ms":{"p50":16.683,"p90":16.692,"p99":16.700,"max":16.707},"gpu_busy_ms_per_present":9.957,"worker_busy_pct":{"queue worker 0x0":66.046},"top_phases_ms_per_frame":{"VideoOut.Flip":16.653,"VideoOut.Flip.vblank_wait":14.901,"Driver.Packet":10.944,"Driver.Packet.draw":9.098,"Driver.Draw":9.069,"Driver.Draw.device_setup":3.380,"Graphics.Draw":3.320,"Driver.Draw.draw_enqueued":2.903},"trace_dropped":false,"trace":"aps5-trace-9c518277b4e2-2971618.json.gz"}

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: AMD Radeon 760M, RADV Mesa 25.0.7-2+deb13u1, Debian Linux 7.2.12-x64v3-xanmod1
  • AI-assisted: yes

@github-actions github-actions Bot added the perf Performance change label Nov 5, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 9c51827 merged onto main 080dbd0 · tested 2026-11-05 19:47 UTC · 24 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,880 passed · 5 failed (0 new, 3 also fail on main, 2 unstable on main) · 52 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,937 of 4,077 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (970 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.3 s, ⚠️ agc_driver_indirect_thread_dimensions 36.1 s, ⚠️ agc_driver_interpolation_modes 31.0 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 2 of the last 10 main runs
agc_submit_progress: failed in 1 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (9 IDs in 588 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (588 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, and 580 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08739 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08741 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
Skipped (52)
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_device_capability: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_disabled: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_four_k: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_height_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_limit: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_malformed: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_width_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display 
Reproduce
git fetch origin 9c518277b4e2b9f7918424cd0c0131aadc0d4ece 080dbd08c6f83be5a1768af7d3342d701bf34d21
git checkout 080dbd08c6f83be5a1768af7d3342d701bf34d21 && git merge --no-ff 9c518277b4e2b9f7918424cd0c0131aadc0d4ece
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@github-actions github-actions Bot added shader core/shader agc libSceAgc* labels Nov 5, 2026
@JJenkx

JJenkx commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Independent Dusk Diver 2 / PPSA06565 check of exact head 9c518277b4e2b9f7918424cd0c0131aadc0d4ece on pinned main 7264864185f8455d30a11130a17d670a84fb7723; private integration e672a38463545c5438a467a760ca997f8cd1da26 contains only your three-file patch. Thanks for keeping the multiply/payload repair and rejecting exceptional factors.

Correctness and applicability: the same six focused NaN/denormal/RVE cases pass on both arms with required Vulkan, disabled shader caches and the real KHR validation layer (RX 6650 XT, RADV Mesa 26.2.6, Linux 7.2.11). Zero skips or VUIDs. All 42 private captured requests replay; 9 offline SPIR-V outputs change and 33 remain byte-identical. Total words 1276377→1274402; heavy shader 0x200f940000 is 66654→66519. Format 53's missing robustness target flags still limit offline/native equivalence, so those counts alone are not a native cost measurement.

No demonstrated Dusk speedup. The two observed pairs reverse sign:

Attempt Main FPS Change FPS Qualification
Exploratory 30s 12.3604 15.2636 Readiness focus differs; detailed trace buffers fill. Confounded.
Both windows unfocused, 10s 14.1746 11.2610 Focus sampled inactive throughout; both traces complete. Slower in this repeat.

FPS is (presents−1)*1000/window.ms. The complete 10s repeat has median 69.559→87.036ms and GPU 59.612→67.319ms/present. It does not establish a general regression: main had a pre-capture desktop-focus restoration delay, so settling time differed (scene readiness 136.48s/72.16s), and GPU clocks/power and unrelated desktop GPU load were not controlled. No progressing compiler/replay jobs were observed in the capture samples. I would not add the positive pilot as a speedup claim or select it over the negative repeat.

Both builds ran the same title-menu save-icon notice, 3840×2160 output, 974×548 window on the same monitor, separate private copied warmed caches/fresh save state, no FAST_F32. All other SDK components/relinker are pinned main; only the AGC driver and source-proof file differ. Before/after images were reviewed and match. No input or readback during capture; source/bank/cache/input integrity and kernel/mount cleanup checks pass.

Protocol disclosure: both arms additionally use documented APS5_TRACE_TRIGGER_FILE after verified readiness. This is an explicit exception to the form's blanket no-other-TRACE checkbox; no buffer-limit/profiler options are added. An initial candidate pre-capture harness attempt failed when optional active-window verification rejected an unfocused scene and navigated past it; it emitted no trace and is retained, rather than being counted as a result.

All four timing traces/digests, summaries, screenshots, focused test logs/JUnit, exact pins, protocols and attempt records, SHA-256 ea7d8f47e499c5300f208e6e7d43708864e3ec2989b6f89d864cdd7843a20369 (download verified). No requests, SPIR-V, guest binaries/saves or memory captures are included. No additional pairs selected for favorable results; further attribution needs a steadier scene/replication.

The main bundle includes all four measured traces and the failed pre-capture attempt. Its broad “all native attempt records” wording also requires this baseline warm-up record addendum, SHA-256 45a95bd6bc71d93596dcce0fac983ee55dd4f4475001bfb821a86a3bd930849c (download verified): successful original main warm-up result, report and frozen-bank manifest. Other startup/setup logs remain locally preserved.

The complete repeat's unmodified summary lines:

{"commit":"7264864185f8","dirty":false,"env":{"APS5_HOST_IMPORT_MIB":"16384","APS5_PAD_INPUT_FILE":"<path>","APS5_PLAYGO_UNLISTED_CHUNKS":"installed","APS5_TRACE_SECONDS":"10:10","APS5_TRACE_TRIGGER_FILE":"<path>"},"gpu":"AMD Radeon RX 6650 XT (RADV NAVI23)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 9 7950X 16-Core Processor","cpu_threads":32,"memory_mib":127901,"title_id":"PPSA06565","title":"Dusk Diver 2","content_version":"01.000.000","resolution":"3840x2160","window":{"spec":"seconds 10:10","first_present":2370,"ms":10017.907},"presents":143,"frame_ms":{"p50":69.559,"p90":74.634,"p99":80.77,"max":88.68},"gpu_busy_ms_per_present":59.612,"worker_busy_pct":{"queue worker 0x0":98.833,"queue worker 0x20":99.26},"top_phases_ms_per_frame":{"Driver.Packet":138.058,"Driver.Packet.memory_wait":62.902,"Recorder.Sync":35.662,"Driver.Packet.draw":16.752,"Driver.Draw":16.676,"Graphics.Draw":15.312,"Graphics.Draw.draw_and_resource_release":13.451,"Driver.Packet.dispatch":10.982},"trace_dropped":false,"trace":"aps5-trace-7264864185f8-1288353.json.gz"}
{"commit":"e672a3846354","dirty":false,"env":{"APS5_HOST_IMPORT_MIB":"16384","APS5_PAD_INPUT_FILE":"<path>","APS5_PLAYGO_UNLISTED_CHUNKS":"installed","APS5_TRACE_SECONDS":"10:10","APS5_TRACE_TRIGGER_FILE":"<path>"},"gpu":"AMD Radeon RX 6650 XT (RADV NAVI23)","driver":"radv Mesa 26.2.6-arch1.1","os":"Linux 7.2.11-arch1-1","cpu":"AMD Ryzen 9 7950X 16-Core Processor","cpu_threads":32,"memory_mib":127901,"title_id":"PPSA06565","title":"Dusk Diver 2","content_version":"01.000.000","resolution":"3840x2160","window":{"spec":"seconds 10:10","first_present":1293,"ms":10034.615},"presents":114,"frame_ms":{"p50":87.036,"p90":97.678,"p99":105.614,"max":117.946},"gpu_busy_ms_per_present":67.319,"worker_busy_pct":{"queue worker 0x0":98.948,"queue worker 0x20":99.235},"top_phases_ms_per_frame":{"Driver.Packet":173.648,"Driver.Packet.memory_wait":81.737,"Driver.Packet.draw":37.85,"Driver.Draw":37.766,"Graphics.Draw":35.326,"Graphics.Draw.draw_and_resource_release":33.31,"Recorder.Sync":31.6,"Driver.Draw.draw_enqueued":24.958},"trace_dropped":false,"trace":"aps5-trace-e672a3846354-1402523.json.gz"}

AI-assisted: yes (Codex).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* perf Performance change shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants