Skip to content

fix(agc): bind a written TYPE 0 or 1 static image slot as a null storage image - #10906

Merged
oneandonlydean merged 6 commits into
boykopovar:mainfrom
EagleBearerYS:fix/shader-null-storage-image-type0
Nov 2, 2026
Merged

oneandonlydean merged 6 commits into
boykopovar:mainfrom
EagleBearerYS:fix/shader-null-storage-image-type0

Conversation

@EagleBearerYS

@EagleBearerYS EagleBearerYS commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

What

A static image slot (no image table) that is written, and not atomic, whose T# has TYPE 0 or 1, is now bound as a null storage image. A read-only slot with such a T# has been bound that way since #4779, #5473 and #5828, and so has a written slot with a zero base. With VK_EXT_robustness2's nullDescriptor, its stores are discarded and its loads return zero; without it, the heap's placeholder image is used, which keeps stores (already in the debt file). Atomic slots, and TYPE 2 to 7 in any slot, still throw.

Ratchet & Clank: Rift Apart (PPSA01474) stops at 1,300 s on a compute shader whose image 4 is a written, never-read storage slot holding a buffer V# (04efd000 00040011 00017a00 00005204 ..., TYPE 0). No other source reads those SRT words, and the store is reached on every path (#9749).

  • nullImageDescriptor (ResourceMaterializer.cpp): TYPE <= 1 is null for a read or written, non-atomic slot with no table, instead of read-only slots only.
  • DrawWriteRanges (WrittenBuffers.cpp): a written storage image whose words are IsNullTextureResource adds no write range, as DispatchWriteRanges already does. It skipped only a zero base, and threw on a TYPE 0 or 1 T#. IsNullTextureResource itself already returns true for TYPE <= 1 in any slot.
  • docs/dev/debt/libSceAgcDriver.md: a written-slot entry after the TYPE 0/1 entry gives the store measurement (second commit, split out of that entry in the merge of main 5b5d24c).

Measurement: on an AMD Radeon PRO V620 (gfx1030, RDNA2; Ubuntu 24.04.5, kernel 7.0.0-38, in-kernel amdgpu, ROCm 6.3.3), Tamalero ran tools/hw-oracle/probe_type0_store.py (test/hw-oracle-type0-store) with PPSA01474's eight words (result):

  • control: a valid TYPE 9 image_store changed its 32 dwords;
  • TYPE 0 and TYPE 1: the image_store changed no dword from base−0xe00 to base+0xf000, with no fault or hang.

Not measured: atomics, other RDNA generations, and the console's gfx1013.

Related: #9749 (the PPSA01474 diagnostics), #9633, #4139 and #5828 (the read measurements), #4779, #5473. Overlaps:

