Skip to content

feat(shader): follow pointer chains from image-table records to the T# - #6232

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
ANONYMOUSZED-beep:feat/image-table-pointer-chains
Oct 18, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
ANONYMOUSZED-beep:feat/image-table-pointer-chains

Conversation

@ANONYMOUSZED-beep

Copy link
Copy Markdown
Contributor

What

Part of #6191: the Guardians of the Galaxy chain (constant buffer → pointer → pointer → T#). The Ratchet & Clank chain (record → pointer → V# → T# at a second readfirstlane index) needs a second key and is not covered here.

#4475 plans an image-table record that holds a pointer to the T#. When the pointer itself is loaded through another pointer, the column was refused: TryMakeIndirectColumn wanted both pointer dwords to be scalar buffer reads, so the stop is GetImageResource dword 0 is not a valid runtime value with the chain LoadAddressU32(GetAddressResource(LoadAddressU32(GetAddressResource(ReadConstBuffer …)))).

  • Tracker. Walks back from the T#'s GetAddressResource while both of its dwords are consecutive LoadAddressU32 reads (offset n and n + 4, immediate offset, same or equivalent pointer). Each step is one PointerHop {offset, immediate}. The record at the end of the chain is matched as before. Any depth is accepted; a chain that does not end in a keyed record read is refused as before.
  • Materializer. After it reads a record's pointer, it follows column.pointerHops in order. A hop that is unaligned, wraps, or reaches an unmapped page makes the record Unmapped poison, like an unreadable T#. Each link's 8 bytes are added to the table's ranges, so a changed link rebuilds the table.
  • Planning-only loads. A hop load is planning-only when every use of its pointer is a planning-only load. This runs to a fixed point, so the whole chain stops reading through BDA.
  • TableColumn gains pointerHops; the plan encoder and decoder carry it, and the ShaderDiskCache layout asserts are updated. A column with no hops is planned and encoded as before.

Tested

Amazon Linux 2023 (x86-64, GCC 14.2.1, Release), main d92a8dad3. I have no GPU and no game, so I could not run Guardians or Ratchet.

  • agc_shader_bindless: new verifyPointerChainImageTable. A compute shader reads a record pointer with s_buffer_load_dwordx2 at key * 16 + 8, loads a second pointer with s_load_dwordx2 at +0x10, and the T# with s_load_dwordx8 at +0x20. It checks the column (indirect, stride 16, offset 8, pointerHops == {{0, 0x10}}), that every scalar address load is planning-only and the shader does not use BDA, that two chains to the same T# share one element and a different T# gets its own, that records whose chain hits a null pointer are Unmapped poison, that the links are in the captured regions and snapshot ranges, and that moving one record's second pointer changes its T#.
    • On the unchanged tracker it fails with GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x4c(GetAddressResource(LoadAddressU32@pc=0x44(GetAddressResource(ReadConstBuffer@pc=0x3c(…, the same shape as the Guardians report.
    • With the fixed-point marking turned off it fails with "a load along the pointer chain still reads through BDA".
  • agc_shader_disk_cache. The hand-built plan now has two pointer hops. It passes, and it fails ("the decoded hand-built plan differs…") when the hop encoding is removed.
  • agc_driver_image_table: new RunPointerChainRecordTests (PointerChainRecordCode, which is IndirectRecordCode plus one s_load_dwordx2). It checks texels per record, one element per distinct T#, and that moving record 1's second pointer changes what it samples. It passes on lavapipe (Mesa 24.2.6, CPU only, no hardware GPU). On the unchanged tracker it fails with the same GetImageResource dword 0 chain.
    • On lavapipe the rest of agc_driver_image_table behaves the same with and without this change. RunAnisoOverrideTests fails ("a direct pair changed its texels"), and RunGraphicsTests did not finish within 15 minutes. Each group was run on its own: the other groups pass, including RunPointerRecordTests, RunSplitRecordTests and RunPointerStorageWriteTests. I could not run the full suite on real hardware.
  • agc_shader_memory, agc_shader_bindless, agc_shader_srt_read_patching, agc_shader_frontend_pair(_off), agc_shader_quad_mask_no_demote, agc_shader_layout_pair(_off) and agc_shader_disk_cache pass.
  • python3 tools/check_conventions.py --base origin/main reports no findings for the code.

Checklist

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 6440 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L2517, L6166, L6219
PR 7395 core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp L281-282, L1218
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ControlFlowInfo.hpp L51
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp L821
core/shader/recompiler/Optimization/src/ResourceTracker.cpp L690-692, L699, L734-735
core/shader/recompiler/ShaderDiskCache.cpp L152

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 907 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 1341 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 3247 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 5500 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 5609 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 5925 core/shader/recompiler/ShaderDiskCache.cpp
PR 6177 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6280 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6312 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
PR 6412 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6481 core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp
PR 6486 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ControlFlowInfo.hpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6503 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6539 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6645 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6683 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 6879 core/shader/recompiler/ShaderDiskCache.cpp
PR 6941 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6970 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6977 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 7223 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ControlFlowInfo.hpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 7332 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 7381 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 7388 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
PR 7390 core/shader/recompiler/ShaderDiskCache.cpp
PR 7642 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp

This was referenced Oct 15, 2026
@Neithennn

Copy link
Copy Markdown
Contributor

Windows NVIDIA run, since the description lists lavapipe only.

Windows 11 Pro 26200, NVIDIA GeForce RTX 4080 (driver 617.42), AMD Ryzen 7 5800X, WinLibs GCC 15.2.0 r7, Ninja, Release, bundled dependencies, BUILD_TESTING=ON, ANYPS5_NO_SHADER_CACHE=1. Head 6b662dd8b merged onto main ff23657f3; full build succeeds.

As far as I can tell from the source, verifyPointerChainImageTable compiles and materializes on the host and does not dispatch on the GPU, so this mainly shows the change does not regress the GPU-dispatching image-table tests on NVIDIA/Windows. No title run.

AI-assisted: yes (runs done with Claude Code).

@Tamalero

Copy link
Copy Markdown
Contributor

Title run on Guardians of the Galaxy (PPSA01748), the title this PR targets from #6191. Head 6b662dd8b merged onto main 03c4cb5e7, with a control on that main alone. Both use the same relinked executable and no local patches.

Build Level-1 load (shield screen)
main 03c4cb5e7 music starts, then stops on the #6191 chain: shader 0x3b94a7500 stage 5, GetImageResource dword 0 is not a valid runtime value, LoadAddressU32@pc=0x84(GetAddressResource(LoadAddressU32@pc=0x70(GetAddressResource(ReadConstBuffer@pc=0x30(…ReadFirstLane(GetInterpolationParameter…
this PR no descriptor stop in 3 runs; the load gets further, then stops on something unrelated (below)

So the constant buffer → pointer → pointer → T# half of #6191 is covered on the title. Menu frame rate with a warm shader cache is the same on both builds, about 11–14 FPS.

The next stop is in the draw path, not in this PR's code. A DRAW_INDEX_INDIRECT_MULTI (opcode 0x38, 144 records, stride 20) is issued after INDEX_BUFFER_SIZE is set to 0x10000000 with 16-bit indices. For indirect indexed draws the driver binds that whole declared range (Pm4.cpp, "the declared range is the hardware's view of the index buffer"), so it asks for 512 MiB at 0x383240000. Only about 54 MiB of it is mapped:

AGC driver: guest memory is not readable at 0x386590000 (range 0x383240000+0x20000000)

The stack, from a local print added for this run only: Driver::draw → Pm4::ResolveDraw (indirect path) → GuestMemory::CheckRange. I'll open a separate issue for it.

Details

Tested and written by Claude (AI assistant) on a contributor's machine.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@adriadam10 adriadam10 self-assigned this Oct 18, 2026
@adriadam10
adriadam10 force-pushed the feat/image-table-pointer-chains branch from 6b662dd to 486f306 Compare October 18, 2026 19:19
@github-actions github-actions Bot added unblocks title Names a title ID on the Unblocks line and removed needs rebase Conflicts with main, rebase needed labels Oct 18, 2026
@adriadam10
adriadam10 merged commit c7e2860 into boykopovar:main Oct 18, 2026
10 checks passed
adriadam10 pushed a commit that referenced this pull request Oct 19, 2026
Keeps this branch's tagVariantRuns declaration next to main's dumpRequest suffix parameter in Driver.hpp, and reads #6232's pointer-chain test words from its table's snapshot, where this branch keeps them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants