Skip to content

feat(agc): keep driver pipeline caches and costly compute pipeline binaries across updates - #13931

Merged
adriadam10 merged 6 commits into
boykopovar:mainfrom
liskeee:perf/agc-persistent-pipeline-cache-upstream
Nov 1, 2026
Merged

adriadam10 merged 6 commits into
boykopovar:mainfrom
liskeee:perf/agc-persistent-pipeline-cache-upstream

Conversation

@liskeee

@liskeee liskeee commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

What

A large compute pipeline can take many minutes to build in the driver (#13538 reports 13 minutes on an RTX 4090), and today every AnyPS5 update throws that work away. Two changes keep it, with review fixes on top:

1. fix(agc): preserve driver pipeline caches across source updates (+ fix(agc): skip unchanged periodic pipeline cache snapshots). The driver blob moves out of the source-version directory, which every AnyPS5 update replaces with a new one (the old one is removed after 14 unused days), and a compatible legacy blob is imported once. SaveNow and the final save now write a content change of equal size (it was skipped before), while the 10-second background save keeps its cheap size-and-header check and copies nothing while the cache is unchanged. An incomplete snapshot no longer replaces the previous file.

 <shader cache dir>/
 ├── <source version>/
-│   └── vk-pipelines-<vendor>-<device>-<driver>-<uuid>.bin   # not reused after an AnyPS5 update
+└── driver/
+    └── vk-pipelines-<vendor>-<device>-<driver>-<uuid>.bin   # kept; the driver still validates it

2. feat(agc): persist costly compute pipeline binaries (+ fix(agc): retain driver cache fallback after binary capture failures and fix(agc): disable pipeline binaries with outdated wrapping layers). Costly compute pipelines are stored with VK_KHR_pipeline_binary and restored without a rebuild:

 create compute pipeline
+  recipe >= APS5_PIPELINE_BINARY_MIN_WORDS (100000):
+    key = full recipe (SPIR-V, specialization, layout, flags, subgroup size)
+          + driver fingerprint + the extension's global key
+    stored binary, recipe and keys match -> create from the binary
+    no binary and no marker              -> build with capture (null pipeline cache, as pNext-09617 requires)
+      built in >= APS5_PIPELINE_BINARY_MIN_MS (1000) -> store the binary atomically
+      faster, or the capture failed      -> remember the recipe in a .bin.threshold file
   everything else, and marked recipes: vkCreateComputePipelines through the driver cache

Anything missing, corrupt, rejected or mismatched falls back to a normal build. APS5_NO_PIPELINE_BINARIES turns the store off. The store also stays off when an enabled VK_LAYER_KHRONOS_validation or VK_LAYER_LUNARG_gfxreconstruct is older than Vulkan 1.3.294, because such a layer wraps handles but does not know the extension's commands. A marker never replaces a captured binary. Lowering the time threshold retries a recipe that was below it, but not one whose capture failed; a driver update retries both, because the key holds the driver fingerprint.

Rollback: reverting the PR restores today's behaviour. At run time, APS5_NO_PIPELINE_BINARIES turns the binary store off (the driver cache stays in its new place), and deleting the cache directory resets both caches. Blast radius: compute pipeline creation and disk use. Nothing is evicted yet; the debt entry and USAGE.md say so first.

Overlap: #9508 replaces the compute creation call this touches, #11435 adds a pipeline-cache option beside the new store, and #7622 edits PipelineCache.cpp's includes. The pr-overlap bot also lists open PRs that touch neighbouring lines in VulkanDevice.cpp, Recorder.cpp, USAGE.md and the debt file. These are textual neighbours, not duplicates; I am happy to rebase on whichever lands first.

Tested

Windows 11 Pro 25H2 (build 26200), NVIDIA GeForce RTX 4080, driver 610.88.

  • Ratchet & Clank: Rift Apart (PPSA01474), functional check of the restore path on real content, not a performance measurement: in one run the store captured a 1,988,739-word compute pipeline ([pipeline-binary] built key=bb77041da96ad820 words=1988739), and the next run restored it from the store instead of building it again. This PR makes no frame-time claim, so there are no aps5-summary.jsonl lines; main cannot reach that pipeline in this title.
  • Synthetic tests (each well under 30 s): equal-size snapshot write, incomplete snapshot kept, periodic save without a copy while the cache is unchanged, also right after loading it (failed before the review fix), legacy blob import, key changes for each tested recipe and driver field, threshold persistence and lowering, competing writers (a below-threshold marker must not erase a captured binary), a failed capture remembered so the next run uses the driver cache (failed before the review fix), the layer guard (old validation or gfxreconstruct layers and failed enumeration switch the store off, other layers do not), rejection and corruption fallback, opt-out, missing entry points, and a cross-process capture, restore and corruption run through the real Vulkan path.
  • Validation layer (VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1), selection agc_(pipeline_cache|pipeline_binary|pipeline_journal|driver_recorder|driver_pipeline_journal): main b8f0a6b 14/14, this branch 19/19; zero VUID- and zero missing-layer messages in both.
  • AMD Radeon RX 6700 XT, driver 26.10.1, Windows 11 Enterprise (build 22621), run by @JJenkx at 8727a38: all 114 CTest entries of agc_driver_recorder_tests, agc_pipeline_binary_store_tests and agc_pipeline_cache_allocation_tests pass 3 of 3 runs with the validation layer, no VUIDs.
  • Full suite (at 8727a38): 3,171 passed. The failures in my restricted runner are permission errors in shared-memory, mlock and JIT-mapping tests, plus guest_wide_formatting (cp1250 zone name, fix(libc): convert Windows time zone names to UTF-8 #10987); none of them touches these files.
  • tools/check_conventions.py --base origin/main: all checks passed.

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 4080, driver 610.88, Windows 11 Pro 25H2 (build 26200); AMD Radeon RX 6700 XT, driver 26.10.1, Windows 11 Enterprise (build 22621), run by @JJenkx at 8727a38
  • AI-assisted: yes

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — changes requested

The PR claims a pipeline-creation speed improvement but does not include the matched performance captures required by the repository contribution rules.

What I ran

Reviewed head 8727a380d7a8ff14a8a65b40c31ba3ef83a85864 against base cd087bd12c258cf6dbb82e203bafd20d9fe2596c; the precheck reports a clean merge preview. Environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. No build or C++ tests were run locally.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13931
gh pr diff 13931 --repo boykopovar/AnyPS5

Results

Check Result
git diff --check Passed
Repository conventions and PR template Passed
Merge preview Clean against main at cd087bd12c258cf6dbb82e203bafd20d9fe2596c
ABI audit and test-quality helper Could not execute: the helper scripts are absent from the isolated PR checkout; this PR changes no exports and no Python tests
Hosted CI Intake, conventions, and labels passed on the exact head at the final refresh
Tests The PR description reports 18/18 focused Vulkan CTests on an RTX 4080 and 3,171 full-suite passes, with some unrelated restricted-runner failures. I did not independently run these tests.
Unedited precheck output
All conventions checks passed.
/usr/bin/python3: can't open file '/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-13931-8727a380d7a8/head-8727a380d7a8-ab4a4570/tools/pr_abi_audit.py': [Errno 2] No such file or directory
/usr/bin/python3: can't open file '/tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-13931-8727a380d7a8/head-8727a380d7a8-ab4a4570/tools/pr_test_quality.py': [Errno 2] No such file or directory

git diff --check produced no output. The precheck report records both head and base unchanged at completion.

Findings

Blocking

The PR description claims that a 1,988,739-word pipeline took about 32 minutes to build and 202.7 ms to restore. The repository requires a speed claim to include aps5-summary.jsonl lines for main and the change from the same machine and scene, the corresponding traces, and the performance-report evidence. The PR currently provides driver log timings but no matched summary lines, trace attachments, or trace_digest.py output. Please add the required matched artifacts, or remove the unsupported speed claim and describe the measured scope accurately.

Non-blocking

None identified in this source review.

Sources

Not verified

I did not build or run the new C++ tests locally. The author-reported test results are not independently confirmed here; other GPUs and console behavior were not tested by me.

To get this to a good state

Add the matched main/PR summaries, traces, and digest output required for the speed claim, or revise the claim to match the evidence provided. I will rerun the relevant checks on the updated head.

@liskeee

liskeee commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, @MarcZX10. You are right that the timings were a speed claim without the matched captures. I removed it:

  • The description now makes no performance claim. The title run is kept only as a functional check: one run captured a 1,988,739-word compute pipeline, and the next run restored it from the store instead of building it again.
  • Matched aps5-summary.jsonl lines are not possible for that title: main stops before it reaches that pipeline. The change also does not affect frame time. It only decides whether a pipeline is rebuilt at startup.
  • The behaviour the PR does claim is covered by the synthetic tests in the description, including the cross-process capture, restore and corruption run through the real Vulkan path.

AI-assisted: yes

@github-actions

github-actions Bot commented Oct 31, 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 8212 docs/dev/ARCHITECTURE.md L139
PR 8319 docs/dev/debt/libSceAgcDriver.md L114
PR 8887 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp L12545
PR 9875 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp L51
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L2240-2241, L5454-5455, L5494
docs/dev/ARCHITECTURE.md L139
docs/user/USAGE.md L461
PR 11435 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L2241
PR 12696 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L2241
PR 12764 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L5454-5455
PR 12840 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L332, L5454
PR 13920 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp L12545
PR 13928 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L2240-2241, L5454-5455, L5494
docs/dev/ARCHITECTURE.md L139
docs/user/USAGE.md L461
PR 13929 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L2240-2241, L5454-5455, L5494
docs/dev/ARCHITECTURE.md L139
docs/user/USAGE.md L461
PR 13942 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp L603

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/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 1896 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/user/USAGE.md
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ARCHITECTURE.md
docs/dev/debt/libSceAgcDriver.md
docs/user/USAGE.md
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ARCHITECTURE.md
docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6501 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6804 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6924 docs/dev/ENVIRONMENT.md
docs/user/USAGE.md
PR 6970 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6977 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7223 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7256 docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 7464 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7508 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7514 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
core/libs/prx/libSceAgcDriver/tests/cmake/agc_pipeline_cache_allocation_tests.cmake
docs/dev/ARCHITECTURE.md
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
docs/user/USAGE.md
PR 7684 docs/dev/ARCHITECTURE.md
PR 7689 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7694 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7978 docs/dev/debt/libSceAgcDriver.md
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 8014 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 8707 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8874 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 9012 docs/dev/ENVIRONMENT.md
PR 9020 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 9248 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 9335 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 9345 docs/dev/ENVIRONMENT.md
docs/user/USAGE.md
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ARCHITECTURE.md
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ARCHITECTURE.md
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 9432 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9445 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9489 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9508 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
core/libs/prx/libSceAgcDriver/tests/cmake/agc_pipeline_cache_allocation_tests.cmake
docs/dev/ARCHITECTURE.md
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
docs/user/USAGE.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9712 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 9748 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 9852 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 9884 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9898 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 9915 docs/dev/debt/libSceAgcDriver.md
PR 9950 docs/dev/debt/libSceAgcDriver.md
PR 10026 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 10069 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ARCHITECTURE.md
docs/dev/ENVIRONMENT.md
PR 10233 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 10256 docs/dev/debt/libSceAgcDriver.md
PR 10351 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10359 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 10442 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/ENVIRONMENT.md
PR 10469 docs/dev/debt/libSceAgcDriver.md
PR 10492 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 10497 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 10547 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 10652 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 10757 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 10861 docs/user/USAGE.md
PR 10867 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 10894 docs/dev/ENVIRONMENT.md
PR 10920 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 11126 docs/dev/debt/libSceAgcDriver.md
PR 11351 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ARCHITECTURE.md
docs/dev/ENVIRONMENT.md
PR 11436 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
PR 11442 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 11444 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 11483 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 11551 docs/dev/debt/libSceAgcDriver.md
PR 12120 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 12323 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 12324 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
PR 12544 docs/dev/ENVIRONMENT.md
PR 12565 docs/dev/debt/libSceAgcDriver.md
PR 12567 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 12568 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/ENVIRONMENT.md
docs/dev/debt/libSceAgcDriver.md
PR 12678 docs/user/USAGE.md
PR 12746 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/ENVIRONMENT.md
docs/user/USAGE.md
PR 12828 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 12855 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 12863 docs/dev/ENVIRONMENT.md
docs/user/USAGE.md
PR 12904 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13148 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 13262 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 14212 docs/dev/debt/libSceAgcDriver.md

@JJenkx

JJenkx commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Windows GPU run of head 8727a380d7, merged onto main 73f4f7e06e (clean merge, local only).

Windows 11 Enterprise 10.0.22621, Ryzen 9 5950X, Radeon RX 6700 XT with AMD proprietary driver 26.10.1 (Vulkan 1.4.315), WinLibs GCC 15.2.0 UCRT r7, Ninja, Release, BUILD_TESTING=ON. Khronos validation layer 1.4.363 requested for every test (VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation).

  • All 114 CTest entries of agc_driver_recorder_tests, agc_pipeline_binary_store_tests, agc_pipeline_cache_allocation_tests, which builds the test files this PR changes: pass, 3 of 3 runs each (--repeat until-fail:3), no failures, no skips.
  • They create Vulkan instances on the RX 6700 XT: the validation layer was inserted 270 times across the runs and reported no VUIDs.

AI-assisted: yes (Claude Code).

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@liskeee Reviewed at 8727a380d7. The content key and the fallbacks hold up: the stored key covers the driver fingerprint, the extension's global and pipeline keys and the full recipe, every unreadable or mismatched entry goes back to a normal build, and a capture build uses a null pipelineCache, which VUID-vkCreateComputePipelines-pNext-09617 requires. One change, in PipelineCache::save in PipelineCache.cpp: the removed early return if (liveBytes == settledBytes && onDisk == settledFile) return; is what kept the 10-second worker save (SaveIntervalSeconds, save(false, false)) cheap when nothing had changed. Now every tick takes the exclusive snapshot lock, copies the whole driver cache with vkGetPipelineCacheData and hashes it with HashBytes before it finds header == *settledFile and returns. LockForPipelineUse is the shared side of that mutex, so pipeline creation waits for each copy, and a cache of several hundred MiB makes that a recurring stall for an unchanged cache. Please keep the cheap size-and-header check for the periodic worker and run the content comparison only where an equal-size change must be caught (SaveNow and the final save), or show with matched captures that the per-tick copy costs nothing on a large cache. The same-size test then still passes through SaveNow.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, changes requested

The prior performance-report gap has been addressed, but the periodic saver now copies the full Vulkan cache under an exclusive lock every ten seconds even when nothing changed.

What I ran

Reviewed head 8727a380d7a8ff14a8a65b40c31ba3ef83a85864 against base cd087bd12c258cf6dbb82e203bafd20d9fe2596c; the live dependency/mergeability check passed and the PR head and base stayed unchanged during the precheck. Environment: Linux x86_64, Python 3.11.2, Git 2.39.5. No C++ compiler or build was run.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13931
git diff --check cd087bd12c258cf6dbb82e203bafd20d9fe2596c...8727a380d7a8ff14a8a65b40c31ba3ef83a85864

Results

Check Result
Diff check Passed
Conventions and PR template Passed
Live dependency and mergeability Passed
Export ABI and test-quality helpers Not executable in the isolated precheck checkout: those local helper files are absent there; this is not a PR-source failure.
C++ build and tests Not run; initial review checks do not build.
Precheck output
Conclusion: checks failed
Head unchanged at completion: True
Base unchanged at completion: True
All conventions checks passed.

The precheck's overall checks failed status is from its inability to find the optional local pr_abi_audit.py and pr_test_quality.py helpers in its isolated checkout; the diff, conventions, and live mergeability checks passed.

Findings

Blocking

PipelineCache::save(false, false) runs on the 10-second saver thread. The new path removes the previous unchanged-size/unchanged-header fast return, then takes PipelineCacheSynchronization::SnapshotLock and copies the entire VkPipelineCache payload with vkGetPipelineCacheData before comparing its hash with the settled header. That exclusive lock blocks LockForPipelineUse, so an unchanged large cache can stall pipeline creation on every saver tick. The later equality check avoids rewriting the file, but it occurs only after the full snapshot copy. Please restore a cheap unchanged check for periodic SaveUnlessBusy saves while retaining full-content comparison for explicit/final saves where same-size changes must be detected.

Non-blocking

None.

Sources

Not verified

  • Runtime cost on a large real driver cache; I have not run matched performance captures.
  • C++ build, CTest, GPU behavior, or console behavior.

To get this to a good state

Keep periodic saves from taking a full exclusive snapshot when both the cached size and on-disk header are unchanged, while preserving the same-size-change check for explicit/final saves. I will rerun the same checks on the updated head.

@TechLevelZero

Copy link
Copy Markdown
Contributor

❌ NVIDIA GPU test: failed

PR head 8727a38 merged onto main 73f4f7e · tested 2026-10-31 14:19 UTC · 28 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ❌ 2,432 passed · 5 failed (1 new: 1 not compared, 4 also fail on main) · 50 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,487 of 3,072 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (927 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_graphics_maps_fallback 44.9 s, ⚠️ agc_driver_bda_device 33.0 s

Failing tests

This PR changes test files, so each failing test was also built and run on main with only the PR's test changes applied. ✅ there means the failure comes from the PR's other changes; ❌ means the test fails on main too, so this run does not show the PR caused it.

Test With this PR Same test on main 73f4f7e (main + this PR's test changes only)
agc_pipeline_binary_vulkan ❌ failed not compared: the PR's tests do not build without its other changes
agc_pipeline_binary_vulkan: Failed (also failed when re-run alone), assertion and diagnostics
ctest: Failed

  capture failed: Segmentation fault
Failing on main too (4, not counted against this PR)
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
agc_driver_job_manager_compute_capacity: Failed in the parallel run; also passed only on retry in 178 other runs in the last 7 days
Validated but not compared (4, not in the main baseline's validation pass)
agc_pipeline_binary_store
agc_pipeline_binary_vulkan
agc_pipeline_cache_allocation_incomplete
agc_pipeline_cache_allocation_same-size
Validation IDs already present on main (4 IDs in 426 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (426 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 418 more
VUID-vkCmdCopyImage-srcImage-01548 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-vkCmdCopyImage-srcImage-01551 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (50)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or pla
Reproduce
git fetch origin 8727a380d7a8ff14a8a65b40c31ba3ef83a85864 73f4f7e06e4f210a8c6570e335fd654dc0a86134
git checkout 73f4f7e06e4f210a8c6570e335fd654dc0a86134 && git merge --no-ff 8727a380d7a8ff14a8a65b40c31ba3ef83a85864
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1
# the failing tests, on this merge and on main:
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc_pipeline_binary_vulkan)$' --parallel 1 -V

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@liskeee

liskeee commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean @MarcZX10 thank you, you are both right: commit 1 dropped the cheap check that kept the 10-second save free while nothing changed. I fixed that and two more problems I found while checking it, in three new commits on top (no force-push):

7562085af5 fix(agc): skip unchanged periodic pipeline cache snapshots

  • The periodic save (the worker tick and SaveUnlessBusy, both save(false, false)) works as on main again: it tries the snapshot lock only for the size query and returns when the size and the file header are unchanged. No vkGetPipelineCacheData copy and no hash while the cache is unchanged. That now also holds for the first tick after loading a current cache; I had missed main's settledBytes at load. A legacy import is still written by the first periodic save.
  • SaveNow and the final save still compare content, so they write an equal-size change. As on main, an equal-size change made between explicit saves waits for SaveNow, the final save or the next size change.
  • New test agc_pipeline_cache_allocation_periodic: an unchanged periodic save, after a save and after reopening, makes one size query and no copy. An equal-size change is not copied by a periodic save; SaveNow writes it, and the final save writes another one. It failed on 8727a38 (an unchanged periodic save copied the driver cache) and passes now.

805b649bce fix(agc): retain driver cache fallback after binary capture failures

  • A capture build runs with a null pipeline cache, as VUID-vkCreateComputePipelines-pNext-09617 requires. Before this commit, a costly build whose binaries could not be extracted or stored (or a rejected capture build) recorded nothing, so every later run repeated the capture build and never used the warm driver cache. Now such a recipe gets a capture-failure marker, and later runs build it through the driver cache. Lowering the time threshold does not retry these markers; a driver change does. Tests for extraction failure, an oversized binary and a rejected capture build failed before the fix and pass now.

e65ab33664 fix(agc): disable pipeline binaries with outdated wrapping layers (the NVIDIA CI segfault, see below)

Validation layer, same selection as in the description: main b8f0a6b 14/14, this head 19/19, zero VUID- in both (RTX 4080, driver 610.88).

@TechLevelZero thank you for the run. My best explanation for agc_pipeline_binary_vulkan crashing in capture: the validation layer on that machine was built against Vulkan header 1.3.275 (the log shows unknown VkStructureType 1000483000/1000483008), which predates VK_KHR_pipeline_binary (1.3.294). That layer wraps non-dispatchable handles and passes commands it does not know, such as vkGetPipelineKeyKHR and vkCreatePipelineBinariesKHR, straight to the driver, so the driver receives wrapped shader-module, layout and pipeline handles. I could not reproduce it here, because my layer is 1.4.363, so this is not confirmed. e65ab33 keeps pipeline binaries off when an enabled VK_LAYER_KHRONOS_validation or VK_LAYER_LUNARG_gfxreconstruct is older than 1.3.294 (it logs [pipeline-binary] disabled: ...), and the test then skips. Other layers are not judged by age: on my machine the OBS and RTSS overlay layers report 1.3.216 and 1.3.224, and with them, with and without validation 1.4.363, the test still captures and restores. If it still crashes on the new head, I would be grateful for the output of agc_pipeline_binary_vulkan with VK_INSTANCE_LAYERS unset.

@JJenkx thank you for the RX 6700 XT run. I added it to "GPUs tested", marked as run at 8727a38.

I also corrected several sentences in the description that overstated what the code does (cleanup timing, rollback, the threshold wording and the test descriptions).

AI-assisted: yes

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head e65ab33 merged onto main 73f4f7e · tested 2026-10-31 16:07 UTC · 34 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,432 passed · 5 failed (0 new, 4 also fail on main, 1 unstable on main) · 51 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,488 of 3,072 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (928 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 33.5 s, ⚠️ agc_driver_graphics_maps_fallback 31.1 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_submit_progress: failed in 7 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (5, not in the main baseline's validation pass)
agc_pipeline_binary_store
agc_pipeline_binary_vulkan
agc_pipeline_cache_allocation_incomplete
agc_pipeline_cache_allocation_periodic
agc_pipeline_cache_allocation_same-size
Validation IDs already present on main (4 IDs in 426 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (426 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target_cpu, and 418 more
VUID-vkCmdCopyImage-srcImage-01548 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-vkCmdCopyImage-srcImage-01551 (13 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_cpu_write_after_memo, agc_driver_depth_plane_cpu_write_after_page_unwatch, agc_driver_depth_plane_cpu_write_after_partial_unwatch, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_partial_store_unimported, agc_driver_depth_plane_sampling, and 5 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (51)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_driver_vertex_elected_atomic_max: skipped, the device runs vertex programs in subgroups, so they keep their cross-lane reductions
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_pipeline_binary_vulkan: skipped, VK_KHR_pipeline_binary is unavailable
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not config
Reproduce
git fetch origin e65ab33664a8351420b0e7bf890e87d9c7abee12 73f4f7e06e4f210a8c6570e335fd654dc0a86134
git checkout 73f4f7e06e4f210a8c6570e335fd654dc0a86134 && git merge --no-ff e65ab33664a8351420b0e7bf890e87d9c7abee12
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-checked — new head, looks good

The updated head fixes the periodic cache snapshot regression and retains the driver-cache fallback when pipeline-binary capture fails.

What I ran

Reviewed head e65ab33664a8351420b0e7bf890e87d9c7abee12 against the PR base cd087bd12c258cf6dbb82e203bafd20d9fe2596c; the live merge preview is clean against current main at 474030e58424fefdb65e5df9f3820810fbb4553c. Environment: Linux x86_64, Python 3.11.2, Git 2.39.5. I did not invoke a compiler or build locally.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13931 --output-dir /tmp/anyps5-13931-update-precheck
gh pr checks 13931 -R boykopovar/AnyPS5

I also inspected the complete PR diff and update discussion, including the periodic-save logic, binary-capture failure markers, active-layer check, and added tests. The precheck ran its live dependency/mergeability check against current main.

Results

Check Result
Diff whitespace check Passed
Repository conventions and PR template Passed
Live dependency and mergeability preview Passed; clean against current main at 474030e58424fefdb65e5df9f3820810fbb4553c
Current GitHub checks conventions and labels passed on the exact head; no upstream build/test job is present in this check rollup
ABI and test-quality helper scripts Not executable in the isolated precheck checkout because those helper files are absent there; this PR changes no public exports or Python tests. I manually inspected the new C++ assertions.
Focused Vulkan tests Not run locally. The author reports 14/14 selected tests on main (b8f0a6b202) and 19/19 on this head using an RTX 4080 with validation enabled and no VUIDs.
NVIDIA GPU CI report Not run by me. TechLevelZero reports a successful build and 2,432 passed tests on this exact head, with five failures reported as not new (four also fail on its main baseline and one is unstable there), plus 51 skips. Its run merged the PR head onto older main 73f4f7e; it is useful corroborating evidence, not a current-main run.
C++ build, local CTest, physical console Not run by me
Unedited precheck command output

Conventions stdout:

All conventions checks passed.

ABI helper stderr:

/usr/bin/python3: can't open file '/tmp/anyps5-13931-update-precheck/head-e65ab33664a8-c37535f0/tools/pr_abi_audit.py': [Errno 2] No such file or directory

Test-quality helper stderr:

/usr/bin/python3: can't open file '/tmp/anyps5-13931-update-precheck/head-e65ab33664a8-c37535f0/tools/pr_test_quality.py': [Errno 2] No such file or directory

The precheck's recorded conclusions were diff_check: passed, conventions_and_pr_template: passed, and live_dependency_and_mergeability_check: passed. These are report statuses; the successful diff check produced no output.

Findings

Blocking

None found in the updated head.

Non-blocking

  • The periodic-save update restores the cheap unchanged-cache path while retaining full snapshots for explicit/final saves. The new cases cover unchanged reopened caches, same-size changes, and legacy import.
  • Capture failures now leave a marker so later runs use the ordinary driver-cache path instead of retrying capture on every run. The added tests cover extraction failure, oversized data, rejected capture, reopening, and a lowered time threshold.
  • The layer guard disables pipeline binaries if active-layer enumeration fails or an older validation/gfxreconstruct layer is present; its tests cover these branches. I did not independently reproduce the reported NVIDIA layer crash.

Sources

Not verified

  • I did not independently run the author-reported Vulkan CTests or the NVIDIA GPU CI suite.
  • No local C++ build/CTest, macOS/Linux test matrix, or physical-console behavior was run by me.

@TechLevelZero

TechLevelZero commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 6ca7ba4 merged onto main 0836dfd · tested 2026-11-01 03:35 UTC · 14 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,452 passed · 5 failed (0 new, 4 also fail on main, 1 unstable on main) · 45 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,502 of 3,087 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ✅ no new validation IDs vs main (931 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 40.7 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_submit_progress: failed in 7 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_driver_idle_store_yields
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (5, not in the main baseline's validation pass)
agc_pipeline_binary_store
agc_pipeline_binary_vulkan
agc_pipeline_cache_allocation_incomplete
agc_pipeline_cache_allocation_periodic
agc_pipeline_cache_allocation_same-size
Validation IDs already present on main (5 IDs in 476 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (476 tests): agc_driver, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, agc_driver_bda_span_reads, and 468 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (45)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_pipeline_binary_vulkan: skipped, VK_KHR_pipeline_binary is unavailable
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fresh: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or no
Reproduce
git fetch origin 6ca7ba404299227587dbcfe6ba534a46ad93853a 0836dfdf4fecb1e0326100c490476e15d3a74da5
git checkout 0836dfdf4fecb1e0326100c490476e15d3a74da5 && git merge --no-ff 6ca7ba404299227587dbcfe6ba534a46ad93853a
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

liskeee and others added 6 commits November 1, 2026 11:56
Keep driver blobs outside source-version cleanup and import compatible
legacy caches. Persist equal-size content changes and retry incomplete
snapshots without replacing the previous file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Capture costly compute builds and restore matching recipes after checking
full recipes, driver fingerprints and Vulkan compatibility keys. Add size
and time thresholds, opt-out, atomic persistence and corruption/rejection
fallback.

Remember below-threshold recipes in separate files so competing decisions
cannot overwrite captured binaries. Prefer saved binaries and retry
capture when the time threshold is lowered.

Cover compatibility, fallback, deterministic competing writers and
cross-process capture, restore and corruption.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restore the cheap size-and-header check for the 10-second worker save,
with the size query still under the snapshot lock, so an unchanged cache
is no longer copied and hashed on every tick, including the first tick
after loading a current cache. A legacy import is still written by the
first periodic save. SaveNow and the final save keep the content
comparison that writes equal-size changes.

Cover periodic copy avoidance after saving and after reopening, legacy
migration and equal-size persistence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A costly build whose binaries cannot be extracted or stored, and a
rejected capture build, now leave a capture-failure marker, so later
runs build that recipe through the driver cache instead of repeating a
capture build with a null pipeline cache. Lowering the time threshold
does not retry these markers; a driver change does. Existing
below-threshold markers stay compatible and retryable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Check the enabled layers before querying pipeline binary features. A
validation or gfxreconstruct layer older than Vulkan 1.3.294 wraps
handles but passes the extension's commands to the driver unchanged, so
keep the driver pipeline cache path there and when enumeration fails.
Cover the layer decisions with a fake enumerator.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@adriadam10
adriadam10 force-pushed the perf/agc-persistent-pipeline-cache-upstream branch from 6ca7ba4 to ad8567f Compare November 1, 2026 11:25
@adriadam10
adriadam10 merged commit d8b60b4 into boykopovar:main Nov 1, 2026
11 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the content key (driver fingerprint, extension keys, full recipe), the null pipelineCache on capture builds, the fallbacks on missing/corrupt/rejected entries, the layer guard, the unchanged-snapshot early return and the tests against the NVIDIA and AMD runs in the thread. Added one commit on top: docs/dev/ARCHITECTURE.md describes the driver/ caches and the binary store, and the skip message of agc_pipeline_binary_vulkan now says "the device lacks VK_KHR_pipeline_binary" so tools/check_skips.py accepts it on lavapipe; merged.

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@liskeee thank you for the pipeline-cache work. We've had to revert it for now in #14839, because with the default settings it crashes at device creation on our NVIDIA test machine, and we'd like to help it land again.

What we see (RTX 4090, NVIDIA driver 610.57.04, Linux): every Vulkan device creation with the shader cache enabled segfaults in AgcDriver::Graphics::PipelineBinaryStore::PipelineBinaryStore (frame #1 VulkanDevice::VulkanDevice). The faulting instruction is the first read of this->globalKey.keySize right after the getKey(device, nullptr, &globalKey) call at PipelineBinaryStore.cpp:127 returns VK_SUCCESS, so this is unusable immediately after the driver's vkGetPipelineKeyKHR for the global key. We haven't established whether it's a driver bug in that path or something in how the call is made.

Why CI didn't catch it: most AGC tests set ANYPS5_NO_SHADER_CACHE=1, which makes the store return before the driver call; CI runs on lavapipe, and the community NVIDIA bot also runs with the cache disabled. Ten agc_driver tests that set their own environment without that variable (for example agc_driver_small_copy_sync and the two agc_driver_address_passes tests) reach the path and crash. APS5_NO_PIPELINE_BINARIES=1 avoids it.

When you re-land it, could you add a test that runs with the cache enabled (no ANYPS5_NO_SHADER_CACHE), so this path is covered, and check the global-key call on an NVIDIA driver if you can? We're happy to run a candidate on the same machine.

oneandonlydean added a commit that referenced this pull request Nov 1, 2026
…binaries across updates (#13931)

This reverts commit d8b60b4, reversing
changes made to d94fad1.
oneandonlydean added a commit that referenced this pull request Nov 1, 2026
revert(agc): keep driver pipeline caches and costly compute pipeline binaries across updates (#13931)
winstrex added a commit to winstrex/AnyPS5 that referenced this pull request Nov 1, 2026
Resolve the include list in tests/Recorder.cpp after the revert of boykopovar#13931:
take main's ShaderCacheSourceVersion.hpp and keep WatchedBlock.hpp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants