Skip to content

fix(shader): follow a conditional pointer chase through a V# behind a pointer-keyed record pointer - #9633

Open
EagleBearerYS wants to merge 107 commits into
boykopovar:mainfrom
EagleBearerYS:fix/shader-pointer-chase-closure
Open

EagleBearerYS wants to merge 107 commits into
boykopovar:mainfrom
EagleBearerYS:fix/shader-pointer-chase-closure

Conversation

@EagleBearerYS

@EagleBearerYS EagleBearerYS commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What

On Ratchet & Clank: Rift Apart (PPSA01474), with #8939, a compute shader stops with GetImageResource dword 0 is not a valid runtime value at LoadAddressU32@pc=0x10b84. #8939 itself got it past its earlier stop at 0x9a30. The sources are a retail run on #8939 (comment), and two IR readings of the shader (1, 2).

The descriptor pointer is a Phi of the record's pointer R and up to two chased pointers. The shader conditionally replaces P by the 64-bit pointer read at offset 0 of a buffer whose V# sits at P+0x60, up to twice. It then loads the T# at the final P+0. So the pointer is R, H(R) or H(H(R)).

The change:

  • Tracker: a chase arm is a buffer read at dwords 0/1 of one handle whose V# is four words loaded through GetAddressResource(P) at an immediate offset, where P resolves to R or to another chase arm.
  • Materializer: for each record's pointer, the column also publishes H(R), H(H(R)) and so on up to its depth, breadth-first, as pointer-keyed entries, each with its own T#.
  • The disk cache format goes to 70, above fix(shader): follow pointer hops and fixed-offset V# reads behind a record pointer #9457's 67 (see Tested).
  • A V# whose words the shader edits (6c13924): a chased V# word may also be the word as read, shifted left, ANDed or ORed by one constant. The chase keeps that edit per word, the snapshot applies it to the words it reads before it decodes the V#, and the shader disk cache stores it; other edits of a V# word stay refused. The format then stayed 55, since the source version already kept this recompiler's caches apart; this PR's format is now 70 (see Tested). This is Ghostrunner (PPSA03685)'s compute shader 0x200c520000 (see Tested).
  • A debt entry for the depth cap and refused loops.

Overlap: checked with git merge-tree against every open PR touching these files, on main da54c65, and rechecked at 7928543 (with main 3ca07d0) against the PRs below: the conflicts are the same. #9508's other conflict there, in GuestMemory.cpp, is with main itself.

Tested

Checklist

EagleBearerYS and others added 18 commits October 21, 2026 04:37
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.
… pointer-keyed record pointer

A T# read at a pointer that a shader chases conditionally from a
pointer-keyed record pointer, loading a V# at a fixed offset of the
pointer and reading the next pointer from that buffer, stayed unplanned:
the merged pointer's chase arms read another buffer at another offset
than the record word, so PointerRecordRead refused them (Ratchet & Clank:
Rift Apart stops at compute LoadAddressU32 with this shape).

The walk now takes such an arm when its V# is read from a pointer that is
the record pointer or another chase arm, records each distinct chase as a
hop of the column, and refuses a chase that reaches itself or a depth
over 4. The snapshot then also captures every record pointer's chase
closure up to that depth as pointer-keyed entries, each with the T# at
its own offset, so the GPU's lookup finds the pointer the shader reached.
@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@Tamalero @oneandonlydean this draft follows a conditional pointer chase through a V# behind a pointer-keyed record pointer, the shape we read behind the 0x10b84 refusal on #8939. Its branch, fix/shader-pointer-chase-closure at 6a72841, includes #9457, #8939, #7395 and #7223, so one build of it is enough. Would you run Ratchet & Clank: Rift Apart (PPSA01474) on it and post where it stops after 0x10b84, or that it doesn't? If it still stops at 0x10b84, please post the stderr lines around the refusal: they show whether the chase's two words come from Phis in different blocks, a join this PR still refuses.

@github-actions

github-actions Bot commented Oct 22, 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 6416 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 10351 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 11551 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 14636 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 14871 core/shader/recompiler/ShaderDiskCache.hpp L16
PR 14904 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp L1875

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 5021 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 5371 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
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/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
docs/dev/debt/shader.md
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
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 6412 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.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/tests/execution/ImageTable.cpp
PR 6488 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.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 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 6970 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.cpp
PR 7085 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 7392 docs/dev/debt/shader.md
PR 7410 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 7684 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.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
PR 8004 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 9020 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 9183 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 9335 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 9356 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 9387 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 9748 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 9852 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 9889 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
core/shader/recompiler/ShaderDiskCache.hpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 9897 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_shader_memory_tests.cmake
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
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/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_shader_memory_tests.cmake
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/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
docs/dev/debt/shader.md
PR 10359 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
PR 10757 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
PR 10867 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 11351 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
PR 11483 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 12324 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/ControlFlowInfo.hpp
core/shader/recompiler/Recompiler.cpp
PR 12548 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 12790 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
docs/dev/debt/shader.md
PR 12828 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/shader/recompiler/Recompiler.cpp
PR 12944 core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
docs/dev/debt/shader.md
PR 13928 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_shader_memory_tests.cmake
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 13929 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_shader_memory_tests.cmake
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 14032 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_shader_memory_tests.cmake
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp
PR 14212 docs/dev/debt/shader.md
PR 14217 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 14218 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/shader/recompiler/Recompiler.cpp
docs/dev/debt/shader.md
PR 14561 core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
PR 14621 core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
PR 14702 core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp
PR 14944 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp
core/libs/prx/libSceAgcDriver/tests/cmake/agc_shader_memory_tests.cmake
core/shader/recompiler/Optimization/src/ResourceTracker.cpp
core/shader/recompiler/Recompiler.cpp
core/shader/recompiler/ShaderDiskCache.cpp
core/shader/recompiler/ShaderDiskCache.hpp

@oneandonlydean

Copy link
Copy Markdown
Collaborator

@EagleBearerYS thanks, I'll build your branch at 6a72841 as is and run PPSA01474 on it. If it stops at or near 0x10b84 again, I'll post the stop and the stderr lines around the refusal here. It's queued behind today's PR runs, so it'll be a few hours.

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

Run on NVIDIA, since the tests so far are llvmpipe only.

Machine: Ubuntu 26.04, i7-8700, GCC 15.2, Release, full build with BUILD_TESTING=ON. GPUs: NVIDIA GeForce RTX 3070 (driver 595.99.02, Linux) and lavapipe (Mesa 26.0.3, LLVM 21.1.8). Head 6a72841 (with its stack) merged into main da54c65.

  • agc_driver_pointer_chase_table (agc_driver_image_table_tests --pointer-chase) passes 3 of 3 on both devices, including the moved link, the link outside the snapshot, and the refused loop and five-step chase.
  • Control: the same tree with this PR's own ResourceTracker.cpp change reverse-applied (the diff from #9457's head to this head) fails on both devices the way the title does: GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x000000c0(GetAddressResource(Phi(Phi(ReadConstBuffer@pc=0x00000074(....
  • ^agc suite, excluding the flip, display DCC and lds_atomics64 tests: 875/878 on the 3070 and 877/878 on lavapipe. The failures are the same as on main on this machine: the three sample_order tests on the 3070 (no 2x2 sample-location grid at 2 samples) and multisample_retirement on lavapipe.

So the chase also works on a real GPU with subgroup 32, not only on llvmpipe's subgroup 8.

GPUs tested: NVIDIA GeForce RTX 3070 (595.99.02, Linux), lavapipe

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@jotitadev thanks for the RTX 3070 run with the reverse-applied control. A real GPU at subgroup 32 was the gap in this draft's testing. It's in Tested and on the GPUs tested line now.

@MarcZX10

Copy link
Copy Markdown
Contributor

The current evidence is strong for the modeled pointer-chase path: the focused test has a reverse-applied negative control, Linux validation-layer A/B shows no new VUIDs, and an independent RTX 3070 run confirms subgroup-32 behavior. The remaining title-specific gate is the promised PPSA01474 run on this exact stack; the body correctly says Unblocks: none yet until that confirms the 0x10b84 stop is passed. Please keep the draft until that result is available, then update the Game bring-up discussion and Unblocks checklist with its link. Also keep the declared stack order and disk-cache version coordinated with the listed overlapping PRs before merge.

@Tamalero

Copy link
Copy Markdown
Contributor

@EagleBearerYS ran it: PPSA01474 (content 01.005.003) gets past the 0x10b84 stop with this PR, and stops on the next T# load, whose pointer goes through a third chased read.

Setup: Linux (CachyOS, kernel 7.2.9), GCC 16.2.1, Release, RTX 4090 (NVIDIA 615.78.08). The same relinked executable for both builds, a cold shader cache, no input (the stop is in the black load after the logos).

Build Result
Control: c00cb0f (this PR's parent, so the same stack without the chase) 321 s, compute 0x116bb67b00, LoadAddressU32@pc=0x10b84, chain through ReadConstBuffer@pc=0xfd94 and @pc=0x10350 (the stop from #8939)
This PR: 6a72841 351 s, no refusal at 0x10b84; new stop in compute 0x116bb67100 at LoadAddressU32@pc=0x13bc0

Same shader on both builds: a second control run with APS5_DUMP_SHADERS=1 stopped on a sibling, compute 0x116bb5e100, at the same site at pc=0xf898 (its chase reads are at 0xeaa8 and 0xf064). Replaying its prepare request offline with agc_shader_replay from each build:

  • control: refused at LoadAddressU32@pc=0xf898;
  • this PR: passes 0xf898, refused at LoadAddressU32@pc=0x128d4, a later T# load.

So the chase is followed on the title's own shader, not only on the test one.

The next stop: in both refusals (0x13bc0 in game, 0x128d4 in the replay), the pointer Phi has the two chase reads you modelled plus a third read:

  • in game: ReadConstBuffer@pc=0x12e9c(GetBufferResource(LoadAddressU32@pc=0x12de8(GetAddressResource, …)));
  • in the replay: ReadConstBuffer@pc=0x11bb0 through a V# loaded at pc=0x11afc from the current pointer.

In the replayed shader that third read is an s_buffer_load_dwordx16, where the two reads you modelled are x4 (0xeaa8) and x8 (0xf064). The pointer also still passes through the lane-mask BitwiseAnd32(…, CompositeExtractU32x4(Ballot, Immediate)) arms. This log can't show whether the refusal comes from the third read's offset or word position, a V# at an offset other than 0x60, or the Phi join you mentioned. The tracker logs nothing before the throw, so the chain below is all the stderr has. If it helps, I can run APS5_DUMP_IR on 0x116bb67100 and post the blocks around the third read.

Full refusal, in game (compute 0x116bb67100)
compute shader 0x116bb67100: shader 0x116bb67100 stage 0: ShaderRecompiler::Recompile: GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x00013bc0(GetAddressResource(Phi(Phi(Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, Phi)), BitwiseAnd32(Phi(Phi, Phi), CompositeExtractU32x4(Ballot, Immediate))), Phi(Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x00010350)), Phi(Phi(Phi, Phi), Phi(Phi, Phi)))), Phi(Phi(Phi(Phi(Phi, Phi), BitwiseAnd32(Phi, CompositeExtractU32x4)), Phi(Phi(Phi, Phi), Phi(Phi, Phi))), ReadConstBuffer@pc=0x00012e9c(GetBufferResource(LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate), LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate), LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate), LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate)), Immediate))), Phi(Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x00010350)), Phi(Phi(Phi, Phi), Phi(Phi, Phi))), BitwiseAnd32(Phi(Phi(Phi, BitwiseAnd32), Phi(Phi, Phi)), CompositeExtractU32x4(Ballot(Immediate), Immediate))), Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, Phi)), Phi(Phi(Phi, Phi), ReadConstBuffer@pc=0x00010350(GetBufferResource, Immediate))), Phi(Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x0000fd94)), Phi(Phi(Phi, Phi), Phi(Phi, Phi)))))), Phi(Phi(Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, Phi)), Phi(Phi(Phi, Phi), ReadConstBuffer@pc=0x00010350(GetBufferResource, Immediate))), Phi(Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x0000fd94)), Phi(Phi(Phi, Phi), Phi(Phi, Phi)))), Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x00010350)), Phi(Phi(Phi, Phi), Phi(Phi, Phi))), ReadConstBuffer@pc=0x00012e9c(GetBufferResource(LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate), LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate), LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate), LoadAddressU32@pc=0x00012de8(GetAddressResource, Immediate, Immediate, Immediate)), Immediate))), Phi(Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x0000fd94)), Phi(Phi(Phi, Phi), Phi(Phi, Phi))), Phi(Phi(Phi(Phi, Phi), Phi(Phi, Phi)), ReadConstBuffer@pc=0x00010350(GetBufferResource(LoadAddressU32@pc=0x00010338, LoadAddressU32@pc=0x00010338, LoadAddressU32@pc=0x00010338, LoadAddressU32@pc=0x00010338), Immediate))), Phi(Phi(Phi(Phi(Phi, Phi), Phi(Phi, Phi)), Phi(Phi(Phi, Phi), ReadConstBuffer@pc=0x0000fd94(GetBufferResource, Immediate))), Phi(Phi(Phi(Phi, Phi), Phi(Phi, CompositeExtractU32x4)), Phi(Phi(Phi, Phi), Phi(Phi, ReadConstBuffer@pc=0x00001aa8))))))), Immediate, Immediate, Immediate)

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

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@Tamalero thanks for running it on Ratchet & Clank: Rift Apart (PPSA01474), with the parent as a control and the offline replay of the sibling shader. Getting past 0x10b84 on the title's own shader is the run this draft was waiting for, and it's in Tested and on the Unblocks line now. The third chased read at 0x13bc0 is the next step. The IR blocks around it (APS5_DUMP_IR on 0x116bb67100), as you offered, would show whether it's the read's offset or word position, a V# away from 0x60, or the Phi join.

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 22, 2026
@Tamalero

Copy link
Copy Markdown
Contributor

@EagleBearerYS here is the third read. It's none of the three you listed: the pointer's two words are not adjacent. The V# offset differs too, but the per-site PointerChase already covers that.

Same shader, both builds: a dump run of this PR stopped in compute 0x116bb67b00 at LoadAddressU32@pc=0x13bc0 (the same sites as the 0x116bb67100 refusal above). The control stopped in that same shader at 0x10b84. I replayed its prepare request and its sibling's (0x116bb5e100, stop at 0x128d4) through a copy of this PR's ResourceTracker.cpp with tracing added.

Step V# load V# at Pointer words read
R record read at 0x1aa8
H1 0xfd88 P+0x60 0xfd94: offsets 0x0 / 0x4
H2 0x10338 P+0x60 0x10350: offsets 0x0 / 0x4
H3 0x12de8 P+0x110 0x12e9c: low at 0x54, high at 0x6c

The sibling has the same shape: H1 0xea9c/0xeaa8, H2 0xf04c/0xf064, H3 0x11afc/0x11bb0 (V# at P+0x110, words 0x54/0x6c).

  • Where it fails: ChaseHighRead requires highImmediate == readImmediate + 4. For H3 the high read's immediate is 0x6c against a low of 0x54, so walk() returns false at the ChaseHighRead call, and PointerRecordPairs and then TryMakeIndirectColumn refuse.
  • The shader really splits the pointer: in the sibling's code, H3 is one s_buffer_load_dwordx16 from offset 0x40, and the next pointer is rebuilt from dword 5 (low) and dword 11 (high) of that load before the next s_load through it.
  • What does pass:
    • H3's V# comes off the pointer the walk is already following (the same Phi pair).
    • The unpaired Phis from different blocks and the lane-mask BitwiseAnd32(…, Ballot) arms walk without failing.
    • With only the adjacency check relaxed, in a local scratch build, the tracker finds three sites with no loop and depth 3, within your cap of 4.

So the step is structurally the one you modelled, with two different parameters: a V# immediate of 0x110, which per-site chases already cover, and a high word at its own immediate.

A possible change: keep the high read's own immediate in PointerChase, for example readHighImmediate. ChaseHighRead would still require the same handle and readOffset, and could require the high word to be 4-aligned. ResourceMaterializer would then read the high word there instead of readImmediate + 4u, and the field would go into the disk-cache serialization.

After that: in the relaxed scratch build, both shaders get past the T# and stop on sampler resource limit exceeded (MaxSamplers = 32). That build is only the relaxed check, not a real fix, so I can't yet say the same stop follows your change. I'll run Ratchet on it when it's pushed.

The IR stays local (it's the title's code), but I can trace any value you need.

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

PointerRecordPairs found an existing chase site by its V# alone. A
second chase arm that reads its next pointer through the same V# at
other words therefore kept the first arm's PointerChase, and the
snapshot never followed the second arm: a T# behind a node whose V#
holds two links (words 0 and 1, words 2 and 3), each taken in its own
lanes, faulted as outside the snapshot when the second link was taken.

Sites are now keyed by the V# and the whole PointerChase, so each word
pair of one V# is its own chase in the column and in the snapshot's
closure. This follows the chase work for Ratchet & Clank: Rift Apart
(PPSA01474); its trace has not shown this shape yet.
Main's 1D array layer rows add a loop to the table snapshot that
records each table's registered image views, keyed by the table's
index. This branch copies a column's records in a helper that also
serves nested child columns, which have no table index, so the loop
stays in the snapshot of the top-level table after the copy.
EagleBearerYS added a commit to EagleBearerYS/AnyPS5 that referenced this pull request Nov 2, 2026
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Nov 2, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head b9fab3f merged onto main 1d91f29 · tested 2026-11-02 18:01 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,700 passed · 5 failed (0 new, 3 also fail on main, 2 unstable on main) · 45 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,750 of 3,544 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 (1004 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s, ⚠️ agc_driver_graphics_maps_fallback 32.3 s, ⚠️ agc_driver_graphics 31.6 s
Unstable on main (2, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 3 of the last 10 main runs
agc_submit_progress: 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
Validated but not compared (20, not in the main baseline's validation pass)
agc_driver_nested_image_table
agc_driver_nested_image_table_budget
agc_driver_nested_image_table_large
agc_driver_nested_sampler_table
agc_driver_pointer_chase_edited_table
agc_driver_pointer_chase_table
agc_driver_pointer_chase_words_table
agc_driver_pointer_hop_table
agc_driver_pointer_phi_ballot_table
agc_driver_pointer_phi_copies_table
agc_driver_pointer_phi_high_second_lane_table
agc_driver_pointer_phi_high_table
agc_driver_pointer_phi_lane_and_table
agc_driver_pointer_phi_lane_not_table
agc_driver_pointer_phi_sampler_table
agc_driver_pointer_vsharp_fixed_offset_table
agc_driver_pointer_vsharp_fixed_table
agc_driver_pointer_vsharp_select_table
agc_shader_nested_sampler_snapshot_retry
agc_shader_nested_snapshot_retry
Validation IDs already present on main (4 IDs in 510 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (510 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 502 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
Skipped (45)
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_fps_limit: 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_o
Reproduce
git fetch origin b9fab3f82e9329479940da71b24f2cc81a7bab94 1d91f2966d0eef82a021628a7aa8e78e615ac807
git checkout 1d91f2966d0eef82a021628a7aa8e78e615ac807 && git merge --no-ff b9fab3f82e9329479940da71b24f2cc81a7bab94
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.

liskeee pushed a commit to liskeee/AnyPS5 that referenced this pull request Nov 2, 2026
…t-words-on-c2

# Conflicts:
#	core/libs/prx/libSceAgcDriver/tests/cmake/agc_driver_image_table_tests.cmake
#	core/shader/recompiler/ShaderDiskCache.hpp
liskeee pushed a commit to liskeee/AnyPS5 that referenced this pull request Nov 2, 2026
…at, 72

boykopovar#9633 now takes 70, so this PR takes 72, above it and every other open PR's number.
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 3, 2026

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

This pull request does not merge cleanly into main (4f41f4c): head b9fab3f conflicts in

  • core/shader/recompiler/ShaderDiskCache.hpp
  • docs/dev/debt/shader.md

Please rebase it onto current main. I will review the change once it merges cleanly.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head b9fab3f merged onto main 7feb37e · tested 2026-11-03 09:49 UTC · 57 min

GPU AMD Radeon RX 6300 (RADV NAVI24), driver Mesa 25.2.8-0ubuntu0.24.04.4, Vulkan 1.4.318
Host Ubuntu 26.04.1 LTS, kernel 7.0.0-42-generic, container ubuntu:24.04
Logs build and test logs for this run
Build ✅ passed (Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON)
Tests ✅ 2,755 passed · 9 failed (0 new, 8 also fail on main, 1 unstable on main) · 58 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,822 of 3,743 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 (955 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.3 s, ⚠️ public_headers 71.9 s, ⚠️ agc_driver_image_sample_unnormalized 46.6 s, ⚠️ agc_driver_lazy_resolved_abi 36.9 s, ⚠️ agc_driver_sample_multisample_target 33.5 s
Unstable on main (1, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 7 of the last 9 main runs
Failing on main too (8, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_idle_publish_wait
agc_submit_progress
agc_submit_progress_no_timeline
guest_mmap_executable
guest_socket_options_multicast
Validated but not compared (2, not in the main baseline's validation pass)
agc_shader_nested_sampler_snapshot_retry
agc_shader_nested_snapshot_retry
Validation IDs already present on main (4 IDs in 537 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (537 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 529 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_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth, agc_driver_stencil_null_feedback
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_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth, agc_driver_stencil_null_feedback
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
Skipped (58)
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_copied_writer_label_order: skipped, the device reports a minStorageBufferOffsetAlignment of 4, so the dispatch binds its record at +0x1004 in place and nothing is written back; the test needs an alignment above 4
agc_driver_float16_unused_nan_payloads: skipped, the device has no native f16 conversions with RTE rounding and kept f16 denormals
agc_driver_image_table_vouched_lookups: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a watched imported table cannot be vouched for
agc_driver_linear_target_direct_write_completion: skipped, the device does not keep host imports write-watched, so no completion stamp over the target is tracked
agc_driver_ngg_vertex_wave_reduction: skipped, s3 describes a 32-lane wave only on 32-lane subgroups, and the device has 64 lanes
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_unit_shadow: skipped, the device does not import watched host memory for unit shadows
agc_driver_unit_shadow_budget: skipped, the device does not import watched host memory for unit shadows
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_shadowed_key_stores: skipped, the device imports no watched host memory under a unit shadow
agc_small_tiled_shadow_label: skipped, host imports are unavailable: the test block is not imported and watched
agc_storage_clear_hand_over: skipped, the device imports no watched host memory for the clear-key hand-over
agc_unit_shadow: skipped, the device does not import watched host memory for unit shadows
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 co
Reproduce
git fetch origin b9fab3f82e9329479940da71b24f2cc81a7bab94 7feb37ee3e30e10139b483fb4df689d5b5b69ab8
git checkout 7feb37ee3e30e10139b483fb4df689d5b5b69ab8 && git merge --no-ff b9fab3f82e9329479940da71b24f2cc81a7bab94
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 12 --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 16 --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 AMD machine; it does not replace upstream CI. A new comment is posted for each new push. Full logs.

@XairRrR XairRrR 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 — approved

The head moved to ce7a09f, a merge of main onto b9fab3f. The merged tree builds, the focused chase, pointer, nested and disk-cache tests pass, and reverting this PR's own production diff over #9457 turns the three chase tests red with the title's refusal.

What changed since my last review

The text of my previous review isn't available to this run, so this review covers the whole change again. It does not compare against earlier findings.

  • The newest commit, ce7a09f, is a merge of main. Between b9fab3f and ce7a09f it changes no chase code in Optimization/ or ControlFlowInfo.hpp.
  • What this PR adds over #9457: I isolated it as git diff 0a4f7cdbed b9fab3f82e, where b9fab3f is this branch's merge of #9457's 0a4f7cd.
    • Production code: ControlFlowInfo.hpp, ResourceTracker.cpp, ResourceMaterializer.cpp, ShaderDiskCache.{cpp,hpp} and one debt entry.
    • Tests: three chase tests in ImageTable.cpp.
  • Disk-cache format: FormatVersion is 70 here and 52 on main.

What I ran

Head ce7a09f3f13259ed5129371c1ac22f33ba4be5df, main 4f41f4c375f5abb487dbd184fbc150f31994d762, merged tree f3d829311ada5c98ebc5032edd2f862735f62fb5. Debian 13 VM, GCC 14.2.0, Release, lavapipe (Mesa 26.1.6, LLVM 19).

git diff --check 4f41f4c375f5abb487dbd184fbc150f31994d762...ce7a09f3f13259ed5129371c1ac22f33ba4be5df
python3 tools/check_conventions.py --base 4f41f4c375f5abb487dbd184fbc150f31994d762
ctest --test-dir build -j8 --test-load 32 -R "agc_driver_pointer_|agc_driver_nested_|agc_shader_disk_cache|agc_shader_nested_|agc_driver_image_table" --output-on-failure
# negative control 1: reverse this PR's own production diff over #9457
git diff 0a4f7cdbed b9fab3f82e -- core/shader | git apply -R
ninja -C build agc_driver_image_table_tests
ctest --test-dir build -R "agc_driver_pointer_(chase|hop|vsharp)" --output-on-failure
# negative control 2: key chase sites by V# handle only (undo 2c1a65045c), on the merged tree
ninja -C build agc_driver_image_table_tests
ctest --test-dir build -R agc_driver_pointer_chase --output-on-failure
# restore the merged files, rebuild, rerun
ninja -C build agc_driver_image_table_tests agc_shader_disk_cache_tests
ctest --test-dir build -R "agc_driver_pointer_chase|agc_shader_disk_cache$"
git status --porcelain
Check Result
git diff --check clean
check_conventions.py All conventions checks passed
Configure, build, libs (script) ok
Selected tests (script, 2234 run) 0 new failures, 0 timeouts; 7 known failures that also fail on main (agc_driver_division, denormal-mode tests and others), none of them table tests
Validation layer (script, 788 tests) layer loaded, missing in none, 0 tests with a new VUID-
30 focused tests 30/30 pass, each under 9 s
Control 1: this PR's own production diff reversed agc_driver_pointer_chase_table, _chase_words_table and _chase_edited_table fail; hop and vsharp tests pass
Control 2: chase sites keyed by handle only agc_driver_pointer_chase_words_table fails ("the T# behind one of the two links faulted"); the other two pass
Worktree after restore clean, chase and disk-cache tests pass again
Control 1 output (truncated)
1/7 Test #1832: agc_driver_pointer_chase_table .................***Failed    0.12 sec
ShaderRecompiler::Recompile: GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x000000c0(GetAddressResource(Phi(Phi(ReadConstBuffer@pc=0x00000074(...
2/7 Test #1834: agc_driver_pointer_chase_edited_table ..........***Failed    0.12 sec
ShaderRecompiler::Recompile: GetImageResource dword 0 is not a valid runtime value; chain: LoadAddressU32@pc=0x000000b4(GetAddressResource(Phi(ReadConstBuffer@pc=0x00000074(...
3/7 Test #1833: agc_driver_pointer_chase_words_table ...........***Failed    0.12 sec
4/7 Test #1830: agc_driver_pointer_vsharp_select_table .........   Passed
5/7 Test #1836: agc_driver_pointer_vsharp_fixed_offset_table ...   Passed
6/7 Test #1835: agc_driver_pointer_vsharp_fixed_table ..........   Passed
7/7 Test #1831: agc_driver_pointer_hop_table ...................   Passed
57% tests passed, 3 tests failed out of 7
Control 2 output
1/3 Test #1833: agc_driver_pointer_chase_words_table ....***Failed    0.41 sec
AGC graphics: pointer table with two chase links in one V#: the T# behind one of the two links faulted:
2/3 Test #1834: agc_driver_pointer_chase_edited_table ...   Passed
3/3 Test #1832: agc_driver_pointer_chase_table ..........   Passed

Previous findings

The previous review's text isn't available, so its findings can't be checked one by one. Every blocking-class check below passes on the current head.

New findings

Blocking

None.

Non-blocking

  • The chase closure keeps working after the entry limit (core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp:1150-1156). Once records.keys >= limit, ChaseClosure still calls Chase for every remaining frontier pointer and chase. Each call adds up to six 4-byte entries to tables.ranges (lines 1127 and 1134-1135). With 65536 records, several chase sites and depth 4, that can be a few million range entries per snapshot.
    • The ranges for links already followed are needed for invalidation. The work after outside is set adds no entries.
    • Suggested fix: stop the closure once the limit is reached, and add the V# as one 16-byte range.
  • The description is out of date in two places.
    • It still says "The format stays 55" for 6c13924, while the head is at 70.
    • Under Tested it says "a chase in a loop and a five-step chase are refused. Disabling each rule turns its case red". Those cases were removed in ee8767f, so the loop and depth-cap refusals in PointerRecordPairs (ResourceTracker.cpp:1170-1192) no longer have a test. Removing them follows the test policy, but the description should say so.

Code reading notes (no action needed)

  • Over-approximation is safe: the closure applies every chase site to every frontier pointer, not only the sites reachable from that pointer. Mixed low/high pairs (looseHandles) are also accepted. Both are safe because the GPU looks entries up by the full 64-bit pointer, and each entry's T# is read at that pointer's own offset. An extra entry is never wrong, and a missing one faults as outside the snapshot.
  • Decoder checks: decodePlan checks the chase list (at most 64 entries), the depth (pointerChases.empty() == (depth == 0), at most MaxPointerChaseDepth, pointer-keyed only) and the edit shift (at most 31).

Not verified

  • No hardware GPU here, only lavapipe. NVIDIA, AMD RDNA2 and RX 6300 runs are reported by others in the discussion.
  • Windows was not built.
  • The Ratchet & Clank: Rift Apart and Ghostrunner results are author- and contributor-reported. I did not run any title.
  • The whole stack's diff (#7223, #7395, #8939, #9457) is in this merge. I reviewed only this PR's own code over #9457 in detail.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 3, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head ce7a09f merged onto main 4f41f4c · tested 2026-11-03 14:57 UTC · 35 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,783 passed · 6 failed (0 new, 3 also fail on main, 3 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,837 of 3,811 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 (951 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s
Unstable on main (3, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 4 of the last 10 main runs
agc_submit_progress: failed in 6 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 5 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
Validated but not compared (2, not in the main baseline's validation pass)
agc_shader_nested_sampler_snapshot_retry
agc_shader_nested_snapshot_retry
Validation IDs already present on main (4 IDs in 530 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (530 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 522 more
VUID-vkCmdCopyImage-srcImage-01548 (9 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, agc_driver_stencil_null_feedback, and 1 more
VUID-vkCmdCopyImage-srcImage-01551 (9 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, agc_driver_stencil_null_feedback, and 1 more
VUID-VkPipelineColorBlendStateCreateInfo-pAttachments-00605 (1 test): agc_driver_srgb8_color_target
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_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
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 co
Reproduce
git fetch origin ce7a09f3f13259ed5129371c1ac22f33ba4be5df 4f41f4c375f5abb487dbd184fbc150f31994d762
git checkout 4f41f4c375f5abb487dbd184fbc150f31994d762 && git merge --no-ff ce7a09f3f13259ed5129371c1ac22f33ba4be5df
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.

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

Thanks for the re-check.

  • The chase closure past the entry limit. Agreed: once records.keys reaches the limit, ChaseClosure still chases the rest of the frontier, and those calls add range work without adding entries. No title we know of reaches the record limit, so this PR leaves it as it is.
  • The description: both places are updated. The format line now says this PR is at 70, and Tested says that ee8767f removed the loop and five-step chase cases, so the loop and depth-cap refusals in PointerRecordPairs no longer have a test.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
boykopovar#7223 has merged. The conflicts are this branch's additions on top of it:
its tests in the image-table test lists, pointerKeyed in the image-table
column and its equality check, the plan encoder's field count and list
version, and FormatVersion 63.

agc_shader_memory_tests.cmake merged without a conflict but registered
agc_shader_nested_snapshot_retry twice: boykopovar#7223's block after
agc_shader_descriptor_phis and this branch's before it. The merge keeps
this branch's block, which adds agc_shader_nested_sampler_snapshot_retry,
at boykopovar#7223's place.
e94fb3f is boykopovar#7395 with its merge of main after boykopovar#7223. The two
conflicts are this branch's own changes over boykopovar#7395: FormatVersion 66, and
its wording of the pointer-keyed image-table debt entry.
4769d4a is boykopovar#8939 with boykopovar#7395's merge of main after boykopovar#7223. The one
conflict is this branch's FormatVersion 67.
6e403b4 is boykopovar#9457 with the stack's merges of boykopovar#7395's main merge after
boykopovar#7223. The conflicts are this branch's own: FormatVersion 70 and its
pointer-keyed chase debt entry.
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Nov 4, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 6089e58 merged onto main b8efa62 · tested 2026-11-04 07:12 UTC · 21 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,852 passed · 7 failed (0 new, 3 also fail on main, 4 unstable on main) · 50 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,909 of 3,878 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 (988 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.1 s
Unstable on main (4, these also failed in recent main runs on this machine; not counted against this PR)
agc_driver_pipeline_journal: failed in 3 of the last 10 main runs
agc_driver_submit_progress: failed in 3 of the last 10 main runs
agc_submit_progress: failed in 4 of the last 10 main runs
agc_submit_progress_no_timeline: failed in 3 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
Validated but not compared (1, not in the main baseline's validation pass)
agc_shader_nested_sampler_snapshot_retry
Validation IDs already present on main (13 IDs in 554 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (554 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 546 more
VUID-VkShaderModuleCreateInfo-pCode-08737 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08739 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
VUID-VkShaderModuleCreateInfo-pCode-08741 (8 tests): agc_driver_dpp16_operands, agc_driver_dpp8_pk_fmac, agc_driver_dx10_clamp, agc_driver_float16_fma_rounding, agc_driver_float16_unused_nan_payloads, agc_driver_packed_alu, agc_driver_packed_f16_denormal_modes, agc_driver_packed_float16_native
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_srgb8_color_target
VUID-VkPipelineShaderStageCreateInfo-module-parameter (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkPipelineShaderStageCreateInfo-pSpecializationInfo-06849 (1 test): agc_driver_float16_unused_nan_payloads
VUID-VkSamplerCreateInfo-addressModeU-01079 (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeU-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeV-parameter (1 test): agc_driver_image_gather_volume
VUID-VkSamplerCreateInfo-addressModeW-parameter (1 test): agc_driver_image_gather_volume
Skipped (50)
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_gcn_display_present: skipped, no display: Vulkan support is either not configured in SDL or not available in current SDL video driver (offscreen) or platform
agc_driver_sample_order_grid_reference: skipped, the device does not keep depth drawn at custom sample locations at those locations, even after a transition that names them: the composite of uniform renders holds the guest's depth in 0 of 3005 sloped samples, so no path can be compared with it bit for bit
agc_driver_scattered_runs: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_sparse_dma_buf_import: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_driver_stencil_ref_export: skipped, the device lacks VK_EXT_shader_stencil_export
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 platform
vide
Reproduce
git fetch origin 6089e589a8985de747fe93b9781294a1dd3cc567 b8efa6292ae69dfdebbeffcc869b66ddbb8739fc
git checkout b8efa6292ae69dfdebbeffcc869b66ddbb8739fc && git merge --no-ff 6089e589a8985de747fe93b9781294a1dd3cc567
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.

liskeee pushed a commit to liskeee/AnyPS5 that referenced this pull request Nov 5, 2026
…ords-on-c2

f498717 is boykopovar#9633 with the stack's merges of boykopovar#7395's main merge after
boykopovar#7223. The conflicts are this branch's own: FormatVersion 72 and its
wording of the pointer-keyed chase debt entry.

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.

10 participants