Skip to content

fix(agc): keep a CPU store that rewrote a pending block with its baseline bytes - #14302

Merged
oneandonlydean merged 7 commits into
boykopovar:mainfrom
hugodearaujo:fix/agc-storage-cpu-rewrite
Nov 3, 2026
Merged

oneandonlydean merged 7 commits into
boykopovar:mainfrom
hugodearaujo:fix/agc-storage-cpu-rewrite

Conversation

@hugodearaujo

Copy link
Copy Markdown
Contributor

What

A storage image write-back keeps the CPU's bytes in a 64 KiB block the write watch stamped after the layer's generation. #1599 made one exception: if the stamped range still holds the image's baseline bytes (the guest bytes the image was uploaded from), the GPU results are stored anyway. The debt file already lists the gap: a CPU store that writes the baseline value back after the GPU changed it can't be told apart from no store, so the GPU result wins.

Control (PPSA34547) runs into exactly that gap. It writes its per-frame constant buffers over memory that a storage image (format 13 or 29) still covers with pending results. The constants it writes match the bytes the image was uploaded from. A dispatch then binds that memory as a buffer, and the imported buffer region flush stores the stale texels over the constants. Several shaders take loop counts from those constant buffers (s_buffer_load_dword → s_cmp_lt_u32 loop, for example program 0x1004260100 at pc 0xaec), so they read texel pairs as counts (0x43954395, 0x46d446d4, 0x025a000c).

  1. fix(agc): keep a CPU store that rewrote a pending block with its baseline bytes

    • markLayersPending now records the write generation of each layer's last GPU results. When a layer first becomes pending, it collects the layer's range first, so CPU stores from before the results get older stamps.
    • In the keep decision (writeBackLayers, and the same rule in saveBeforeUnwatch), a range whose bytes equal the baseline still stores the GPU results, except when the range is a whole 64 KiB block of the layer and a CPU store (ChangedBlocks' CPU flag) reached it after that generation. In a whole block every stamped page holds the layer's own bytes, so that store is the later write, whatever value it wrote.
    • Edge blocks keep fix(agc): store GPU results over CPU-stamped bytes the CPU left unchanged #1599's byte comparison, because their stamps can come from bytes beside the image. That is the font atlas case fix(agc): store GPU results over CPU-stamped bytes the CPU left unchanged #1599 fixed, and agc_unchanged_cpu_stamps keeps passing.
  2. fix(agc): a unit kept for the CPU stays kept when it is written again before a re-upload
    A write-back that keeps blocks of a unit for the CPU leaves the unit stale at its old generation, without saved guest bytes. A dispatch looks up its storage images before it flushes the images pending over its imported buffers (ShaderResources, step (2)), so it can write such a unit again without re-uploading it. With 1. alone that went wrong twice:

    • the new results moved the unit's pending-since generation, so the CPU store of the baseline bytes from before them no longer counted as the later write, and the next write-back stored the stale texels over it;
    • when the memory left the write watch in between (the import of that buffer), the next write-back threw storing storage image results pending over memory outside the write watch without the guest bytes saved before them is not implemented. Control stopped on that once in 10 runs with 1. alone (below).

    The blocks a write-back keeps for the CPU are now recorded with the unit's generation, in the record saveBeforeUnwatch already keeps for the blocks it finds written when memory leaves the watch (keptAtUnwatch). While the record holds (the unit's generation hasn't moved), new results leave the unit's pending-since generation alone. If they land outside the write watch, markLayersPending first saves the unit's guest bytes, so the next write-back compares with them and still keeps the recorded blocks. The next upload of the unit gives it a new generation, which ends the record.

  • The debt entry now describes the narrower gap that is left, and the rule that a kept block stays the CPU's until its unit is uploaded again.

Related: #7048 (open) saves guest bytes for the same error in a wider set of units (any unit without saved bytes, whatever its generation). This PR covers only units with blocks a write-back kept for the CPU, and it also keeps those blocks at the next write-back.

Runtime evidence: Control, cold shader cache, a diagnostic build that logs each range a dispatch or draw captures that a storage write-back stored to within the previous second. Three separate runs show the same chain. Example (run chi-9):

[wb-hit] 145736.1 ms: dispatch 0x1004260100 captured 0x36a7ca618+0x4 (first dword 43954395) that a copy write-back of image 0x36a730000+0xb0000 (format 13, reason imported buffer region) stored over [0x36a7c0000,0x36a7d0000) at 145719.5 ms
[gpu] loop guard: the loop exit at pc 0xaec of shader 0x1004260100 ran past 65536 evaluations

The keep decision for that block (run chk-1, the same chain on image 0x38b120000):

block 0x38b160000+0x10000 layer 4: written 0 (tracked 1 unknown 0 kept 0 changed 1 ... edge 0 storedOver 1 baselineUnchanged 1 watched 1) layerGeneration 5324683 ... newestStamp 6166896

The block was stamped after the layer's generation (changed 1), but baselineUnchanged 1 dropped it from the kept set. Without APS5_LOOP_GUARD these runs end in a GPU ring timeout ([device-fault] unfinished dispatch: ... program 0x1004260100) or in buffer descriptor uses an unsupported type (buffer 2 V# ff1a1514 ff1a1514 ff191612 ff171410), which is a vertex shader V# table filled with texels. With an empty shader cache this happened in about 30% of runs. A warm cache never hit it in our runs, because the timing differs.

Tested

Linux (Arch, kernel 7.2.11), x86-64, RX 9070 XT, RADV (Mesa 26.2.6), on main cc26ab4.

  • New test agc_storage_rewritten_blocks: a linear storage image over write-watched memory, cleared on the GPU and marked pending. The CPU then writes the baseline bytes back into one whole 64 KiB block, and the image is written back. The block keeps the CPU's bytes and the other blocks get the clear color. A second case writes the same bytes before the GPU results are recorded and expects the GPU results everywhere, as fix(agc): store GPU results over CPU-stamped bytes the CPU left unchanged #1599 does. On main the first case fails: (c) a CPU store of the baseline bytes after the GPU results: the GPU results were stored over the CPU's later store at +65536. With the fix it passes.

  • New test agc_storage_rewritten_stale_units: a 64 KiB R_X storage image (8 block units) over write-watched memory, cleared red and marked pending; the CPU writes unit 1's baseline bytes back, and the write-back keeps unit 1 and stores red elsewhere. The image is then cleared blue and marked pending again without a refresh, and written back. It runs twice: once with the memory taken out of the write watch between the two write-backs, once with it still watched. Both expect unit 1 to keep the CPU's bytes and the other units to be blue.

    • main + the tests: fails at the first write-back ((r) memory that left the write watch: the first write-back stored over unit 1, which the CPU rewrote with its baseline bytes after the results).
    • Commit 1 + the tests: fails with storing storage image results pending over memory outside the write watch without the guest bytes saved before them is not implemented. With that case moved second, the watched case fails: (r) watched memory: the second write-back stored the image's stale unit 1 over the CPU's store, which nothing re-uploaded.
    • This branch: both cases pass.
  • Paired run with VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1, ctest -V -R 'agc_storage|agc_unchanged_cpu_stamps|agc_driver_recorder$|agc_slice_dirty|agc_import_watch' (18 tests): main + the tests, 14 pass, and agc_storage_rewritten_blocks, agc_storage_rewritten_stale_units and agc_driver_recorder (which includes the first) fail. This branch, 17 pass. On both, agc_storage_clear_hand_over is skipped by its own skip code, and no VUID- line appears.

  • Control (PPSA34547), new game, empty shader cache per run, about 420 s, base main de83e8f + fix(shader): load and store 16-bit data of converted packed images #11580 + fix(shader): leave pixel helpers out of EXEC values only where ballots skip them #12458, alternating runs (series 1 used commit 1 alone, series 2 this branch):

    series build runs texel V# abort GPU ring timeout other stop
    1 base 10 2 (buffer descriptor uses an unsupported type (buffer 2 V# ff000000 ff000000 ff000000 ff000000) at 377 s, ... V# ff23201b ff221f1a ff231f1a ff24201b at 183 s) 0 0
    1 base + commit 1 10 0 0 1 (storing storage image results pending over memory outside the write watch without the guest bytes saved before them is not implemented, 127 s)
    2 base 20 1 (... V# ff000000 ff000000 ff000000 ff000000 at 183 s) 0 0
    2 base + this branch (both commits) 20 0 0 0

    Every other run reached the 420 s limit. The counts are too small to prove anything: series 2 alone gives a two-sided Fisher p of 1.0, and the base's 3 stops in 30 runs against 0 in 20 for this branch give p = 0.27. The base hit the abort less often in series 2 (1 in 20) than in earlier runs (about 30%). Series 2 never showed the error from series 1's commit-1 run, and its 20 runs with this branch had no stop at all.

  • Conventions: pass (0 errors; the debt entry length warning was already there before this change)

Rerun on this branch merged with main c674f8c (one conflict in markLayersPending, where main now skips the capture when every unit is already pending; the pending generation is still recorded for every unit): the same 18 tests pass under VK_LAYER_KHRONOS_validation, with agc_storage_clear_hand_over skipped by its own skip code and no VUID- line.

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: PPSA34547
  • GPUs tested: AMD Radeon RX 9070 XT, RADV Mesa 26.2.6, Linux 7.2.11 (Arch)
  • AI-assisted: yes (Claude Code)

…line bytes

A storage write-back stores the GPU results over a CPU-stamped range whose
bytes still equal the image's baseline (boykopovar#1599). When the CPU stored those same
bytes into a whole 64 KiB block of the image after the GPU results were
recorded, that store is the later write. Control (PPSA34547) rewrites its
per-frame constant buffers over memory a storage image covers; the bytes match
the snapshot the image was uploaded from, so a write-back forced by a buffer
import stored the stale texels over them and shaders read loop counts such as
0x43954395.

Each tracked layer now records the write generation of its last GPU results;
a whole-block range that a CPU store reached after it keeps the CPU's bytes.
Edge blocks, whose stamps can come from bytes beside the image, keep the byte
comparison.
…ad keeps the CPU's block

A write-back keeps a unit's block for the CPU, then the image is written
again without a refresh (a dispatch's imported-buffer flush comes after
its image lookups). With the memory still watched, the second write-back
must keep the block; after the memory left the write watch, it must not
throw for missing saved guest bytes and must keep the block too.
… before a re-upload

A write-back that keeps blocks of a unit for the CPU leaves the unit stale
at its old generation, and no saved guest bytes. A dispatch looks up its
storage images before it flushes the images pending over its imported
buffers, so it can write such a unit again without re-uploading it. Two
things then went wrong: the new results reset the unit's pending-since
generation, so a CPU store of the baseline bytes before them no longer
counted as the later write and the stale texels were stored over it; and
when the memory had left the write watch in between, the next write-back
threw 'storing storage image results pending over memory outside the
write watch without the guest bytes saved before them is not
implemented'. Control (PPSA34547) stopped on that error once in 10 runs
with the previous commit.

The blocks a write-back keeps for the CPU are now recorded with the
unit's generation (the record the write-watch exit already uses). While
it holds, new results leave the unit's pending-since as it was, and
results recorded outside the write watch save the unit's guest bytes
first, so the next write-back compares with them and still keeps the
recorded blocks.
…e watching

Both tests now return 77 when the host has no write watching, so ctest reports
them as skipped instead of passed. A failed allocation while watching is on
stays a failure.
@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Nov 1, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@hugodearaujo thanks for the fix. Reviewed at b649003.

One change: in the new --rewritten-blocks-only test, when no write-watched block can be allocated it prints "not tested" and returns 0, so ctest reports a pass with no assertions run. SKIP_RETURN_CODE is already 77 for this test, so please return 77 there. The new stale-unit test fails on the same missing prerequisite; please make it return 77 too when write watching is unavailable, keeping real setup or allocation failures as failures and every byte check when watching is available. Could you also confirm the two new tests report Passed, not Skipped, on your host?

Not blocking: an edge-block case and a CPU store between two GPU writes to an already-pending layer are not covered.

@github-actions

github-actions Bot commented Nov 1, 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 862 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 1368 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 1395 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 2434 docs/dev/debt/libSceAgcDriver.md
PR 4448 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 5021 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 5372 docs/dev/debt/libSceAgcDriver.md
PR 5609 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 5925 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6108 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6146 docs/dev/debt/libSceAgcDriver.md
PR 6185 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 6186 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 6187 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6192 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6197 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6209 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6412 docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6615 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 6743 docs/dev/debt/libSceAgcDriver.md
PR 6804 docs/dev/debt/libSceAgcDriver.md
PR 6808 docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6905 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 6926 docs/dev/debt/libSceAgcDriver.md
PR 6970 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 6973 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6987 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6989 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6995 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7002 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7085 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7449 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
docs/dev/debt/libSceAgcDriver.md
PR 7457 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 7514 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 7604 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 7668 docs/dev/debt/libSceAgcDriver.md
PR 7978 docs/dev/debt/libSceAgcDriver.md
PR 8246 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 8484 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 8707 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9020 docs/dev/debt/libSceAgcDriver.md
PR 9289 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 9318 docs/dev/debt/libSceAgcDriver.md
PR 9335 docs/dev/debt/libSceAgcDriver.md
PR 9356 docs/dev/debt/libSceAgcDriver.md
PR 9387 docs/dev/debt/libSceAgcDriver.md
PR 9508 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9672 docs/dev/debt/libSceAgcDriver.md
PR 9673 docs/dev/debt/libSceAgcDriver.md
PR 9674 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9675 docs/dev/debt/libSceAgcDriver.md
PR 9700 docs/dev/debt/libSceAgcDriver.md
PR 9712 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9742 docs/dev/debt/libSceAgcDriver.md
PR 9748 docs/dev/debt/libSceAgcDriver.md
PR 9875 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 9884 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 9891 docs/dev/debt/libSceAgcDriver.md
PR 9892 docs/dev/debt/libSceAgcDriver.md
PR 9893 docs/dev/debt/libSceAgcDriver.md
PR 9895 docs/dev/debt/libSceAgcDriver.md
PR 9898 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 9915 docs/dev/debt/libSceAgcDriver.md
PR 9950 docs/dev/debt/libSceAgcDriver.md
PR 9999 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 10049 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10064 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10159 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 10193 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 10233 docs/dev/debt/libSceAgcDriver.md
PR 10249 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10256 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10351 docs/dev/debt/libSceAgcDriver.md
PR 10359 docs/dev/debt/libSceAgcDriver.md
PR 10442 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 10443 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 10469 docs/dev/debt/libSceAgcDriver.md
PR 10472 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10492 docs/dev/debt/libSceAgcDriver.md
PR 10497 docs/dev/debt/libSceAgcDriver.md
PR 10656 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 10743 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10779 docs/dev/debt/libSceAgcDriver.md
PR 10920 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 11104 docs/dev/debt/libSceAgcDriver.md
PR 11346 docs/dev/debt/libSceAgcDriver.md
PR 11444 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 11485 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 11551 docs/dev/debt/libSceAgcDriver.md
PR 11557 docs/dev/debt/libSceAgcDriver.md
PR 11587 docs/dev/debt/libSceAgcDriver.md
PR 11825 docs/dev/debt/libSceAgcDriver.md
PR 11847 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 11995 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 11998 docs/dev/debt/libSceAgcDriver.md
PR 12070 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12120 docs/dev/debt/libSceAgcDriver.md
PR 12158 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 12452 docs/dev/debt/libSceAgcDriver.md
PR 12565 docs/dev/debt/libSceAgcDriver.md
PR 12567 docs/dev/debt/libSceAgcDriver.md
PR 12568 docs/dev/debt/libSceAgcDriver.md
PR 12617 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12662 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12745 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 12746 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12764 docs/dev/debt/libSceAgcDriver.md
PR 12792 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 12813 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 12840 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
docs/dev/debt/libSceAgcDriver.md
PR 12855 docs/dev/debt/libSceAgcDriver.md
PR 12904 docs/dev/debt/libSceAgcDriver.md
PR 12921 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 12980 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 13021 docs/dev/debt/libSceAgcDriver.md
PR 13023 docs/dev/debt/libSceAgcDriver.md
PR 13044 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 13146 docs/dev/debt/libSceAgcDriver.md
PR 13147 docs/dev/debt/libSceAgcDriver.md
PR 13151 docs/dev/debt/libSceAgcDriver.md
PR 13251 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 13263 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 13474 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/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 13796 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
PR 13809 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 13858 docs/dev/debt/libSceAgcDriver.md
PR 13863 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 13920 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 13928 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 13929 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
docs/dev/debt/libSceAgcDriver.md
PR 13942 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 13991 docs/dev/debt/libSceAgcDriver.md
PR 13994 docs/dev/debt/libSceAgcDriver.md
PR 14018 docs/dev/debt/libSceAgcDriver.md
PR 14085 docs/dev/debt/libSceAgcDriver.md
PR 14212 docs/dev/debt/libSceAgcDriver.md
PR 14220 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14243 docs/dev/debt/libSceAgcDriver.md
PR 14248 docs/dev/debt/libSceAgcDriver.md
PR 14261 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 14262 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 14265 docs/dev/debt/libSceAgcDriver.md
PR 14296 docs/dev/debt/libSceAgcDriver.md
PR 14311 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14330 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_recorder_tests.cmake
PR 14344 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
docs/dev/debt/libSceAgcDriver.md
PR 14561 docs/dev/debt/libSceAgcDriver.md
PR 14621 docs/dev/debt/libSceAgcDriver.md
PR 14628 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14868 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 14909 docs/dev/debt/libSceAgcDriver.md
PR 14914 core/libs/prx/libSceAgcDriver/tests/Recorder.cpp
PR 14943 core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md
PR 14944 docs/dev/debt/libSceAgcDriver.md
PR 14950 docs/dev/debt/libSceAgcDriver.md
PR 14963 docs/dev/debt/libSceAgcDriver.md
PR 14964 docs/dev/debt/libSceAgcDriver.md
PR 14976 docs/dev/debt/libSceAgcDriver.md
PR 14982 docs/dev/debt/libSceAgcDriver.md
PR 14993 docs/dev/debt/libSceAgcDriver.md
PR 15058 core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
docs/dev/debt/libSceAgcDriver.md

@hugodearaujo

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Thanks, done in 34d48019fd. Both new tests return 77 when the host has no write watching: rewrittenBlockTests checks GuestMemory::WriteWatched() first, and a failed watched allocation while watching is on is now a Require failure instead of a silent return; rewrittenStaleUnitTests returns 77 instead of throwing on the same missing prerequisite and keeps its setup checks. On my host (Linux, RADV, RX 9070 XT) both report Passed, not Skipped, under the validation layer:

1/3 Test #1620: agc_storage_rewritten_blocks ........   Passed    0.09 sec
2/3 Test #1621: agc_storage_rewritten_stale_units ...   Passed    0.07 sec
3/3 Test #1656: agc_driver_recorder .................   Passed    0.85 sec

and with APS5_NO_WRITE_WATCH=1 both report Skipped (no write watching: rewritten blocks not tested, no write watching: stale unit tests not run).

The edge-block case and a CPU store between two GPU writes to an already-pending layer are noted; I'll look at covering them separately.

AI-assisted: yes (Claude Code)

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — changes requested

The new AGC regression cases appear targeted, but this head conflicts with open #8246 in Texture.cpp and has no recorded landing-order agreement or corresponding dependency declaration.

What I ran

Reviewed PR head 34d48019fdbdbe48c76364f438ed6e49084f24f6, targeting main at PR base c674f8c14da93df7a6b37657117ca3f58357477f. A merge preview against current main 26fa1212b82f76dd49cf12d65e445d6ff3e0844c is clean; a separate pairwise preview against open #8246 head 9377004c3c38bc505be16eafb509609386318a94 conflicts in Texture.cpp. Static checks ran in the Linux review environment; I did not invoke a local compiler or build.

git diff --check c674f8c14da93df7a6b37657117ca3f58357477f 34d48019fdbdbe48c76364f438ed6e49084f24f6
python3 tools/check_conventions.py --base c674f8c14da93df7a6b37657117ca3f58357477f --head 34d48019fdbdbe48c76364f438ed6e49084f24f6 --title 'fix(agc): keep a CPU store that rewrote a pending block with its baseline bytes' --body /tmp/anyps5-pr-precheck/boykopovar-AnyPS5-pr-14302-34d48019fdbd/pr-body.md
git merge-tree --write-tree 26fa1212b82f76dd49cf12d65e445d6ff3e0844c 34d48019fdbdbe48c76364f438ed6e49084f24f6
git merge-tree --write-tree 34d48019fdbdbe48c76364f438ed6e49084f24f6 9377004c3c38bc505be16eafb509609386318a94
gh pr checks 14302 --repo boykopovar/AnyPS5
gh run view 41289132063 --repo boykopovar/AnyPS5 --log-failed

Results

Check Result
git diff --check Passed; no output.
Repository conventions and PR template Passed with 0 errors and one debt-length warning.
Merge preview against current main Clean; the merge preview emitted no conflict output.
Pairwise preview with #8246 Content conflict in core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp.
Hosted Windows job, head 34d48019 Failed: guest_pad exited with 0xc0000409; CTest reports one failure out of 2,583, with several tests skipped. This test is outside the changed paths, so I cannot attribute the failure to this PR.
Hosted conventions, labels, eligibility, library portability, report Passed. Linux and specialized jobs were skipped.
New AGC tests (local) Not run locally; they require a build. The PR description reports paired Linux/RADV results, including 17/18 tests passing on the branch with the remaining test explicitly skipped; I did not independently reproduce them.
ABI audit and test-quality heuristic The precheck could not execute these optional checks because their helper scripts are absent from its isolated PR snapshot. No PRX export changes are in this diff.
Raw output — conventions and diff check
docs/dev/debt/libSceAgcDriver.md:246: warning: [debt-length] Technical debt entry over 1000 characters: state the gap first (what differs from the console, what is unverified, what throws) and keep only the behaviour it needs: 3155 characters
1 findings, 0 errors; GitHub shows at most 10 error annotations, the job summary lists all

git diff --check produced no output.

Raw output — clean current-main preview
2c099548a0d859536097dad63f9e3f9a8acdba31
Raw output — pairwise preview
decc8c9f3d05bf844c83a376da87da1fe1157e1c
100644 4ea2a6f08a3af1cba780b9c86835df3ddfe592aa 1	core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
100644 8a6f697280065d2711b4e51f175038cc4d1984fd 2	core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
100644 d3a72b19ae352c24a9d25b17f6b3372b929c85bf 3	core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp

Auto-merging core/libs/prx/libSceAgcDriver/CMakeLists.txt
Auto-merging core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
Auto-merging core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
Auto-merging core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
CONFLICT (content): Merge conflict in core/libs/prx/libSceAgcDriver/Graphics/src/Texture.cpp
Auto-merging core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
Auto-merging docs/dev/ENVIRONMENT.md
Raw output — hosted checks
windows	fail	0	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124797886511
conventions	pass	18s	https://github.com/boykopovar/AnyPS5/actions/runs/41289129030/job/124796521573
labels	pass	9s	https://github.com/boykopovar/AnyPS5/actions/runs/41289129014/job/124796521584
linux	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124797887767
register-context	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124797887530
relinker	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124797887927
relinker-asan	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124797887408
write-watch	skipping	0	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124797887669
eligibility	pass	5s	https://github.com/boykopovar/AnyPS5/actions/runs/41289132063/job/124796581354
library-portability	pass	1m45s	https://github.com/boykopovar/AnyPS5/actions/runs/41289132060/job/124796529417
report	pass	44s	https://github.com/boykopovar/AnyPS5/actions/runs/41289132081/job/124796529161
Raw output — failing Windows test
windows	Build and run changed guest core/libs tests	2026-11-01T09:09:22.9080036Z 2100/2583 Test #2513: guest_pad ................................................................Exit code 0xc0000409***Exception:   1.75 sec
windows	Build and run changed guest core/libs tests	2026-11-01T09:09:22.9096421Z FATAL: abort() (SIGABRT) on thread 10092
windows	Build and run changed guest core/libs tests	2026-11-01T09:10:35.7707941Z 99% tests passed, 1 tests failed out of 2583
windows	Build and run changed guest core/libs tests	2026-11-01T09:10:35.8058239Z 	2513 - guest_pad (Exit code 0xc0000409)

Findings

Blocking

  • Unresolved overlap with #8246. The open PR heads conflict when previewed together in Texture.cpp. CONTRIBUTING.md requires authors of overlapping changes to agree which lands first and record the dependency in Depends on where applicable. This PR currently says Depends on: none, and I found no recorded agreement with #8246's author. Please coordinate the order with that author and update the checklist; if this PR must land second, declare #8246 and rebase after the dependency lands. I am not asking either author to close their PR.

Non-blocking

  • Windows CI failure needs triage. The failing test is guest_pad, which is not among this PR's changed paths. The log does not establish a connection to this change. Please confirm whether it reproduces on the same head or compare against the current base before treating it as unrelated.

Sources

Not verified

  • No local configure, build, CTest, Linux runtime, GPU/title run, or console behavior was performed. The Linux/RADV evidence in the PR description is author-reported, not an independent run.
  • I did not independently reproduce the Windows guest_pad failure or establish whether it occurs on current main.

To get this to a good state

Please record the agreed landing order with #8246 and update Depends on accordingly, then investigate or document the Windows guest_pad result. I will refresh the PR head and rerun the same applicable checks on the updated revision.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 34d4801 merged onto main e6f5730 · tested 2026-11-01 15:08 UTC · 28 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,484 passed · 5 failed (0 new, 3 also fail on main, 2 unstable on main) · 45 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,534 of 3,148 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 (933 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 112.1 s
Unstable on main (2, 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
agc_submit_progress_no_timeline: failed in 8 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
Validated but not compared (2, not in the main baseline's validation pass)
agc_storage_rewritten_blocks
agc_storage_rewritten_stale_units
Validation IDs already present on main (5 IDs in 484 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (484 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 476 more
VUID-vkCmdCopyImage-srcImage-01548 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
VUID-VkShaderModuleCreateInfo-pCode-08737 (1 test): agc_driver_image_sample_derivatives
Skipped (45)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fps_limit: 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_o
Reproduce
git fetch origin 34d48019fdbdbe48c76364f438ed6e49084f24f6 e6f57307fa7f47165d7fc1bee945abdb2f6816e7
git checkout e6f57307fa7f47165d7fc1bee945abdb2f6816e7 && git merge --no-ff 34d48019fdbdbe48c76364f438ed6e49084f24f6
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.

@hugodearaujo

Copy link
Copy Markdown
Contributor Author

@MarcZX10 on the overlap with #8246 (your PR, so I'm asking you directly). A trial merge of #8246's head 9377004c3c with this head 34d48019fd conflicts in Texture.cpp at two places, both textual:

  1. Both PRs add a new StorageTexture member at the same spot: fix(agc): preserve CPU writes after resident linear target draws #8246 adds PrepareLinearDraw/FinishLinearDraw, this PR adds cpuLeftUnchanged. Keep both.
  2. The written line in the write-back loop. fix(agc): preserve CPU writes after resident linear target draws #8246's head predates main renaming rectStore to drawn.rect, and this PR replaces !unchangedSinceBaseline(from, to) with !cpuLeftUnchanged(layer, from, to, edge) there. The resolution is main's drawn.rect plus this PR's call.

Neither change uses the other's code, so there is no functional dependency. My proposal: this PR goes first, since it is current with main and #8246 needs a refresh onto main anyway (oneandonlydean's request of 10-29), and the resolution above is all #8246 needs then. If you'd rather #8246 land first, I'll put it under Depends on and merge main into this branch once it lands.

On the Windows job: the failing test is guest_pad, the intermittent abort in CheckLatchedPressLifetime documented in #12115 (2 of 1,771 Windows runs on main, exit 0xc0000409, before this PR existed). This PR touches nothing under libScePad. I can't re-run the job from here.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@hugodearaujo

Copy link
Copy Markdown
Contributor Author

Merged main a4eca2a056 (2c6b5e4477). The conflicts were in Texture.cpp and tests/Recorder.cpp. In Texture.cpp, main had reworked the two places this PR changes, so here is how each was resolved:

  • markLayersPending: main now classifies why a newly pending unit has no saved bytes (BaselineMiss, savedTicket) and saves the bytes of any unsaved unit when the surface isn't fully watched (that covers part of what this PR's second commit did). The resolution keeps main's classification and adds this PR's one case on top: a unit with blocks a write-back kept for the CPU (keptForCpu) counts as unsaved, both in the trims pre-check and in the per-unit loop, so its bytes are saved before the new results. For such a unit baselineMiss would otherwise report the CPU's bytes as an upload or hash difference and save nothing. The CollectWritesUncached over the newly pending range and the layerPendingSince stamping stay as before.
  • saveBeforeUnwatch: main moved its keep loop into keepWrittenSince, which is also used for units that become pending outside the watch. That loop now uses cpuLeftUnchanged(unit, from, to, edge) instead of unchangedSinceBaseline(from, to), the same rule as in writeBackLayers.
  • The constructor keeps both layerPendingSince and main's unwatchHash/pendingMiss. Recorder.cpp runs both PRs' tests and main's repeatedNeighbourStoreTests.

RX 9070 XT, RADV Mesa 26.2.6, with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1: all 96 tests run by agc_driver_recorder_tests pass on the merge except agc_idle_publish_wait (the idle publish's bytes are wrong), which fails the same way on main on this GPU (noted in #13883). agc_storage_rewritten_blocks, agc_storage_rewritten_stale_units, agc_unchanged_cpu_stamps, agc_storage_kept_unit_settle and agc_repeated_neighbour_stores pass. check_conventions passes. Its only finding is the existing length warning on this PR's debt entry.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 2, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 2c6b5e4 merged onto main 9090972 · tested 2026-11-03 03:26 UTC · 27 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,700 passed · 6 failed (0 new, 3 also fail on main, 3 unstable on main) · 45 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,751 of 3,607 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 (978 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.2 s, ⚠️ agc_driver_graphics_maps_fallback 33.2 s, ⚠️ agc_driver_native_depth_clears 30.1 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_job_manager_compute_capacity: failed in 1 of the last 10 main runs
agc_driver_pipeline_journal: failed in 3 of the last 10 main runs
agc_submit_progress: failed in 7 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
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_native_depth_clears: Timeout in the parallel run; also passed only on retry in 31 other runs in the last 7 days
Validated but not compared (2, not in the main baseline's validation pass)
agc_storage_rewritten_blocks
agc_storage_rewritten_stale_units
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 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (7 tests): agc_driver_depth_clear_hle, agc_driver_depth_plane_buffer_memory, agc_driver_depth_plane_partial_store, agc_driver_depth_plane_sampling, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_prepared_exports
Skipped (45)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_backtoback: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_controls: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_cpuflip_in_order: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_dcc: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_aftergpu: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_eop_main: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
video_out_flip_fps_limit: 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_o
Reproduce
git fetch origin 2c6b5e4477304cc97541184a73c266b83fa99b7d 9090972b7e91fd266819cbd77a8b058e177b5682
git checkout 9090972b7e91fd266819cbd77a8b058e177b5682 && git merge --no-ff 2c6b5e4477304cc97541184a73c266b83fa99b7d
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.

@oneandonlydean oneandonlydean self-assigned this Nov 3, 2026
@oneandonlydean
oneandonlydean merged commit 8b1be62 into boykopovar:main Nov 3, 2026
12 checks passed
oneandonlydean pushed a commit that referenced this pull request Nov 3, 2026
…their units

#14302 records the blocks a storage write-back keeps for the CPU with the
unit's generation, and keptForCpu holds while the unit keeps that
generation: new GPU results then leave the unit's pending-since as it
was, so a CPU store made before them still wins at the next write-back.
A re-upload ends the record by giving the unit a new generation. On
memory outside the write watch the generation is 0 before and after the
upload, so the record held for good: every later result of the unit kept
the pending-since of the first, the CPU store that the upload had just
taken counted as newer than the new results, and the next write-back
kept the CPU's bytes over them.

The contention checks of agc_driver_image_atomics show it: their texel is
in a global array outside the write watch. After the image_atomic_add
check, the umax check rewrites the texel while the add's results are
pending, the umax dispatch keeps those bytes and re-uploads them, and the
read-back dispatch kept them again, so the texel read back its initial 5
instead of the largest stored value.

An upload now forgets the kept blocks of each unit it restamps, since the
image takes the guest bytes there.
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.

4 participants