Skip to content

fix(agc): accept GDS DMA_DATA register address controls - #16345

Open
AlexWhitehouse wants to merge 1 commit into
boykopovar:mainfrom
AlexWhitehouse:fix/agc-dma-data-gds-address-controls
Open

AlexWhitehouse wants to merge 1 commit into
boykopovar:mainfrom
AlexWhitehouse:fix/agc-dma-data-gds-address-controls

Conversation

@AlexWhitehouse

Copy link
Copy Markdown
Contributor

What

A PM4 DMA_DATA (opcode 0x50) with a GDS endpoint was refused whenever that endpoint's address-control bits were set. dmaSource() and dmaDestination() in core/libs/prx/libSceAgcDriver/Execution/src/Pm4.cpp fold SAS/SAIC (packet[6] bits 26 and 28) and DAS/DAIC (bits 27 and 29) into the selector. So GDS (selector 1) with both bits set became selector 13, and validation rejected it with DMA_DATA register source is not implemented or DMA_DATA register destination is not implemented.

That is the encoding Mesa's radeonsi emits for every GDS DMA. Mesa 24.0.0 si_cp_dma.c, lines 72–86:

  • a GDS destination is DST_SEL(GDS) | DAS(REGISTER) | DAIC(NO_INCREMENT);
  • a GDS source is SRC_SEL(GDS) | SAS(REGISTER) | SAIC(NO_INCREMENT);
  • Mesa's comment says the GDS advances the address itself.

The bit positions match PAL's GFX9+ packet definition at c5e8000 (selectors, lines 1238–1249; address controls, lines 1285–1289) and Mesa's pkt3.json.

Change:

Tested

  • New testDmaGdsAddressControls in core/libs/prx/libSceAgcDriver/tests/Pm4.cpp (ctest agc_driver_pm4). Existing assertions are unchanged, and testCopies is untouched.
    • Round trips: memory to GDS with the radeonsi destination encoding, then GDS to memory with the source encoding, returns all four distinct words (none repeated). The same holds for GDS to GDS with both encodings, and for an immediate fill into GDS.
    • Same treatment as clear controls: for each case, Validate, ResolveStore and DecodeStores give the same result as the clear-control GDS packet, and a GDS destination reports no guest memory store.
    • Still refused: out-of-range GDS offsets still fail the range checks. Every other selector with partial or full controls (both endpoints, all four selectors) still fails with the existing register-source or register-destination message.
  • Linux (Ubuntu 26.04, GCC 15, lavapipe Mesa 26.0.8), with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, over the 18 tests matching agc_driver_pm4|agc_driver_recorder|agc_driver_register_key:
    • main passes 18/18. With only the new test added, agc_driver_pm4 fails with DMA_DATA register destination is not implemented; a source-only variant fails with DMA_DATA register source is not implemented;
    • this PR passes 18/18;
    • no VUID- lines and no missing-layer messages.
  • Mutation check: removing the source-side normalisation fails with DMA_DATA register source is not implemented.
  • Windows 11, NVIDIA RTX 3060 (driver 610.88, WinLibs MinGW-w64 GCC 15.2.0, Release), with the same three variables:
    • the 18 matching tests pass at ab1d54e. Windows registers agc_driver_pm4_ring_report_heap where Linux registers agc_driver_pm4_priority_refused;
    • with main's Pm4.cpp, agc_driver_pm4 fails with DMA_DATA register destination is not implemented;
    • no VUID- lines and no missing-layer messages. A VK_LOADER_DEBUG=layer rerun of agc_driver_recorder confirmed that the validation layer was inserted at instance and device level.
  • python3 tools/check_conventions.py --base origin/main: all conventions checks passed.
  • python3 tools/pr_overlap.py --branch fix/agc-dma-data-gds-address-controls: no confirmed overlap.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 3060, driver 610.88, Windows 11 (build 26300); Mesa lavapipe 26.0.8 (LLVM 21.1.8), Ubuntu 26.04
  • AI-assisted: yes

🤖 Generated with Claude Code

Normalize only GDS endpoints with both register-space and no-increment controls to the existing consecutive GDS transfer path. Preserve all other selector rejections and range checks. Cover execution, store resolution, decoding and unsupported combinations independently of testCopies.

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

JJenkx commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Correction (rerun): my first run rebuilt only the main test target, but the test pattern also matched the test from agc_driver_pm4_replay_tests, which was left from an earlier build and so didn't include this PR. I reran with every matching executable rebuilt from a fresh merge onto main d60ebec0c2 (a79971e6f9): same result, same counts, none skipped, no VUID- errors.

Windows check of head ab1d54e4e4, merged onto main 5299939ecf (86d1bcbb05, clean merge).

Setup: Windows 11 Enterprise 22621, WinLibs GCC 15.2 UCRT, Release, Radeon RX 6700 XT, AMD driver 26.10.1. Run through the Windows test queue with ANYPS5_REQUIRE_VULKAN=1 and Vulkan validation layers 1.4.363. The hosted Windows check does not run these tests on pull requests.

  • All 16 tests matching ^agc_driver_pm4, built with agc_driver_pm4_tests, pass in 3 of 3 runs, none skipped.
  • None of them created a Vulkan instance, so this covers the PM4 packet handling under MinGW, not GPU execution.

AI-assisted: yes.

@github-actions github-actions Bot added docs agc libSceAgc* labels Nov 6, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head ab1d54e merged onto main 5299939 · tested 2026-11-06 11:41 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,916 passed · 5 failed (0 new, 4 also fail on main, 1 unstable on main) · 52 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,973 of 4,210 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 (979 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 1 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
web_library_assets
Validation IDs already present on main (9 IDs in 587 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (587 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, and 579 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08739 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 more
VUID-VkShaderModuleCreateInfo-pCode-08741 (14 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_f16_fma_denormal_modes, agc_driver_f16_fma_invalid_nan, agc_driver_float16_fma_rounding, agc_driver_float16_modifiers, agc_driver_float16_native, and 6 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-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
Skipped (52)
agc_driver_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_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
guest_http_uri_locale: 
guest_net_ctl: skipped, the host has no IPv4 address
guest_net_ctl_disconnected: 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_device_capability: 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_host_resolution_disabled: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_four_k: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_height_only: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_limit: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_malformed: skipped, no display or Vulkan device: SDL_InitSubSystem(VIDEO | GAMECONTROLLER) failed: wayland,x11 not available
guest_video_out_host_resolution_width_only: 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 a
Reproduce
git fetch origin ab1d54e4e4c65c1639fcee27a5e829aa7843dedb 5299939ecfa9e186e1eb457c6f4bd133bdb087c7
git checkout 5299939ecfa9e186e1eb457c6f4bd133bdb087c7 && git merge --no-ff ab1d54e4e4c65c1639fcee27a5e829aa7843dedb
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.

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

Checked that the normalisation reaches every consumer on main. Nothing reads the SAS/SAIC/DAS/DAIC bits outside dmaSource/dmaDestination. The users of the selectors all go through Pm4::DmaSource/Pm4::DmaDestination:

  • the pipeline overlap check for DMA_DATA in PacketExecution.cpp (the GDS source range against DrawPipeline::Queue0());
  • the GDS copies and the GDS-destination checks in PacketMemory.cpp (gdsDestination, gdsWritesPending, the store-limit split);
  • describeDmaEnd in tools/Pm4Analysis.cpp.

So a controlled GDS endpoint takes the same paths as a plain one everywhere, not just in validation. The refusal loop in the test covers the other 11 selector and control combinations. testDmaGdsAddressControls is CPU-only, so a GPU run adds nothing beyond the CI result above.

AI-assisted: yes (Claude Code)

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* docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants