Repository navigation
perf(shader): evict prepared SPIR-V to its disk cache entry - #3247
ponhei9502 wants to merge 1 commit into
Conversation
Every prepared artifact kept its SPIR-V words resident in the process-wide source registry, although they are read again only to build a specialised module or to be copied into a result. The same words are in the shader disk cache entry. SharedSpirv can now hold a backing instead of the words. After the disk cache writer has written an entry and checked that the file holds the artifact's words byte for byte, it evicts them in favour of a file backing (entry path, key size, word count, file size); a cache hit evicts right after decoding. - Pin() returns the words for as long as the returned pointer lives and reads them back from the entry when they were evicted, without keeping them. - Words() makes them resident again and marks the holder so a later eviction is refused, because callers keep the reference. - A copy reads the words back and is never evicted, so a RecompileResult the driver holds stays resident as before. - The reload applies the checks Load applies (magic, format, source version, key size, payload size and hash) and the stored word count; a missing or altered entry throws. All SharedSpirv state is guarded by one mutex that is not held while a file is read. The entry format is unchanged. Nothing is evicted when the disk cache is off or when APS5_NO_PERF_SPIRV_EVICTION is set. CompiledShaderArtifact and RecompileResult grow by 24 bytes (the backing pointer and the flag); the size assertions follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thank you for your interest in the project! We are sorry, but we cannot accept more PRs while we work through the existing backlog. This PR has been automatically closed and labeled "intake paused". This is not a judgment of the quality of your changes. |
|
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.
|
|
Thanks for reopening this. It no longer merges cleanly into current main: Recompiler.hpp has moved since this was written. Could you rebase onto current main? Evicting prepared SPIR-V is still wanted (main keeps it resident). We'll review and run full CI on the new head. |
|
Closing this as superseded by #4806 (merged 14 Oct, 43349d4, "map retained SPIR-V from shader cache entries"). On A correction to our 17 Oct comment: we said Thanks @ponhei9502 for the work on this. If you see a case #4806 doesn't cover, please open a new PR against current |
Adapt the disk-entry backing idea from ponhei9502/AnyPS5 PR boykopovar#3247 (36307ed) to shared storage. Verify the encoded entry and original words through an owned file handle before releasing RAM or spool backing, preserving exposed borrows and exact transient reads. Gate adoption with APS5_CACHE_SPIRV_BACKING=1 without changing cache keys. Retain cold backing during specialization and report cache bytes separately. Cover real Store/Load ownership, replacement, failures, moves, concurrency and materialization.
|
Thanks. Our reading of main (10-16): #4806's eviction is on by default (evictToEntry after Persist), so the prepared variants are covered. The case still outside a view is the specialized modules ( Measured 10-25 with heaptrack on a Demon's Souls level run (RTX 3080, Linux): malloc grows +337 MiB per minute of play, of which the buildSpecializedModule cache is +61.6 MiB per minute (gpucomp 75.6, glcore 44.1, ResolveImageTables 27.2, memo results 17.9). #10473 (10-25, release specialized modules no result uses) may already cover part of that; we have not measured on a tree with it yet. |
What
Every prepared shader artifact keeps its SPIR-V words resident in the process-wide source registry, although they are read again only to build a specialised module or to be copied into a result. The same words are already in the shader disk cache entry. Measured by the author on one Demon's Souls level load: the disk cache holds 8,766 entries, 11.5 GB, 99.4% of it SPIR-V words, and all of those words stayed resident.
SharedSpirvcan now hold a backing instead of the words:Pin()returns the words for as long as the returned pointer lives, reading them back from the entry when evicted, without keeping them. The readers of a prepared artifact (SpecializeVertexInputTypes,PrepareVertexInputSpecialization,EncodeEntry) use it.Words()makes them resident again and marks the holder so a later eviction is refused, because callers keep the reference.RecompileResultthe driver holds stays resident as before.Loadapplies (magic, format, source version, key size, payload size and hash) plus the stored word count. A missing or altered entry throws.The entry format is unchanged. Nothing is evicted when the disk cache is off or when
APS5_NO_PERF_SPIRV_EVICTIONis set.CompiledShaderArtifactandRecompileResultgrow by 24 bytes; the size assertions follow.Review notes, stated plainly:
SharedSpirvstate is behind one process-wide mutex (not held during file reads). Copying aSharedSpirvnow takes it. I did not measure contention.size(),empty(),data()and iteration go throughWords()and therefore keep the words resident for that holder; this is safe but forfeits the saving for it.Tested
main961b25f.verifySpirvEvictioninagc_shader_disk_cache: stored words reload identically, a copy stays resident after the entry file is removed, the evicted holder throws while its entry is missing and reloads once it is restored, and a holder with a liveWords()reference is not evicted. It fails withAPS5_NO_PERF_SPIRV_EVICTION=1, as expected.libsand ran, on this branch:agc_shader_disk_cache,agc_shader_memory,agc_shader_bindless,agc_shader_frontend_pair,agc_shader_frontend_pair_off,agc_masked_select,agc_shader_control_flow,agc_shader_mode_register: 8 of 8 passed.python3 tools/check_conventions.py --base origin/mainpasses.mainplus several open pull requests plus local fixes), not from this branch alone.agc_driver_*), the full ctest run. This branch as submitted was not run in a title; it differs from the measured one by the removal of code comments and local accounting, the renamed switch and the size assertions formain.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)🤖 Generated with Claude Code