Skip to content

feat(agc): read individual multisample image samples - #6601

Merged
adriadam10 merged 4 commits into
boykopovar:mainfrom
Amoenus:codex/feat-msaa-sampled-readback
Oct 19, 2026
Merged

adriadam10 merged 4 commits into
boykopovar:mainfrom
Amoenus:codex/feat-msaa-sampled-readback

Conversation

@Amoenus

@Amoenus Amoenus commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

What

Shared sample-preserving readback foundation requested in #6570 (Onimusha: Way of the Sword, PPSA27836). Adds TextureDetiler::DispatchMultisampleReadback, which records per-sample fetches into a linear storage buffer, in layer/y/x/fragment order. Supports unsigned 1/2/4/8/16-byte element views and D32 depth, 2/4/8 samples, array layers and partial element windows. Invalid formats, counts, ranges and dispatch limits throw.

Uses a sampled 2D-array view in GENERAL. The depth variant fetches floating-point depth and bitcasts to DWORDs; the unsigned variant preserves element bits and the unused bytes of a final packed word. The caller owns image/view lifetimes, producer/readback barriers and completion. Descriptor/pipeline ownership is lazy and follows the detiler's existing descriptor-ring lifecycle.

Semantics: Vulkan specifies floating-point reads of depth aspects and per-sample OpImageFetch without a sampler. Both generated modules require only Shader capability. Source images need sampled usage; storage usage is not used by the fixtures. This avoids a storage-image prerequisite for native D32 readback.

@simonbronk will consume the reader in the depth publisher discussed in #6570; the reported stop is AGC graphics: sample-preserving guest publication of native multisample depth is not implemented. Guest-memory publication, ownership/coherence and HTILE remain that follow-up. #6588 provides the complementary CPU layout/retile helper independently. No dependency on #5881 and no title-unblock claim from this utility alone. No duplicate reader found in current source/open PRs and exact-helper/related-readback searches.

Tested

Current submitted head: 7f53a96a9f, rebased directly onto main 0bb238b4a447f448e5d6592eae39d43a6a8c7d8c. Only adjacent debt entries conflicted; both are retained, with this entry before the final existing entry. No production resolution was needed. The reader implementation, shaders and fixture are unchanged from the previously tested3e3cf1da06, including cache locking and snapshot exclusion.

  • Full Release relinker/system-library and reader/graphics/recorder builds pass on Windows11 Enterprise26200 / WinLibs GCC15.2r7 and Ubuntu24.04 WSL2 / GCC13.3.
  • All six reader groups (uint8/16/32/64/128 and D32) pass3/3 on each actual physical RTX5080 and AMD Radeon Graphics:36 fresh processes. Each exercises2x/4x/8x, two layers, full/partial reads, sentinels, reuse,2D controls and guarded pipeline-cache creation. No unavailable subcases or whole-test skips. Selected names/IDs and Khronos1.4.363 loading are verified; no observed VUIDs, validation errors or warnings. NVIDIA tests overlapped a separate ordinary Sonic replay, so no uncontended timing/performance claim.
  • Linux llvmpipe LLVM20.1.2/Mesa25.2.8: the six reader groups pass3/3,18 processes. Available4x runs;36 explicit2x/8x unavailability lines are excluded from exercised coverage. No whole-test skip. Linux validation layer unavailable.
  • Connected graphics, pipeline-cache and pipeline-library clear/build-exclusion controls pass3/3 on each OS:18 additional invocations, 72 passing processes total; every selected invocation finishes below30s (maximum6.0s). Cache build/snapshot exclusion is also checked inside each reader invocation. Shader cache/pipeline journal disabled; driver caches uncontrolled.
  • Cppcheck2.20 then clang-tidy23.1.3 analyzed all four changed C++ TUs in90.141s, no parser/configuration failures. No selected clang-tidy diagnostics. Two Cppcheck reports concern the same existing thin-equation lookup; its null branch calls throwing Require(false) before either dereference. These are inspected advisories, not a clean Cppcheck claim. Conventions and diff checks pass.
  • Earlier unsupported-count red/green controls and jotitadev's independent RTX3070/Mesa26.0.3 retest retain their prior source pins in the review thread; they are not represented as fresh7f53 runs. No new title-unblock, guest-publication, HTILE-completion, FPS, whole-suite or console-equivalence claim: this remains the shared sample reader for AGC: compute buffer read of a native 4-sample D32 depth target needs sample-preserving publication (Onimusha: Way of the Sword, PPSA27836) #6570 and dependent PRs.
cmake --build build --target relinker libs agc_driver_multisample_readback_tests agc_driver_graphics_tests agc_driver_recorder_tests
ctest --test-dir build -V -j1 --repeat until-fail:3 --timeout 30 -R '^agc_driver_multisample_readback(_(uint8|uint16|uint64|uint128|depth))?$'
ctest --test-dir build -V -j1 --repeat until-fail:3 --timeout 30 -R '^(agc_driver_graphics|agc_pipeline_cache|agc_pipeline_library_clear_waits_for_build)$'

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 by itself; foundation for PPSA27836 in AGC: compute buffer read of a native 4-sample D32 depth target needs sample-preserving publication (Onimusha: Way of the Sword, PPSA27836) #6570
  • GPUs tested: NVIDIA GeForce RTX5080 (10de:2c02),610.62/32.0.16.1062; AMD Radeon(TM) Graphics (1002:13c0),32.0.21036.18; Windows11 Enterprise26200. Mesa25.2.8 llvmpipe LLVM20.1.2, Ubuntu24.04 WSL2
  • AI-assisted: yes, Codex; author responsible

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

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 1341 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 4449 docs/dev/debt/libSceAgcDriver.md
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5372 docs/dev/debt/libSceAgcDriver.md
PR 5426 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5480 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5499 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/TextureDetiler.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5656 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6044 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6146 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6185 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6249 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6501 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6611 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6612 docs/dev/debt/libSceAgcDriver.md
PR 6636 docs/dev/debt/libSceAgcDriver.md
PR 6683 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6701 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6727 docs/dev/debt/libSceAgcDriver.md
PR 6747 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6762 docs/dev/debt/libSceAgcDriver.md
PR 6763 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6786 docs/dev/debt/libSceAgcDriver.md
PR 6788 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6868 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6937 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6941 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6946 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6947 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6958 docs/dev/debt/libSceAgcDriver.md
PR 6963 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6966 docs/dev/debt/libSceAgcDriver.md
PR 6977 core/libs/prx/libSceAgcDriver/Graphics/src/TextureDetiler.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7008 docs/dev/debt/libSceAgcDriver.md
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7223 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7254 docs/dev/debt/libSceAgcDriver.md
PR 7256 docs/dev/debt/libSceAgcDriver.md
PR 7258 docs/dev/debt/libSceAgcDriver.md
PR 7332 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 7390 docs/dev/debt/libSceAgcDriver.md
PR 7395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7432 docs/dev/debt/libSceAgcDriver.md
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7505 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 7514 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 7615 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 7650 docs/dev/debt/libSceAgcDriver.md
PR 7800 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md

@jotitadev jotitadev 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.

First Linux run (the body says Linux/lavapipe is unverified). It passes on NVIDIA, but on lavapipe, which the Linux CI job uses, all six new tests fail.

Machine: NVIDIA GeForce RTX 3070, driver 595.99.02, Vulkan 1.4.329, plus lavapipe (Mesa 26.0.3, LLVM 21.1.8) on the same machine. Ubuntu 26.04 (kernel 7.0.0-38), i7-8700, GCC 15.2, Release, BUILD_TESTING=ON. Head 4681a51bd merged into main 5d9dcc42d (clean merge). It builds with GCC on Linux without the #6452 change.

RTX 3070:

  • agc_driver_multisample_readback and the _uint8/_uint16/_uint64/_uint128/_depth cases pass 3/3.
  • ctest -R "^agc|shader|recompiler" -j1 (flip, display and lds_atomics64 excluded) gives the same result as main plus the 6 new tests. The only failure is store_over_untracked, which also fails on main here (#6347).

lavapipe (VK_DRIVER_FILES=.../lvp_icd.json ANYPS5_GPU=llvmpipe):

  • All six fail right away with AGC graphics: readback fixture format does not support its sample count or extent.
  • lavapipe reports sampledImage*SampleCounts and framebuffer*SampleCounts = 1, 4, 8. There is no 2x, and the test's loop starts at {2u, 4u, 8u}. The Require in Surface throws, so the test returns 1 instead of skipping that count.
  • With a local edit that only drops 2u from that loop, all six pass on lavapipe, including D32 and the 128x64 4x depth case. So the reader itself works there.
  • The other multisample tests (native_multisample_depth, sample_mask_multisample, sample_multisample_target, multisample_fill_host_only, agc_multisample_guest_access) pass on lavapipe.

Skipping sample counts the format doesn't support would fix it, with a message such as "the device does not support 2 samples" that tools/check_skips.py accepts. Mesa 25.x lavapipe on the CI runner probably lacks 2x too, but I only checked 26.0.3.

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02), lavapipe (Mesa 26.0.3, LLVM 21.1.8), Ubuntu 26.04

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@Amoenus

Amoenus commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor Author

@jotitadev Thank you for isolating the unsupported 2x count. Fixed in 4b24b3ca0: the fixture reports unsupported format/count/extent combinations and runs the remaining counts; optional 4x cases are checked too. It skips the whole case only when no count can run or per-sample shading is unavailable. Unexpected Vulkan errors and actual readback failures still fail; production code is unchanged.

All six modes pass 5/5 on both physical Windows GPUs (RTX 5080 and AMD Radeon(TM) Graphics): 60 fresh processes, no skips, maximum 0.34 s. Full Windows build/checks and selected Cppcheck/clang-tidy diagnostics pass. The PR body records the exact validation composition and credits your Linux results.

Local Linux update: exact head 4b24b3ca0 now builds and passes all six modes 5/5 on Ubuntu 24.04 WSL2 / GCC 13.3 / Mesa 25.2.8 lavapipe (LLVM 20.1.2). This device supports 4x for these fixtures and explicitly reports 2x/8x unavailable: 30 passing processes, no whole-test skips, maximum 0.14 s. The original 4681a51bd fails all six modes 5/5 in the same environment; restoring this head passes all six again. The large D32 case passes too. This was the reader target/dependencies, not a full Linux app/suite build.

Update: thank you for confirming the corrected head on Mesa 26.0.3 and RTX 3070. Your lavapipe run supplies the requested 4x/8x coverage (all six modes 3/3; only 2x unavailable), and RTX 3070 runs 2x/4x/8x. The PR body now records your source pin and machine separately from our local results. The requested retest is complete.

Written with AI assistance (Codex); I ran the local checks above.

@jotitadev jotitadev 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.

@Amoenus, as you asked, I re-ran 4b24b3ca0 on the same Mesa 26.0.3 setup. It passes, and both 4x and 8x run there.

Machine: NVIDIA GeForce RTX 3070, driver 595.99.02, Vulkan 1.4.329, plus lavapipe (Mesa 26.0.3, LLVM 21.1.8) on the same machine. Ubuntu 26.04 (kernel 7.0.0-38), i7-8700, GCC 15.2, Release, BUILD_TESTING=ON. Head 4b24b3ca0 merged onto main 0615cd2b8, clean merge (main did not build at the time, #6784).

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02), lavapipe (Mesa 26.0.3, LLVM 21.1.8), Ubuntu 26.04

lavapipe (ctest -R multisample_readback -V, 3 runs):

  • All six pass in every run, about 0.05 s each.
  • Every mode prints samples=4 and samples=8 as passed. Each also prints one skipped, the device does not support readback fixture format=<f> samples=2 extent=17x5 layers=2. So on this Mesa only 2x is missing, not 8x as on your 25.2.8.

RTX 3070:

  • All six pass, with 2x, 4x and 8x printed for every mode.
  • ctest -R "^agc|shader|recompiler" -E "agc_display_buffer_dcc|agc_driver_flip|agc_driver_lds_atomics64|display|flip" -j1 --timeout 60: 619 tests, only agc_driver_store_over_untracked fails, which also fails on unchanged main here (#6347).

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@Amoenus
Amoenus force-pushed the codex/feat-msaa-sampled-readback branch from 3e3cf1d to 7f53a96 Compare October 18, 2026 01:30
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 18, 2026
@adriadam10 adriadam10 self-assigned this Oct 19, 2026
@adriadam10
adriadam10 merged commit 9a5726c into boykopovar:main Oct 19, 2026
10 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the reader against the diff: input validation (format, fragments, extent, element and buffer ranges, dispatch limits) throws, pipeline/pool/layout lifetime follows the detiler's ring, pipeline creation holds the cache use lock, and the fixture compares every sample, layer and pixel with sentinels and partial windows. Debt entry is under Functional. Lavapipe and NVIDIA runs by @jotitadev cover the Linux driver paths; merging through the queue.

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

Labels

agc libSceAgc* build docs unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants