Repository navigation
perf(agc): build shader pipeline libraries when shaders are registered - #4152
Conversation
|
I tested this on PPSA36082 cold starts on my machine (RTX 4090, Linux) and posted the details in the discussion: #2242 (reply in thread) In short:
LLM assistance used. |
8335996 to
0680aa5
Compare
|
Changes since opening, after the first two CI rounds (the body is updated):
Third round: full build green on Linux (926/926) and Windows, plus all PR checks. Astro's Playroom coverage: 1937 libraries prebuilt, 5.41 GB peak against 5.07 GB with prebuild off. Still waiting on a PPSA36082 cold start before merging. AI-assisted: yes (Claude). |
|
Reran PPSA36082 cold starts on 14b52c1 on my machine (RTX 4090, Linux), details in the discussion: #2242 (reply in thread) Short version: the formatted buffer helper still makes the loading frame's compute shader 236,457 words with a 794 ms pipeline create, and the stock boot still crashes loading LLM assistance used. |
|
Same formatted buffer helper, registration form this time. On Demon's Souls (PPSA01341), dumped on my machine and compiled offline, the helper still switches over every format when the format is specialized at the call site, because it takes word 3 as a parameter. That makes the vertex shaders' registration form 3.3x their specialized form, with 39 of the 58 largest over LLM assistance used. |
Independent Windows / RTX 5080 validation of exact 14b52c1I built the exact PR head Windows 11 Enterprise 26200, Ryzen 9950X3D, RTX 5080 / NVIDIA 610.62 ( Serial
The same two failures on both revisions, in both modes:
Each failure reproduces 5/5 isolated attempts on each revision. The eight GPL-off skips are the For the NVIDIA LDS concern in #2242: Limits: NVIDIA driver disk-cache coldness is not established. This is behavior validation, not a registration/first-draw speedup measurement. No PR-head title cold boot, PPSA36082/Hades II, PPSA01341, or Astro shader replay was performed; PPSA99902 needs additional startup/graphics prerequisites on this base. No game binaries/shaders/images were uploaded. AI-assisted independent build/test/report: Codex. |
… built at registration Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…on their own thread Co-Authored-By: Claude <noreply@anthropic.com>
…ation Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…tex and pixel shaders take the registration form Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…ed with the descriptor's format Co-Authored-By: Claude <noreply@anthropic.com>
…ialization constants when the format is known Co-Authored-By: Claude <noreply@anthropic.com>
…gistration form Co-Authored-By: Claude <noreply@anthropic.com>
|
@Amoenus thanks, that's a useful control, especially Since 14b52c1, three changes are coming in the next push (rebased onto current
AI-assisted: yes (Claude). |
…he zero-position pixel shader its push slot Co-Authored-By: Claude <noreply@anthropic.com>
123c11b to
b1ee794
Compare
|
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.
|
…kground linking #4152 dropped the device-wide module list that #3173 added, so Pipeline destroys the shader modules right after the library parts are created, also for the parts prebuilt at registration. AMD's Windows driver still reads them during the background link-time-optimized link and faults inside amdvlk64.dll. Hand the modules of each new part to the device's library store again and destroy them in ClearPipelineLibraries. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What
Phase B of #2242: on devices with graphics pipeline libraries (GPL), vertex and pixel shaders get their pipeline libraries built when they are registered, not at their first draw. A draw whose shaders were prebuilt only links (about 0.01 ms). Devices without GPL keep today's path unchanged; every test passes in both modes.
What each commit does:
ResourceMetadata, so direct images read mode, swizzle and mip range at run time the way indirect ones already did.VUID-vkCmdDispatch-None-08611).INDEPENDENT_SETS, so each stage's library depends only on its own set layout. The layout no longer enters the vertex library's key, which should also remove the repeated vertex-library compile Raghav measured when only the pipeline layout changed (not measured on NVIDIA).DescribeSetLayoutsbuilds the set layouts from the compiled shaders alone, which registration needs.APS5_VERIFY_SET_LAYOUTS=1compares them with the draw's layouts on every pipeline build; the whole suite passes with it.ResolveGraphicsStagesAbi(vertex stages) and the registered or static-ABI preparation of pixel shaders hand a registration result toPrebuildStageLibrary, which builds that stage's library with a stub partner and a fixed default state.VkShaderModuleuntil the device is torn down. A module can be destroyed once the pipeline is built (vkDestroyShaderModule), and the optimized link does not need it. This also changesmain's draw path. Its cost shows with large modules: about 1.1 MB per library on RADV with Astro's Playroom shaders (3.17 GB → 1.98 GB peak for 1200 headers).registrationWordLimit(200000 SPIR-V words) is re-emitted specialized and compiles at its draw as today.CompiledShaderArtifact::registrationModulerecords the form and is stored in the disk cache. Prebuilds run on their own one-thread pool (APS5_PREBUILD_THREADS), separate from the registration pool, as Raghav suggested.main. In registration form, theagc_driver_dword_pattern_fillcompute shader hung CI's lavapipe in the build withANYPS5_ENABLE_SPIRV_TOOLS=ON(not RADV, not without SPIRV-Tools). I didn't find the cause, so compute stays out until someone does (TechnicalDebt has the reproduction).agc_driver_wait_shutdownandagc_driver_flip_computeon Windows CI, where no prebuild ever runs.buffer_*_format). As a runtime value, every such access compiled the decoder of every format:agc_driver_vertex_fetchwent from 0.59 s to 9.96 s on CI's lavapipe with a cold driver cache (2 cores, SPIRV-Tools on, 88 % of the time in LLVM), past the 5 s fence on CI. With the word specialized it takes 1.05 s. This was most likely also behind the compute "hang" in item 11, which looked like a very long JIT rather than a loop. Shaders that still specialize something (these buffers, or texel-offset folding) get no prebuild, since their prebuilt module would never match a real draw.DontInlinethe driver couldn't fold the format switch anymore. That grew a compute shader in PPSA36082's loading frame from 51k to 236k words (22 → 794 ms) and kept that boot crashing (@Raghav314, Compiling Vulkan shader code at registration, not at the first draw (VK_EXT_shader_object) #2242).FormattedBufferOncepins it: one formatted load gives 26.5k words (117.5k before;main26.5k), and the vertex registration form stays under 1.5× its specialized form.agc_driver_pixel_lds's pixel shader, which hung an RTX 4090 for Raghav (Xid 109) 3 times in 4 whilemainpasses. Both forms of that shader now have no loops or atomics, andFormattedBufferOncechecks that registration form has no more compare-exchanges than the specialized form. Not yet confirmed on the 4090.Why the word limit
Astro's Playroom registers 907 pixel shaders of 200k to 900k SPIR-V words (ubershaders). With runtime selectors the driver can no longer prune them: the largest one compiles as a fragment library in 7.1 s and 366 MB instead of 0.9 s and 132 MB, and prebuilding all of them took the process past 10 GB.
A paired sample of 60 pixel shaders (same shaders,
mainvs this branch, RADV Radeon 660M, Mesa 26.2.4, cache off) gave two clear groups:No shader falls between 141k and 280k, so the limit sits in that gap. Re-measured after items 14-15: below the limit ×1.84 (<100k) and ×2.24 (100-200k) compile with modules only ×1.10-1.14 the words; above it, in registration form with the limit off, 20 shaders still compiled ×5.9 (p10 ×5.2, p90 ×7.4) slower and ×20 on the optimized link, so the limit stays. The cost is the runtime values the driver can't fold, not module size. Below it, the extra compile time is paid once, on the background thread, and taken off the draw.
Tested
Linux (CachyOS), RADV Radeon 660M (Mesa 26.2.4), GCC 16, Release, rebased on
main8c4a295 (head b1ee794):^agc_|^shader, GPL on (withAPS5_VERIFY_SET_LAYOUTS=1)APS5_NO_GPL=1^agc_underVK_LAYER_KHRONOS_validation, GPL on and off^agc_on CI's lavapipe (Mesa 25.2.8)/dev/udmabuf,--timeout 120 --parallel 4, clean build)New or extended tests:
BufferDescriptorRuntime: every V# case gives byte-identical SPIR-V and the same pipeline variant in registration form.TypedHeaps: present and null images give the same module.ZeroStrideVertexFetch: two swizzled cases (W Z 1 0), in and out of range, checked by value; all 7 cases give identical SPIR-V in registration form.VertexFetch: a mixed pipeline (vertex in registration form, pixel forced specialized withregistrationWordLimit = 1).PreparedGraphics: the vertex stage alone and the pixel stage alone each build exactly their library without linking, the pair then finds both, and a second preparation of the same stages finds them again.ShaderMemory: serializer v17 round trip and cache key.The new assertions were checked to fail when their expected value is mutated.
Astro's Playroom, every
Shaderheader registered and resolved through the realAgcDriverRegisterShader/Resolve*Abipath (offline harness, not committed):mainNot measured here: the effect on a real boot. I can't run titles on this machine. @Raghav314, a PPSA36082 cold start on this branch would be the deciding number. Your phase B simulation in #2242 suggested this boot survives once libraries are built at registration. Please don't merge before that run.
Checklist
main; no other open PR implements the same functions (shares files with fix(agc): render all attachment layers with dynamic rendering #3763, perf(shader): convert f16 operands with UnpackHalf2x16 where f16 denormals are kept #3988, feat(agc): capture and replay compute pipeline compilation #3717, fix(agc): store D16 depth with stencil as D24 or D32 where the device lacks it #3846, fix(agc): name the shader address and stage in preparation failures #3946, fix(agc): read a merged program's vertex tables past its hidden user words #3738, fix(shader): decode a GPU-selected formatted load from a format table #3656; none implements these functions)NotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)