Skip to content

fix(agc): validate mesh index descriptors on cached draws - #5791

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
Ondra97:codex/fix-draw-mesh-index-cache
Oct 15, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
Ondra97:codex/fix-draw-mesh-index-cache

Conversation

@Ondra97

@Ondra97 Ondra97 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

What

Fixes the missing logo, text and language buttons in VLC PPSA85300 v0.4 (#5731, bring-up #5732). NGG draws can share register and SRT state while their DRAW_INDEX_2 packets select different index ranges. The generated index descriptor is absent from the register key and captured SRT memory, so a cache hit can retain the previous draw's index buffer descriptor.

Retain its four words with each mesh stage variant, require them to match before reuse, and include them in variant deduplication. A matching push offset with a different descriptor counts as a differing front stage. The regression checks rendered pixels, count and address changes, miss classification, reuse of each changed descriptor, and return to an earlier descriptor. It shares the existing NGG fixture with the mesh test.

The metadata field and capture sit beside the compiled result, keeping the insertions separate from the relocation fields in #4943 and #5609. Neither PR implements this correction; both merge cleanly with this branch.

Tested

Current head ed26cb81a, based on main a453108cf. Windows 11 Pro 10.0.26300, WinLibs GCC 15.2.0, NVIDIA GeForce RTX 4070 Ti SUPER, driver 32.0.16.1714 / NVIDIA 617.14.

  • Full default Windows build passed. All six focused CTest cases passed in 3.37 s with Vulkan required: agc_shader_memory, agc_driver_mesh, agc_driver_mesh_index_cache, agc_driver_draw_cache_reuse, agc_driver_draw_cache_reuse_off, and agc_driver_prepared_graphics.
  • The mesh-index regression passed three consecutive runs with GPL disabled (1.95 s total). On the preceding main base 84b01f9cd, removing the descriptor match makes it fail at the rendered-pixel assertion when the index count grows from 3 to 6; restoring the match passes again. The subsequent rebase adds only the independent Voice reset-port change.
  • Four visible VLC runs with the normal draw, recipe, GPL and disk shader caches enabled show the logo, headings, all 16 labeled language buttons, and Continue/Skip hints: 20 s, 20 s and 60 s on 8260e3c44, then 60 s on the final rebased head. I checked the original BMP pixels and enlarged crops. All 129 runtime library copies were hash-verified; the final driver contains no temporary diagnostic flags. This validates the welcome page; media playback and input beyond it were not tested.
  • The source is the official PPSA85300 v0.4 release, relinked with --windows --registry --windows-fixed-base 0x400000 and its bundled libc. Executable ELF SHA-256: eec51934aa2debed99152c3996f39a41be25e17d9ca14de01cee2d17b62d8e3f; the unwrapped payload segments were independently verified.
  • Refreshed 461 open PR heads and reviewed the 37 PRs sharing changed files. The repository overlap checker reports no overlap with open pull requests. git merge-tree succeeds with perf(agc): find cached draws across moved user-data pointers #4943 1c72efdc9 and perf(agc): reuse cached draw stages when only buffer base addresses moved #5609 d6abd5555. Earlier combined-tree validation with their changes passed eight focused tests on main caee23fd9; that tree was not pushed.
  • Conventions and whitespace checks passed. Shader instruction semantics are unchanged; no performance claim.

Correction to the earlier draft note: I misread the full-frame previews when reporting that the lower three rows were missing. The original BMP files contain all four rows and their labels, including the normal-cache runs. The clean runs above confirm that result; no speculative cache changes or diagnostic code are included.

External validation of earlier rendering-fix heads:

Window closure still aborts on this rendering branch (0xc0000409), as in the main control and external Windows runs. That separate fix is in #5843, which depends on #5236. Full Linux/Windows runtime CI requires a write-access collaborator to dispatch it under repository policy.

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; no silent stubs added
  • No notes, investigation files or images added to the repository
  • New third-party code is a submodule built from source; none added
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: PPSA85300 VLC (PPSA85300) #5732 (missing welcome-page rendering)
  • GPUs tested: local NVIDIA GeForce RTX 4070 Ti SUPER, driver 32.0.16.1714 / NVIDIA 617.14, Windows 11 Pro 10.0.26300; external earlier-head validation: AMD RX 7700 XT, RADV/Mesa 26, Bazzite 44 at d41effbac; AMD Radeon 860M, driver 32.0.13058.8001, Windows 11 26300 at d1e050d4c
  • AI-assisted: yes, Codex

@YossiYad

Copy link
Copy Markdown
Contributor

Linux check of this PR, and one note on how a mismatch is counted.

Setup: Bazzite 44, GCC 16.2, Release, RX 7700 XT with RADV (Mesa 26), head d41effbac merged onto main 23be5a02b.

  • agc_driver_mesh_index_cache, agc_driver_draw_cache_reuse and agc_driver_draw_cache_reuse_off pass 3 of 3 (--repeat until-fail:3).
  • VLC (PPSA85300, catalog release, with feat(relinker): load Linux executables at a fixed base #4593 for --linux-fixed-base 0x400000), first-run page, 48 s, captured at 40 s: on main only the gradient and the page dots; with this PR the logo, "Welcome to VLC", all 16 language buttons with their labels and the Continue/Skip hints, at 59.94 fps. That's the same page APS5_NO_DRAW_KEY gives on main.

The note: in lookupDraw the descriptor check continues before anyLayout = true. So when no variant matches the draw's index range, miss becomes DrawMiss::Layout, and the draw-cache report (APS5_PROFILE_DRAW) shows these draws under "layout (push offset)" instead of "front stage differing". I hit this with a test of my own: four indexed draws of an NGG program with one register key (first range twice, another range, the first again), checking that the third draw misses as a differing front stage. Against this PR the third draw does miss, but it's counted as a layout miss, so a front-stage check reads 0. Marking the mismatch as differing would keep the statistics honest, for example:

if (programs[i].binary.stage == ShaderRecompiler::ShaderStage::Mesh && !std::equal(...)) {
    if (!anyLayout) outcome = EntryOutcome::Differing;
    anyLayout = true;
    continue;
}

Your dedupe change in insertDrawEntry is needed too: without it, a variant that differs only in the descriptor is taken as already present and never inserted, so draws over that range would miss every time.

@Ondra97

Ondra97 commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

@YossiYad Thanks for checking this on Linux/RADV and confirming the VLC rendering fix on the RX 7700 XT.

I reproduced the statistics issue and corrected it in d1e050d4c. When the push offset matches but the mesh index descriptor differs, I now mark the layout as present and classify the mismatch as EntryOutcome::Differing, preserving the existing first-candidate outcome handling.

I extended agc_driver_mesh_index_cache to check that both range and address changes increment FrontDiffering without incrementing Layout. It also checks cache hits when each changed descriptor is repeated and when returning to the earlier descriptor, covering the deduplication requirement you pointed out. The classification assertion failed before the correction and passes afterward.

I rebased onto main 51031742e. The full Windows Release build and all six focused CTest cases passed; the strengthened regression also passed three consecutive runs with GPL disabled on my RTX 4070 Ti SUPER.

AI-assisted: yes. — Codex

LeandroLP23 added a commit to LeandroLP23/AnyPS5 that referenced this pull request Oct 14, 2026
LeandroLP23 added a commit to LeandroLP23/AnyPS5 that referenced this pull request Oct 14, 2026
@LeandroLP23

Copy link
Copy Markdown
Contributor

Windows/AMD check with VLC (PPSA85300 v0.4, catalog release): Windows 11 (26300), Radeon 860M (RDNA 3.5, driver 32.0.13058.8001), WinLibs GCC 15.2.0, Release. Relinked with --windows --registry --windows-fixed-base 0x400000, 60 s per run, frames from APS5_DUMP_FRAMES (one every 600 presents).

Build Runs Welcome page at the second dump
main 9a3e2ac 1 gradient and the four page dots only, as in #5731
main 9a3e2ac + this PR (d1e050d) 2 logo, "Welcome to VLC", "Choose your language", all 16 language buttons and the Continue/Skip hints, in both runs
main with this PR
main PR

The window title reads 20.0 FPS on main and 27.4 / 29.2 FPS with the PR.

agc_driver_mesh and agc_driver_mesh_index_cache pass 3 of 3 (--repeat until-fail:3) with an empty test shader cache.

Not tested: the new test against main's sources, input past the welcome page. All runs end with abort() (exit 0xc0000409) when the window is closed at 60 s, with and without the PR.

AI-assisted: yes (Claude Code)

@Ondra97
Ondra97 force-pushed the codex/fix-draw-mesh-index-cache branch from b3e26ae to ed26cb8 Compare October 14, 2026 15:37
@Ondra97
Ondra97 marked this pull request as ready for review October 14, 2026 15:39
@screamm

screamm commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Windows/NVIDIA check with VLC (PPSA85300 v0.4, catalog release).

  • Head ed26cb81a merged onto main 2559e9623: clean, no conflicts (merge 96f751835). Windows 11 Pro 26220, WinLibs MinGW-w64 GCC 15.2.0 r7, Ninja, Release, NVIDIA GeForce RTX 4070 (driver 596.21).
  • Build: full default build and libs pass; the only warnings are the existing ones main also has (-Wstringop-overread in PipelineLibrary.cpp/ShaderFusion.cpp, u8path in General.cpp).
  • ANYPS5_REQUIRE_VULKAN=1, --repeat until-fail:3: agc_driver_mesh_index_cache, agc_driver_draw_cache_reuse, agc_driver_draw_cache_reuse_off, agc_driver_mesh, agc_shader_memory, agc_driver_prepared_graphics: 6/6, 3 of 3.
  • Negative control: this head's agc_driver_mesh_index_cache_tests.exe with main's libSceAgcDriver.prx first on PATH exits 1 with AGC graphics: cached mesh draw used another draw's indices: count=6.
  • ctest -R '^agc_' with the display available: 565/565 passed (3 skipped, the same as main's 564/564).
  • ctest -j8 --timeout 120 -E '^agc_driver_|^video_out_flip': 810/812 on the first pass. hardware_oracle_compare (20 s limit) timed out, as it also does on main under -j8. guest_file_lock_process exited 0xc0000409 after 11.6 s under load. Both pass 3 of 3 when rerun alone, guest_file_lock_process passes in the main suite, and neither test involves libSceAgcDriver.
  • VLC relinked with relinker --windows --registry unused-filter=0 --windows-fixed-base 0x400000, 60 s, window captured with PrintWindow at 20 s and 50 s, plus APS5_DUMP_FRAMES at present 1200:
Build On screen (20 s and 50 s) Window title at 60 s
main 2559e96 gradient and the four page dots only (no text) VLC | FPS: 72.31 (4432)
main + #5791 logo, "Welcome to VLC", "Choose your language", all 16 language buttons with their labels, Continue/Skip hints VLC | FPS: 90.28 (5333)

No stop line in either build. With this PR alone, closing the window still exits 0xC0000409 (after 1.1 s), as on main; #5843 fixes that. FPS varied with other load on the machine, so these figures do not support a performance claim.

Verdict: the missing welcome-page text and buttons are fixed on NVIDIA too, with no AGC test regressions.

AI-assisted: yes (Claude Code)

@github-actions

github-actions Bot commented Oct 15, 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 6454 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCache.cpp L128

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 1896 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCache.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
PR 3891 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4156 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4396 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4397 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4422 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4423 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4424 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4520 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4521 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4522 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4523 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4566 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4599 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4718 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4740 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4749 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4760 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 4813 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 5021 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
PR 5656 core/libs/prx/libSceAgcDriver/Execution/include/Driver/Dispatch/DispatchCache.hpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCache.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
PR 5867 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCache.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
PR 5884 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
core/libs/prx/libSceAgcDriver/tests/Mesh.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCache.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp
PR 6235 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawLookup.cpp

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the three-line change in DrawCapture/DrawLookup/DrawCache against the cache flow: the mesh index descriptor is retained per stage variant, required to match on lookup, and part of the variant dedup. A push-offset match with a different descriptor is counted as FrontDiffering.

Built and ran the AgcDriver tests on the PR merged onto current main: all pass except agc_driver_tessellation, which segfaults on main as well. agc_driver_mesh_index_cache fails when the non-test changes are reverted, so it tests the fix. Thanks to @YossiYad, @LeandroLP23 and @screamm for the Linux/AMD, Windows/AMD and Windows/NVIDIA runs; merging.

@adriadam10
adriadam10 merged commit 03c4cb5 into boykopovar:main Oct 15, 2026
10 checks passed
adriadam10 added a commit that referenced this pull request Oct 15, 2026
…5791)

agc_driver_mesh_index_cache aborts on the linux job (lavapipe, LLVM 20.1.2:
"LLVM ERROR: Cannot emit physreg copy instruction") on every main push build
since the merge (first red: 38777177302). The PR was merged on a
windows-only run after a linux-red batch was split.

Co-Authored-By: Claude <noreply@anthropic.com>
adriadam10 added a commit that referenced this pull request Oct 15, 2026
Revert "fix(agc): validate mesh index descriptors on cached draws" (#5791)
@adriadam10

Copy link
Copy Markdown
Collaborator

Reverted by #6552: agc_driver_mesh_index_cache aborts on the linux job of every main push build since this merged (lavapipe LLVM 20.1.2, LLVM ERROR: Cannot emit physreg copy instruction compiling the test shaders; e.g. run 38786745473). Please reopen with a test shader that the runner's lavapipe compiles; the linux job must pass before it lands.

adriadam10 added a commit that referenced this pull request Oct 15, 2026
)

Reapplies #5791 (reverted by #6552). agc_driver_mesh_index_cache now skips
on llvmpipe like agc_driver_mesh does: llvmpipe aborts compiling these mesh
programs (LLVM ERROR: Cannot emit physreg copy), which is what turned main's
linux job red.

Co-Authored-By: Claude <noreply@anthropic.com>
adriadam10 added a commit that referenced this pull request Oct 15, 2026
fix(agc): zero the pending key store block, reapply #5791 with an llvmpipe skip
@Ondra97
Ondra97 deleted the codex/fix-draw-mesh-index-cache branch October 17, 2026 14:38
oneandonlydean pushed a commit that referenced this pull request Oct 17, 2026
relocateDrawEntry copied a cached variant field by field and left out
meshIndexDescriptor, which the variant gained in #5791 before #4943 merged.
lookupDraw compares a mesh stage's descriptor with the draw's index buffer
words before validating anything else, and no draw has an all-zero one, so
every relocated mesh-path stage was refused as a differing front stage. With
no hits the shader set's relocation trial stopped admitting new aliases too.

The copy now takes the donor's descriptor, so a relocated mesh stage matches
the same index buffer the donor was built for and misses on any other.

agc_driver_mesh_draw_relocation draws a mesh-path triangle whose vertex
buffer descriptor is loaded through a user-data pointer, at eight addresses
with the same contents: the last four now hit the cached draw (before: four
differing front stages, no hit).

AI-assisted: yes
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.

5 participants