Skip to content

fix(agc): key a stage without push constants at offset 0 in every pipeline key - #16748

Open
chitters2004 wants to merge 1 commit into
boykopovar:mainfrom
chitters2004:fix/prebuild-pushless-fragment-offset
Open

chitters2004 wants to merge 1 commit into
boykopovar:mainfrom
chitters2004:fix/prebuild-pushless-fragment-offset

Conversation

@chitters2004

Copy link
Copy Markdown
Contributor

What

With graphics pipeline libraries, registration prebuilds a pixel shader's libraries at its fixed push slot (FixedPushOffset(Stage::Fragment) in ShaderRegistry.cpp), also when the shader has no push constants. A draw places such a stage at offset 0 (Driver::draw, Execution/src/Driver/Draw/Draw.cpp). The push offset is part of the fragment shader library key, so a draw never found the library prebuilt for a pixel shader without push constants and built it again.

Graphics::KeyedPushOffset now holds the rule (no push constants, offset 0), and every key that hashes a stage's push offset uses it: the pipeline library keys and the full pipeline key in Pipeline.cpp, and the draw validation and shape keys in Graphics/src/Draw.cpp. Prebuild and draw both reach the library keys through the Pipeline constructor, so neither caller needs to normalize the offset. Slot and push cursor allocation are unchanged, and a stage with push constants keeps its offset in the key.

Every pixel shader without push constants that a title registers is affected when graphics pipeline libraries are in use: its prebuilt fragment library was built and never used, and its first draw built another one. Prebuilt libraries that differ from the draw's in depth or stencil attachment formats still miss; that is a separate change.

Overlap, checked on 2026-11-07 against main 46552cb461 with tools/pr_overlap.py and by hand: one open pull request changes lines this branch changes: #9508 adds descriptor heap helpers to Shaders.hpp beside KeyedPushOffset and edits libraryKeys and ValidationKey a few lines from it, adding descriptor placements to the same keys; the rebase is mechanical. No open pull request implements the same thing, and none keys a pipeline by a push offset outside the functions changed here: #9356, #9387 and #15548 build a mesh compute stage from shaders.front().pushConstantOffset, which goes through the same key functions, and #11551 and #16413 use the offset to patch push data, not to key a pipeline. Rechecked against 4977f64052: the tool confirms no conflict and could not compare 49 pull requests because they conflict with main, among them those named here.

Tested

Head 0a25af4ca7 on main 4977f64052.

Refreshed onto main 4977f64052. Head 0a25af4ca7; git range-diff against 0e323b1bdc shows the same patches (1 commit, =). Local RTX 3080 gate on both, same environment as below (ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation), built one after the other in one build tree, with the focused AGC set of all five pull requests of this series (232 tests on this head, 232 on main): both 100 % passed, no VUID- line in either log or in replay subprocess logs, and neither log contains was not found but was requested by env var VK_INSTANCE_LAYERS. Fork CI on the rebased head against 4977f64052: run 42371889894: Linux 11 of 11 passed; Windows 10 of 11, where agc_driver_recorder fails on main too. No VUID- line on either side, conventions check passed. The full runs below were on the previous base 46552cb461.

