Skip to content

feat(recompiler): read the scalar aperture sources as values - #5005

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
fdfawef324:feat/recompiler-aperture-source-values
Oct 14, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
fdfawef324:feat/recompiler-aperture-source-values

Conversation

@fdfawef324

@fdfawef324 fdfawef324 commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

What

Fixes #3803. Since #1940, a shader that reads src_shared_base, src_shared_limit, src_private_base or src_private_limit (scalar source codes 235-238) as a value was refused with the scalar aperture source ... is not modelled. These four sources now return the 64-bit apertures that the flat routing from #1190 already uses. A flat pointer built from them goes to LDS or scratch, and comparing against the limits gives the hardware's ordering.

Source 64-bit value 32-bit read
235 src_shared_base 0x80000000_00000000 0x00000000
236 src_shared_limit 0x80000000_ffffffff 0xffffffff
237 src_private_base 0x70000000_00000000 0x00000000
238 src_private_limit 0x70000000_ffffffff 0xffffffff
  • Read width. A 64-bit read (s_mov_b64, a 64-bit VALU source such as v_cmp_*_u64, or a lane mask in wave64) returns the whole value. A 32-bit read returns the low dword, as on gfx1030 and gfx1035. Titles take the high dword from an s_mov_b64, the same way LLVM does.
  • One definition. SharedApertureHigh and PrivateApertureHigh moved from SpirvMemoryInstructions.cpp to RdnaInstructionDecoder.hpp. RdnaApertureSourceValue builds the four values from them, so the routing (SplitAperture) and the reads cannot diverge. The routing itself is unchanged.
  • Paths. readRawU32 returns the low dword. readU32Pair returns low and high, which covers readU64, readF64Bits and every 64-bit scalar or VALU source. readMask reads the 64-bit value as a lane mask. Before, a wave64 lane mask would have used the low dword for every lane. readScalarCode 235-238 goes through the same values.
  • TechnicalDebt (docs/dev/debt/shader.md):

Sources:

Not measured on a console: the PS5's two high dwords. They are the values #1190 inferred from GTA V's traversal addresses (shared 0x8000 and private 0x7000 in the high 16 bits), and this PR reads exactly those values so that reads and routing agree. The wave is assumed to use 64-bit addressing (PTR32 clear). The debt entry records both.

Tested

Windows Server 2025, NVIDIA GeForce RTX 3060 (driver 591.86), MinGW-w64 GCC 15.2.0 (WinLibs r7), Release. The full run was on main c2565f0. After rebasing onto a24da90, the aperture, agc_driver_flat_apertures_* and agc_driver_flat_store tests were run again, and all 17 pass.

  • New test agc_driver_flat_aperture_sources (tests/execution/FlatApertureSources.cpp). One compute dispatch per wave size (wave32, and wave64 where the device can run it). Every lane checks:
    • the s_mov_b32 and s_mov_b64 (low and high) result of each of the four sources;
    • an LDS round trip: a flat_store_dword through a pointer whose high dword comes from src_shared_base, read back with ds_read_b32 and flat_load_dword;
    • a scratch round trip: the same through src_private_base, read back with scratch_load_dword and flat_load_dword;
    • eight v_cmp_le_u64/v_cmp_ge_u64 compares of those pointers against the bases and limits, including the limit itself and the first address past it;
    • v_cndmask_b32 with each source as the lane mask.
  • aperture_sources. It asserted the refusal and now asserts the translated constants for s_mov_b32 and s_mov_b64 of each source.
  • Red without the change. The source changes were reverted and the tests kept:
    • agc_driver_flat_aperture_sources fails with ShaderRecompiler::Recompile: TranslationContext::readRawU32: the scalar aperture source src_shared_base is not modelled.
    • aperture_sources aborts with the same message.
    • With the change, both pass (0.8 s and 0.1 s).
  • Routing check. Changing only SplitAperture to compare with SharedApertureHigh + 1 makes the new test fail with BDA access failed: address=0x8000000000000000. The test therefore pins that the value read and the routing match.
  • Full ctest: 1039 of 1040 passed and 7 were skipped for the environment (agc_driver_stencil_ref_export and the video_out_flip_* tests). This includes agc_driver_flat_apertures_0-13 and every other flat, global, BDA, LDS, scratch, scalar and recompiler test. The one failure is log_macros. It links only libc, and it fails the same way in another worktree build on this machine without this change.
  • tools/check_conventions.py --base upstream/main: all checks passed. tools/check_test_registration.py: none new.
  • Titles. I did not run a title with this change. Three titles stop at this refusal:

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
  • Unblocks: shader: reading a scalar aperture source as a value refuses (Ghost of Yōtei PPSA26344, shader 0x8000356b00) #3803 (Ghost of Yōtei PPSA26344); GTA V PPSA04264 and Marvel's Wolverine PPSA03671 stop at the same refusal
  • GPUs tested: NVIDIA GeForce RTX 3060 12 GB, driver 591.86 (32.0.15.9186), Vulkan 1.4.325, Windows Server 2025 10.0.26100
  • AI-assisted: yes (written with Claude Code; reviewed and tested by me)

🤖 Generated with Claude Code

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

Copy link
Copy Markdown
Contributor Author

I ran a title with this change. The build was my integration branch, main plus open PRs, with this PR cherry-picked.

Marvel's Wolverine (PPSA03671) logged the scalar aperture source src_shared_base is not modelled and the same for src_private_base without this PR. With it, neither refusal appears. The title gets further and now stops on an unrelated vkAllocateMemory failure (VK_ERROR_OUT_OF_DEVICE_MEMORY) on a 12 GB GPU.

@fdfawef324
fdfawef324 force-pushed the feat/recompiler-aperture-source-values branch from 3254ca4 to 0d771e3 Compare October 13, 2026 18:10
@fdfawef324
fdfawef324 force-pushed the feat/recompiler-aperture-source-values branch 3 times, most recently from 346694e to 823cdc0 Compare October 13, 2026 23:21
@xXPBSXx

xXPBSXx commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Windows test of #5005: Windows 10 (19045), MinGW-w64 GCC 15.2, Release, ninja -j 4, ctest called directly, GPU selected by the execution tests: NVIDIA GeForce RTX 4080 SUPER (Selected GPU log line). Tree: main feddf7f4c + merge of PR head 823cdc0c4c06b60ba1118ac3c4a457992a482282 (local merge d2d34b987).
16 ctest targets, 3 runs each, exit code 0 in all 48 runs: agc_driver_flat_aperture_sources, agc_driver_flat_apertures_0 to _13 (14 targets) and aperture_sources. Logs: rtx5005_*_N.log.
Not tested: that the new tests fail without the change (no baseline run), the AMD GPU (present, not selected), other ctest targets, Linux, a title run (PPSA26344).

AI-assisted (Claude Code).

@fdfawef324

Copy link
Copy Markdown
Contributor Author

Thanks for the independent run. This adds Windows 10 / RTX 4080 SUPER evidence on feddf7f: 16 targets, three runs each, 48/48 passed. I am keeping your stated limits alongside the result: no baseline failure check, AMD, Linux or title-run coverage in this report.

@fdfawef324
fdfawef324 force-pushed the feat/recompiler-aperture-source-values branch from 823cdc0 to c2931c1 Compare October 14, 2026 00:58
@xXPBSXx

xXPBSXx commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Correction to my Windows test above: I wrote that the GPU was shown by a Selected GPU log line, but that line was not in the ctest logs of those runs (ctest without -V does not print the output of passing tests). Re-run with ctest -V on main 1633843382ecb1434ac76ac0c4d4655d88bb241f + this PR's current head c2931c18fad759a2af20733c56a3b12930baaba7 (the head has moved since my first run on 823cdc0c4): the log shows Selected GPU name=NVIDIA GeForce RTX 4080 SUPER, and agc_driver_flat_aperture_sources exits with code 0 (1 run). The 16 targets of my first comment were not re-run.

AI-assisted (Claude Code).

Reading src_shared_base, src_shared_limit, src_private_base or
src_private_limit (scalar source codes 235-238) refused the shader since
boykopovar#1940, because their values were unknown. They now read as the 64-bit
apertures that the flat routing from boykopovar#1190 classifies: a base is the
aperture's high dword over a low dword of 0, a limit is the same high
dword over 0xffffffff (shared 0x80000000, private 0x70000000).

A 64-bit read (s_mov_b64, a 64-bit VALU source, a wave64 lane mask)
gets the whole value and a 32-bit read gets the low dword. A flat
pointer built from the high dword therefore reaches LDS or scratch, and
64-bit compares against the limits order as on the hardware. The flat
routing and the reads share one definition of the two high dwords.

Sources: LLVM SIRegisterInfo.td (aperture registers are 64-bit, their
low 32 bits are always 0 for a base and -1 for a limit) and
getSegmentAperture in AMDGPULegalizerInfo.cpp and SIISelLowering.cpp
(a 64-bit read whose high half is the aperture); the RDNA 2 ISA guide,
sections 5.2, 5.8 (SH_MEM_BASES holds 16-bit bases) and 9.3; the KFD's
MAKE_LDS_APP_LIMIT (limit = base | 0xffffffff); the gfx1030 and gfx1035
readouts on boykopovar#1190 and boykopovar#3803. The PS5's two high dwords stay inferred,
as the shader technical debt records.

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

Copy link
Copy Markdown
Contributor

Hey everyone, I ran another Windows check of this PR, including the before-and-after controls. The final run passed all 40 selected tests on an RTX 4070 SUPER.

Tested PR head c2931c18fad759a2af20733c56a3b12930baaba7 merged into main 52d134c0282920d58a9ec07da51db08350e3d6dd. That is the pinned tree for these results; newer main commits were not tested.

Windows 11 build 26300, NVIDIA driver 617.42, WinLibs GCC 15.2 r7, Release, BUILD_TESTING=ON, ANYPS5_ENABLE_SPIRV_TOOLS=ON. The verbose logs confirm Selected GPU name=NVIDIA GeForce RTX 4070 SUPER ... subgroup=32. Vulkan was required. CTest set ANYPS5_NO_SHADER_CACHE=1, and the new aperture GPU test also sets request.useCache=false.

  • With the PR: full build passed. The final test selection passed 40/40 with no skips, including aperture_sources, agc_driver_flat_aperture_sources, all 14 agc_driver_flat_apertures_* partitions (126 checked rows), and the related FLAT/LDS and shader tests.
  • Baseline control: kept both test sources unchanged and restored the six changed production files from the pinned main. The targeted rebuild succeeded; both new tests failed with src_shared_base is not modelled.
  • Routing control: restored the PR, then changed only the shared comparison in SplitAperture to SharedApertureHigh + 1u. The CPU test passed, while the GPU test failed at BDA address 0x8000000000000000 with an unwritten 0xdeadbeef result.
  • Restored check: removed that deliberate fault, verified the production files matched the original bytes, rebuilt, and ran the final 40 tests. Test-source hashes stayed unchanged throughout, and the checkout is clean.

One environment wrinkle: the initial sandbox run was 39/40 because agc_shader_disk_cache could not write its initial cache entry. After restoration, that test failed again in the sandbox and passed on desktop with the same executable hash and no intervening rebuild. I have not identified the exact failing Windows file operation. The disk-cache test enables its own isolated cache.

The new GPU test ran guest wave32 and wave64 on host subgroup32. These results check the emulator's aperture values and routing together; they do not measure the PS5 high words or PTR32 state. I did not run a game, Linux, other GPUs, or the whole CTest suite.

Thanks for the work on this. AI-assisted with Codex; the logs, controls, restored source and binary hashes were independently checked in a second review.

@fdfawef324
fdfawef324 force-pushed the feat/recompiler-aperture-source-values branch from c2931c1 to dc1c12a Compare October 14, 2026 02:49
@oneandonlydean oneandonlydean self-assigned this Oct 14, 2026
@oneandonlydean
oneandonlydean merged commit 591d39c into boykopovar:main Oct 14, 2026
8 checks passed
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.

shader: reading a scalar aperture source as a value refuses (Ghost of Yōtei PPSA26344, shader 0x8000356b00)

4 participants