Skip to content

fix(shader): follow pointer hops and fixed-offset V# reads behind a record pointer - #9457

Open
EagleBearerYS wants to merge 40 commits into
boykopovar:mainfrom
EagleBearerYS:fix/shader-table-family-6191
Open

EagleBearerYS wants to merge 40 commits into
boykopovar:mainfrom
EagleBearerYS:fix/shader-table-family-6191

Conversation

@EagleBearerYS

@EagleBearerYS EagleBearerYS commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

Two shapes from #6191's family that the planner still refuses on #8939. Each gets its own commit and test.

1. Pointer hops after a pointer-keyed record pointer (Gran Turismo 7 (PPSA01317), frankea on #6191, comment).

  • The chain: 28 of the World Map's 29 refused compute shaders read a record (an SRT V#, a readfirstlane key in a waterfall loop) whose dwords 2-3 are a pointer P1. P1's words are a Phi of the record read under several keys and a Ballot lane-mask word. Then P2 = [P1 + 0] and the T# at [P2 + 0x340]:

    GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x00002404(GetAddressResource(LoadAddressU32@pc=0x000020ec(GetAddressResource(Phi(Phi(ReadConstBuffer@pc=0x00000160(...), CompositeExtractU32x4(Ballot(LogicalAnd), Immediate)), ReadConstBuffer@pc=0x00000160(...)), ...
    
  • Why it refuses: TryMakeIndirectColumn refuses any pointer hop once the record pointer is merged: if (!hops.empty() && (buffer || merged)) return false;.

  • What the steps after it already do for a pointer-keyed column: the snapshot stores each record's pointer before it applies pointerHops. The shader looks the T# up by the record-level pointer (parentPointer). ShaderDiskCache already serializes and accepts hops on such columns.

  • The change: the guard now refuses hops only for buffer columns.

2. A T# at a fixed offset of a pointer-loaded V# (Marvel's Spider-Man 2 (PPSA03016), hugodearaujo on #8939, comment).

  • The chain: a record keyed by readfirstlane << 4, dwords 2-3 a pointer, a V# loaded at that pointer plus an immediate, and the T# read at a fixed offset of that V#'s buffer, with no second key:

    GetImageResource dword 0 is not a valid runtime value; chain: ReadConstBuffer@pc=0x8560(GetBufferResource(LoadAddressU32@pc=0x854c(GetAddressResource(ReadConstBuffer@pc=0x1fc4, ...
    
  • Why it refuses: TryMakeTableColumn refused it, because MatchAffineOffset fails on an immediate offset.

  • The change: hugodearaujo's change, kept as their commit. A fixed offset under a pointer-loaded V# becomes a one-key child of the nested path: key 0, stride the descriptor size, addend the immediate. A fixed offset under a runtime V# still refuses, as before.

Not in this PR:

Overlap:

Tested

Checklist

Related: #6191

yabanana and others added 21 commits October 17, 2026 18:48
…mers

A T# read from a nested child table stayed a runtime read when one of
its words also fed another instruction. That read goes through a V#
that exists only in the snapshot, so the dispatch read a garbage
address; lavapipe crashed in the shader. The nested branch now refuses
a child whose descriptor words are used by anything but equal handles,
as it already does for a V# with another consumer.

(cherry picked from commit 0df7d32)
An S# read from a V# that a scalar record selects through a pointer
was refused, so recompiling failed with "GetSamplerResource dword 0 is
not a valid runtime value". The nested branch now takes sampler
columns: they get child tables per distinct V# like nested T#s, share
equal children, count against the nested key budget and the S# entry
budget, and fault on an unmapped, non-buffer or uncaptured parent. The
plan decoder accepts a nested sampler column; the plan encoding is
unchanged.
An S# or T# loaded through a pointer that a scalar record holds was
refused when a Phi merged the pointer's low word with constants, so
recompiling failed with "GetSamplerResource dword 0 is not a valid
runtime value". Such a column is now pointer-keyed: the snapshot
captures every record's pointer and the descriptor behind it, the map
holds boykopovar#7223's sorted pointer dictionary with descriptor records as its
codes, and the GPU looks up the actual 64-bit pointer. A pointer that
was not captured faults as outside the snapshot, and a null one as
unmapped.

The plan gains TableColumn::pointerKeyed and the snapshot gains
ImageTableColumnSnapshot::pointerKeyed, so the disk-cache format moves
to 43 and the image-table ABI to 4.
A T# loaded through a record pointer whose low word passes nested Phis
was refused when one Phi arm held a word of a Ballot lane mask, as in a
waterfall loop that reuses the pointer's SGPR for an s_and_saveexec or
v_cmp mask, so recompiling failed with "GetImageResource dword 0 is not
a valid runtime value". A pointer-keyed column now accepts such a word
as an arm that is not a record pointer, as it does for constants, and
still refuses any other foreign arm. At run time a pointer built from a
lane mask is not a captured pointer and faults as outside the snapshot.

A pointer-keyed column also accepts low-word reads, and a high-word read,
of the same record word under different keys: same table, record offset,
stride and addend. The GPU looks the pointer up by its value, so the key
does not matter there. The column takes its table and record offset from
the high-word read, which dominates the descriptor load.

A shader that planned before plans the same way, so the disk-cache
format stays at 43.
…ed record pointer

A T# loaded through a record pointer was still refused with "GetImageResource
dword 0 is not a valid runtime value" when the pointer's low word passed
ANDs with lane masks, as a waterfall loop that copies EXEC into the
pointer's SGPR builds them, or when its high word was a Phi of the
record's high word read under several keys.

For a pointer-keyed column, the walk of the low word now takes an AND
with a lane-mask operand (a Ballot word, or an AND or Phi of only Ballot
words and immediates) and keeps walking its other operand, so its
record reads must still match the column and anything else still
refuses. The high word is walked the same way: its record reads must
be the record word at the low word's offset plus 4. A high word that is
one read still gives the column its table and record offset, as before.
Otherwise the table comes from a record read whose V# words are defined
before the descriptor load, and the record offset from the high word,
which the GPU does not read for a pointer-keyed column.

A high-word arm read from another buffer, such as one whose V# is
loaded through a pointer, stays refused. A shader that planned before
plans the same way, so the disk-cache format does not change.
… a pointer-keyed record pointer

A T# loaded through a record pointer was still refused with "GetImageResource
dword 0 is not a valid runtime value" when a Phi of the pointer's low word
merged the record read, a zero, and the waterfall's lane mask with the
handled lane's bit cleared, BitwiseAnd32(CompositeExtractU32x4(Ballot(...), 0),
BitwiseNot32(ShiftLeftLogical32(1, index))), as s_ff1, s_lshl and s_not with
s_and, or s_andn2, build it in the SGPR the pointer reuses. The walk took only
Ballot words and ANDs of them as lane masks, so it walked into the NOT and
refused.

A lane-mask operand is now a Ballot word or the loop's lane bit, a shift of 1
by an index from FindILsb32, FindUMsb32 or ReadFirstLane (through the AND,
add, subtract and select that s_ff1_i32_b64, s_bitset0 and the shift's own
mask put around it), or an AND, OR, NOT or Phi of only those and immediates.
An arm of the pointer that is entirely such an operand is skipped. An AND
with a record read in it still has the read matched against the column, and
anything else still refuses.

agc_driver_pointer_phi_lane_not_table builds that shape in a wave64
waterfall: the low word's Phis merge the record read at +0, a zero and the
lane mask without the handled lane's bit, cleared by s_not and s_and and by
s_andn2, and the high word is one read at +4. Each lane samples the T# of its
record, and every masked word faults outside the snapshot.
agc_driver_pointer_vsharp_select_table reads a record keyed by
ReadFirstLane(SelectU32(LogicalAnd, IAdd32, Phi)), a pointer from it, a V#
through the pointer and the T# through the V#; it passes without this change
and keeps that chain checked, including a record pointer moved to the other
V# without a recompile.

Shaders that planned before plan the same way, and a refusal is never cached,
so the disk-cache format does not change.
…keyed records

A pointer-keyed record pointer now also takes lane-mask ANDs, the
waterfall loop's lane bit and its OR and NOT forms, and a high word
merged from the record's next word. A high word read from a second buffer
stays refused.
The low and high words of a pointer-keyed record pointer were walked
separately, so a high-word arm on a path whose low word is a lane mask
refused the plan even though that pair is no pointer. Ratchet & Clank:
Rift Apart (PPSA01474) stops this way at LoadAddressU32@pc=0x9a30: one
high-word arm reads a second buffer, and on that edge the low word is a
lane mask, the waterfall loop reusing the SGPR pair.

Walk the two words together. Where both are Phis of one block, each
low-word edge takes the high word of the same predecessor. An edge whose
low word is a constant or a lane mask is skipped with its high word. A
record low word still needs every high word it can meet to be a constant,
a lane mask or the same record column at offset + 4, so a second-buffer
high word paired with the record word stays refused.

agc_driver_pointer_phi_high_second_lane_table adds the lane-mask low word
to the second-buffer arm: it plans, each group samples the T# its record
selects, and that arm faults outside the snapshot.
…nter

The two words of the pointer are now walked edge by edge, and an edge
whose low word is a constant or a lane mask is skipped with its high
word. A high word read from a second buffer stays refused on an edge
whose low word is the record word.
Brings boykopovar#8991 (match image-table T# halves offset before and after
readfirstlane).

ResourceTracker.cpp: main's FirstLaneOffset, ParseFirstLaneOffset and
SameFirstLaneOffset go before TryMakeTableColumn, which keeps this
branch's signature with the buffer parameter. Main's first-lane base
check in the column loop merged on its own.
…ane-masks

Brings boykopovar#7395's merge of main bd4d801, with boykopovar#8991. It merged without conflicts.
TryMakeIndirectColumn refused every pointer hop once the record's
pointer words were merged, so a T# read through a pointer loaded from a
pointer-keyed record pointer stayed unplanned (Gran Turismo 7's World
Map compute shaders, issue boykopovar#6191). Only buffer handles still refuse hops:
the materializer keys the records by the innermost pointer before it
follows the hops, and the plan's parent pointer is that innermost one.
…one-key child

From hugodearaujo's change on boykopovar#8939 (Marvel's Spider-Man 2, PPSA03016).
Spider-Man 2's shape: a record keyed by a first-lane read, its dwords
2-3 a pointer, a V# loaded at that pointer plus 0xa0, and the T# read at
offset 0 or 0x40 of that V#'s buffer with no second key. Two records
point at V#s of different T#s; a moved record pointer and a moved V#
must change the result without recompiling.
@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@frankea @hugodearaujo @spiff637, this draft is the next step on #6191's chain for your titles, stacked on #8939 (fix/shader-table-family-6191, c00cb0f):

Its tests pass on lavapipe. It hasn't run on either title or on real hardware yet.

@github-actions

github-actions Bot commented Oct 21, 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 6959 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 7085 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9508 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 9852 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 10228 core/shader/recompiler/Optimization/src/ResourceTracker.cpp L15, L702-703
PR 10351 core/shader/recompiler/ShaderDiskCache.hpp L16

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
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 1896 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 5609 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6235 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
docs/dev/debt/shader.md
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
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
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ResourcePlan.hpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/execution/ImageTable.cpp
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ImageTableAbi.hpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ControlFlowInfo.hpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ResourcePlan.hpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 6539 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 6642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6858 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 6924 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7410 core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7677 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7684 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
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 7689 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 8004 core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 8014 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8077 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
docs/dev/debt/shader.md
PR 8246 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8874 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8998 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
PR 9248 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9335 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 9356 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 9387 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 9700 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9889 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
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 9892 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9897 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 9898 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10046 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10049 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 10193 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/ImageTableAbi.hpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
PR 10233 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/shader.md
PR 10442 core/libs/prx/libSceAgcDriver/CMakeLists.txt

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

The new lavapipe tests exercise both reported resource-chain shapes, include negative controls and relocation-without-recompile cases, and the PR reports Windows compilation plus the relevant focused CI results. I cannot treat the AGC/shader validation protocol as complete from the current report: it does not show the same focused tests run on current main and this change with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, confirm the requested validation layer loaded in both runs, or compare new VUID- messages. Please attach those paired logs/results and name the GPU/driver/OS as required. Also, this head is based on 0c6a5bd rather than current main (110a18ba01); please rebase and rerun conventions, overlap and the focused validation suite on the updated tree. I did not run local GPU tests.

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

frankea commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

@EagleBearerYS Gran Turismo 7 (PPSA01317) data for this stack: the World Map's 29 compute shaders from #6191, replayed offline (agc_shader_replay --prepare, ANYPS5_NO_SHADER_CACHE=1) on the requests the driver dumped at use in a run today.

Both builds are my GT7 integration branch (main 513ca7e plus the GT7 pull requests in the #4697 list and local diagnostics; its requests use #9020's serializer format), without and with #9969 at 7588a53 (its newer head d01f290 changes only a memo footprint count; 7588a53 carries #9790 809d880, this PR 7f3a25e, #8939 9162d9d, #7395 4661f4b and #7223 94a91a4). The stack merged with only the shader disk cache format number in conflict.

  • Without the stack, all 29 refuse their first T#: 21 of them at 0x2404 behind the pointer loaded at 0x20ec, the shape in your description, and seven at the same pair slightly later (0x2408 to 0x2460).
  • With it, 28 of the 29 get past that read and refuse at the shader's next T#, 0x2660 bytes later: 0x4a64 behind 0x4a4c in the 21, the matching pair in the seven. 0x120aed7f00 is unchanged (0x19a0 behind 0x198c), the shader you left out.
  • The new refusal's record pointer is a Phi that mixes the record read at 0x160 and its Ballot word, as at 0x2404, with arms that are the pointer loaded at 0x20ec, so on some edges the second hop starts from the first hop's result:
GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x00004a64(GetAddressResource(LoadAddressU32@pc=0x00004a4c(GetAddressResource(Phi(Phi(Phi(Phi(ReadConstBuffer@pc=0x00000160, CompositeExtractU32x4), ReadConstBuffer@pc=0x00000160(GetBufferResource, ShiftLeftLogical32)), Phi(LoadAddressU32@pc=0x000020ec(GetAddressResource, Immediate, Immediate, Immediate), Phi(LoadAddressU32@pc=0x000020ec, Phi))), Phi(Phi(ReadConstBuffer@pc=0x00000160(GetBufferResource, ShiftLeftLogical32), CompositeExtractU32x4(Ballot, Immediate)), ReadConstBuffer@pc=0x00000160(GetBufferResource(ReadConst, ReadConst, ReadConst, ReadConst), ShiftLeftLogical32(ReadFirstLane, Immediate)))), ...

RTX 4090, Windows 11, replay only. In the title, the same branch without the stack and with a local switch that skips dispatches whose shader is refused draws the World Map, so these shaders' output is what's missing there. I can post the IR of 0x120aea1900 around 0x4a4c, or rerun the 29 on a new head.

AI-assisted: yes (Claude Code)

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

Thanks, @frankea, that's the replay this PR was waiting for: 28 of the 29 World Map shaders get past the 0x2404 read and stop at their next T#, where the second hop can start from the first hop's result. It's in the Tested section. The IR of 0x120aea1900 around 0x4a4c would be the place to start on that shape, if you can post it.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@adriadam10 adriadam10 self-assigned this Oct 24, 2026

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The change itself looks right to me: the hop guard now refuses only buffer columns, the fixed-offset case is limited to a pointer-loaded V# (a runtime V# still refuses), and the three new tests each fail on the base chains shown in the description.

What blocks it:

  • This branch stacks on #7223, #7395 and #8939, which are all open and conflict with main since #7880 merged (TryMakeIndirectColumn now reads through UnwrapTableRead). This PR inherits that conflict and can't land before them.
  • Once the bases are in, please rebase and re-check the if (!hops.empty() && buffer) return false; guard in TryMakeIndirectColumn against main's UnwrapTableRead path, rerun the three new tests, and renumber FormatVersion to whatever is next on main.

main took 46 for the 4_4_4_4 target merge (6ab7bd2) after this branch took it for nested tables, so a cache written by main would be read here under the same number with a different layout.
…th immediates

The pointer walk skips an edge whose low word is an immediate, as a waterfall loop's Phi gives one beside the record column read. Where the pointer's two words are Phis of one block, an edge on which both are immediates is a constant pointer that no record holds, such as a null pointer, so the walk now refuses the column there instead of planning it.
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@adriadam10 an update ahead of the bases landing: the stack now merges main 379b1dc, #7880 included. This branch's head is dc18bf7, a merge of #8939's merge, and this PR's own diff is unchanged. On your points:

When the bases land I'll merge main again and rerun these. Could you take another look at the two planner changes above in the meantime?

alex73630 added a commit to alex73630/AnyPS5 that referenced this pull request Oct 24, 2026
Apply PR boykopovar#9969 at d01f290 and its nested-table prerequisites, including PR boykopovar#9457 pointer hops. Preserve local mip-query handling and isolate the resulting shader cache format.
alex73630 added a commit to alex73630/AnyPS5 that referenced this pull request Oct 24, 2026
Apply PR boykopovar#9969 at d01f290 and its nested-table prerequisites, including PR boykopovar#9457 pointer hops. Preserve local mip-query handling and isolate the resulting shader cache format.
alex73630 added a commit to alex73630/AnyPS5 that referenced this pull request Oct 24, 2026
Apply PR boykopovar#9969 at d01f290 and its nested-table prerequisites, including PR boykopovar#9457 pointer hops. Preserve local mip-query handling and isolate the resulting shader cache format.

This branch has not been deployed

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

Labels

agc libSceAgc* build docs 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.

8 participants