Skip to content

fix(shader): throw for DPP, ds_swizzle, ds_bpermute and v_permlane16 reads of another lane on one-lane waves - #14072

Open
frankea wants to merge 8 commits into
boykopovar:mainfrom
frankea:fix/one-lane-cross-lane-reads
Open

frankea wants to merge 8 commits into
boykopovar:mainfrom
frankea:fix/one-lane-cross-lane-reads

Conversation

@frankea

@frankea frankea commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

What

Follow-up to #14068, which this branch sits on. On a device whose subgroupSupportedStages lacks the vertex stage (lavapipe, MoltenVK), vertex and local programs run as one-lane waves (#4470): the invocation is lane 0, a ballot is its own bit and a shuffle returns its own value. DPP moves, ds_swizzle_b32, ds_bpermute_b32 and v_permlane16_b32 had no lane check on that path, so a value the console reads from another lane's VGPR came back as an inactive lane's (0, the bound_ctrl value or the old value) or, with fetch-inactive, as the invocation's own. #14068 listed them in the "One-lane vertex waves" debt entry as unchecked. Merged hull programs also run at one lane, but requireOwnLanes in TessellationLowering.cpp refuses every cross-lane opcode before the SPIR-V emitter, so they never reach these checks.

  • Change. On a one-lane wave these reads now throw through FailOutsideHostSubgroup when lane 0 reads another lane, for example DPP read of lane 1 is outside the 1-lane host subgroup that runs this wave64 program at one lane per invocation.
  • DPP (EmitDppMoveU32). Lane 0's source comes from DPP_CTRL (RDNA 2 ISA, 13.3.9, Table 91, page 268): quad_perm reads dpp_cntl[1:0], row_shl:n lane n, row_ror:n lane 16 - n, row_mirror lane 15 and row_half_mirror lane 7. row_share:n and row_xmask:n (0x150-0x16F, LLVM's dpp16_ctrl and DppCtrl in SIDefines.h) read lane n. DPP8 reads LANE_SEL0 (13.3.10, Table 92, page 269). row_shr gives lane 0 no source ("else use bound_cntl"), so the row_shr steps of the wave scans still build, the elected f32 maximum of verifySingleLaneElectedAtomicMax among them.
  • ds_swizzle_b32 (EmitSwizzleU32). Lane 0's source comes from the offset (12.13.1, page 207): or_mask ^ xor_mask in the 32-thread mode, offset[1:0] in the 4-thread mode, and the rotate mode as EmitDsSwizzleTargetLane decodes it.
  • ds_bpermute_b32 (EmitBpermuteU32). Lane 0 reads lane (ADDR + OFFSET) / 4 (12.13, page 206) of its 32-lane half, as the emitter takes it. A constant address must name lane 0. Any other address throws unless OwnLaneSelectorWalk from fix(shader): throw for v_readlane_b32 of a register-selected lane on one-lane waves #14068 proves it is the address the translator builds for image_sample_*_cd, which takes its derivatives from the quad's first active lane: Select(mask != 0, quad + FindILsb32(mask), lane) << 2, where lane is the lane id, quad is an AND with it, and mask is a word built from ballots (for it the walk also accepts a ballot word shifted right). On one lane that is the invocation's own lane, so these samples keep building. Guest code reaches the lane id only through v_mbcnt, which lowers to a BitCount the walk never accepts, so every register address a guest program writes throws.
  • v_permlane16_b32 (EmitPermlane16U32). Lane 0 reads S1[3:0] (12.12, page 186, lanesel = {S2, S1}), so S1 must be a constant with those bits clear. v_permlanex16_b32 was already checked.
  • Unchanged. Accepted programs emit the same SPIR-V as before, and devices with vertex subgroups are not affected. The integer half-wave scan of verifyNarrowVertexWave already throws on one lane at its v_permlanex16_b32 and still does. The DPP reads in the vertex programs of the execution tests are row_shr steps and quad_perm:[0,1,2,3], and none of them uses ds_swizzle_b32, ds_bpermute_b32 or v_permlane16_b32, so lavapipe runs them as before.
  • Debt. The "One-lane vertex waves" entry now states these checks instead of listing the reads as unchecked (987 characters, next to fix(shader): throw for v_readlane_b32 of a register-selected lane on one-lane waves #14068's non-empty mask rule). With fix(shader): run tessellation evaluation stages one lane per invocation on devices without subgroups there #13807 in main, the merge also drops the tessellation evaluation entry's note that a register-selected v_readlane_b32 lane is not checked, which fix(shader): throw for v_readlane_b32 of a register-selected lane on one-lane waves #14068 makes untrue; that entry already defers to the one-lane vertex rules.
  • Tessellation evaluation. fix(shader): run tessellation evaluation stages one lane per invocation on devices without subgroups there #13807, now in main, puts tessellation evaluation programs without subgroups on the same path, so they get these checks with no further code; its verifySingleLaneDomainWave passes with them.

Title: none. In my Gran Turismo 7 (PPSA01317) shader disk cache from MoltenVK runs on an Apple M5 Max (27,036 entries), the 1,198 distinct programs compiled at one lane per invocation (1,055 vertex, 137 tessellation evaluation, 6 local; the cache key records the host width) hold no DPP, ds_swizzle_b32, ds_bpermute_b32, v_permlane16_b32 or v_permlanex16_b32, so none of them starts throwing. They were disassembled with llvm-mc 18 as gfx1013, since gfx1030 lacks the v_mad_f32 these programs use, and a raw scan of the DS and VOP3 opcodes agrees.

Tested

Windows 11 on an RTX 4090 (driver 616.92, Vulkan 1.4.341), winlibs GCC 15.2.0, Release with BUILD_TESTING=ON. The 4090 has vertex subgroups, so its draws keep the subgroup path; the one-lane path runs there only in the agc_shader_memory_tests checks, which compile for explicit targets.

  • 40 ctest entries pass 3 times in a row on this branch (067a530fec: fix(shader): throw for v_readlane_b32 of a register-selected lane on one-lane waves #14068's dcd3021fea plus this change) merged onto main ed5c169: the 25 entries of agc_shader_memory_tests, agc_driver_read_lane, agc_driver_write_lane, agc_driver_lds_mask_waterfall, agc_driver_exec_host_lanes, agc_driver_ngg_vertex_wave_reduction, agc_driver_pixel_wave_reduction, agc_driver_pixel_row_reduction, agc_driver_wave32_subgroup, agc_driver_window_lane_spill, agc_driver_scalar_sop1, agc_driver_tessellation, agc_driver_tessellation_depth_range_remap, agc_driver_relative_ancillary, agc_driver_image_sample_derivatives and agc_driver_vertex_elected_atomic_max (skipped: the 4090 has vertex subgroups). They pass once more under VK_LAYER_KHRONOS_validation with ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1 (ctest -V), with no VUID- lines and no was not found but was requested by env var VK_INSTANCE_LAYERS; the loader log for agc_driver_read_lane in that environment shows the layer inserted. The same entries, then 36 (21 in agc_shader_memory_tests), passed the same way on the earlier heads 2928046282, 6617bb0427, 4d7358d6ac, 68c45dc452 and 4b3d7091e6 and on main 029463c and e8c25dd.

Apple M5 Max, macOS 27.0.1, x86-64 under Rosetta 2: the 21 agc_shader_memory_tests entries pass 3 times in a row on this branch (067a530fec), built natively. These compile for explicit targets and run no GPU work. One local build aid that is not part of this pull request was needed for the build: the GuestMemory.cpp part of #11447.

New checks, in verifySingleLaneCrossLaneReads (tests/ShaderMemory.cpp, before verifySingleLaneVertexWave), all in wave64 vertex programs:

  • Without vertex subgroups these build and use no subgroup operation: DPP quad_perm:[0,0,2,2], row_shr:1, row_share:0 and dpp8:[0,0,0,0,4,4,4,4], ds_swizzle_b32 swizzle(BROADCAST,4,0), ds_bpermute_b32 of address 0, v_permlane16_b32 with selects 0x76543210, and image_sample_cd.
  • Without vertex subgroups these throw with the lane they name, and they build on a 32-lane vertex subgroup: DPP quad_perm:[1,0,3,2] (lane 1), row_shl:1 (1), row_ror:4 (12), row_mirror (15), row_xmask:2 with fi:1 (2) and dpp8:[7,6,5,4,3,2,1,0] (7), ds_swizzle_b32 swizzle(SWAP,1) (1) and swizzle(QUAD_PERM,2,1,0,3) (2), ds_bpermute_b32 of address 4 (1) and at offset:4 (1), ds_bpermute_b32 (register-selected) of the vertex index, of the v_mbcnt lane id plus the vertex index, of the vertex index plus 32, of the vertex index ORed with 32 and of the vertex index at offset:128, v_permlane16_b32 with selects 1 (1) and with a select v_readfirstlane_b32 took from the vertex index (register-selected).
  • Guest code cannot write the addresses that pin the walk's shift count and its first-active-lane sum, since the only address that passes its lane rule is the translator's image_sample_*_cd address. So three programs are built as IR and emitted for a one-lane host subgroup: with that address the ds_bpermute_b32 builds, and with it shifted left by 3 instead of 2, or with the next quad's first active lane, (quad + 4) + FindILsb32(mask), it throws (register-selected).
  • With any one of the four checks removed, or with the walk's first-active-lane, AND, shift or lane id rule removed, the test fails at the matching case, and so it does with a sum, OR or offset rule added back that accepts a register next to a lane-0 term, with any shift count accepted, or with a first active lane plus any value accepted.

tools/check_conventions.py --base origin/main passes on the branch, and it merges cleanly with main ed5c169. tools/pr_overlap.py --branch fix/one-lane-cross-lane-reads against main 0da8261 finds one overlap, #15573, which rewords the debt line next to the tessellation evaluation entry this branch edits; 41 pull requests that conflict with main themselves share files with this branch and could not be compared.

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: fix(shader): throw for v_readlane_b32 of a register-selected lane on one-lane waves #14068
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA RTX 4090 (Windows 11, driver 616.92, Vulkan 1.4.341)
  • AI-assisted: yes (Claude Code)

…one-lane waves

Vertex and local programs on a device without vertex subgroups run as
one-lane waves, where a shuffle returns the invocation's own value.
v_readlane_b32 checked its lane only when a constant named it: a lane
held in an SGPR read the invocation's value whatever lane it named,
where the console reads that lane's VGPR (RDNA 2 ISA 12.12,
V_READLANE_B32: the lane is S1 % 64 in wave64).

On a one-lane wave a register-selected lane must now be the s_ff1 of a
mask built from EXEC and ballots, as in a waterfall loop. Such a mask
holds no lane but the invocation's own, so the read is its own value;
the -1 of an empty mask (RDNA 2 ISA 12.3, S_FF1_I32_B64) reads it too.
Any other selector throws through FailOutsideHostSubgroup. Accepted
programs emit the same SPIR-V as before.

The one-lane rules leave the vertex entry debt line for an entry of
their own, which also lists the cross-lane reads still unchecked there:
DPP moves, ds_swizzle_b32, ds_bpermute_b32 and v_permlane16_b32.

@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 — looks good

The exact head’s lane guards and regression cases are internally consistent, and the author reports the focused shader tests passing on this head.

What I ran

Reviewed head 2928046282310a415ae3c922ff7b035dbf852706 against base 0f302813cebfc09e3e0b6f8fced15262d186879e; the dependency #14068 is included, and each PR’s merge preview against that base was clean. Environment: Debian Linux 6.1, Python 3.11.2, GCC 12.2.0; no C++ compiler or build was run.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14072 --output-dir /tmp/anyps5-14072-review
git diff --check 0f302813cebfc09e3e0b6f8fced15262d186879e...2928046282310a415ae3c922ff7b035dbf852706
python3 tools/check_conventions.py --base 0f302813cebfc09e3e0b6f8fced15262d186879e --head 2928046282310a415ae3c922ff7b035dbf852706 --title "fix(shader): throw for DPP, ds_swizzle, ds_bpermute and v_permlane16 reads of another lane on one-lane waves" --body /tmp/pr-14072-body.md
python3 tools/pr_test_quality.py --root /tmp/anyps5-14072-review/head-292804628231-ffa8523b --json core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
git show 2928046282310a415ae3c922ff7b035dbf852706:core/libs/prx/libSceAgcDriver/CMakeLists.txt | grep -n 'tests/ShaderMemory.cpp\|ShaderMemory.cpp'
gh api repos/boykopovar/AnyPS5/commits/2928046282310a415ae3c922ff7b035dbf852706/check-runs --jq '[.check_runs[] | {name,status,conclusion}]'

Results

Check Result
Patch whitespace Passed: git diff --check emitted no output.
Repository conventions and PR template Passed.
Dependency and merge previews Passed: #14068’s exact head is included; both PRs preview cleanly against the current base.
Test-quality heuristic One possible-registration warning; verified against the PR head’s CMake file, which registers tests/ShaderMemory.cpp in agc_shader_memory_tests. The warning is a false positive.
Source review No blocking issue found in the selector/address walk or the DPP, DS-swizzle, bpermute, and permlane16 lane-0 guards. The added cases cover accepted own-lane forms, rejected cross-lane forms, and 32-lane subgroup compilation.
Author-reported focused tests The PR description reports its targeted CTest set passing three times on this head and a prior main ancestor, plus validation-layer runs without VUID output. These are author-reported, not independently rerun here.
Hosted checks at final refresh Windows and ASAN passed; eligibility, conventions, library portability, intake, labels, and report passed. Linux was skipped. Two relinker jobs were in progress and two macOS relinker jobs queued; these are not shader-focused test results.
Raw outputs and relevant report excerpts

git diff --check output (empty):

check_conventions.py:

All conventions checks passed.

Dependency report:

Dependency order: #14068 → #14072

- PR #14068: **clean** against current base; head `5e086eaac896fb794a8a59c947e3427ca6ebde43`
- PR #14072: **clean** against current base; head `2928046282310a415ae3c922ff7b035dbf852706`
- #14068 → #14072: **head_included**

Test-quality heuristic output:

{
  "findings": [
    {
      "path": "core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp",
      "line": 1,
      "kind": "possible-unregistered-cpp-test",
      "message": "Changed C++ test source path was not found literally in CMake files; inspect registration, generated source lists, and workflow coverage."
    }
  ],
  "negative_control_candidates": [],
  "limits": [
    "Heuristics can miss weak assertions and can flag valid tests; inspect every finding.",
    "A test that passes against base is not by itself proof that the PR test is inadequate.",
    "Negative controls are only candidates until the test actually runs against base and fails by assertion rather than import/setup error."
  ]
}

CMake registration at the reviewed head:

787 add_test_executable(agc_shader_memory_tests EXCLUDE_FROM_ALL
788         tests/ShaderMemory.cpp
789         Execution/src/ShaderMemory.cpp

Hosted-check snapshot (the response to the command above):

[
  {"name":"write-watch","status":"completed","conclusion":"skipped"},
  {"name":"register-context","status":"completed","conclusion":"skipped"},
  {"name":"linux","status":"completed","conclusion":"skipped"},
  {"name":"relinker-asan","status":"completed","conclusion":"success"},
  {"name":"relinker (macos-latest, clang++, x86_64)","status":"queued","conclusion":null},
  {"name":"relinker (ubuntu-latest, g++)","status":"in_progress","conclusion":null},
  {"name":"relinker (windows-latest, g++)","status":"in_progress","conclusion":null},
  {"name":"relinker (macos-latest, clang++)","status":"queued","conclusion":null},
  {"name":"windows","status":"completed","conclusion":"success"},
  {"name":"intake","status":"completed","conclusion":"success"},
  {"name":"labels","status":"completed","conclusion":"success"},
  {"name":"conventions","status":"completed","conclusion":"success"},
  {"name":"report","status":"completed","conclusion":"success"},
  {"name":"eligibility","status":"completed","conclusion":"success"},
  {"name":"library-portability","status":"completed","conclusion":"success"}
]

The precheck also attempted a changed-export ABI audit, but that helper was absent from its isolated PR checkout; this PR changes no exports, so that audit is not applicable. I did not treat that helper-launch error as a PR failure.

Findings

Blocking

None found in the reviewed source.

Non-blocking

The focused shader tests and validation-layer runs are reported by the author; I did not independently reproduce them. The author reports testing against e8c25dd3ba, an ancestor of the current base; the only change between that test base and current main touching these tests is CMake registration metadata.

Sources

Not verified

I did not build or compile the recompiler, run CTest, or exercise a GPU/console locally. The final hosted snapshot still had relinker jobs in progress or queued; Linux was skipped. The PR description’s hardware and validation-layer results were not independently confirmed.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewed — changes requested

I am correcting my earlier approval after finding that the inherited selector proof can accept a register-selected lane other than the current lane.

What I ran

Reviewed head 2928046282310a415ae3c922ff7b035dbf852706 against base 0f302813cebfc09e3e0b6f8fced15262d186879e; the reported merge preview was clean. Environment: Debian Linux 6.1, Python 3.11.2, GCC 12.2.0; no build or CTest was run.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14072 --output-dir /tmp/anyps5-14072-review
python3 tools/pr_stack_check.py 14072 --repo boykopovar/AnyPS5 --output-dir /tmp/anyps5-14072-review/stack

Results

Check Result
Earlier no-build precheck and stack preview The exact head/base above were checked; the dependency/merge preview was clean.
Selector proof Blocking source issue confirmed: an empty FindILsb32 input can produce -1/lane 63, and the SelectU32 shortcut does not validate that its condition is related to the low mask.
Hosted CI Windows relinker job is failing on this head; Linux and macOS relinker jobs passed; remaining queued/skipped jobs are not evidence of a full platform matrix.
Earlier review My previous approval is superseded by this request for changes.
Raw outputs

The precheck report and raw command output were generated under /tmp/anyps5-14072-review. No build or CTest output exists because neither was run.

Negative control

Assertion Mutation or input Did the new test fail?
A one-lane host must not substitute lane 0 for a possible guest lane 63. FindILsb32(0) as the lane selector, and SelectU32(unrelated_false, FindILsb32(1), 0xffffffff). These false-acceptance cases are not covered by the tests I inspected and were not run locally.

Findings

Blocking

The inherited OwnLaneSelectorWalk::selector() proof accepts FindILsb32(word) when word is proven to contain no bits outside bit 0, but that proof accepts word == 0. The ISA S_FF1_I32_B32 result for zero is 0xffffffff (-1); EmitReadLane masks it with waveSize - 1, yielding lane 63 for a wave64 guest. In a one-lane host subgroup, EmitSubgroupShuffle copies the current value, so an executing guest lane 0 can receive lane 0's value where the console reads lane 63.

The SelectU32 shortcut has a separate gap: it checks the true/false values but never verifies that the select condition tests the same low mask. An unrelated false condition can therefore select 0xffffffff even when bit 0 is present. Please make the proof fail closed unless it establishes lane 0 for every executing invocation, including non-emptiness and the relationship between the condition and both branches. Add regressions for an empty low mask while lane 0 remains active and for the unrelated-condition case.

Non-blocking

The Windows relinker CI job is failing. Its failure is not the basis of this request, but should be diagnosed and reported with the next update.

Sources

Not verified

No build, CTest, GPU, or console run was performed. Hosted CI does not substitute for the missing regression cases. The Windows failure's cause has not been diagnosed here.

To get this to a good state

Fix the selector proof and add both regressions, then diagnose the Windows job. I will rerun the same relevant no-build checks on the new head.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 2928046 merged onto main 73f4f7e · tested 2026-10-31 18:15 UTC · 15 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,335 passed · 5 failed (0 new, 4 also fail on main, 1 unstable on main) · 48 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,388 of 3,072 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 (878 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_graphics_maps_fallback 35.5 s, ⚠️ agc_driver_bda_device 31.3 s, ⚠️ agc_driver_depth_clear_hle 31.0 s, ⚠️ agc_driver_graphics 30.6 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 7 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (3 IDs in 387 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (387 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 379 more
VUID-vkCmdCopyImage-srcImage-01548 (12 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 4 more
VUID-vkCmdCopyImage-srcImage-01551 (12 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 4 more
Skipped (48)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_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_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_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 plat
Reproduce
git fetch origin 2928046282310a415ae3c922ff7b035dbf852706 73f4f7e06e4f210a8c6570e335fd654dc0a86134
git checkout 73f4f7e06e4f210a8c6570e335fd654dc0a86134 && git merge --no-ff 2928046282310a415ae3c922ff7b035dbf852706
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 commented Oct 31, 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 5021 core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp
docs/dev/debt/shader.md
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 6235 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 6280 docs/dev/debt/shader.md
PR 6412 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 6924 docs/dev/debt/shader.md
PR 7085 docs/dev/debt/shader.md
PR 7223 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 7392 docs/dev/debt/shader.md
PR 7410 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp
docs/dev/debt/shader.md
PR 7642 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 7684 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 8004 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 9183 docs/dev/debt/shader.md
PR 9356 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 9387 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 9748 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 9889 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 9897 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 10193 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 10233 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 10359 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 10757 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 10867 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 11351 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp
PR 11483 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 12324 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/SpirvBackend/src/SpirvAlu/SpirvAluEmitterMath.cpp
PR 12548 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
PR 12790 docs/dev/debt/shader.md
PR 12828 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 12944 docs/dev/debt/shader.md
PR 13928 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 13929 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 14032 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 14212 docs/dev/debt/shader.md
PR 14561 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 14853 docs/dev/debt/shader.md
PR 14944 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@frankea the lane-0 sources look right at 2928046282 (I checked DppFirstLaneSource and DsSwizzleFirstLaneSource against the RDNA 2 tables and against EmitDsSwizzleTargetLane for lane 0, and the row_shr / quad_perm:[0,1,2,3] / image_sample_cd programs still build), and the new refusals are a deliberate behaviour, not a pinned unimplemented throw. Two things to address:

  1. The sum rules of OwnLaneSelectorWalk are not pinned. In a copy of the branch, changing walk(value->Argument(0), AddressKind) && walk(value->Argument(1), AddressKind) in address() (the IAdd32 case) to ||, and separately the IAdd32 case of lane() to ||, both leave every agc_shader_memory_tests run passing. With either change a ds_bpermute_b32 whose address is the lane id plus a register that is not lane 0 (for example the vertex index) would build and read the invocation's own value. Dropping the xor term of DsSwizzleFirstLaneSource and changing the row_ror source are caught, so the DPP and swizzle tables are covered. Please add a ds_bpermute_b32 case with an address of (lane id + v5) << 2 (and one for v_or_b32 if you keep that rule) expecting the register-selected refusal.

  2. Merged hull programs cannot reach these checks. The description says merged hull programs run at one lane on every device and that devices with vertex subgroups are affected "only in merged hull programs". Lowering::Run in core/shader/recompiler/Optimization/src/TessellationLowering.cpp calls requireOwnLanes() for a merged hull program, which already throws for ReadLane, WriteLane, DppMoveU32, DppUpdateU32, Permlane16U32, SwizzleU32, PermuteU32 and BpermuteU32, and that lowering runs before the SPIR-V emitter. So on a device with vertex subgroups these refusals are not reached at all, and the laneZero / "lane id is not accepted in hull programs" handling in OwnLaneSelectorWalk has no caller that can use it. Please correct the description and drop the unreachable branch (or say what reaches it).

…ane_b32 lane on one-lane waves

The selector proof accepted the s_ff1 of a mask built from EXEC and
ballots whenever that mask held no lane but the invocation's, empty
masks included. s_ff1 of an empty mask is -1 (RDNA 2 ISA 12.3,
S_FF1_I32_B64), which v_readlane_b32 reads as lane 63, the read a
constant lane 63 already refuses. It also took
Select(c, FindILsb32(mask), -1) without checking that c tests that mask.

The mask must now hold the invocation's bit wherever the read runs: it
is the entry EXEC, or a branch on the way to the read tested it for
zero, which covers the back edge of an s_ff1 waterfall and a guard
before one. The select must test mask != 0. Selects and phis of
selectors are no longer accepted.

New cases: a waterfall over an unguarded compare result and an
s_cselect_b32 of s_ff1_i32_b32 of EXEC or -1 throw; the same waterfall
behind s_cbranch_scc0 and a plain s_ff1_i32_b32 of EXEC build. Both
rejected cases build with the previous selector proof.
@github-actions github-actions Bot added shader core/shader docs agc libSceAgc* labels Oct 31, 2026
frankea added a commit to frankea/AnyPS5 that referenced this pull request Oct 31, 2026
…e ds_bpermute_b32 address

The review of boykopovar#14072 found the sum and OR rules of the address proof
unpinned: weakening either let a ds_bpermute_b32 whose address added the
vertex index to a lane-0 term build and read the invocation's own value.
Guest code reaches neither rule. Its lane id comes from v_mbcnt as a
BitCount, which the proof never accepts, so the only register address
it needs is the one the translator builds for image_sample_*_cd. The
proof now accepts just that: the lane id, an AND with it, or the quad's
first active lane, shifted left by 2. Sums, ORs, selects and offsets
throw. Four new cases pin this: the v_mbcnt lane id plus the vertex
index, the vertex index plus 32, the vertex index OR 32, and the vertex
index at offset 128.

Merged hull programs never reach these checks, because
TessellationLowering's requireOwnLanes already throws for every
cross-lane opcode before emission. The lane id is therefore accepted in
every stage, and the v_readlane_b32 call site is back to boykopovar#14068's.
@frankea

frankea commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks, both are addressed in 6617bb0.

  1. Sum rules. Guest code reaches the IR lane id only through v_mbcnt, which lowers to BitCount(src & lanes below) + addend, and the walk never accepted a BitCount. So the sum, OR, select and constant rules served no address a guest program can write; only the translator's image_sample_*_cd address needs the walk. Rather than pin rules nothing uses, I dropped them: the walk now accepts the lane id, an AND with it, or the quad's first active lane, shifted left by 2. New rejected cases pin the refusal: (v_mbcnt lane id + v5) << 2, (v5 + 32) << 2, (v5 | 32) << 2 and v5 << 2 at offset:128. Adding back your two || mutations (as rules next to a constant lane-0 term) or an offset rule fails them, and removing the first-active-lane, AND or lane id rule fails the image_sample_cd case.

  2. Merged hull. Right, requireOwnLanes refuses these opcodes before emission. The laneZero branch and the stage parameter are gone, the v_readlane_b32 call site is back to fix(shader): throw for v_readlane_b32 of a register-selected lane on one-lane waves #14068's, and the description no longer says merged hull programs or devices with vertex subgroups are affected.

Tested on 6617bb0: the 21 agc_shader_memory_tests entries 3 times on the Mac, and the same 36 entries as before 3 times plus once under the validation layer on the RTX 4090 (no VUID- lines). The Windows relinker failure on 2928046282 is three tools/tests/test_check_compile_modes.py tests hitting their 30 s timeout; this PR changes nothing they run.

MarcZX10's requested change is in the selector proof this branch takes from #14068. It is being fixed there, and I will rebase this branch onto it.

…reads of another lane on one-lane waves

Vertex and local programs on a device without vertex subgroups run as
one-lane waves: the invocation is lane 0 and a shuffle returns its own
value. DPP moves, ds_swizzle_b32, ds_bpermute_b32 and v_permlane16_b32
had no lane check there, so a value the console reads from another
lane's VGPR came back as an inactive lane's (0, bound_ctrl or the old
value) or, with fetch-inactive, as the invocation's own.

On a one-lane wave they now throw through FailOutsideHostSubgroup when
lane 0 reads another lane:
- DPP: lane 0's source from DPP_CTRL (RDNA 2 ISA 13.3.9, Table 91:
  quad_perm, row_shl, row_ror, row_mirror, row_half_mirror; row_share
  0x150-0x15F and row_xmask 0x160-0x16F as LLVM's dpp16_ctrl and
  SIDefines.h DppCtrl define them) or DPP8 LANE_SEL0 (13.3.10, Table
  92). row_shr gives lane 0 no source, so its scan steps still build.
- ds_swizzle_b32: lane 0's source from the offset (12.13.1: or_mask ^
  xor_mask in the 32-thread mode, offset[1:0] in the 4-thread mode;
  rotate mode as the emitter decodes it).
- ds_bpermute_b32: a constant address must name lane 0
  ((ADDR + OFFSET) / 4, 12.13). A register address must be the one the
  translator builds for image_sample_*_cd, which takes its derivatives
  from the quad's first active lane, the invocation's own on one lane:
  OwnLaneSelectorWalk proves it is the lane id, an AND with it, or
  Select(mask != 0, quad + FindILsb32(mask), lane) over a ballot mask,
  shifted left by 2. Guest code reaches the lane id only through
  v_mbcnt, a BitCount the walk never accepts, so every register address
  a guest program writes throws.
- v_permlane16_b32: lane 0 reads S1[3:0] (12.12, lanesel = {S2, S1}),
  so S1 must be a constant with those bits 0. v_permlanex16_b32 was
  already checked.

Merged hull programs never reach these checks, because
TessellationLowering's requireOwnLanes refuses every cross-lane opcode
before emission. Accepted programs emit the same SPIR-V as before.
@frankea
frankea force-pushed the fix/one-lane-cross-lane-reads branch from 6617bb0 to 4d7358d Compare October 31, 2026 18:42
@frankea

frankea commented Oct 31, 2026

Copy link
Copy Markdown
Contributor Author

@MarcZX10 the selector proof you flagged comes from #14068 and is fixed there in 283e3e773a: a register selector must now be FindILsb32(mask), or a select on mask != 0 of the same mask, and the mask must hold the invocation's bit wherever the read runs (the entry EXEC, or a mask a branch tested for zero on the way). Both of your cases, the empty compare mask and the unrelated s_cselect condition, throw there. This branch is rebased onto it as 4d7358d6ac; its own walk only proves the image_sample_*_cd address and never takes the selector path. The Windows relinker failure on the earlier head was three tools/tests/test_check_compile_modes.py tests hitting their 30 s timeout, which this PR does not touch. Tested on 4d7358d6ac: the 21 agc_shader_memory_tests entries 3 times on the Mac, and 36 entries 3 times plus once under the validation layer on the RTX 4090 with no VUID- lines.

@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-checked — new head, looks good

The revised lane-address proof and added refusals address the prior findings, and I found no remaining blocking issue at this head.

What I ran

Reviewed head 4d7358d6acffae2b952295dc0db17e9c5f6da593 against PR base ca073ec3ad0d766ea9f4658e418a5c977001a353; the no-build precheck recorded a clean merge preview against current main ca073ec3ad0d766ea9f4658e418a5c977001a353. The head includes dependency #14068 at 283e3e773aecc5d9d744b223ff2d11331b11dd7e. I inspected the address proof and accepted/rejected one-lane test cases. No local C++ build or test was run.

python3 /root/.codex/skills/anyps5-pr-review/scripts/pr_snapshot.py 14072 --repo boykopovar/AnyPS5
python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14072 --output-dir /tmp/anyps5-14072-review-new
gh api repos/boykopovar/AnyPS5/commits/4d7358d6acffae2b952295dc0db17e9c5f6da593/check-runs

Results

Check Result
Diff and conventions Passed
Current-main merge preview Clean
Hosted Windows product job Passed
Hosted Ubuntu relinker and ASan Passed
Author-reported focused tests 36 focused CTest entries passed 3 times on Windows and on main; 21 shader-memory entries passed 3 times on macOS. Not independently reproduced.
Hosted Linux product job Skipped
Hosted Windows relinker In progress at review time
Hosted macOS relinker jobs Queued at review time

Findings

Blocking

None found on this re-check.

Non-blocking

The focused Windows/macOS results are author-reported, not independently reproduced. The Windows relinker job is still running and the macOS relinker jobs are queued; the reported earlier Windows relinker timeout was on an older head and in unrelated compile-mode tests.

Sources

Not verified

I did not run a local build, Linux runtime/GPU test, or console behavior. The hosted Linux product job was skipped; Windows relinker and macOS relinker checks were unfinished at the time of this review.

@MarcZX10

Copy link
Copy Markdown
Contributor

Re-checked — unchanged head, looks good

Your follow-up confirms the selector proof is in the included #14068 head and adds focused test results; #14072 remains at the head I already approved, 4d7358d6acffae2b952295dc0db17e9c5f6da593.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 6617bb0 merged onto main 73f4f7e · tested 2026-10-31 19:02 UTC · 18 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,336 passed · 4 failed (0 new, 4 also fail on main) · 48 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,388 of 3,072 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 (878 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_bda_device 38.0 s, ⚠️ agc_driver_graphics_maps_fallback 32.6 s, ⚠️ agc_driver_graphics 31.3 s
Failing on main too (4, not counted against this PR)
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Passed on retry (1, failed in the parallel run, passed when re-run with a 360 s timeout; not counted against this PR)
agc_driver_job_manager_compute_capacity: Failed in the parallel run; also passed only on retry in 195 other runs in the last 7 days
Validation IDs already present on main (3 IDs in 387 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (387 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 379 more
VUID-vkCmdCopyImage-srcImage-01548 (12 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 4 more
VUID-vkCmdCopyImage-srcImage-01551 (12 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 4 more
Skipped (48)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_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_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_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 plat
Reproduce
git fetch origin 6617bb042758da88725cf56cf66962837a697a18 73f4f7e06e4f210a8c6570e335fd654dc0a86134
git checkout 73f4f7e06e4f210a8c6570e335fd654dc0a86134 && git merge --no-ff 6617bb042758da88725cf56cf66962837a697a18
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.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 4d7358d merged onto main 73f4f7e · tested 2026-10-31 19:31 UTC · 22 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,334 passed · 6 failed (0 new, 4 also fail on main, 2 unstable on main) · 48 skipped (ANYPS5_REQUIRE_VULKAN=1)
Test setup CPU-only tests without a GPU; GPU tests (and any CPU-only test that failed or skipped without one) once on the GPU with VK_LAYER_KHRONOS_validation and ANYPS5_NO_SHADER_CACHE=1; main ran the same way
Test selection 2,388 of 3,072 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 (878 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_graphics_maps_fallback 31.7 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_depth_clear_hle: failed in 2 of the last 10 main runs
agc_driver_submit_progress: failed in 7 of the last 10 main runs
Failing on main too (4, not counted against this PR)
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (4 IDs in 387 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (387 tests): agc_compute_pipeline_replay, agc_driver, agc_driver_address_passes, agc_driver_address_passes_draw_transitions, agc_driver_address_passes_targets_split, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, and 379 more
VUID-vkCmdCopyImage-srcImage-01548 (12 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 4 more
VUID-vkCmdCopyImage-srcImage-01551 (12 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 4 more
VUID-vkCmdCopyBuffer-commonparent (1 test): agc_driver_depth_clear_hle
Skipped (48)
agc_driver_bda_reads_shadowed_results: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_bda_reads_shadowed_results_per_build: skipped, the device reports watched host memory written when it imports or reads it
agc_driver_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_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_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 plat
Reproduce
git fetch origin 4d7358d6acffae2b952295dc0db17e9c5f6da593 73f4f7e06e4f210a8c6570e335fd654dc0a86134
git checkout 73f4f7e06e4f210a8c6570e335fd654dc0a86134 && git merge --no-ff 4d7358d6acffae2b952295dc0db17e9c5f6da593
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.

…-register-selector

# Conflicts:
#	docs/dev/debt/shader.md
Tessellation evaluation programs without subgroups now take the one-lane
path from boykopovar#13807, so verifySingleLaneDomainWave checks that a
v_readlane_b32 at the lane v_readfirstlane_b32 takes from v5 throws there
and builds on a 32-lane tessellation evaluation subgroup.
@RNK123

RNK123 commented Nov 1, 2026

Copy link
Copy Markdown

Linux / AMD RDNA 4 (RADV) paired validation run for current head 4b3d7091e6 (which includes #14068 at dcd3021fea) merged cleanly onto main 0a148be963 (the PR checklist currently covers Windows NVIDIA and macOS).

Host & GPU: CachyOS Linux (7.3.1-1-cachyos), 12th Gen Intel Core i5-12400F, GCC 16.2.1 (Release, -DBUILD_TESTING=ON), AMD Radeon RX 9060 XT (1002:7590, RADV GFX1200, Mesa 26.2.5-1, Vulkan 1.4.354, subgroup 64), Khronos validation layer 1.4.363.

Environment: ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ctest --repeat until-fail:3 -V across the 38 focused CTest entries listed in the PR description (request_serializer, all 21 agc_shader_memory_tests entries including agc_shader_memory with the new DPP / ds_swizzle / ds_bpermute / v_permlane16 one-lane checks, the 13 agc_driver_* wave/lane/tessellation entries, and the 3 agc_tessellation_* entries). VK_LOADER_DEBUG=layer confirmed Insert instance layer "VK_LAYER_KHRONOS_validation", and neither log reports was not found but was requested by env var VK_INSTANCE_LAYERS.

Tree Passed (3x serial) Skipped Known Mesa 26.2.5 RADV bug (#5444) VUID- / SYNC-HAZARD-
main (0a148be963) 35 / 38 (3/3 each, 7.35 s total) 2 (agc_driver_ngg_vertex_wave_reduction, agc_driver_vertex_elected_atomic_max: GFX1200 has vertex subgroups and subgroup size 64) 1 (agc_driver_tessellation segfaults in libvulkan_radeon.so nir_opt_varyings) 0
main + #14072 (4b3d7091e6) 35 / 38 (3/3 each, 8.55 s total) Same 2 Same 1 (#5444) 0 (0 new)

AI-assisted hardware test run (Antigravity).

@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-checked — new head, looks good

The current head 4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68 includes #14068's current tessellation-evaluation regression test and debt update; I found no blocking issue in that addition or in the previously reviewed cross-lane changes.

What I ran

Reviewed exact PR head 4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68. The PR's recorded base is 029463ceb62c97e3a82cfea423f884f158a4f023; current main is dc9dc7eaaeaf99b1c491d426e68bb999def3da16. The merge preview against current main was clean (264fdc10582a6a33022a48dbba961f20a6a7134f). Environment: Linux x86_64, Python 3.11.2, Git 2.39.5; no compiler invoked.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 14072 --output-dir /tmp/anyps5-pr-precheck-14072-current
git diff --check dc9dc7eaaeaf99b1c491d426e68bb999def3da16...4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68
git merge-tree --write-tree dc9dc7eaaeaf99b1c491d426e68bb999def3da16 4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68
python3 tools/check_conventions.py --base dc9dc7eaaeaf99b1c491d426e68bb999def3da16 --head 4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68 --title 'fix(shader): throw for DPP, ds_swizzle, ds_bpermute and v_permlane16 reads of another lane on one-lane waves' --body /tmp/anyps5-pr-precheck-14072-current/pr-body.md
python3 /marc/AnyPS5/tools/pr_test_quality.py --root /tmp/review-14072-4b3d --json core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
gh api repos/boykopovar/AnyPS5/commits/4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68/check-runs --jq '.check_runs[] | [.name,.head_sha,.status,.conclusion] | @tsv' | sort -u

The PR description reports 36 focused CTest entries passing three times on Windows for the branch and its pinned main baseline, plus 21 shader-memory entries passing three times on macOS. A separate RADV report on this exact head records 35/38 focused checks passing three times on both its main baseline and the PR head, the same two expected skips, the same Mesa tessellation crash on both trees, and zero VUID/SYNC hazards. I did not build or run these tests locally.

Results

Check Result
Current-head diff and integration Passed; the current PR diff is clean, and Git's merge preview against current main is clean. The new verifySingleLaneDomainWave test is called by the test runner.
Repository conventions Passed against current main.
Test registration Confirmed in agc_shader_memory_tests.cmake. The workspace-local test-quality heuristic flagged the changed C++ path as possibly unregistered because it did not match the relative path in the CMake fragment; direct inspection confirms registration.
Hosted checks on exact head Windows product job, conventions, labels, library portability, and relinker jobs passed. The Linux product job was skipped.
Focused Windows/macOS tests The PR author reports the listed CTest runs passing; I did not reproduce them locally.
Linux/RADV paired run PR comment #6552362448 reports 35/38 passes on both main and this exact head over three runs; the same two stage-subgroup skips and same Mesa #5444 tessellation crash occur on both trees, with zero VUID/SYNC hazards.
Local build and runtime tests Not run.
No-build precheck helpers The precheck could not launch its ABI and test-quality helper scripts because they were absent from the detached PR checkout. ABI auditing is not applicable to this change; I ran the available workspace-local test-quality heuristic separately and checked the registration directly.
Unedited output from checks

git diff --check stdout (empty):

git merge-tree --write-tree:

264fdc10582a6a33022a48dbba961f20a6a7134f

Conventions checker:

All conventions checks passed.

Test-quality heuristic output:

{
  "findings": [
    {
      "path": "core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp",
      "line": 1,
      "kind": "possible-unregistered-cpp-test",
      "message": "Changed C++ test source path was not found literally in CMake files; inspect registration, generated source lists, and workflow coverage."
    }
  ],
  "negative_control_candidates": [],
  "limits": [
    "Heuristics can miss weak assertions and can flag valid tests; inspect every finding.",
    "A test that passes against base is not by itself proof that the PR test is inadequate.",
    "Negative controls are only candidates until the test actually runs against base and fails by assertion rather than import/setup error."
  ]
}

Precheck helper errors:

/usr/bin/python3: can't open file '/tmp/anyps5-pr-precheck-14072-current/head-4b3d7091e600-031cf366/tools/pr_abi_audit.py': [Errno 2] No such file or directory
/usr/bin/python3: can't open file '/tmp/anyps5-pr-precheck-14072-current/head-4b3d7091e600-031cf366/tools/pr_test_quality.py': [Errno 2] No such file or directory

Exact-head hosted checks (the cancelled conventions attempt is superseded by the successful run on the same head):

conventions	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	cancelled
conventions	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
eligibility	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
labels	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
library-portability	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
linux	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	skipped
relinker (macos-latest, clang++)	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
relinker (macos-latest, clang++, x86_64)	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
relinker (ubuntu-latest, g++)	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
relinker (windows-latest, g++)	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
relinker-asan	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
report	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
windows	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	success
write-watch	4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68	completed	skipped

Negative control

Assertion Change to code under test Did the new test fail?
Cross-lane reads on one-lane waves must throw, while supported own-lane reads remain accepted. The PR reports removing each lane check or relaxing the selector-walk rules. The PR reports the matching test fails; I did not run these mutations.

Findings

Blocking

None.

Non-blocking

The Linux product job was skipped, and I did not independently reproduce the author-reported focused tests or mutation checks. The added domain-wave test is registered despite the heuristic warning.

Sources

Not verified

I did not compile or run the CTest cases locally, nor test on a console. The Windows/macOS results and mutation checks are author-reported; the separate Linux/RADV results are from the linked PR comment and were not independently reproduced here. The clean merge preview against current main dc9dc7eaaeaf99b1c491d426e68bb999def3da16 was not built.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 4b3d709 merged onto main 3741ca9 · tested 2026-11-01 08:06 UTC · 25 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,424 passed · 4 failed (0 new, 3 also fail on main, 1 unstable on main) · 44 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,472 of 3,121 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 (929 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 61.5 s, ⚠️ agc_driver_lookup_log_fits_build 53.9 s, ⚠️ agc_driver_graphics_maps_fallback 33.3 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_submit_progress_no_timeline: failed in 8 of the last 10 main runs
Failing on main too (3, not counted against this PR)
agc_driver_image_table
guest_mmap_executable
guest_socket_options_multicast
Validation IDs already present on main (5 IDs in 480 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (480 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 472 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 (44)
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_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_f
Reproduce
git fetch origin 4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68 3741ca9327246d0df81638726a986cef862b6db5
git checkout 3741ca9327246d0df81638726a986cef862b6db5 && git merge --no-ff 4b3d7091e60031ba0cd1635edb8f8ba5e6a3ee68
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

Automated build and test on a contributor's NVIDIA machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@oneandonlydean oneandonlydean self-assigned this Nov 5, 2026
@oneandonlydean

Copy link
Copy Markdown
Collaborator

Hi @frankea, the new ds_bpermute_b32 cases (lane id plus the vertex index, plus 32, or 32, offset 128) now fail when the Address walk stops requiring the lane, which closes most of my earlier request. In a copy of the branch at 4b3d7091e6 two rules in your own walk can still be weakened without any test in agc_shader_memory_tests failing:

  • OwnLaneSelectorWalk::Address: dropping the IsU32(value->Argument(1), 2u) check, so any left shift (not only the << 2 that turns a lane number into a byte address) is accepted.
  • OwnLaneSelectorWalk::firstActive: changing first(found) && walk(base, LaneKind) to || in the IAdd32 form, so a first-active-lane plus anything is accepted.

Please add a rejected ds_bpermute_b32 case for each (an address shifted left by a count other than 2, and a first-active-lane index plus a value that is not the invocation's own lane), expecting the "register-selected lane" refusal. The same kind of gap exists in the lane-selector rules from #14068; that request is on that PR.

@frankea

frankea commented Nov 6, 2026

Copy link
Copy Markdown
Contributor Author

@oneandonlydean thanks, both are pinned in 067a530. Guest code cannot write either address: under the shift the walk accepts only the lane id, an AND with it or the first-active-lane select, and guest code reaches the lane id only through v_mbcnt, whose BitCount the walk refuses. A guest ds_bpermute_b32 of the v_mbcnt lane id shifted left by 3 therefore throws at the lane rule whether or not the shift is checked. The only address that passes the lane rule is the one the translator builds for image_sample_*_cd, so the two new cases build that address as IR in a one-lane vertex program (as tests/TessellationLowering.cpp emits hand-built programs) and change one detail each: shifted left by 3 instead of 2, and the next quad's first active lane, (quad + 4) + FindILsb32(mask). Both throw ds_bpermute_b32 of a register-selected lane, and the unchanged address builds. With the IsU32(value->Argument(1), 2u) check dropped, the test fails at the shifted case; with && changed to ||, it fails at the next-quad case.

Tested on 067a530: the 21 agc_shader_memory_tests entries 3 times on the Mac, and on the RTX 4090, with the branch merged onto main ed5c169, the 40 entries listed in the description (now 25 in agc_shader_memory_tests) 3 times plus once under the validation layer, with no VUID- lines.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 067a530 merged onto main e9247a9 · tested 2026-11-06 04:05 UTC · 11 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,886 passed · 3 failed (0 new, 3 also fail on main) · 51 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,940 of 4,105 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 (969 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 103.7 s
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 (9 IDs in 585 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (585 tests): agc_driver, agc_driver_address_draw_space_reuse, 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, and 577 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 (51)
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_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 available in current SDL video driver (offscreen) or platform
video_out_flip_deferred: skipped, no
Reproduce
git fetch origin 067a530fec45492baf95288d1da60f8f81743d0a e9247a966ff6cce55816ffe1d73a2679074348a4
git checkout e9247a966ff6cce55816ffe1d73a2679074348a4 && git merge --no-ff 067a530fec45492baf95288d1da60f8f81743d0a
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* docs shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants