Repository navigation
Conversation
7b097cc to
b4c4a26
Compare
CnRJay
left a comment
There was a problem hiding this comment.
This needs changes before it can help. As written it is more likely to add pipeline compiles and per-draw CPU time than to remove stalls.
1. The prewarm key doesn't match the draw's key, so some draws compile twice. PrewarmPipeline rebuilds the inputs of CachedPipeline from the pre-lock state. Draw changes some of them after resolving its targets (Graphics/src/Draw.cpp, around CachedPipeline in Draw):
leanisrecorded && !drawTransitions, andrecordeddepends on residency, completion work and leases. The prewarm assumesrecordDraws && !drawTransitions, so every draw that isn't recorded gets aGENERAL-layout pipeline built ahead and aCOLOR_ATTACHMENT_OPTIMALone built inDraw.- Proxied targets:
Drawreplaces the attachment format withAttachmentProxyFormatand masks the write mask. The prewarm builds with the original format, which is the format the device can't render to (that is why it is proxied). That is a second pipeline at best, and a creation failure outside the draw's error handling at worst.
Each mismatch is a full extra vkCreateGraphicsPipelines. The extra entries also count against the store's 1024-entry bound and can evict pipelines that live draws use.
2. The compile doesn't actually leave the critical section. CachedPipeline holds Pipelines().mutex for the whole std::make_shared<Pipeline>(...) (Graphics/src/Pipeline.cpp), and every draw on every queue takes that mutex for its lookup. Moving the call from under GpuMutex to before lockForDraw still blocks every other draw for the duration of the compile. Only work that takes GpuMutex and never looks up a graphics pipeline gains.
3. Every draw pays for it. For the more than 99% of draws that hit, this adds a second CachedFragmentOutputs (which builds a std::set), BuildVertexInputLayout, DescribeSetLayouts, a key build and a hash lookup under the store mutex. That is CPU time on the hottest path in the driver, spent to warm a cache that is already warm.
4. GPL devices already avoid the long compile. With VK_EXT_graphics_pipeline_library, the stage libraries are prebuilt on PrebuildStageLibrary's pool and the draw only fast-links. The multi-second monolithic compile described here applies only to the whole-pipeline paths (no GPL, or the cases listed in ARCHITECTURE.md). Please name the device and driver and say which path the measured pipelines took.
5. The numbers. A 5–9 s stall per new pipeline doesn't fit a mean frame time of 54 ms. One such stall in a capture would dominate the mean. The runs also used APS5_PROFILE_DRAW=1, which the Performance report form rules out. Please attach the aps5-summary.jsonl lines and traces as CONTRIBUTING asks for perf( changes.
#4897 takes the same approach for compute: the pipeline is created from the exact resources the dispatch will use, and builds of the same key are deduplicated with a shared_future. A graphics version would need to compute the key from the resolved targets (after lean, proxies and masked are known) and release the store mutex during the build, which means the same in-flight dedup.
|
|
|
putting this pr on hold while i re-evaluate telemetry and profiling on full in-engine scenes. |
|
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.
|
|
Understood, on hold. The 10-14 points stand for when you pick it up: create the pipeline outside |
|
closing to clear obsolete telemetry and rebase overhead; will revisit once in-engine profiling is ready. |
What
Pre-warms Vulkan graphics pipelines outside the driver's global GPU mutex during draw preparation.
In
Driver::draw,lockForDrawacquiresGuestMemory::GpuMutex. Previously, if an indirect or direct draw encountered an unseen pipeline configuration or cold shaders,CachedPipelinebuilt and compiled the Vulkan graphics pipeline (vkCreateGraphicsPipelines) while holdingGpuMutex. In titles such as Astro Bot (PPSA21567), compiling monolithic graphics pipelines underGpuMutexinduces 5,000–9,500 ms stalls that starve concurrent compute queues (Queue 0x40 and Queue 0x48).PrewarmPipelineresolves the vertex input layout, masked fragment output states, and descriptor set layouts prior tolockForDraw, caching the pipeline inPipelines()which is independently protected by its own granular mutex. Subsequent execution inDrawinsidelockForDrawhits the warm pipeline cache in < 1 µs without stalling the global GPU mutex during compilation.Tested
prewarmPipelineTestsincore/libs/prx/libSceAgcDriver/tests/Graphics.cppverifying that cold misses create the pipeline, while subsequent calls hit the cached entry without creating new pipelines (mock.graphicsPipelineCreateCount).tests/agc_driver_graphics_tests(Graphics validation tests passed).python3 tools/check_conventions.py.Standard #218 Multi-Sample Telemetry (Astro Bot -
PPSA21567):Measured across alternating runs on Astro Bot intro/world loading scene against base
0aa4cb1c2(APS5_PROFILE_DRAW=1):origin/main(0aa4cb1c2)GpuMutexmain + #5441GpuMutex(pre-warmed ahead)origin/main(0aa4cb1c2)GpuMutexmain + #5441GpuMutexorigin/main(0aa4cb1c2)GpuMutexmain + #5441GpuMutexPipelines()outsideGpuMutexallows monolithic Vulkan PSO compilation (vkCreateGraphicsPipelines) to execute concurrently with compute queues, eliminating up to 9,000 ms of mutex lock hold time per new shader configuration.Checklist