Skip to content

feat(agc): publish a written native multisample D32S8 surface to its guest planes on a guest read - #13021

Merged
oneandonlydean merged 14 commits into
boykopovar:mainfrom
JAB-dev:feat/agc-publish-native-d32s8-guest-planes
Nov 3, 2026
Merged

oneandonlydean merged 14 commits into
boykopovar:mainfrom
JAB-dev:feat/agc-publish-native-d32s8-guest-planes

Conversation

@JAB-dev

@JAB-dev JAB-dev commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

What

Arcade Game Zone (PPSA19015) stops on a guest read of a native multisample D32S8 depth surface that a draw has written, with sample-preserving guest publication of native multisample depth is not implemented. With this change, a guest read now publishes the surface back to guest memory, and the title keeps playing: it ran for 27 minutes without a stop on this change together with the pull requests listed below.

A read over a written native multisample D32S8 surface (a CPU read, a DMA source, a texture, storage, index or vertex read) now reads the samples back in the guest's layer, row, column, fragment order, retiles them into the Z_X planes with the descriptor's pipe-bank XOR, and rewrites the HTILE words to the expanded clear word. The surface keeps its host image and stays resident. The planes the guest wrote are never overwritten: the guest's bytes are snapshotted when the host takes ownership (and again after a proven whole-plane clear), and a byte is taken from the host only where the write tracker proves the guest did not write it. A byte it cannot prove (the guest stored the value the byte already held, which the tracker cannot tell from no store) throws native multisample depth publication cannot distinguish an unwritten byte from a same-value guest store rather than guess. A capture that cannot be taken (a colour alias, a pending GPU write, an unproven store since import) leaves the owner unavailable for publication: draws keep rendering and a guest read throws the earlier refusal. D16 and D32-only owners, unproven clear transitions and publication inside a GPU completion still throw.

After a guest byte was merged over the host's, a later draw on that target throws guest writes over native multisample depth instead of re-importing a cleared image. Publication's own stores are recorded as possible stores, not complete ones, so the HTILE clear proof is unaffected; WriteChanged and every other caller are unchanged from main.

Late guest stores. Each changed byte is exchanged with a compare-and-swap (8-byte words when aligned, bytes otherwise) only while it still holds the snapshot value, and a part is refused when the tracker saw a CPU store since its last collect. A late store of any other value is kept and the read throws guest writes raced native multisample depth publication; planes already committed stay published and later reads throw. The one case still overwritten is a CPU store of the snapshot's own value that lands in a byte the host changes while that part commits. It is in the debt entry.

Lock order. GpuMutex, surfacesMutex, the multisample targets mutex, then guardedMutex or depthGuardMutex, then the write tracker. The allocation lease is a snapshot taken under the registry mutex and released at once, and publication drops depthGuardMutex before the colour-target lookup. Publication runs with GpuMutex held, so the flush hook re-enters it at depth 2 and never releases it while surfacesMutex is held. By reading the code, no production thread takes GpuMutex while holding the targets mutex (nothing enforces it, and some tests acquire targets without GpuMutex): acquisition, sampling, storage and resolve record commands under GpuMutex, and NoteColorMetadataFill holds the targets mutex without GpuMutex but waits on nothing. Read-guard callers without GpuMutex are game-thread host reads and the PM4 DMA-source check; they take GpuMutex as their outermost driver lock.

Other titles. NoteDepthSurfaceWrite returns at once for a single-sample target. For a multisample depth-writing draw it takes the surfaces lock, marks every active matching owner as host-written, and throws a native multisample depth attachment was retired while its draw resolved resources when no active owner matches the draw's target; it now runs after the resources and the recipe proof, so a draw that a proof or a resource build refuses no longer marks the surface written.

Evidence limits. The Z_X retile, the pipe-bank XOR and the HTILE word expansion are checked against this driver's own import path, not against an independent reading of the console. The title run was on a stack of four changes (this one, the stencil plane change, the staged 4_4_4_4 partial write change and the D32S8 import change), not on this one alone.

Tested

Windows 11, NVIDIA RTX 4070 SUPER, driver 610.88.

  • agc_driver_native_depth_publication (new): 2, 4 and 8 samples with each kind of clear; guest writes to depth, stencil and HTILE pages; a driver store of the same value; a queued fill; partial unmaps, remapped and inaccessible holes; a write during the copy; a concurrent read from two threads; a colour alias, a pending draw and publication inside a GPU completion (each throws with its own message); a draw after publishing sees the published samples; a DCC colour target over a host-written surface throws instead of deadlocking. A guest store after the last validation and one between the plane commits are kept and refused; WriteChangedIfHeld is checked on unaligned heads and tails, on a byte the host leaves alone and on a byte it changes; publication while another thread holds the GPU mutex and the multisampled target list completes once it is released. States that are valid but not implemented (a GPU completion, a colour alias, a pending draw, a same-value store, a DCC target) assert that a refusal changes no guest byte and keeps the owner, and that a publication writes only host bytes and keeps every byte the guest stored.
  • agc_driver_native_multisample_depth and the other agc_driver_native_depth_* tests, agc_driver_multisample_retirement, DepthPlaneFill, DepthSurfaceFromStorage and NativeDepthBdaClear.
  • The 79 agc_driver tests that touch draws, targets, multisampling and pipelines, and check_conventions.py.
  • Validation layers: same VUID sets as the base (main with the open D32S8 import change) in all 37 focused tests (the VUIDs are VUID-VkDeviceCreateInfo-pNext-pNext, VUID-VkPhysicalDeviceProperties2-pNext-pNext, VUID-VkGraphicsPipelineCreateInfo-renderPass-06053 and VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605, all reported by the base), and no log reports was not found but was requested by env var VK_INSTANCE_LAYERS. agc_driver_native_depth_publication reports none.
  • Arcade Game Zone: 27 minutes of play without a stop (this change, the stencil plane change and the staged 4_4_4_4 partial write change together).

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; the two imports it was built on have merged. It overlaps feat(agc): publish a written native multisample D32 depth surface to its guest planes on access #9950, which publishes a written D32 surface, in DepthSurface.cpp and its test, and the maintainers can pick the order
  • Fixes: none
  • Unblocks: PPSA19015 Arcade Game Zone (PPSA19015) #8562
  • GPUs tested: NVIDIA RTX 4070 SUPER, driver 610.88, Windows 11
  • AI-assisted: yes

🤖 Generated with Claude Code

JAB-dev and others added 2 commits October 29, 2026 23:48
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
…guest planes on a guest read

A native multisample D32S8 surface the host has written leaves its guest depth, stencil and HTILE planes stale. A guest read now takes the host samples back, retiles them into the guest layout, writes expanded HTILE words, and keeps every byte the guest itself wrote, proven by the write tracker. A byte it cannot prove (a same-value CPU store) still throws. The owner stays resident after publishing; once a guest byte was merged over the host's, a later draw on that target throws instead of re-importing a cleared image.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@JAB-dev thanks for this. The per-byte rule (take a host byte only where the tracker proves the guest did not write it, and refuse when that can't be told) is the right shape for a publication that must not clobber a title's stores. We reviewed the commit on top of the branch (0a32528: 10 files, +807/-54; the 33 commits under it are #6300's and #9533's). This is not a full verdict on the numerics: the Z_X retile, the pipe-bank XOR and the HTILE word expansion rest on MultisampleTextureLayout and expandedHtileWord as they stand. Six requests:

  1. A late guest store can still be overwritten. In Graphics/src/DepthSurface.cpp:2146-2157 the final generation and ownership checks finish before the WriteChanged calls. WriteChanged (Execution/src/GuestMemory.cpp:2865-2911) compares the host result with the earlier snapshot, not with what the destination holds now, and its storeOwn helper collects CPU stores without rejecting a new one. A guest CPU thread that stores into a live plane after those checks, before that plane is committed, loses its byte. For example: the snapshot byte is 0x11, the host byte is 0x22, and the guest stores 0x7e after validation; the result is still 0x22. The same window exists between the depth and the stencil/HTILE commits, and it doesn't have to be the byte that triggered the read. The allocation lease stops remapping, but the GPU and surface mutexes don't exclude ordinary CPU stores. Please make the final validate/merge/commit safe against those stores, keeping the late byte or refusing before the overwrite. Please also add deterministic tests: one with a store after the last validation, and one with a store between plane commits. The current CopyRace hook fires at GuestCopied, before the final checks, so it can't catch this case.

  2. Lock order. RequireNoResidentDepthRead now calls publishWrittenDepth. That function blocks on the GPU mutex and takes surfacesMutex; PublishToGuest then takes the multisample-targets mutex (via MultisampleColorTargetOver), the depth-guard mutex, the allocation lease and the tracker. The read guard can run on a game thread that holds none of these. MultisampleTarget.cpp has paths that hold the targets mutex and then call GuestMemory::FlushGpuWrites (for example createFilled), and its hook takes the GPU mutex (FlushForAccess). If such a thread doesn't already own the GPU mutex, the two threads can wait on each other. HoldsMultisampleTargetsLock covers only the same-thread case. Please:

    • write down the lock order you rely on;
    • say which callers of the read guard can reach it without the GPU mutex;
    • add a test where one thread holds the targets mutex inside a multisample-target acquisition while another reads the written depth surface.

    The same shape hung a title on fix(agc): save the guest bytes of results that become pending over a surface that is no longer fully write-watched #7048 recently.

  3. feat(agc): publish a written native multisample D32 depth surface to its guest planes on access #9950 defines the same member. feat(agc): publish a written native multisample D32 depth surface to its guest planes on access #9950 adds DepthSurface::PublishToGuest for D32 owners, and both PRs rewrite the same guard in RequireNoResidentDepthRead, the same tests and the same debt line. They conflict in three files and can't both land as they are. Please agree an order with the feat(agc): publish a written native multisample D32 depth surface to its guest planes on access #9950 author and end with one PublishToGuest that keeps feat(agc): publish a written native multisample D32 depth surface to its guest planes on access #9950's D32 publication and its missing-detiler test coverage alongside your D32S8 three-plane path. The D32S8 owner gate is not a replacement for the D32 path. The D16 unsupported path stays a separate limitation; we aren't asking for D16.

  4. Behaviour outside the feature. Two edits reach every title, not only D32S8 owners:

    • WriteChanged now stores with complete = false for every caller, including the GPU buffer write-backs;
    • NoteDepthSurfaceWrite moves in prepareDraw and DrawWithRecipe from before the resource lookup to after it.

    Please say why neither changes what the fast proofs accept on other paths. Back it with the proof-hit/miss counters, or a frame-time pair, from a title that doesn't use this feature, on the same machine and settings as main.

  5. Tests. Several new checks require a valid but unsupported state to throw a specific message: publication inside a GPU completion, a colour alias, a pending draw, a same-value guest store, and a DCC target over a host-written surface. Please assert the property that matters instead: the guest planes keep every byte they held and the owner is retained. Accept either a refusal or a later implementation, as on feat(agc): back extra guest mip levels with storage images #7085. Keep the "a refused publication changed no guest bytes" check.

  6. Dependencies and the conventions check. The body says the title ran "together with the pull requests listed below", but no list follows, and it doesn't name feat(agc): import cleared native multisample D32S8 targets and whole HTILE fills #6300, fix(agc): import native multisample D32S8 targets with a separate stencil plane and a depth-only HTILE #9533 (this branch contains both) or fix(agc): import a native multisample D32S8 target whose stencil plane the guest stored its clear value into #13023. The failing conventions check wants the dependency field in its accepted form, starting with #9533. Please list them as Depends on in order, and explain the feat(agc): publish a written native multisample D32 depth surface to its guest planes on access #9950 overlap separately. The debt-length finding is only a warning.

Evidence limits worth stating in the description: the retile and the XOR are checked against your own import path, not against an independent console reading, and the title run was on a stack of four changes, not on this one alone. #13023 is built on this branch, so it waits for these changes.

@github-actions

github-actions Bot commented Oct 29, 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 9489 docs/dev/debt/libSceAgcDriver.md L64-65
PR 10469 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp L10, L904, L906-907, L2231, L2665-2666, L2680, L2683-2684
core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp L5, L2682-2683
docs/dev/debt/libSceAgcDriver.md L68
PR 10492 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp L10, L904, L2231, L2680, L2683-2684
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_native_multisample_depth_tests.cmake L20
core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp L5, L2681-2683
docs/dev/debt/libSceAgcDriver.md L68
PR 10497 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp L10, L904, L906-907, L2231, L2665-2666, L2680, L2683-2684
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_native_multisample_depth_tests.cmake L20
core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp L5, L2681-2683
docs/dev/debt/libSceAgcDriver.md L68
PR 10678 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp L3114
PR 12840 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp L55
PR 13963 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L1364-1365, L1371-1372, L1379-1380, L1467-1468, L1503-1504
PR 14051 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp L3114
PR 14084 core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp L2681-2682
PR 14137 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp L2167

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1368 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 2434 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
PR 5021 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6187 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 6192 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6209 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6280 docs/dev/debt/libSceAgcDriver.md
PR 6412 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6481 docs/dev/debt/libSceAgcDriver.md
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6804 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7464 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7604 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7668 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7689 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 7978 docs/dev/debt/libSceAgcDriver.md
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8246 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 8707 docs/dev/debt/libSceAgcDriver.md
PR 9012 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 9020 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9289 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9318 docs/dev/debt/libSceAgcDriver.md
PR 9335 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9508 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9592 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
docs/dev/debt/libSceAgcDriver.md
PR 9673 docs/dev/debt/libSceAgcDriver.md
PR 9674 docs/dev/debt/libSceAgcDriver.md
PR 9675 docs/dev/debt/libSceAgcDriver.md
PR 9700 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9712 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9748 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9852 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9897 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 9915 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9950 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10049 core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10249 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 10256 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10359 docs/dev/debt/libSceAgcDriver.md
PR 10442 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 10894 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 10920 core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp
PR 11435 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 11436 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 11444 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 11452 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 11483 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 11551 core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 11825 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 11995 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 11998 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 12565 docs/dev/debt/libSceAgcDriver.md
PR 12828 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 12904 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13148 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 13486 core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13599 docs/dev/debt/libSceAgcDriver.md
PR 13707 docs/dev/debt/libSceAgcDriver.md
PR 13793 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13796 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 13809 core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13858 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13863 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13920 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13928 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13929 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/MultisampleTarget.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13994 docs/dev/debt/libSceAgcDriver.md
PR 14032 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
PR 14212 docs/dev/debt/libSceAgcDriver.md
PR 14217 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 14218 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 14261 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
PR 14262 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 14344 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14871 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 14943 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14944 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14964 docs/dev/debt/libSceAgcDriver.md
PR 14969 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 15015 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
PR 15058 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15059 core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
PR 15136 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15169 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15302 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
PR 15529 core/libs/prx/libSceAgcDriver/Execution/include/GuestMemory.hpp
core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
docs/dev/debt/libSceAgcDriver.md
PR 15548 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
docs/dev/debt/libSceAgcDriver.md
PR 15570 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp

… still holds the snapshot

A guest store that landed after the last publication check, or between the
plane commits, was overwritten by the host byte. The commit now exchanges
each changed byte only while it still holds the snapshot value, refuses the
whole part when the tracker saw a CPU store since the last collect, and
throws when any byte was lost, keeping the guest's byte. WriteChanged keeps
its previous behaviour for every other caller.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…for a held target list

The tests for states that are valid but not implemented required one exact
refusal message. They now accept a refusal or a later implementation: a
refusal must change no guest byte, and a publication must write only host
bytes and keep every byte the guest stored. A new case publishes while another
thread holds the GPU mutex and the multisampled target list.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@TechLevelZero

TechLevelZero commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

❌ NVIDIA GPU test: failed

PR head 94e65ca merged onto main 98ddd9c · tested 2026-10-30 14:18 UTC · 29 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,370 passed · 6 failed (0 new, 2 also fail on main, 4 unstable on main) · 41 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,417 of 2,987 tests run: the ones this change can reach, chosen by tools/select_tests.py from main's build graph
Vulkan validation ❌ 1 new validation ID(s) vs main (910 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) none

New validation errors

This PR changes test files, so each test below was also run on main with only the PR's test changes applied; 0 there means the PR's other changes cause the error.

ID Test main 98ddd9c main + this PR's test changes only PR PR, test re-run alone
VUID-vkCmdCopyBuffer-commonparent agc_driver_depth_clear_hle 0 not compared: tests do not build on main 6 6 (in 2 runs)
agc_driver_depth_clear_hle: new validation messages
VUID-vkCmdCopyBuffer-commonparent(ERROR / SPEC): msgNum: -1223163212 - Validation Error: [ VUID-vkCmdCopyBuffer-commonparent ] Object 0: handle = 0x705b90006550, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0xb71802b4 | vkCmdCopyBuffer(): srcBuffer (VkBuffer 0x3d900000003d9) was created, allocated or retrieved from VkDevice 0x610eb45ae520[], but command is using (or its dispatchable parameter is associated with) VkDevice 0x705b9016f560[]. The Vulkan spec states: Each of commandBuffer, dstBuffer, and srcBuffer must have been created, allocated, or retrieved from the same VkDevice (https://www.
VUID-vkCmdCopyBuffer-commonparent(ERROR / SPEC): msgNum: -1223163212 - Validation Error: [ VUID-vkCmdCopyBuffer-commonparent ] Object 0: handle = 0x705b90006550, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0xb71802b4 | vkCmdCopyBuffer(): dstBuffer (VkBuffer 0x3dd00000003dd) was created, allocated or retrieved from VkDevice 0x610eb45ae520[], but command is using (or its dispatchable parameter is associated with) VkDevice 0x705b9016f560[]. The Vulkan spec states: Each of commandBuffer, dstBuffer, and srcBuffer must have been created, allocated, or retrieved from the same VkDevice (https://www.
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_depth_clear_hle: failed in 1 of the last 8 main runs
agc_driver_submit_progress: failed in 5 of the last 8 main runs
agc_submit_progress: failed in 5 of the last 8 main runs
agc_submit_progress_no_timeline: failed in 6 of the last 8 main runs
Failing on main too (2, not counted against this PR)
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 110 other runs in the last 7 days
Validated but not compared (7, not in the main baseline's validation pass)
agc_driver_native_depth_aliased_stencil
agc_driver_native_depth_driver_path
agc_driver_native_depth_driver_queued_fill
agc_driver_native_depth_expand_gate
agc_driver_native_depth_publication
agc_driver_native_depth_separate_stencil
agc_driver_native_depth_stencil
Validation IDs already present on main (4 IDs in 425 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (425 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_array_layer_target_cpu, agc_driver_bda_span_reads_draw_pipeline, agc_driver_bindless_images, agc_driver_branch_past_endpgm, and 417 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 (41)
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_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_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 not available in current SDL video driver (offscreen) or plat
Reproduce
git fetch origin 94e65cabcc326ae8f77d5f134c15748435cf06cf 98ddd9c1792bbab016ceed5db267a93d1d61f00a
git checkout 98ddd9c1792bbab016ceed5db267a93d1d61f00a && git merge --no-ff 94e65cabcc326ae8f77d5f134c15748435cf06cf
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_driver_depth_clear_hle)$' --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.

@bunbeans2-arch

Copy link
Copy Markdown
Contributor

Data point on Windows with AMD's driver: AMD Radeon RX 9070 XT (RDNA 4), driver 32.0.32015.7029, Windows 11 Pro 22631, MSYS2 UCRT64 GCC 16.1, Release, BUILD_TESTING=ON, with the Khronos validation layer loaded.

Tree: main 409fe64199 with this PR merged on top (it merges cleanly). Every test executable was rebuilt for the tree before running. 3 of 3 runs, the same each time, 0 VUID- lines:

  • Pass: the 6 new tests agc_driver_native_depth_stencil, native_depth_separate_stencil, native_depth_aliased_stencil, native_depth_expand_gate, native_depth_publication and native_depth_driver_path.
  • Also pass, as on main: agc_driver_native_multisample_depth, native_depth_bda_clear, native_depth_retirement, native_depth_clears, native_depth_clear_refusals, sample_multisample_target and cached_image_multisample_guard.
  • Skipped: agc_driver_native_depth_driver_queued_fill. In a verbose run (of the fix(agc): import a native multisample D32S8 target whose stencil plane the guest stored its clear value into #13023 build, which contains this PR) it prints skipped, host imports are compared here, not write-watched, and a queued fill's HTILE proof needs a write-watched import. So its HTILE check does not run on this Windows setup. (The same process reports host imports of write-watched memory keep the write watch: yes.)

#13023 (this PR plus one commit) gives the same results on the same machine.

AI-assisted: yes (Claude Code)

@oneandonlydean oneandonlydean self-assigned this Oct 30, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 30, 2026
# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
#	core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
@JAB-dev

JAB-dev commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks, pushed the changes for requests 1, 2, 4, 5 and 6; request 3 needs your call.

  1. The commit now exchanges each changed byte with a compare-and-swap only while it still holds the snapshot value, and refuses a part when the tracker saw a CPU store since its last collect. A late store of another value is kept and the read throws; the one case still overwritten is a store of the snapshot's own value landing during that part's commit (stated in the debt entry). New tests: a store after the last validation, a store between the plane commits, and WriteChangedIfHeld on unaligned heads and tails.
  2. The lock order is in the description. Publication still blocks on the targets mutex while holding GpuMutex: I tried a non-blocking lookup and dropped it, because no production path takes GpuMutex while holding the targets mutex, so it would only have added rare refusals. New test: another thread holds GpuMutex and the targets mutex while a read publishes; the read completes once it is released.
  3. The D32 publication PR is further along. Which order do you prefer: this one rebased onto it with its D32 path kept and the D32S8 three-plane path added beside it in one PublishToGuest, once it merges?
  4. WriteChanged is back to its main behaviour for every other caller; publication has its own stores. NoteDepthSurfaceWrite returns at once for single-sample targets and only sets a flag no proof reads.
  5. The states that are valid but not implemented now assert that a refusal changes no guest byte and keeps the owner, and that a publication writes only host bytes and keeps every byte the guest stored.
  6. Depends on lists the two earlier PRs in order, and the overlap with the D32 publication PR is explained separately; the stencil-plane PR depends on this one.

Rebase: main moved on by 1,200 commits and now conflicts with the import PR this one depends on in MultisampleTarget.cpp and DepthSurface.cpp: its guard() still takes the hostOnly flag that main replaced with the TargetUse model. I merged main into this branch in bb085f7a40 and resolved those two files by taking main's guard and claimOverlapping and keeping both sides' additions. That resolution is not part of this PR's change and drops out once that PR is rebased; I did not touch its branch. The 79 scoped agc_driver tests and the depth plane tests pass on the merged head.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 30, 2026

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

Linux run of head bb085f7a40, since the description and the AMD data point are both Windows. On Linux NVIDIA the queued-fill HTILE check that skips on bunbeans2-arch's RX 9070 XT does run.

Setup: Ubuntu 26.04, GCC 15.2, Release. RTX 3070 (NVIDIA 595.99.02) and lavapipe (Mesa 26.0.3), one at a time via VK_DRIVER_FILES. Khronos validation layer 1.4.341, ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1, ctest -j1. The head merged --no-ff onto current main de96e3efbd with no conflicts. Every executable of the focused set was rebuilt for the tree.

  • Focused set, 15 tests: agc_driver_native_multisample_depth, the agc_driver_native_depth_* tests (including publication, driver_path and driver_queued_fill), multisample_retirement, depth_plane_fill and depth_surface_from_storage. 15/15 in 3 of 3 runs on each device, 0 VUID- lines.
  • agc_driver_native_depth_driver_queued_fill is not skipped here:
    • RTX 3070: cases checked=6 unavailable=0. Each case prints cleared by a queued DMA_DATA fill of 128 KiB from its HTILE through the driver and sampled.
    • lavapipe: cases checked=4 unavailable=2. The 2-sample cases are the unavailable ones; the 4- and 8-sample cases pass.
    • So the HTILE proof that bunbeans2-arch's Windows AMD setup skips ("host imports are compared here, not write-watched") is exercised on Linux NVIDIA.
  • agc_driver_native_depth_bda_clear skips on lavapipe (the device does not keep write watching for native clear imports), as on main.
  • Full ^agc suite (without display/flip/lds_atomics64, no layer, --timeout 60) on #13023's head, which contains this branch: 1136/1136 on the RTX 3070 and 1136/1136 on lavapipe.
  • ninja all plus every agc*_tests target builds. GCC prints no warnings on the lines this PR adds.

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02, Linux); lavapipe (Mesa 26.0.3, Linux).

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

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head bb085f7 merged onto main 6b48aee · tested 2026-10-31 03:41 UTC · 30 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,415 passed · 4 failed (0 new, 3 also fail on main, 1 unstable on main) · 42 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,461 of 3,041 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 (915 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 47.9 s, ⚠️ agc_driver_graphics 32.4 s, ⚠️ agc_driver_graphics_maps_fallback 30.5 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 6 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (7, not in the main baseline's validation pass)
agc_driver_native_depth_aliased_stencil
agc_driver_native_depth_driver_path
agc_driver_native_depth_driver_queued_fill
agc_driver_native_depth_expand_gate
agc_driver_native_depth_publication
agc_driver_native_depth_separate_stencil
agc_driver_native_depth_stencil
Validation IDs already present on main (4 IDs in 421 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (421 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 413 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 (1 test): agc_driver_srgb8_color_target
Skipped (42)
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_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_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 not available in current SDL video driver (offscreen) or plat
Reproduce
git fetch origin bb085f7a404b24d6b4ee547c14f504d693775549 6b48aee5d2ea9fce6155163d78f8ce8dc84f7827
git checkout 6b48aee5d2ea9fce6155163d78f8ce8dc84f7827 && git merge --no-ff bb085f7a404b24d6b4ee547c14f504d693775549
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.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 31, 2026
# Conflicts:
#	core/libs/prx/libSceAgcDriver/CMakeLists.txt
#	core/libs/prx/libSceAgcDriver/Graphics/include/DepthSurface.hpp
#	core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
#	core/libs/prx/libSceAgcDriver/tests/execution/NativeMultisampleDepth.cpp
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 31, 2026
@EagleBearerYS

Copy link
Copy Markdown
Contributor

On the order with #9742 (a colour alias over a native multisample depth plane when HTILE proves its clear), which conflicts with this PR in MultisampleTarget.hpp, MultisampleTarget.cpp and the AGC debt file: this PR can go first, and #9742 resolves the conflict after it, keeping both sides. #9742's MultisampleColorTargetsOver takes this PR's TargetsLock, and the debt file keeps this PR's "Native D32S8 guest publication" entry and its edit of "Native multisampled depth sampling" beside #9742's two "under a colour target" entries.

They also meet in a title. In Ghost of Tsushima Director's Cut (PPSA02225), the run with #9742 next stops on sample-preserving guest publication of native multisample depth is not implemented (xXPBSXx's run), the line this PR adds a D32S8 path in front of.

#9742's checklist now says Depends on: #13021 (merge order only).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 3, 2026
…ve-d32s8-guest-planes

# Conflicts:
#	core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp
#	docs/dev/debt/libSceAgcDriver.md

@XairRrR XairRrR 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 — approved

The only change since my last review is a merge of main (0180bafe62). It resolves the conflicts in GuestMemory.cpp and the AGC debt file correctly, and it brings in #14005's D32S8 owner without HTILE. The PR now refuses that owner cleanly. The focused depth tests pass. The one new validation message the script reported comes from main's own test, not from this PR.

What changed since my last review

  • The PR's five commits (0a3252876f to f6e7798ba9) are unchanged. The range-diff shows = for each one.
  • One new commit, 0180bafe62, merges origin/main 4f41f4c375. It resolves conflicts in Execution/src/GuestMemory.cpp and docs/dev/debt/libSceAgcDriver.md:
    • GuestMemory.cpp: main (#6185) split WriteChanged into a static writeChanged(..., keepGuest) and added WriteChangedKeepingGuest. The merge keeps both of main's functions unchanged. The PR's own additions sit beside them: cpuUnchanged, UnchangedSinceLastCollect, the walked parameter of rangeUnchanged (default true, so existing callers behave as before), storeOwn's complete parameter (default true) and WriteChangedIfHeld. WriteChanged is still main's for every other caller.
    • Debt file: the merge keeps main's edits to the "Native multisampled depth sampling" entry. It also keeps the PR's dropped "Guest publication of a written surface" phrase, which was oneandonlydean's earlier request, and the new "Native D32S8 guest publication" entry.
  • From main, #14005 adds uniformPlaneTarget: D32S8 with a separate stencil plane and no HTILE, whose sampling.initial has 2 ranges ({depth, stencil}). I checked how the PR handles these owners:
    • NoteHostWrite captures both ranges (DepthSurface.cpp:797).
    • PublishToGuest then refuses with ... not implemented for this owner, because publication.size() == 3u fails (DepthSurface.cpp:2170). This happens before any readback dispatch.
    • RebasePublication(2u) and RebasePublication(1u) cannot index out of range for these owners. The stencil-fill path that sets stencilClearGeneration requires sampling.initial.size() > 2u. Both places that set clearGeneration need an HTILE range, and this owner has none.
    • So a guest read of a written owner without HTILE still throws, as it does on main, only with a different message.
  • No author replies and no description edits since my last review.

What I ran

Head 0180bafe62f4dee4cdc04aee0d565be70c838460, main 4f41f4c375f5abb487dbd184fbc150f31994d762, merged --no-ff (tree d8eebd68d272cf9c6f239d7842d913b1dfd5119b) in a clean worktree. The machine is a Debian 13 VM with 2× Xeon Gold 6136, GCC 14.2.0 and lavapipe (Mesa 26.1.6, LLVM 19). It has no GPU.

git show --stat 0180bafe62f4dee4cdc04aee0d565be70c838460
git diff 4f41f4c375f5abb487dbd184fbc150f31994d762 d8eebd68d272cf9c6f239d7842d913b1dfd5119b -- core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp docs/dev/debt/libSceAgcDriver.md
git diff d1ae628bc2f62459cce1e9872ba5632c938c71f2 4f41f4c375f5abb487dbd184fbc150f31994d762 -- core/libs/prx/libSceAgcDriver/Execution/src/GuestMemory.cpp core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp
git diff --check 4f41f4c375f5abb487dbd184fbc150f31994d762...0180bafe62f4dee4cdc04aee0d565be70c838460
python3 tools/check_conventions.py --base 4f41f4c375f5abb487dbd184fbc150f31994d762
ctest --test-dir build -j8 --test-load 32 --output-on-failure -R "agc_driver_native_depth|agc_driver_native_multisample_depth|multisample_retirement|depth_plane_fill|depth_surface_from_storage|stencil_write_intent"
VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 ctest --test-dir build -V -R "^agc_driver_native_depth_uniform_planes$"
diff <(git show 4f41f4c375:…/NativeMultisampleDepth.cpp | sed -n '/^void CheckUniformPlanesWithoutHtile/,/^}/p') <(sed -n '/^void CheckUniformPlanesWithoutHtile/,/^}/p' …/NativeMultisampleDepth.cpp)
git status --porcelain
Check Result
git diff --check clean
check_conventions.py 0 errors, 1 warning: the debt entry at docs/dev/debt/libSceAgcDriver.md:69 has 3982 characters (unchanged)
Configure / build / libs (script) ok
Selected tests (script, 2230 run) 0 new failures, 0 timeouts. 7 known failures also fail on main: agc_driver_division, the denormal-mode tests, vector_constant_factor_tininess and unwrap_self_…
Skips (script) 114, all expected according to check_skips.py
Validation (script, 770 tests, layer loaded in 769, none missing) 1 test with a VUID not in the baseline: agc_driver_native_depth_uniform_planes, a test the baseline did not run. It comes from main; details below
Focused set (18 tests) 17 passed. 1 skipped: agc_driver_native_depth_bda_clear, which skips on lavapipe on main too
Where the VUID-vkCmdDispatch-groupCountX-00386 comes from
Native D32S8 without HTILE, samples=4: uniform planes imported and sampled, other planes refused
Validation Error: [ VUID-vkCmdDispatch-groupCountX-00386 ] | MessageID = 0x8e927036
vkCmdDispatch(): groupCountX (69144) exceeds device limit maxComputeWorkGroupCount[0] (65535).
… (4 times)
Native D32S8 without HTILE, samples=8: uniform planes imported and sampled, other planes refused
  • 69144 = 129 × 67 × 8. That is the test-side fetch.Run(batch.Handle(), extent.width * extent.height * samples) in CheckUniformPlanesWithoutHtile, which issues one workgroup per sample. It runs twice per value pair: once for the depth fetch and once for the stencil fetch.
  • That function came from main with #14005. It is byte-identical in the merged tree (the diff above prints nothing).
  • None of the PR's dispatches run for this owner: PublishToGuest refuses before its readback.
  • So this is not a finding against this PR. It belongs to #14005's test on main, which should split the dispatch across X/Y.

I tried a second check: restore main's versions of the PR's files and rebuild, to rerun the test on main directly. The build tree could not be regenerated in this sandbox: configure_file fails with "Operation not permitted". I restored the merged files without rebuilding anything, so the binaries I tested are the script's build of the merged tree. git status --porcelain is empty.

Previous findings

  1. NoteDepthSurfaceWrite throws for every multisample depth draw when no active surface matches (now DepthSurface.cpp:2741). Still open, non-blocking. The code is unchanged and the description still does not mention this throw.
  2. Unmeasured capture cost on the draw path: NoteHostWrite (now DepthSurface.cpp:792-808) copies every plane on each false-to-true flip. Still open, non-blocking. It now also runs for #14005's owners without HTILE, which can never be published (see the new finding), so that copy buys nothing for them. There are still no frame-time numbers.
  3. The debt entry does not mention the "another identity" refusal (now DepthSurface.cpp:2848), and the entry is 3982 characters. Still open, non-blocking. The debt file still does not mention it.

New findings

Blocking

None.

Non-blocking

  • Owners without HTILE now reach PublishToGuest and are refused, but neither the debt entry nor the description says so (core/libs/prx/libSceAgcDriver/Graphics/src/DepthSurface.cpp:2170, docs/dev/debt/libSceAgcDriver.md:68).
    • In the 2026-11-02 reply to hugodearaujo, the author said "an owner without HTILE cannot exist on this branch". That was true then. With #14005 merged into main, a two-plane D32S8 owner now exists.
    • On a guest read after a draw, such an owner throws sample-preserving guest publication of native multisample depth is not implemented for this owner.
    • The new debt entry lists only "D16/D32-only owners" among the owners that throw.
    • Suggested fix: add "D32S8 owners without HTILE" to that list. Alternatively, now that the two-plane owner and its --uniform-planes fixture are on main, take hugodearaujo's two-plane change (skip the HTILE rewrite when there is none) as a follow-up.
    • Either way, skip the capture in NoteHostWrite for owners that cannot be published.

Not verified

  • Running agc_driver_native_depth_uniform_planes on main directly: the build tree could not be regenerated in this sandbox. Its VUID is attributed to main by reading the code: the function that emits it is unchanged from main, and the dispatch size matches the test's own fetch.
  • The Z_X retile, the pipe-bank XOR and the HTILE word expansion against console behaviour. They are only checked against this driver's own import path.
  • The title runs (PPSA19015, PPSA06866) and any hardware GPU: this machine only has lavapipe.
  • The recordDispatch / StartDrawPass ordering still has no test. I checked it only by reading the merged code.
  • No negative control this round. The PR's tests are unchanged and the new commit is only a merge. In an earlier round, two production mutations each made agc_driver_native_depth_publication fail.

@github-actions github-actions Bot added review queue Next in the maintainer review queue: checks pass, no open change request, no conflict and removed needs rebase Conflicts with main, rebase needed labels Nov 3, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 0180baf merged onto main 4f41f4c · tested 2026-11-03 12:03 UTC · 46 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,760 passed · 6 failed (0 new, 3 also fail on main, 3 unstable on main) · 48 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,814 of 3,811 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 120.1 s, ⚠️ public_headers 30.8 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 4 of the last 10 main runs
agc_submit_progress: failed in 6 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 5 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 517 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (517 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 509 more
VUID-vkCmdCopyImage-srcImage-01548 (9 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, agc_driver_stencil_null_feedback, and 1 more
VUID-vkCmdCopyImage-srcImage-01551 (9 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, agc_driver_stencil_null_feedback, and 1 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (48)
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_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
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_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 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 co
Reproduce
git fetch origin 0180bafe62f4dee4cdc04aee0d565be70c838460 4f41f4c375f5abb487dbd184fbc150f31994d762
git checkout 4f41f4c375f5abb487dbd184fbc150f31994d762 && git merge --no-ff 0180bafe62f4dee4cdc04aee0d565be70c838460
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.

@xXPBSXx

xXPBSXx commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

PPSA02801 on Windows with an NVIDIA GeForce RTX 4080 SUPER (driver 32.0.16.1074), two 600 s runs per arm, libraries built for each arm:

Arm Commit Run (UTC, 2026-11-03) How it ends
main 4f41f4c375 11:26:50 to 11:27:07 sample-preserving guest publication of native multisample depth is not implemented
main 4f41f4c375 11:28:57 to 11:29:14 the same, at SET_CONTEXT_REG_INDIRECT
this PR 0180bafe62 (its merge of 4f41f4c375) 10:32:50 to 10:33:16 native multisample depth publication with an unapplied clear is not implemented
this PR 0180bafe62 10:35:19 to 10:35:47 native multisample depth publication cannot distinguish an unwritten byte from a same-value guest store, at SET_CONTEXT_REG_INDIRECT

The build of the PR arm had one library fewer than the main build (libMozaSDK.prx was not built there; PPSA02801 does not import it: 0 hits in its imports).

On main the title stops at the refusal this PR replaces; with this PR that refusal does not occur in either run, and the title runs a little longer before it stops at one of the two new refusals in the publication path. These are single runs on AnyPS5; what the picture showed was not looked at.

AI-assisted (Claude Code).

@JAB-dev

JAB-dev commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

That order works for us: the sampling PR before this one, and the colour-alias PR after it. If the sampling PR is ready first, this PR merges main on top and takes its stencilRead form in refreshSampleShadow; the colour-alias PR keeps both sides as you describe.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head 0180baf merged onto main 4f41f4c · tested 2026-11-03 17:00 UTC · 36 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,746 passed · 10 failed (0 new, 8 also fail on main, 2 unstable on main) · 58 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,814 of 3,811 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 (932 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 121.4 s, ⚠️ agc_driver_image_sample_unnormalized 61.0 s, ⚠️ agc_driver_lazy_resolved_abi 50.0 s, ⚠️ public_headers 49.1 s, ⚠️ agc_driver_stream_copy 48.9 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 7 of the last 9 main runs
agc_driver_store_over_untracked: failed in 1 of the last 9 main runs
Failing on main too (8, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_driver_submit_progress
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_recorder: Timeout in the parallel run; also passed only on retry in 8 other runs in the last 7 days
Validated but not compared (1, not in the main baseline's validation pass)
guest_job_manager_worker_spin_scale_10
Validation IDs already present on main (4 IDs in 517 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (517 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 509 more
VUID-vkCmdCopyImage-srcImage-01548 (8 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth, agc_driver_stencil_null_feedback, agc_driver_stencil_plane_memory
VUID-vkCmdCopyImage-srcImage-01551 (8 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth, agc_driver_stencil_null_feedback, agc_driver_stencil_plane_memory
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (58)
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_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
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_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
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: DisplayW
Reproduce
git fetch origin 0180bafe62f4dee4cdc04aee0d565be70c838460 4f41f4c375f5abb487dbd184fbc150f31994d762
git checkout 4f41f4c375f5abb487dbd184fbc150f31994d762 && git merge --no-ff 0180bafe62f4dee4cdc04aee0d565be70c838460
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 12 --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 16 --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 AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@JJenkx

JJenkx commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Cross-title data from Spirit of the Island (PPSA13934), Windows / RX 6700 XT. Not a review of the change itself.

On main 4f41f4c375, 3 of 9 runs of a scripted new game stop at about 300 s with your message:

[videoout] presentation failed: AGC graphics: sample-preserving guest publication of native multisample depth is not implemented

That is DepthSurface.cpp:2456 (Require(!range.hostWritten ...)).

With this PR, I made a local merge onto 4f41f4c375 (6c44ca8a85; only libSceAgcDriver.prx differs). For four of the runs I added a one-line fprintf at the start of DepthSurface::PublishToGuest that prints the target format.

Run Result PublishToGuest entered
plain 1 clean to 331 s not logged
plain 2 access violation at 285.4 s (unrelated heap corruption, #15350) not logged
plain 3 access violation at 218.1 s (same) not logged
plain 4 clean to 331 s not logged
logged 1 clean to 331 s no
logged 2 clean to 331 s no
logged 3 299.8 s: guest writes over native multisample depth are not implemented no
logged 4 285.6 s: guest memory is not readable at 0x4dfac00000008 (heap corruption) no

So for this title, the original throw no longer appeared in 8 runs. At the same point in the game, though, one run stopped on guest writes over native multisample depth are not implemented (in the merged tree at DepthSurface.cpp:561 or :584), and PublishToGuest was never entered in any logged run. I can't tell from these logs whether Spirit's surface is D32S8 or D32 (#9950). Spirit may need guest writes merged over the surface rather than a guest read publishing it.

Nothing here argues against the change for PPSA19015. It just doesn't move Spirit past this point.

AI-assisted: yes.

@JJenkx

JJenkx commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Follow-up on the Spirit of the Island (PPSA13934) note above. The surface is D32S8, so this PR's format applies to it.

I logged each native depth guard as main 4f41f4c375 creates it (a local fprintf at the depthGuards().push_back in DepthSurface.cpp):

[guarddiag] guard <addr>+0x800000 format=130 samples=8
[guarddiag] guard <addr>+0x200000 format=130 samples=8
[guarddiag] guard <addr>+0x8000   format=130 samples=8

That is VK_FORMAT_D32_SFLOAT_S8_UINT (130) at 8 samples: depth, stencil and HTILE ranges of the same surface. So #9950 (D32) doesn't apply here. With this PR, the stop I reported was the guest-write path (guest writes over native multisample depth are not implemented), reached before any guest read publishes the surface. Spirit would need guest writes merged into the 8-sample D32S8 planes on top of this PR. I take that as a follow-up, not a defect in this change.

AI-assisted: yes.

@oneandonlydean
oneandonlydean merged commit 0e7d4a2 into boykopovar:main Nov 3, 2026
14 checks passed
@github-actions github-actions Bot removed the review queue Next in the maintainer review queue: checks pass, no open change request, no conflict label Nov 3, 2026
oneandonlydean pushed a commit that referenced this pull request Nov 4, 2026
#13021 takes the multisample targets lock through TargetsLock, which marks the
lock held for HoldsMultisampleTargetsLock; MultisampleColorTargetsOver takes it
the same way. Its declaration sits beside WithMultisampleTargetsLockForTest.
The debt file keeps #13021's guest publication entry and its edit of the
depth sampling entry, then this branch's two colour-target entries.
oneandonlydean pushed a commit that referenced this pull request Nov 4, 2026
Draw.cpp conflicts where #13021 notes a depth surface write after the draw's
resources are resolved. Both are kept, with the injected stop after resolve
first, so an injected failure notes no depth write.
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.