Skip to content

fix(agc): drain queued writes before reading shader callees and call tables - #11442

Open
Sam-mon7 wants to merge 4 commits into
boykopovar:mainfrom
Sam-mon7:fix/queued-shader-call-reads
Open

Sam-mon7 wants to merge 4 commits into
boykopovar:mainfrom
Sam-mon7:fix/queued-shader-call-reads

Conversation

@Sam-mon7

@Sam-mon7 Sam-mon7 commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What

ReadRawShader drains queue 0 when a queued draw-pipeline item writes the shader code it is about to read. The user-data callees, call-table descriptors and tables that LinkUserDataCallees links were read without that check.

ReadUserDataCallee and ReadGuestBytes (which reads call-table descriptors and tables) now apply the same overlap check and drain first. All three paths use one helper, DrainShaderWrites, which replaces the lambda that was in ReadRawShader.

Reachability on current main:

  • Compute: every production caller of InvocationFor already drains queue 0 first, or runs on a thread where DrawPipeline::Active() is false (traced in the review thread). The new drains do not fire there.
  • GCN vertex stages: LinkUserDataCallees also links them (as @Amoenus pointed out). On a draw-cache miss, materializeDrawStage reaches InvocationFor on the queue-0 worker while earlier pipelined draws, DMA or fills can still be outstanding, and nothing before it drains the callee or table bytes. So the new drains can fire on that path. GCN mode is enabled only by AgcDriverUseGcnShaders_nid_postfix, and nothing in this tree calls it.
  • So this is defensive ordering. No failure reachable on main today has been demonstrated.

agc_driver_queued_shader_calls exercises the linking API directly with an overlapping queued producer that rewrites a callee, a call-table descriptor or a table entry until the drain, and checks the linked invocation against one built after the drain. Its red/green result verifies that ordering contract rather than reproducing a failure through packet execution or Driver::dispatch.

Noticed while working on Demon's Souls (PPSA01341) on a local branch; the change is generic.

Tested

Windows 11 Pro 10.0.26200, WinLibs GCC 15.2.0, Release, NVIDIA GeForce RTX 4070 (driver 610.88), Khronos validation layer 1.4.363. Merged current main 0d5e03be8c into the branch as merge commit 84c3b32b3a. It had two conflicts:

  • libSceAgcDriver/CMakeLists.txt (the per-test fragment split): resolved with tools/agc_test_split.py resolve. The test keeps ANYPS5_NO_SHADER_CACHE=1;APS5_PIPELINED_DRAWS=8 and TIMEOUT 30, now in tests/cmake/agc_driver_queued_shader_calls_tests.cmake.

  • ReadUserDataCallee: fix(agc): read user-data callees up to the 1 MiB raw shader program limit #10140's early return on an unreadable page is kept, with the drain ahead of it.

  • Focused tests, ctest -R 'agc_driver_(queued|prepared_shader|user_data|callee|call_table|draw_write_ranges|pipelined|gated_dispatch|copied_writer|draw_cache|finisher_label|same_queue_label|unimported_label|write_data_written)' -V -j2 with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:

    • main 0d5e03be8c: 69/69 pass.
    • Merged head 84c3b32b3a: 70/70 pass. That is the same tests plus agc_driver_queued_shader_calls.
    • Neither log contains VUID- or a missing-layer message, and no test was skipped. VK_LOADER_DEBUG=layer shows the validation layer inserted at instance and device level.
  • Red/green on the new base: with main's ShaderRegistry.cpp, the new test fails in each case when run one case at a time (shader invocation ignored queued callee write, ... descriptor write, ... table write). With this change, all three cases pass (Shader calls observed queued code, descriptor and table writes).

  • python tools/check_conventions.py --base upstream/main, python tools/check_test_registration.py build and git diff --check pass on the merged head.

Overlap and landing order

The overlap report lists #9899, #10103 and #10140 for ShaderRegistry.cpp. I checked each against the current heads (git merge-tree and reading the diffs):

#9899 and #10103 merge cleanly with each other and with current main.

Checklist

🤖 Generated with Claude Code

…tables

ReadRawShader drains queue 0 when a queued draw-pipeline item writes the
shader code it is about to read, but the user-data callees and call-table
descriptors and tables a shader links were read without that drain. A
callee, descriptor or table written by queued work was then read stale and
linked into the invocation. ReadUserDataCallee and ReadGuestBytes now
drain the overlapping queued writes first, through the same helper.

agc_driver_queued_shader_calls holds a queued producer that rewrites a
callee, a call-table descriptor or a table entry until the capture drains
it, and checks the linked invocation against one built after the drain.
All three cases fail on main.

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

@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 head e7da862d03403e694ffa6a1f8f9d1e19d1a3fb92 against current main bf77a9e9cba4b02c358779b35295176dd9cae164. The new shared drain preserves the prior raw-shader read behavior and is applied before reading user-data callees, call-table descriptors and table bytes; each range is bounded to the bytes actually read. The regression test holds an overlapping queued producer and checks all three read paths against a post-drain invocation. The test target is picked up by the existing execution-test glob and registered by the shared CMake loop; its timeout/environment properties are set explicitly. The changed paths merge cleanly with current main, and tools/check_conventions.py --base upstream/main --head upstream/pr-11442 plus git diff --check upstream/main...upstream/pr-11442 pass.

The PR reports 66 focused Windows/Vulkan-validation tests passing and no VUIDs; I did not independently run that GPU suite. Hosted policy checks pass, while product/relinker jobs are skipped by path policy. I found no blocking issue in the change.

@github-actions

github-actions Bot commented Oct 26, 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 6188 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 6743 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 6867 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 7622 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 7682 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 8592 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 9508 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 9563 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 13928 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 13929 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 14296 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 15499 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 16025 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 16413 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp
PR 16421 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp

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

Rechecked exact head e7da862d03403e694ffa6a1f8f9d1e19d1a3fb92 against live main 2dbe9b99f577f5fad8ee675932a0603439e5eb2a. The earlier 66/66 focused Vulkan run was reported against 7b415520b6; since then main changed the AGC CMake registration and tests/ShaderMemory.cpp. The merged tree is clean, and I found no change to this PR’s ShaderRegistry.cpp or QueuedShaderCalls.cpp logic in that interval, but the required main-vs-change validation does not cover the current tree yet.

Please sync the branch to current main, preserve the test registrations, and rerun the same focused suite with the validation layer on current main and the resulting head. Update the tested base/head in the PR description. Local current-main conventions and whitespace checks pass; the merge-tree preview is clean. Hosted product/build jobs are skipped by path policy, and I did not independently run the GPU tests.

@ycbuzi

ycbuzi commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

A Windows run of e7da862d03 with the AMD iGPU and an older NVIDIA card added, to go with your RTX 4070: Windows 11 Home 10.0.26200, WinLibs GCC 15.2.0 r7 (MinGW-w64 UCRT), Release, merged onto main 48c160c58b with no conflicts. One GPU at a time with ANYPS5_GPU, plus ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1, run with ctest -V --repeat until-fail:2. Each log's Selected GPU line names the device.

device agc_driver_queued_shader_calls
GeForce RTX 4070 SUPER (0x2783), NVIDIA 616.92 passes, both runs
GeForce GTX 1650 SUPER (0x2187), NVIDIA 616.92 passes, both runs
AMD Radeon(TM) Graphics (1002:164e, RDNA2 iGPU), AMD 32.0.21030.2001 passes, both runs
  • Control with main's ShaderRegistry.cpp: it fails on the 4070 with shader invocation ignored queued callee write.
  • The build has no warnings.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot added build agc libSceAgc* labels Oct 26, 2026
@adriadam10 adriadam10 self-assigned this Oct 27, 2026

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The change itself looks right: DrainShaderWrites is applied before each callee page, call-table descriptor and table read, bounded to the bytes read, and agc_driver_queued_shader_calls fails without it (the queued producer only releases after a drain, so the old code times out and throws).

One open point, the one @MarcZX10 requested on this head: the tested base (7b415520b6) is behind main. Please merge current main, rerun the focused suite with the validation layer on main and on the result, and update the base/head in Tested. @ycbuzi's run on main 48c160c58b (RTX 4070 SUPER, GTX 1650 SUPER, AMD iGPU, control failing on main) is good supporting evidence, but the numbers in the description should match the head you push.

@oneandonlydean oneandonlydean self-assigned this Oct 27, 2026
@thuanquang

Copy link
Copy Markdown
Contributor

@Sam-mon7 a question about reachability, from reading e7da862d03 and current main. I didn't build or run anything.

On main, the two new DrainShaderWrites calls (ShaderRegistry.cpp:990 and :1007) don't seem to fire from any production path:

  • DrainShaderWrites returns unless DrawPipeline::Active() is true (:83-87).
    • Active() is a thread-local, and its only production setter is PacketExecution.cpp:155, so it holds only on the queue-0 worker.
  • LinkUserDataCallees (and through it, the callee and table reads) is compute-only (:1037-1040), so it is reached only from InvocationFor.
  • On the queue-0 worker, Driver::dispatch drains queue 0 before a non-cached dispatch reaches InvocationFor at Dispatch.cpp:372:
    • with APS5_PIPELINE_DISPATCH unset, the drain is at :155;
    • otherwise it is at :327 or :361.
    • A dispatch can be pipelined only when it is cached, and cached dispatches skip InvocationFor.
  • The other compute callers either drain first, or run on threads where Active() is false:
    • resolve-ahead returns or drains for queue 0 (DispatchAhead.cpp:128/:132);
    • the registration-pool lambda at DispatchAhead.cpp:227 runs on threads where Active() is false.

So Busy() is already false when the new helper runs.

  • The new test is red on main because it sets Active() on the test thread and calls InvocationFor directly while its own producer sits in queue 0 (QueuedShaderCalls.cpp:59-80).
  • No production caller creates that state.
  • This differs from ReadRawShader's existing drain, which is reachable because Dispatch.cpp:85 reads before the :155 drain.

If there is a path I missed (a title, or the local-branch change the description mentions), could the test go through Driver::dispatch or packet execution? Then it would show the failure on main. Otherwise it may help to say in the description that this is defensive ordering with no failure reachable on main today.

@Sam-mon7

Copy link
Copy Markdown
Contributor Author

Merged current main (e2a5118839) into the branch as d68f894df5, no conflicts, and reran the focused suite with the validation layer on both trees: main 65/65, merged head 66/66 (new tests included), no VUID- or missing-layer messages; conventions pass. Tested is updated with the new base and head.

@MarcZX10 @adriadam10, could you take another look?

AI-assisted: yes (Claude Code)

@Sam-mon7

Copy link
Copy Markdown
Contributor Author

@thuanquang thanks, your reachability analysis is right. I traced the packet and dispatch paths on current main, including APS5_PIPELINE_DISPATCH=1, queue-0 group capture and the draw finisher, and on my local branch, and found no route that reaches compute linking with overlapping queue-0 work still pending: the uncached and verification paths drain first, and eligible pipelined cache hits skip linking. A producer-then-uncached-dispatch test through Driver::dispatch would pass on both main and this PR, so the direct InvocationFor test verifies the ordering contract rather than a reachable failure.

I've updated the description to say this is defensive ordering with no failure reachable on main today. If you'd rather not take a defensive change, I'm fine closing it.

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.

Re-reviewed current head d68f894df506cb7f80d48be4424dc0092fc5d599 and the latest reachability clarification.

The clarification resolves the earlier question: this is a defensive ordering change, and the author found no production route on main that reaches compute linking with overlapping queue-0 work pending. That does not by itself make the change incorrect; the bounded InvocationFor test documents the ordering contract. I would keep the change if it is useful as that defensive guarantee.

Two integration items remain before merge:

  1. The PR is based on e2a51188396df488b222521ac517cae715b3652c, while live main is 4c7d275bef89d309313d16bc2bc05d37a1b50be2. The current merge preview is clean, but main has since changed ShaderRegistry.cpp and the AGC CMake test registrations. Please sync to current main, preserve the queued shader-call test registration/environment, and rerun the focused validation-layer suite on the exact current-main base and resulting head. The reported 65/65 and 66/66 comparison is useful evidence for the prior base, not the current integration.
  2. The current overlap report lists this PR with #9899, #10103 and #10140 in ShaderRegistry.cpp. Please manually confirm the interactions and record the agreed landing order/dependencies on both sides where the overlap rule requires it. #10103’s author documents a clean source-only merge with #9899, but I found no recorded agreement covering this PR and all three overlaps.

Checks I ran: current-main git merge-tree --write-tree is clean (36b1914bb6568cc2a90eb367865a706b7b225cee), git diff --check passes, and current-main conventions pass. I did not run the GPU tests locally; this environment has no Vulkan device. The author-reported hardware results remain attributed to the author.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head d68f894 merged onto main 52c09d5 · tested 2026-10-29 08:54 UTC · 30 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,276 passed · 5 failed (0 new, 5 also fail on main) · 39 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,320 of 2,873 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 (894 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) none
Failing on main too (5, not counted against this PR)
agc_compute_pipeline_inspection
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_queued_shader_calls
Validation IDs already present on main (4 IDs in 436 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (436 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alpha_to_coverage, agc_driver_array_layer_target_cpu, agc_driver_bc_block_copy, and 428 more
VUID-vkCmdCopyImage-srcImage-01548 (11 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_storage_dispatch, and 3 more
VUID-vkCmdCopyImage-srcImage-01551 (11 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_storage_dispatch, and 3 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (2 tests): agc_driver_prepared_exports, agc_driver_srgb8_color_target
Skipped (39)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_msaa_dcc_compared_import_2: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_4: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_msaa_dcc_compared_import_8: skipped, the device reports host imports that keep write protection, so the write-watch probe compares none of them
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_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_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 either not configured in SDL or not available in current SD
Reproduce
git fetch origin d68f894df506cb7f80d48be4424dc0092fc5d599 52c09d567d2fa453494dd720fcf53a98149468e4
git checkout 52c09d567d2fa453494dd720fcf53a98149468e4 && git merge --no-ff d68f894df506cb7f80d48be4424dc0092fc5d599
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.

@MarcZX10

Copy link
Copy Markdown
Contributor

Thanks for the updated NVIDIA test report on exact head d68f894. The broad suite and validation-layer comparison are useful; the report says the new queued-shader-call test was validated but not compared to main. My remaining review requests are still open: update this branch from current main (now aaccd0b; this head is substantially behind), compare the focused validation-layer test on both current main and the updated head, and record the overlap/landing order with #9899, #10103 and #10140. I did not run the GPU suite locally.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Sam-mon7

Copy link
Copy Markdown
Contributor Author

@MarcZX10 I synced this branch with current main 466bf10f7f as merge 39c8af55c0. The merge was clean, and the queued shader-call test keeps its registration and ANYPS5_NO_SHADER_CACHE=1;APS5_PIPELINED_DRAWS=8 environment.

Tested. Windows 11, NVIDIA RTX 4070, driver 610.88, Release. Same command on both trees, with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:

  • main 466bf10f7f: 3/3 related shader tests passed (queued raw shaders and user-data calls).
  • 39c8af55c0: 4/4 passed, the same three plus agc_driver_queued_shader_calls.
  • VUID-: 0 on both. Neither log has the missing-layer message, and no tests were skipped.
  • check_conventions.py --base 466bf10f7f and check_test_registration.py pass.

Overlaps. I proposed an order on #9899, #10103 and #10140: this PR first, since it only moves ReadRawShader's drain into DrainShaderWrites and adds two calls, and theirs re-apply those calls when they merge main. I've offered to go second if any author prefers. I'll record the agreed order with Depends on here and on theirs once they reply.

@Amoenus

Amoenus commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

@Sam-mon7 Accepted your offered reverse order: #10103 -> this PR, with the exact shared-function resolution and a current-main GCN-vertex reachability note in our reply. #10103's body now records the order; please add its merge-order prerequisite here. #9899/#10140 coordination remains separate. Source review only, no combined runtime claim. AI-assisted: yes (Codex).

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

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 39c8af5 merged onto main bb04a4f · tested 2026-10-30 01:06 UTC · 30 min

GPU NVIDIA RTX 2000 Ada Generation, driver 595.99.02, Vulkan 1.4.329
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,311 passed · 6 failed (0 new, 5 also fail on main, 1 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,357 of 2,918 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 (896 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 53.9 s
Unstable on main (1, 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 7 main runs
Failing on main too (5, not counted against this PR)
agc_compute_pipeline_inspection
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (1, not in the main baseline's validation pass)
agc_driver_queued_shader_calls
Validation IDs already present on main (4 IDs in 433 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (433 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_array_layer_target, agc_driver_array_layer_target_cpu, agc_driver_bda_anchor_reads, and 425 more
VUID-vkCmdCopyImage-srcImage-01548 (11 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_storage_dispatch, and 3 more
VUID-vkCmdCopyImage-srcImage-01551 (11 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_storage_dispatch, and 3 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_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
agc_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_import_settle_initial_dcc: skipped, the device has no deferred settle of host imports: imports under 1 MiB wait for one only on Windows
agc_unit_shadow_completion_store: skipped, the device reports watched host memory written when it imports or reads it
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_video_out_color_space: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_hdr: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_high_frame_rate: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_output_mode: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_resolution_status: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_wqhd_detection: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
video_out_flip_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 either not configured in SDL or not
Reproduce
git fetch origin 39c8af55c0f4b3051a08e99a1fefe746aa494b45 bb04a4f1ea0175e9e4f149f0359a764d62ff3296
git checkout bb04a4f1ea0175e9e4f149f0359a764d62ff3296 && git merge --no-ff 39c8af55c0f4b3051a08e99a1fefe746aa494b45
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.

@bunbeans2-arch

Copy link
Copy Markdown
Contributor

An AMD RDNA 4 run on Windows of 39c8af55c0 as is, since the GPUs tested are NVIDIA. It conflicts with current main in ShaderRegistry.cpp, so I built the head itself (base 466bf10f7f).

Windows 11 Pro 10.0.22631, AMD Radeon RX 9070 XT (1002:7550, driver 32.0.32015.7029, amdvlk64), MSYS2 UCRT64 g++ 16.1.0, Release. ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation; with VK_LOADER_DEBUG=layer the loader logs Insert instance layer "VK_LAYER_KHRONOS_validation" in every run of every test below that creates a Vulkan instance. 3 runs:

  • agc_driver_queued_shader_calls, which this PR adds, passes 3 of 3 with Shader calls observed queued code, descriptor and table writes.
  • agc_driver_depth_bounds_emulation_draw and agc_driver_packed_unorm4444_multisample_partial_write pass 3 of 3.
  • No VUID- line.

AI-assisted: yes (Claude Code)

Conflicts:
- core/libs/prx/libSceAgcDriver/CMakeLists.txt: main moved AGC test
  registrations into tests/cmake fragments (00dd261). Resolved with
  tools/agc_test_split.py resolve; agc_driver_queued_shader_calls keeps
  ANYPS5_NO_SHADER_CACHE=1;APS5_PIPELINED_DRAWS=8 and TIMEOUT 30 in
  tests/cmake/agc_driver_queued_shader_calls_tests.cmake.
- ShaderRegistry.cpp: ReadUserDataCallee keeps main's boykopovar#10140 early
  return on an unreadable page, with DrainShaderWrites ahead of it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Sam-mon7

Sam-mon7 commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

@MarcZX10 @adriadam10 I merged current main 0d5e03be8c into the branch as 84c3b32b3a. There were two conflicts:

  • libSceAgcDriver/CMakeLists.txt (the fragment split): resolved with tools/agc_test_split.py resolve. agc_driver_queued_shader_calls keeps ANYPS5_NO_SHADER_CACHE=1;APS5_PIPELINED_DRAWS=8 and TIMEOUT 30, now in tests/cmake/agc_driver_queued_shader_calls_tests.cmake.
  • ReadUserDataCallee against fix(agc): read user-data callees up to the 1 MiB raw shader program limit #10140: its early return on an unreadable page is kept, with the drain ahead of it.

Tested (RTX 4070, driver 610.88, Windows 11, Release). I ran the same focused command as in the description on both trees, with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation:

  • main 0d5e03be8c: 69/69.
  • 84c3b32b3a: 70/70, the same tests plus agc_driver_queued_shader_calls.
  • VUID-: 0 in both logs. There is no missing-layer message, no test was skipped, and VK_LOADER_DEBUG=layer shows the layer inserted.
  • Control: the new test with main's ShaderRegistry.cpp fails in each of its three cases (callee, descriptor, table). With this change all three pass.
  • Conventions, test registration and git diff --check pass.

Overlaps, now recorded in the description:

I also updated the reachability note: GCN vertex stages can reach the new drains on a draw-cache miss, but GCN mode has no caller in this tree. No failure reachable on main is claimed.

AI-assisted: yes (Claude Code)

@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Nov 1, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 84c3b32 merged onto main 93dbd0f · tested 2026-11-02 08:31 UTC · 26 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,495 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,545 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 (931 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.6 s, ⚠️ agc_driver_lookup_log_fits_build 46.5 s, ⚠️ agc_driver_graphics 45.8 s, ⚠️ agc_driver_graphics_maps_fallback 45.3 s
Unstable on main (2, 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 1 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 (1, not in the main baseline's validation pass)
agc_driver_queued_shader_calls
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 84c3b32b3a0c738b076c39fd7f1311c25356f30f 93dbd0f82aea684e95f15f06e7d42c0064af18cf
git checkout 93dbd0f82aea684e95f15f06e7d42c0064af18cf && git merge --no-ff 84c3b32b3a0c738b076c39fd7f1311c25356f30f
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.

This branch has not been deployed

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

Labels

agc libSceAgc* build needs rebase Conflicts with main, rebase needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants