Repository navigation
Conversation
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
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.
Right fix for the right problem: a blocking exclusive LockForSnapshot on a writer-preferring shared_mutex stalls every later creation on every queue, and TryLockForSnapshot removes that without touching SaveNow or the teardown save. The thread dumps in the description make the cause clear, merged is destroyed by DestroyMerged on the three early returns, and the debt entry states the cost (no periodic save while creations overlap without a gap).
Minor:
- When the first snapshot succeeds but the merge or the data snapshot loses the try, the function returns after
readHeader()/readFile()and the merge-cache creation, and nothing is settled, so the next interval repeats all of it. During a long compile that is a read of the whole cache file every 10 s for no result. Check for a creation in flight before reading the file, or settleliveBytesso the next interval returns early. - The test only covers the first snapshot point. A second case where the creation starts between the first and the second snapshot would cover the other two
owns_lock()returns.
|
AMD / Windows run of this PR at eb47773: Radeon 780M (RDNA 3, 0x15bf), AMD driver 25.10.20.01 (32.0.21020.1007), Windows 11 Home 10.0.26100, WinLibs GCC 15.2.0 r7, Release. Every ctest entry built from the test targets this PR changes passes (42):
AI-assisted: yes (runs made on the device above). |
…on holds the cache The saver thread took the snapshot lock with a blocking exclusive lock. Behind a pipeline creation that runs for minutes (an NVIDIA compile of a 1.5M-word compute pipeline), the queued writer made the shared_mutex hold every later pipeline creation on every queue until the compile ended. The periodic save now tries the lock and waits for the next interval when it is busy; SaveNow and the teardown save still wait. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
eb47773 to
1d8acd1
Compare
What
PipelineCache's saver thread wakes every 10 s and snapshots the Vulkan pipeline cache withLockForSnapshot(), an exclusive lock on theshared_mutexthat every pipeline creation holds shared (LockPipelineCacheForUse). If a creation is running, the save blocks until it ends, and because the lock prefers a waiting writer, every later creation on every queue blocks behind the save as well.With a compute pipeline that takes minutes in the NVIDIA compiler, this stops all graphics work for the whole compile, though the compile runs on a compute queue. Ghost of Yōtei (PPSA26344) froze its loading at frame 797–799 for 8+ minutes this way on every warm run.
With this change, the periodic save takes the snapshot with
TryLockForSnapshot()at each of its three snapshot points (live size, merge, data). When a creation holds the cache, it returns and tries again at the next interval.SaveNow()and the teardown save still wait for the lock.SaveUnlessBusy()exposes the periodic path for the test.Thread dumps of the freeze (run193, five dumps between 382 and ~800 s, identical)
Symbolized against the build that ran; line numbers from
addr2line:Draw→CachedPipeline→Pipeline::Pipeline(Pipeline.cpp:543) →LinkPipelineFromLibraries→LockPipelineCacheForUse(PipelineLibrary.cpp:214),lock_sharedPipelineCache::run→save(false)LockForSnapshot(PipelineCache.cpp:172),lockPipelineCache::run→save(false)pathMutex(PipelineCache.cpp:168)nvgpucomp64.dllThe driver's periodic stats stopped about when the frame count did (
[gpu] worker ... draw 64.7 sthen silence), while the title's CPU side kept running (2.35 cores, audio streaming).Tests
pipelineCacheFileTests(agc_pipeline_cache_file) gains a case: one thread holdsLockForPipelineUse()like a long creation.SaveUnlessBusy()must return within 5 s, and a secondLockForPipelineUse()must then be granted within 5 s. If the save blocks, the test releases the holder after the timeout and fails, so it doesn't hang.SaveUnlessBusy()routed to the blocking save, the case fails with "a periodic pipeline cache save waited for a pipeline creation to finish".Tested
Windows 11 Pro 26200, RTX 4090, driver 617.42.
main4986aca. 1336 of 1340 pass.guest_shader_linkandagc_shader_helperstimed out under--parallel 8, andagc_driver_pixel_ldsfailed once; all three pass when run alone, as doagc_pipeline_cacheandagc_pipeline_cache_file.select_testsfails on this machine because Windows refuses its test's symlink without the symlink privilege (WinError 1314).misaligned_writer_aheadis not built: main'sGpuIndirectArgumentsMisalignedWriterAhead.cppneeds 65536-byte alignment, which MinGW's object format does not allow.APS5_LAZY_SHADER_PREPARE=1, 900 s per run. The tree ismain82ddae7 plus fix(libSceNetCtl): answer the DHCP host name, PPPoE name and proxy server as empty strings #6227 (needed to get past start-up), perf(agc): wait at submit only for the preparations of the programs a submission binds #6867, fix(agc): keep each set's image table writes in its own draw snapshot… #6537 and three local diagnostics. ItsPipelineCache.cpp,PipelineCache.hpp,PipelineLibrary.cppandPipelineCacheSynchronizationare identical to this branch's base (Context.hppdiffers only by a newstorageImageMultisamplefield), and the change applied there has the same patch-id as this branch's commit.In run194 two periodic saves wrote the file, and a thread dump at 442 s shows no save waiting and the graphics worker idle in its run loop rather than on the lock. The title then stops at frame 813 while a compute queue worker is inside the NVIDIA compiler again; that one is not a lock wait and is still being looked into.
Technical debt
New entry in
docs/dev/debt/libSceAgcDriver.md, "Periodic pipeline cache saves skip busy intervals":Related
PipelineCache.cpp(where the file lives); the two touch different code.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