Tested

  • GitHub's runners: run 40176856334, with the Khronos validation layer loaded: with the fix, 48 AGC tests pass 10 of 10 on Linux (0 skipped) and 47 on Windows (1 skipped). On Windows, with this PR's tests and main's ResourceMaterializer.cpp and WrittenBuffers.cpp, agc_shader_type_zero_image_materialization and agc_driver_draw_write_ranges fail.
  • Linux x86-64 (Ubuntu 24.04, gcc 13.3.0), no title:
    • agc_shader_type_zero_image_materialization: TYPE 0 and 1 written and read-write storage slots materialize as null with their words unchanged; atomic slots and TYPE 2 still throw. Fails on main with runtime image descriptor is invalid.
    • agc_driver_draw_write_ranges: written TYPE 0 and 1 storage images, and the reported words, add no draw or dispatch write range next to a real one. Fails on main with unsupported image type 0.
    • agc_driver_graphics: the reported words are IsNullTextureResource, and DecodeTextureResource refuses them.
    • Each product line alone turns its own test green.
    • CI-configured build, then ctest as an unprivileged user: 2,214 tests, 2,119 passed, 90 skipped and 5 failed. The five need IPv6, which that machine lacks: guest_net_buffer_validation, guest_socket_options, guest_socket_stream_options, guest_socket_address_length and guest_tcp.
  • Khronos validation on main and on this branch over the focused tests: lavapipe (Mesa 25.2.8) with vulkan-validationlayers 1.3.275 loaded on both sides. The only VUID, VUID-VkDeviceCreateInfo-pNext-pNext at device creation, is the same on main and on this branch. On GitHub's Linux runner (the same run), the layer is loaded on both arms and the VUIDs are the same: only VUID-VkDeviceCreateInfo-pNext-pNext; the fix adds none.
  • AMD hardware, per tablefrogpillow's report (comment), on RADV (Mesa 25.2.8) with the Khronos validation layer on, on an RX Vega 56 (GCN5), an RX 7900 GRE (RDNA3) and a Ryzen 7 7800X3D's integrated GPU (RDNA2):
    • agc_driver_graphics, agc_shader_memory, agc_driver_draw_write_ranges and agc_driver_draw_write_ranges_draw_pipeline pass 4 of 4 on all three;
    • 787 shader and AGC tests fail the same set on 0d41b11 and on its merge-base e5f2355: four float tests specific to GCN5, nothing new;
    • with WrittenBuffers.cpp and ResourceMaterializer.cpp back at the merge-base and this PR's tests kept, agc_shader_memory, agc_driver_draw_write_ranges and agc_driver_draw_write_ranges_draw_pipeline fail.
  • a11c83a, a merge of main e05ba6f (run). main's fix(agc): retire an undrawn filled multisampled color target that a guest access overlaps #9186 extends the multisampled colour target debt entry right after the type-0 and type-1 descriptor entry this PR rewrites; the merge keeps both entries, and nothing else conflicted. The agc_driver_draw_write_ranges, agc_driver_graphics, agc_shader_memory and agc_shader_type_zero_image_materialization tests, with the other tests whose names those match, pass 10 runs in a row. Linux: 50 run, 50 pass, 0 skip, 0 fail. Windows: 49 run, 49 pass, 0 skip, 0 fail. The before arm fails agc_shader_type_zero_image_materialization, agc_shader_memory and agc_driver_draw_write_ranges on both. Suites: libc and libkernel pass on Linux (144 and 207) and on Windows (171 and 223). The suites ran with APS5_SKIP_TIMING_TESTS=1, which relaxes precise_wait's median bounds on GitHub's hosted runners.
  • Ratchet & Clank: Rift Apart (PPSA01474), by @Tamalero (comment): RTX 4090, no input, no extra environment, cold shader cache, on test/9749-null-storage (b9d0797: this PR's 38288a4 and 0d41b11 merged onto fix(shader): read a chased pointer's high word at its own offset #9749's head 52ae654), with feat(shader): raise the sampler and sampled-pair limits past the 32-bit sampler masks #10000's 12b8923 merged in locally; without feat(shader): raise the sampler and sampled-pair limits past the 32-bit sampler masks #10000 the branch stops at 214 s on sampler resource limit exceeded. It gets past the 1,300 s stop: there is no runtime image descriptor is invalid line and no other error before 2,632 s, and after the old stop it loads about 980 more textures and compiles new shaders. At 2,632 s a different compute shader, 0x116bb6ef00, stops on GetImageResource dword 0 is not a valid runtime value, with dword 0 coming from a LoadAddressU32 at pc 0xd4d4 behind a tree of Phis. That stop is outside this PR.
  • NVIDIA GeForce RTX 5070 Ti (621.01) and an AMD Radeon RDNA2 iGPU (AMD 2026.04.17), Windows 11, by @wachi35676 (comment): WinLibs GCC 15.2.0, Release, this PR's a11c83a merged onto main aeff26b, ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1, no validation layer. Both drivers report nullDescriptor.
    • agc_driver_graphics, agc_shader_memory, both agc_driver_draw_write_ranges entries, agc_shader_type_zero_image_materialization and the other agc_shader_ tests, 44 entries, pass on both GPUs.
    • With main's ResourceMaterializer.cpp and WrittenBuffers.cpp, agc_shader_type_zero_image_materialization fails with runtime image descriptor is invalid, and both agc_driver_draw_write_ranges entries with unsupported image type 0.
    • A local probe, not part of this PR: a compute image_store through a written slot holding a TYPE 0 T#, a TYPE 1 T# or the words from Ratchet & Clank: Rift Apart (04efd000 00040011 00017a00 00005204 ...) recompiles, binds and dispatches on both drivers with no device fault or error. main refuses all three with runtime image descriptor is invalid, and TYPE 2 is still refused. On the probe's path even a TYPE 9 control store didn't reach guest memory, so it shows that both drivers take the null storage binding, not the discard itself.
    • Of 248 agc_ entries, the same ones fail with and without the change.
  • 83b7421, after oneandonlydean's review (run): agc_shader_type_zero_image_materialization no longer requires TYPE 0 and 1 atomic slots to be refused, since atomics on these descriptors aren't measured. Both atomic cases are out of its loop, including the atomic-only one main's test already had; the materializer still refuses them. The written and read-write null-materialization checks, the unchanged-words checks and the reserved TYPE 2 checks stay. The run's 18 tests, agc_driver_draw_write_ranges, agc_driver_graphics, agc_shader_memory, agc_shader_type_zero_image_materialization and 14 other agc_shader_* tests, pass 10 runs in a row. Linux: 18 run, 18 pass, 0 skip, 0 fail. Windows: 18 run, 18 pass, 0 skip, 0 fail. Suites: libc and libkernel pass on Linux (144 and 207) and on Windows (171 and 223). The suites ran with APS5_SKIP_TIMING_TESTS=1, which relaxes precise_wait's median bounds on GitHub's hosted runners.
  • 06cb325, a merge of main 5b5d24c (run, run). DavidAmsellem's docs: measure type-0 and type-1 texture descriptors on gfx1100 #7910 rewrote main's type-0 and type-1 texture descriptor entry in docs/dev/debt/libSceAgcDriver.md with gfx1100 (RDNA3) read measurements; this PR had extended that entry for written slots. The merge keeps main's entry as it is and moves this PR's written-slot text into a new entry after it, with the same store measurement and atomic rule. Nothing else conflicted, and the code and test lines this PR changes are the same.
    • The first run took the tests for every file the merge changes against 83b7421, 10 runs each, with the Khronos validation layer loaded on Linux. Linux: 269 run, 259 pass, 10 skip, 0 fail, and the validation comparison is clean. Windows: 287 run, 199 pass, 86 skip, 2 fail. The two failures are agc_driver_frame_replay and agc_driver_frame_replay_concurrent, whose agc_frame_replay helper exited with 0xC0000139 (entry point not found) within 0.2 s.
    • The second run, on the same commit, adds the agc_driver_frame_replay tests to this PR's focused tests, and all of them pass 10 runs in a row. Linux: 53 run, 53 pass, 0 skip, 0 fail. Windows: 57 run, 57 pass, 0 skip, 0 fail, including all eight agc_driver_frame_replay tests. The before arm, with main's implementation, fails agc_shader_type_zero_image_materialization on both.
    • Suites: libc and libkernel pass on Linux (145 and 210) in both runs, and on Windows (172 and 231) in the second. In the first, guest_timed_join_import_libkernel_sys and guest_timed_join_import_libkernel_web failed in the Windows libkernel suite; they fail on main too (run). The suites ran with APS5_SKIP_TIMING_TESTS=1, which relaxes precise_wait's median bounds on GitHub's hosted runners.
  • df709c6, a merge of main 2b1ae87, which brings savvaniss's fix(agc): retire a multisampled color target the title wrote over #8223 (run).
    • The conflict: docs/dev/debt/libSceAgcDriver.md only. This PR adds its "Written type-0 and type-1 texture descriptors" entry next to the old "Multisampled color targets … lose their guest-read guards" entry. fix(agc): retire a multisampled color target the title wrote over #8223 replaced that old entry and added "Shader buffer access to native multisample targets".
    • The resolution: this PR's entry, then main's two. This PR's copy of the old entry was the same as the merge base's, and its own diff is unchanged.
    • ×10: this PR's agc_shader_type_zero_image_materialization, the other tests of agc_driver_graphics_tests, agc_shader_memory_tests and agc_driver_draw_write_ranges_tests, and the agc_driver_frame_replay tests.
      • Linux: 71 run, 71 pass, 0 skip, 0 fail.
      • Windows: 68 run, 68 pass, 0 skip, 0 fail.
      • The libc and libkernel suites run 199 and 307 tests on Linux and 226 and 329 on Windows, with 0 failed. The suites ran with APS5_SKIP_TIMING_TESTS=1, which relaxes precise_wait's median bounds on GitHub's hosted runners.

Checklist

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 25, 2026
@MarcZX10

Copy link
Copy Markdown
Contributor

I checked the new TYPE 0/1 handling against the current descriptor path. The materializer identifies these words as null, and the storage binding path passes context.nullDescriptors through to descriptor setup; your description also cites a focused V620 measurement and the new write-range regression. One edge I could not verify from the report is the behavior on a host without nullDescriptor: the description says it falls back to the heap placeholder, while DrawWriteRanges now suppresses writes for any IsNullTextureResource words independent of that capability. Could you add or point to a focused execution test showing the no-nullDescriptor fallback cannot make a placeholder store observable or lose a real guest writeback? The profile test currently checks capability detection, but not this fallback together with written TYPE 0/1 slots. I am leaving approval open on that host-path question.

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@MarcZX10 thanks for checking the descriptor path. On a host without nullDescriptor:

  • No real guest writeback is lost. A TYPE 0 or 1 T# never reaches a guest surface on either host. The storage loop skips IsNullTextureResource words before decoding them (ShaderResources.cpp L4908-L4912), so the slot gets no texture, no write-back and no tracked range. The only thing that depends on the capability is the view bound in its place (L2417-L2420): a null view, or the heap's placeholder. So the store reaches guest memory on neither host, as on the V620, where no dword changed from base−0xe00 to base+0xf000. That's why DrawWriteRanges leaves these words out whatever the capability. Its new cases (DrawWriteRanges.cpp L90-L105) check that a real written image next to a TYPE 0 or 1 one keeps its range, for draws and dispatches.
  • The placeholder does keep the store. Without nullDescriptor, every null descriptor of a storage heap shares one 1×1 placeholder, which is cleared to zero when it is created (PlaceholderImages.cpp L20-L74), and stores to it are kept. A later read through a null storage image of the same heap can return them. This is the limitation already recorded in the debt file, and on main it applies to every null storage descriptor, a written slot with a zero base included. Sampled null images have their own heaps' placeholders, so sampling doesn't see these stores. This PR adds TYPE 0 and 1 written slots to that set and doesn't change the fallback.

So a test can't show the placeholder store as unobservable on that host, because it is observable there, as recorded. What the PR relies on is that nothing reaches guest memory, and that follows from the slot never being decoded, on both hosts.

@github-actions

github-actions Bot commented Oct 25, 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 907 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 2434 docs/dev/debt/libSceAgcDriver.md
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 5925 docs/dev/debt/libSceAgcDriver.md
PR 6186 docs/dev/debt/libSceAgcDriver.md
PR 6194 docs/dev/debt/libSceAgcDriver.md
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6412 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6481 docs/dev/debt/libSceAgcDriver.md
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 6548 docs/dev/debt/libSceAgcDriver.md
PR 6808 docs/dev/debt/libSceAgcDriver.md
PR 6987 docs/dev/debt/libSceAgcDriver.md
PR 6989 docs/dev/debt/libSceAgcDriver.md
PR 6995 docs/dev/debt/libSceAgcDriver.md
PR 7002 docs/dev/debt/libSceAgcDriver.md
PR 7085 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7223 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 7256 docs/dev/debt/libSceAgcDriver.md
PR 7410 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 7449 docs/dev/debt/libSceAgcDriver.md
PR 7604 docs/dev/debt/libSceAgcDriver.md
PR 7684 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 7689 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 8004 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 8592 docs/dev/debt/libSceAgcDriver.md
PR 8707 docs/dev/debt/libSceAgcDriver.md
PR 9020 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9318 docs/dev/debt/libSceAgcDriver.md
PR 9335 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9356 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9508 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/WrittenBuffers.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
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 9675 docs/dev/debt/libSceAgcDriver.md
PR 9700 docs/dev/debt/libSceAgcDriver.md
PR 9748 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9891 core/libs/prx/libSceAgcDriver/tests/GuestTextureResource.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9892 docs/dev/debt/libSceAgcDriver.md
PR 9895 docs/dev/debt/libSceAgcDriver.md
PR 9898 docs/dev/debt/libSceAgcDriver.md
PR 9915 docs/dev/debt/libSceAgcDriver.md
PR 9950 docs/dev/debt/libSceAgcDriver.md
PR 10049 docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/WrittenBuffers.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 core/libs/prx/libSceAgcDriver/tests/GuestTextureResource.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10256 docs/dev/debt/libSceAgcDriver.md
PR 10359 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10743 docs/dev/debt/libSceAgcDriver.md
PR 10757 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 10867 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 11351 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 11483 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 11825 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/WrittenBuffers.cpp
docs/dev/debt/libSceAgcDriver.md
PR 11998 docs/dev/debt/libSceAgcDriver.md
PR 12120 docs/dev/debt/libSceAgcDriver.md
PR 12324 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 12548 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 12568 docs/dev/debt/libSceAgcDriver.md
PR 12828 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 13599 docs/dev/debt/libSceAgcDriver.md
PR 13707 docs/dev/debt/libSceAgcDriver.md
PR 13793 docs/dev/debt/libSceAgcDriver.md
PR 13796 core/libs/prx/libSceAgcDriver/tests/GuestTextureResource.cpp
PR 13809 docs/dev/debt/libSceAgcDriver.md
PR 13863 docs/dev/debt/libSceAgcDriver.md
PR 13920 docs/dev/debt/libSceAgcDriver.md
PR 13928 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/WrittenBuffers.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13929 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/WrittenBuffers.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/libSceAgcDriver.md
PR 13963 docs/dev/debt/libSceAgcDriver.md
PR 14005 docs/dev/debt/libSceAgcDriver.md
PR 14032 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 14212 docs/dev/debt/libSceAgcDriver.md
PR 14302 docs/dev/debt/libSceAgcDriver.md
PR 14311 docs/dev/debt/libSceAgcDriver.md
PR 14344 docs/dev/debt/libSceAgcDriver.md
PR 14853 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 14871 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 14943 docs/dev/debt/libSceAgcDriver.md
PR 14944 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Memory/WrittenBuffers.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/libSceAgcDriver.md

@github-actions github-actions Bot added shader core/shader docs agc libSceAgc* labels Oct 25, 2026

@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 the exact PR head 0d41b11bc190e630d89ddb7d5b52b0bd511c33e8.

The change is scoped to the measured TYPE 0/1 storage-image case: nullImageDescriptor now recognizes read or written non-atomic descriptors without a table; draw write-range collection skips IsNullTextureResource in the same way dispatch collection already does; and the added tests keep the real neighboring range while excluding TYPE 0/1 ranges for both draw and dispatch. The debt update records the remaining limitation. On hosts without Vulkan nullDescriptor, these descriptors bind the existing shared storage placeholder, so stores can be observed later through a null storage image; this PR does not introduce that behavior, and it is explicitly documented. The binding path does not decode the TYPE 0/1 descriptor or schedule a guest-memory writeback for it.

The author reports an AMD Radeon PRO V620 measurement where TYPE 0 and 1 stores leave the guest dwords unchanged. Their hosted focused run reports 48 Linux AGC tests passing 10/10 and 47 Windows tests passing with one skip; the five full-suite Linux failures require IPv6. Hosted policy, intake, labels, conventions and report checks pass; the repository skips product jobs on this PR path. git diff --check and tools/check_conventions.py --base upstream/main --head upstream/pr-10906 also pass locally. I did not independently run the Vulkan execution tests or hardware probe.

The PR declares #10556 as a merge-order dependency and does not claim to fix the broader null-placeholder limitation. I found no blocking issue in the scoped change.

AI-assisted: yes.

@tablefrogpillow

Copy link
Copy Markdown
Contributor

@EagleBearerYS Verified this on AMD/RADV (Mesa 25.2.8) across three arches — RX Vega 56 (VEGA10, GCN5), RX 7900 GRE (NAVI31, RDNA3), 7800X3D iGPU (RAPHAEL, RDNA2).

  • Tests pass: the touched tests — agc_driver_graphics, agc_shader_memory, agc_driver_draw_write_ranges, agc_driver_draw_write_ranges_draw_pipeline — pass 4/4 on all three arches, Khronos validation layer on.
  • No regression: the full shader/agc test surface (787 tests) has an identical failure set on the PR head (0d41b11b) and its merge-base (e5f23554) — only 4 pre-existing GCN5-specific float tests fail on both, nothing new.
  • Coverage: reverting just WrittenBuffers.cpp and ResourceMaterializer.cpp to base while keeping this PR's test assertions makes 3 of the 4 fail (agc_shader_memory, agc_driver_draw_write_ranges, …_draw_pipeline), so the added TYPE 0/1 → null-storage-image materialization and write-range checks genuinely exercise the change on AMD, not just compile.

The linux/windows test jobs are SKIPPED on this PR, so flagging that it does pass on real AMD HW.

AI-assisted: yes.

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@tablefrogpillow thank you, that's the real-hardware run this PR was missing, on three architectures and with the reverted-files check too. I've added it to the Tested section, credited to your comment.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 25, 2026
Main's boykopovar#9186 extends the multisampled color target debt entry right after
the type-0 and type-1 descriptor entry this branch rewrites. The merge
keeps both entries.
@wachi35676

Copy link
Copy Markdown
Contributor

NVIDIA and AMD-proprietary run on Windows. Windows 11 10.0.26300, WinLibs GCC 15.2.0, Release; main aeff26b and this PR (a11c83a) merged onto it; ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 (no validation layer installed here); NVIDIA RTX 5070 Ti (621.01) and AMD Radeon RDNA2 iGPU (AMD proprietary 2026.04.17), both with nullDescriptor.

  • agc_driver_graphics, agc_shader_memory, agc_driver_draw_write_ranges(_draw_pipeline), agc_shader_type_zero_image_materialization and the other agc_shader_ tests (44 entries): 44/44 on both GPUs.
  • Control with main's ResourceMaterializer.cpp and WrittenBuffers.cpp: agc_shader_type_zero_image_materialization (runtime image descriptor is invalid) and both draw_write_ranges entries (unsupported image type 0) fail.
  • Device check (local probe, not proposed for the tree): a compute image_store through a written slot holding a TYPE 0 T#, a TYPE 1 T#, or PPSA01474's exact words (04efd000 00040011 00017a00 00005204 ..., whose base is unmapped in the test process) now recompiles, binds and dispatches on both drivers with no device fault or error. main refuses all three with runtime image descriptor is invalid, and TYPE 2 is still refused with the change. On this harness path (VulkanDevice::Dispatch + StoreIdleResults + FlushGpuWrites) even a TYPE 9 control store didn't reach guest memory, so this doesn't show the discard itself, only that both drivers take the null storage binding.
  • A wider set of 248 agc_ entries has the same failures with and without the change.

AI-assisted: yes (Claude Code); results above were run on this machine.

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@wachi35676 thank you, that's the first run of this on NVIDIA and on AMD's own driver, and the probe with the words from Ratchet & Clank: Rift Apart (PPSA01474) is the case this PR is for. I've put your results in the Tested section and added both GPUs to the list. Your note on the probe's path is fair: it shows both drivers take the null storage binding, while the discard itself comes from the gfx1030 measurement in #9749.

@oneandonlydean oneandonlydean self-assigned this Oct 26, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

@EagleBearerYS One test change: verifyTypeZeroImageMaterialization now adds a written+atomic case, Access{false, true, true} (ShaderMemory.cpp:1150), and then requires TYPE 0/1 atomics to throw (ShaderMemory.cpp:1159-1160). Atomic behaviour on these descriptors hasn't been measured, so the test shouldn't require a refusal there; it would fail once atomics are handled. Could you remove that assertion and avoid adding tests that require unmeasured TYPE 0/1 atomics to throw?

Please keep the successful written and read-write TYPE 0/1 materialization checks, the unchanged-words checks, the neighbouring real draw/dispatch range checks and the reserved TYPE 2 invalid-descriptor check. The code can keep refusing atomics until they are implemented; nothing new is needed there.

Atomic access to these descriptors hasn't been measured, so the test
shouldn't require a refusal: it would fail once atomics are handled.
The materializer still refuses them. The written and read-write
materialization checks, the unchanged-words checks and the reserved
TYPE 2 checks stay.

Asked for in oneandonlydean's review.
@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@oneandonlydean Thanks. Done in 83b7421: both TYPE 0/1 atomic cases, including the atomic-only one main's test already had, are out of the loop, so nothing requires them to be refused; the code still refuses them. The written and read-write materialization checks, the unchanged-words checks, the draw/dispatch range checks and the reserved TYPE 2 check stay. The focused tests pass 10 of 10 on Linux and Windows (run).

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 26, 2026
@TechLevelZero

TechLevelZero commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 06cb325 merged onto main 98ddd9c · tested 2026-10-30 11:06 UTC · 21 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,281 passed · 5 failed (0 new, 2 also fail on main, 3 unstable on main) · 40 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,326 of 2,987 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 (861 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 40.8 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
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
Validation IDs already present on main (4 IDs in 390 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (390 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 382 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 (40)
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_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 platform
video_out_flip_labels: skipped, no display or Vulkan device: DisplayWindow: Vulkan support is eithe
Reproduce
git fetch origin 06cb32528205ec5433ae36513e43603aa7cbff17 98ddd9c1792bbab016ceed5db267a93d1d61f00a
git checkout 98ddd9c1792bbab016ceed5db267a93d1d61f00a && git merge --no-ff 06cb32528205ec5433ae36513e43603aa7cbff17
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.

# Conflicts:
#	docs/dev/debt/libSceAgcDriver.md
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 30, 2026
@TechLevelZero

TechLevelZero commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head df709c6 merged onto main 93dbd0f · tested 2026-11-02 07:25 UTC · 20 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,440 passed · 7 failed (0 new, 3 also fail on main, 4 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,492 of 3,165 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 (930 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_lookup_log_fits_build 72.7 s, ⚠️ agc_driver_graphics_maps_fallback 33.8 s, ⚠️ agc_driver_graphics 33.3 s
Intermittent validation messages (1, seen once in the parallel run, not reproduced when the test was re-run alone 2 times; not counted against this PR)
agc_driver_depth_clear_hle: VUID-vkCmdCopyBuffer-commonparent (6x)
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 10 main runs
agc_driver_pipeline_journal: failed in 1 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 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
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 df709c67fd7fbad8211c39b3fd298fbc904c26fe 93dbd0f82aea684e95f15f06e7d42c0064af18cf
git checkout 93dbd0f82aea684e95f15f06e7d42c0064af18cf && git merge --no-ff df709c67fd7fbad8211c39b3fd298fbc904c26fe
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 review queue Next in the maintainer review queue: checks pass, no open change request, no conflict label Nov 2, 2026
@oneandonlydean
oneandonlydean merged commit 0d02927 into boykopovar:main Nov 2, 2026
16 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 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* docs shader core/shader unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants