Repository navigation
Conversation
|
Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.
|
CnRJay
left a comment
There was a problem hiding this comment.
The idea is sound (rebuilding specialized modules and binding plans on every launch lands on the queue worker during loading), and the key test covers each input. The evidence does not yet show the gain, and the cache has no bound.
- The two summary lines the description attaches point the other way in the window they cover: cache on 438 presents, p90 563 ms, p99 2145 ms,
Driver.Packet343 ms per frame; cache off 783 presents, p90 42 ms, p99 1368 ms,Driver.Packet186 ms per frame. The description explains that the windows cover different parts of loading, which is the problem: they can't be compared. The "119 s against 138 s to the menu" is one pair read off the 10 s intervals, and the earlier runs it cites (83-112 s on, 105-159 s off) overlap. The cache-on trace also lost 344,091 worker events after 35 s (trace_dropped: true). Please post a pair that covers the same stretch (start the window at the same title milestone, e.g. the first menu present, and run to a fixed time after it), a second pair to show the spread, and traces that are whole (APS5_TRACE_EVENTS). - The key includes the captured descriptors and the specialization constants, so a title whose descriptors vary writes a new entry for every distinct combination. Nothing bounds the number or size of these entries or evicts them. Post the entry count and size on disk after the Stellar Blade runs, and add a cap with eviction before this lands, otherwise the shader cache grows with play time.
- Disk cache format 37 is also taken by the rebased #5656 (
SrtUserDataUse) and by JJenkx's refresh of it, and #6947 uses 38. Whoever lands second has to renumber; say which this PR expects to follow. - The test covers store, load, damaged and truncated records. It does not cover a base artifact that changes under the same specialization inputs (the key is the base digest, so it should miss): add that case.
6b77e05 to
80a6016
Compare
|
Bound on the entries. Added. Specialized module and binding-plan entries are capped by Tests: A base artifact that changes under the same specialization inputs. Added Format number. It stays 37 for now. If #5656 lands first, this PR moves to 38, or to 39 if #6947 also lands. The only literal is Tests: |
|
From reading the diff: the disk load and store wrap That is the case raised in the Demon's Souls discussion #1283: 351 specialized modules rebuilt on every launch, about 60 s on Linux NVIDIA with the tools off, where the persistent cache in another branch only covered the tools-on path. A cold and a warm tools-off launch of that title would confirm it. I haven't measured it yet. AI-assisted: yes |
d77d30a to
19054f1
Compare
|
Rebased onto The disk cache format stays at 37. #5656 and #6947 are still open, so the renumbering plan from my earlier comment still applies. @Sam-mon7, correct. Neither @CnRJay, the matched pairs you asked for are still to come: two pairs of cache on and off, each starting at the first menu present and running a fixed time after it, with whole traces. I'll post them in a separate comment. The code is ready for review in the meantime. |
|
Tested on Onimusha's menu: no measurable change in this scene. Setup: Onimusha: Way of the Sword (PPSA27836), boot to the language menu with no input,
This scene may simply not exercise the path this PR speeds up. Summary lines and traces available on request. AI-assisted: yes. |
19054f1 to
3483ed2
Compare
|
Rebased onto The only conflict was that line. @simonbronk, thanks for the Onimusha numbers. A language menu right after boot probably compiles few specialized modules, so no change there is expected. The gain shows up when a title loads its scenes on a second launch. @CnRJay, the matched pairs follow in a separate comment. |
|
@CnRJay, matched runs of this branch at 3483ed2 (rebased onto The first 60 s after the first present are a loading stretch whose frame count swings in both settings (1204, 640, 710 and 663 presents), so the comparison below is 60–240 s from the first present, where all four runs show the same scenes in the same order. Numbers are from the present events and slices in the traces.
The four traces and their Windows 11, AMD Radeon RX 9070 XT, AMD 26.8.1 (LLPC), 3840×2160. |
3483ed2 to
2a816b6
Compare
2a816b6 to
98c84f6
Compare
…er disk cache Specialized modules and their binding plans were rebuilt on every launch even with a warm disk cache. They are now stored next to their base artifact, keyed by its digest plus the exact specialization inputs, and loaded on a warm start; a key mismatch or corrupt record rebuilds. The disk cache format goes to 37. APS5_NO_SPECIALIZED_DISK_CACHE=1 turns it off. The [shader-disk-cache] line reports specialized module and binding plan hits, misses and writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…viction Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ment reference Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…der's DescriptorBinding assert Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… specialized disk cache The specialized module and binding plan entries are keyed by the base artifact's identity, which only findOrCompileVariant fills. Variants compiled with useCache=false (recompileOnce, and RecompileImpl without a cached source) kept an all-zero identity, so every such compile read and wrote the same entries whatever the shader or target. The identity is now empty unless the variant has a disk key, and specializedDiskCache refuses an empty one. The new --uncached-specialized mode compiles one shader twice without the cache, with and without RoundingModeRTE, and requires that the second compile gets its own module and that nothing is stored. After the rebase onto main, the DescriptorBinding encoder assert counts 24 fields and the sameBinding round trip compares imageAtomic64. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e822824 to
d36ab7d
Compare
|
I tested d36ab7d on GTA III, PPSA03527/01.003.000, and found repeated specialization misses that may be worth fixing here. After warming the cache, a separate diagnostic launch reported 57 specialized-module hits and 9 misses/writes, with no load or write failures. All nine newly written records already had an older record with the same base-artifact identity and every other specialized-key field, except
The existing cache does work. The same eight focused test cases pass on both sides. The candidate also passes its cache round trips, changed-base-artifact, corruption, bounds and uncached different-target regressions. The real Khronos validation layer was loaded for the GPU case, with no new errors or skips. Host: RTX 3060 Laptop, NVIDIA 617.42, Windows 10.0.26300, i5-11400H, 32 GiB RAM. The two alternating pairs of complete 20-second automatic-startup traces do not establish an overall speedup. Baseline maximum frame intervals were 4263/4314 ms; with this PR, 4065/4745 ms. All four traces had no dropped events and 61 verified loaded PRXs. Both sides used main 7526640 plus the same deferred-settle correction from #8527; only this PR differed. These are opening-startup observations, not gameplay or a claim that the initial long interval is a shader stall. Update after a local regression and original-title check: changing only the guarded-image descriptor snapshot in a second process reproduces 16 module hits and 1 unnecessary miss/write on the unchanged implementation, although the result matches an uncached compile. Removing The same original GTA III startup, after warming the new cache normally, now reports 66 specialized hits, zero misses and zero new module records, versus 57 hits/9 misses before. All 66 module payloads match payloads already produced by the previous build. Both runs verified 61 loaded PRXs and unchanged original files. The corrected build passes the same eight native cases with the real Khronos layer, no validation errors or skips, plus the new cross-process regression. This proves removal of redundant specialization, not a loading-time or FPS gain. The focused local patch and failing/passing regression are ready for coordination here. Prepared with AI assistance. |
…t in the background The specialized entries under <entries>/specialized grew without a bound and were compressed and written on the thread that built them (the queue worker or a specialization worker). - A background writer compresses and writes each new entry. - An in-memory LRU index (rebuilt from file write times at first use; a hit stamps its file) evicts the least recently used entries past APS5_SPECIALIZED_DISK_CACHE_ENTRIES (65536) or APS5_SPECIALIZED_DISK_CACHE_MAX_MIB (2048), the defaults of upstream boykopovar#6924. - Temp files older than 10 minutes, left by a write the process exit cut off, are removed at the first scan. - One stderr line per 10 s with activity: hits, misses, writes, evictions and the entries held against the caps. - ShaderDiskCache::Flush also waits for the specialized writer. agc_shader_disk_cache_tests hung in its final remove_all: libstdc++ 15.2 kept stat-ing a .tmp. entry the writer had renamed after the listing. Checked: agc_shader_disk_cache_tests and the sin/cos tests pass; agc_shader_replay stores one entry, loads it in a second process with identical SPIR-V, keeps 1 file with APS5_SPECIALIZED_DISK_CACHE_ENTRIES=1 and two shaders, and removes a 1-hour-old temp file while keeping a fresh one. Not measured in game yet.
Integrate PR boykopovar#6924 at d36ab7d and preserve the local image-read and sampler-LOD metadata in cached binding plans. Keep uncached variants outside the persistent cache and bound specialized entries independently of base shader artifacts. Validation: the same 10 focused shader and pipeline tests pass on origin/main d01070d and this integration with required Vulkan and the Khronos validation layer, with no VUID errors. The GT7 warm launch loads specialized modules across processes; matched cache-disabled timing remains under test. Refs boykopovar#6924 Co-authored-by: umang <sheoranumang@gmail.com>
Integrate PR boykopovar#6924 at d36ab7d and preserve the local image-read and sampler-LOD metadata in cached binding plans. Keep uncached variants outside the persistent cache and bound specialized entries independently of base shader artifacts. Validation: the same 10 focused shader and pipeline tests pass on origin/main d01070d and this integration with required Vulkan and the Khronos validation layer, with no VUID errors. The GT7 warm launch loads specialized modules across processes; matched cache-disabled timing remains under test. Refs boykopovar#6924 Co-authored-by: umang <sheoranumang@gmail.com>
What
Runtime-specialized shader modules and their binding plans were rebuilt on every launch, even with a warm shader disk cache. They are built on the queue worker when a draw or dispatch first needs them, so the rebuild lands on the critical path while a title loads.
They are now stored in the shader disk cache next to their base artifact, keyed by the base artifact's digest plus the exact specialization inputs, and loaded on a warm start. A missing, differently keyed or damaged record is rebuilt. The disk cache format goes to 41.
APS5_NO_SPECIALIZED_DISK_CACHE=1turns it off. The[shader-disk-cache]line reports specialized module and binding plan hits, misses and writes.The specialized records are bounded.
APS5_SPECIALIZED_DISK_CACHE_ENTRIES(default 65536) andAPS5_SPECIALIZED_DISK_CACHE_MAX_MIB(default 2048) cap them together, and the least recently used specialized record is deleted when either limit is exceeded, after each specialized write and once at start. Base artifacts and resource plans are never evicted.0keeps none, the same asAPS5_NO_SPECIALIZED_DISK_CACHE=1. Both switches are neutral to the cache key and documented indocs/user/USAGE.md; the defaults are guesses, recorded indocs/dev/debt/shader.md. The start-up[shader-disk-cache]line prints the specialized entry count and size on disk, and the 10 s line reports evictions.A variant compiled without going through
findOrCompileVariant(useCache=false:recompileOnce, andRecompileImplwithout a cache or capture source) has no disk key.CompiledVariant::artifactIdentityis now empty for such a variant instead of zero-filled, andspecializedDiskCachereturns false unless the identity has the full artifact-identity length. Those compiles neither read nor write specialized entries, so two of them with different targets can no longer share one zero-keyed module or binding plan.Tested
Windows 11 Pro 10.0.26300, MinGW Release build, AMD Radeon RX 9070 XT, AMD proprietary driver 26.8.1 (LLPC), 3840x2160. Stellar Blade (PPSA13197). Builds:
main95d901b and this branch rebased on it (e822824); the branch also merges cleanly withmaindbac9fa. Both builds staged as whole library sets, swapped between runs, the embedded commit checked in each summary line. Captures as the Performance report form describes: warm shader and pipeline caches (each cache key ran the scene first), same scene and settings, one session, three runs per build back to back, noAPS5_PROFILE_*switch. Deviations from the form:APS5_TRACE_EVENTS=4194304is set because the default 262144 events per thread fill in about 11 s on the busiest queue worker of this title; stdout and stderr were written to files.Loading: first 90 s from the first present (
APS5_TRACE_SECONDS=0:90): main menu, save load and story start. Specialized time is the sum ofShader.DrawStage.materialize,Driver.Draw.shader_compile_and_linkandDriver.Dispatch.materializeslices in each trace.With the specialized records read from disk (runs 5 and 6), specialized time falls from 19.6-20.0 s to 7.6-8.4 s and the longest loading stall from 15.9-16.6 s to 13.7-14.0 s. Run 4, the first launch after the build switch, read 1041 specialized records but spent 21.2 s, more than main, with 5.4 s in
Shader.PrepareArtifact; it was the first read of that cache directory in the session. Presents and frame percentiles do not improve in this window: the menu runs at its 32 fps cap and the loading frames are dominated byDriver.Packet.memory_waitin both builds. Each run still writes 66-91 new specialized records, so the directory keeps growing (17132 to 19627 entries over the three runs).Steady play: 60-210 s from the first present (
APS5_TRACE_SECONDS=60:150), same machine and session, to check for a regression: main 1417 / 1364 / 1778 presents (9.44 / 9.09 / 11.85 fps), this PR 1755 / 1778 / 1388 (11.70 / 11.85 / 9.25 fps). The spread between runs of one build is larger than the difference between builds; no regression.Summary lines (runs 3 and 6):
{"commit":"95d901b9371f","dirty":false,"env":{"APS5_CONTINUE_AFTER_FLIP_FAILURE":"1","APS5_FLAT_3D_COLOR_TARGET":"1","APS5_HOST_IMPORT_MIB":"16384","APS5_PAD_INPUT_FILE":"<path>","APS5_PREBUILD_THREADS":"16","APS5_TRACE_EVENTS":"4194304","APS5_TRACE_SECONDS":"0:90"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.8.1 (LLPC)","os":"Windows 10.0.26300","resolution":"3840x2160","window":{"spec":"seconds 0:90","first_present":0,"ms":90015.371},"presents":1108,"frame_ms":{"p50":31.386,"p90":133.159,"p99":562.207,"max":15963.420},"gpu_busy_ms_per_present":25.991,"worker_busy_pct":{"queue worker 0x0":87.342,"queue worker 0x20":65.636},"top_phases_ms_per_frame":{"Driver.Packet":123.855,"Driver.Packet.memory_wait":49.825,"Graphics.Draw":31.030,"Graphics.Draw.draw_and_resource_release":26.082,"VideoOut.Flip":24.079,"Driver.Present":23.980,"VideoOut.Flip.present":23.974,"Driver.Present.acquire_image":23.243},"trace_dropped":false,"trace":"aps5-trace-95d901b9371f-6884.json.gz"} {"commit":"e822824b83ce","dirty":false,"env":{"APS5_CONTINUE_AFTER_FLIP_FAILURE":"1","APS5_FLAT_3D_COLOR_TARGET":"1","APS5_HOST_IMPORT_MIB":"16384","APS5_PAD_INPUT_FILE":"<path>","APS5_PREBUILD_THREADS":"16","APS5_TRACE_EVENTS":"4194304","APS5_TRACE_SECONDS":"0:90"},"gpu":"AMD Radeon RX 9070 XT","driver":"AMD proprietary driver 26.8.1 (LLPC)","os":"Windows 10.0.26300","resolution":"3840x2160","window":{"spec":"seconds 0:90","first_present":0,"ms":91383.375},"presents":1028,"frame_ms":{"p50":31.543,"p90":150.496,"p99":705.882,"max":13661.595},"gpu_busy_ms_per_present":26.949,"worker_busy_pct":{"queue worker 0x0":87.391,"queue worker 0x20":68.124},"top_phases_ms_per_frame":{"Driver.Packet":137.629,"Driver.Packet.memory_wait":56.181,"Graphics.Draw":39.495,"Graphics.Draw.draw_and_resource_release":33.229,"Driver.Packet.draw":21.546,"Driver.Draw":21.484,"VideoOut.Flip":20.939,"Driver.Present":20.838},"trace_dropped":false,"trace":"aps5-trace-e822824b83ce-16792.json.gz"}Traces,
trace_digest.pyoutput and summary lines of all twelve captures (load-1 to load-6 and play-1 to play-3 per build): https://github.com/moong15/AnyPS5/releases/tag/pr6924-evidenceTests, all on the same machine and GPU,
ctest -V -j1withANYPS5_REQUIRE_VULKAN=1,ANYPS5_NO_SHADER_CACHE=1andVK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, onmainand on this branch:agc_shader_disk_cache,agc_float16_conversion,agc_denormal_flush_elimination,agc_shader_control_flow,agc_wave_control_decode,agc_driver_f16_denormal_flush,agc_driver_f32_denormal_flush: 7/7 pass on both. Neither log reportswas not found but was requested by env var VK_INSTANCE_LAYERS; neither log has aVUID-line.agc_shader_disk_cachenow also runs a child process (--uncached-specialized) that compiles twice withuseCache=falsefor a device with and one withoutRoundingModeRTEagainst one cache directory, and requires no specialized or binding-plan hit, miss or write and no stored entry. With the identity change reverted it fails: "Recompile(request) with useCache=false for a device without RoundingModeRTE was served the module compiled for a device with it (specialized hits 1, misses 1, writes 1; binding plan hits 1, misses 1, writes 1 ...)".ANYPS5_NO_SHADER_CACHE:agc_float16_conversion_testsinto an empty directory, andagc_shader_control_flow_tests,agc_wave_control_decode_tests,agc_denormal_flush_elimination_testsinto one directory, each with the specialized cache on and withAPS5_NO_SPECIALIZED_DISK_CACHE=1: all pass, and nospecialized-*file is written.agc_shader_disk_cachealso covers store, load, damaged and truncated records,APS5_NO_SPECIALIZED_DISK_CACHE=1, the entry cap (an evicted record misses and is rebuilt, a recently used one survives), the byte cap, a malformed and a zero cap value, a base artifact that changes under the same specialization inputs, and theDescriptorBindinground trip includingimageAtomic64.Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code