Vulkan validation. RTX 3080, ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ctest --test-dir build -R 'agc|write_tracking|guest|indirect_draw|draw_finisher|depth_bias|draw_pipeline' -V on 0e323b1bdc (3199 tests) and on main 46552cb461 (3199 tests). Every test failing in either full run was then rerun alone on both builds, one build at a time with nothing else on the GPU, using ctest -R with the union of the 16 names and the same environment: on both, 15 of 16 passed and only agc_driver_direct_write_completion failed, which fails on main too (#15547); the other failures of the full runs were timeouts and 0xc0000409 exits under load from concurrent gates and did not reproduce alone. Both full logs hold the same 18 VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 lines and no other VUID-; neither contains was not found but was requested by env var VK_INSTANCE_LAYERS. The change adds no validation error.

Fork CI (GitHub runners, Mesa lavapipe with the Khronos validation layer, head against main): run 42329046283, rebased there onto 46552cb461: Linux 11 of 11 passed; Windows 10 of 11, where agc_driver_recorder fails as it does on main on the same runner. No VUID- line on either side, conventions check passed.

Tests.

  • agc_driver_prepared_graphics_prebuild_unset, _0 and _1 (PreparedGraphics.cpp): when the device has graphics pipeline libraries and prebuilding is on, a pixel stage without push constants is prebuilt at its fixed slot, which builds one fragment library, then drawn at offset 0 through VulkanDevice::Draw; the draw must not build another fragment library.
  • agc_pipeline_library and agc_pipeline_library_fast_only (Recorder.cpp): a pixel shader without push constants looked up at its fixed slot reuses the libraries built at offset 0. The existing fixed-slot check now uses a pixel shader of its own, since the same shader no longer builds a second library.
  • Red proof, from the branch history on an earlier main (e509b29247): with KeyedPushOffset returning the raw offset, which is the behaviour of main, these tests fail with "a draw built the fragment library its pixel stage had prebuilt" and "a pixel shader without push constants built its libraries again at its fixed slot"; with this change they pass.

GTA V. This is a fix with no speed claim. The case it fixes made no measurable difference in GTA V (PPSA04263, content 01.011.001) on the RTX 3080 (driver 621.14, Windows 10.0.26220, before Resizable BAR was turned on), counted with a local counter patch that reports pipeline library part lookups, hits and builds per stage, applied identically to both sides and not part of this PR (diag-base.patch, diag-push.patch). Every boot ran APS5_PROFILE_DRAW=1, so these are counts, not timings. main was 7383be1a19; the change was b115d173d8, this branch before its rebase onto 46552cb461 (git range-diff shows the same patch).

  • Standing scene, 75 s after the player stands still, two main boots and one boot of the change: no fragment library part was built at draw time in the window on either side. Boot totals at the window end: fragment parts built at draw time 536 and 540 on main, 535 on the change; hits 226 and 231, and 228.
  • A cold drive over the same route, both sides started with ANYPS5_NO_SHADER_CACHE=1 and an empty driver cache: fragment hit rate 53.6 % on main and 51.6 % on the change, 0.464 and 0.484 fragment parts built per lookup, 3.62 and 3.70 presents per second. The prebuild at load was identical on both sides (3,104 prebuild calls, 2,584 fragment parts built). The hand-driven routes differ by 11 % in library lookups, so differences below about 15 % are within the noise of this comparison. Free roam on this main needs open feat(agc): implement measured single-sample dithered alpha coverage #14561, so both drive builds also carried its diff.

Counter lines: standing counters-base.txt, counters-base2.txt, counters-cand.txt; cold drive counters-cold-base.txt, counters-cold-cand.txt.

On an older main (08a10d2253, committed 2026-10-30) with an earlier form of this fix, cold boots to 150 s of gameplay counted 22 draw-built fragment parts that differed from a prebuilt part only in push offset (0 with the fix) and 271 to 273 fragment parts built by draws on main against 251 with the fix. The current main scenes above show no such difference.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 3080 (driver 621.14, Windows 10.0.26220); Mesa lavapipe on the fork's GitHub runners (Linux and Windows)
  • AI-assisted: yes

🤖 Generated with Claude Code

…eline key

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the agc libSceAgc* label Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

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.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 9508 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp L43

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.

Pull request Shared files not compared
PR 1368 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 5021 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6186 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6192 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6209 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 7275 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 7457 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 7604 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PreparedGraphics.cpp
PR 8484 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9289 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9356 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 9387 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 9748 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9852 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9884 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9915 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10049 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PreparedGraphics.cpp
PR 10442 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 11452 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 11551 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 11825 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 12619 core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 13148 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13251 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 13793 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 13809 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 13863 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 13920 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 13928 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PreparedGraphics.cpp
PR 13929 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/execution/PreparedGraphics.cpp
PR 14944 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 15136 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 15169 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 15343 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 15529 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 15548 core/libs/prx/libSceAgcDriver/Graphics/include/Shaders.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant