Skip to content

fix(shader): accept a nested S# whose V# gives the key of a sibling V#'s T# array - #15555

Open
hugodearaujo wants to merge 133 commits into
boykopovar:mainfrom
hugodearaujo:fix/shader-nested-sibling-vsharp-key
Open

hugodearaujo wants to merge 133 commits into
boykopovar:mainfrom
hugodearaujo:fix/shader-nested-sibling-vsharp-key

Conversation

@hugodearaujo

@hugodearaujo hugodearaujo commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

What

Marvel's Spider-Man 2 (PPSA03016 01.004.003), with #9969 applied, stops on a compute shader whose S# the recompiler refuses:

ShaderRecompiler::Recompile: GetSamplerResource dword 0 is not a valid runtime value; chain: ReadConstBuffer@pc=0x00008ec0(GetBufferResource(LoadAddressU32@pc=0x00008e44(...

The same block also appears 0xbb8 higher, at pc 0x9a78 / 0x99fc. The shape, from the IR posted on #9790 on 2026-11-02:

V# A = 4 words at P+0x50, P = a record pointer
key  = A's word at +0x0 >> 16
V# B = 4 words at P+0x10, same pointer P
T#   = B's buffer at (key >> 16) << 5      (s_buffer_load_dwordx8)
S#   = A's buffer at +0xa0..0xac

#9969 handles a key word whose T# reads go through the same V#. Here the key read through A indexes B. ChildKeyWord required the T# reads to use the key's own handle, so DescriptorWordReads refused A's key read, and with it the S# column read through A.

ChildKeyWord now also accepts T# reads through a sibling V# when DescriptorWordReads asks on behalf of a V# that is read again at dispatch. A sibling is a GetBufferResource whose four words are LoadAddressU32s from the same, or an equivalent, GetAddressResource as the key's V#. Nothing else changes:

  • The key stays the guest's value. The key's V# is read again at dispatch, as for fix(shader): index a pointer-loaded V#'s T# array by a word read from the same buffer #9969's child keys.
  • B's T# column is not narrowed. MatchChildKey still requires the same handle, so the column falls back to MatchKeyDomain: B's table binds every key the key's known bits allow, up to B's num_records. Narrowing it would need the materializer to read the key from the other V#'s buffer.
  • Other uses stay refused. That includes a key that feeds anything other than the offset arithmetic, and a sibling loaded through another pointer.

The debt entry for nested image tables records this form and its limits.

Tested

Arch Linux (kernel 7.2.11), AMD Radeon RX 9070 XT (RADV GFX1201, Mesa 26.2.6), Release. The branch is #9969's head c147aa8647 plus the three commits of this PR.

New test agc_driver_pointer_vsharp_sibling_key_table (agc_driver_image_table_tests --pointer-vsharp-sibling-key). It uses #9969's child-key shader with the T# array in a second V# loaded through the same record pointer. A's buffer holds the key and the S#. B's buffer holds the T# array, plus a decoy key and the opposite S# at the same offsets, so reading A's words from B would show up. It checks:

  • keys 2 and 5;
  • the largest key inside B;
  • swapped S#s;
  • a moved record pointer;
  • keys past B, which read a null T# as the hardware's scalar load does.

None of these recompile the shader.

Paired validation of the 21 agc_driver_(nested_image_table.*|nested_sampler_table|pointer_.*_table|image_table) tests, with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=layer:

tree result VUID- lines "was not found but was requested"
c147aa8647 + the new test, ResourceTracker.cpp from c147aa8647 20 of 21; the new test fails with the title's refusal (below) 0 0
this branch 21 of 21 0 0

On the base, the new test fails the way the title does:

ShaderRecompiler::Recompile: GetSamplerResource dword 0 is not a valid runtime value; chain: ReadConstBuffer@pc=0x000000c0(GetBufferResource(LoadAddressU32@pc=0x00000090(GetAddressResource(Phi(...

The validation layer was inserted in every test of both runs. The 57 ^shader|^agc_shader tests pass on this branch. These results are from the rebase onto c147aa8647 (2026-11-04); the same pair on the earlier base 9e7ac69470 gave the same counts.

Title: Spider-Man 2, relinked with --module-dir . --registry, fresh shader cache, Cross every 30 s, until the first stop. Base: main 4f41f4c + #9969 9e7ac69470 + #8939 58ebe4b440 + #13646 17770dd69f + #15399 7a9ecdc365. #13646 keeps the bindless table's textures inside VRAM, and #15399 stops an intermittent runtime resource snapshot did not stabilize.

  • Without this change (one run): stops at 65 s on the refusal above, at pc 0x8ec0. Two runs on fix(shader): index a pointer-loaded V#'s T# array by a word read from the same buffer #9969's earlier head stopped on the same refusal, at 0x9a78 after 187 s and at 0x8ec0 after 148 s.
  • With it (two runs): no recompile refusal.
    • One run reached its 600 s limit, with the title's internal RenderFrameIndex at 5683. The refusing runs stopped at frame 1460 (this base) and at frames 4856 and 5015 (the earlier head).
    • The other reached frame 5425, the last one it logged. Then VRAM filled (sampled textures at 7.6 GB, device-local heap 1 uses 16314 of its 16304 MiB budget), and my memory guard stopped it at 161 s. That fill comes from the bindless table (Marvel's Spider-Man 2 (PPSA03016) #10195), not from this change.

Not verified: the picture. On this machine the bench's screenshots of this title are black after about 60 s in every run, with or without this change, so I can't judge the rendering. The new test checks the selected T# and S# against the guest's own.

Checklist

EagleBearerYS and others added 30 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.
…andles as nested children

Marvel's Spider-Man 2 (PPSA03016) stops at 131 s on boykopovar#9457 in a compute
shader whose record pointer, at dwords 2-3 of a waterfall-keyed record
with its low word merged by a Phi with a constant, leads to a V# that two
GetBufferResource handles read: a T# at offset 0 and a T# at 0x4c0, each
sampled. The nested branch of TryMakeTableColumn refused the first T#
because the V#'s words also fed the second handle, whose reads belong to
the other T#.

A parent V# whose word reads feed several GetBufferResource handles is
now accepted when every other handle has the same words and its uses are
only reads whose users are T# or S# descriptor handles. Each descriptor
plans its child column from its own handle; both walks reach the same
reads, so the parent interns to one source, the materializer reads its
records once (NestedColumn takes them from Column()), and each child
keeps its own offset. A handle with any other use still refuses, and a
sibling descriptor that cannot be planned still refuses the shader, as
its words are not runtime values.

T# or S# words that have other users stay refused. Planning keeps those
reads in the program: PlanTableColumnPass marks a read planning-only only
when every user is a planned handle (ResourceTracker.cpp:1770-1781). But
they read through the V# handle, whose arguments Run() replaces with the
column offset and the parent pointer words (:154-160), and whose own word
loads become planning-only once every handle over them is planned, so
LoadAddress emits nothing for them (SpirvMemoryInstructions.cpp:599-601).
The kept read would address a V# that only the snapshot holds. Allowing
those uses in this shape, where the second T#'s dwords 0 and 1 reach the
pointer registers on one edge before a later s_load, crashes lavapipe in
the dispatch. Taking it needs that V# kept alive for those reads: an
unrewritten copy of the handle and real loads of its words through the
record pointer.

Shape from hugodearaujo's IR on boykopovar#8939 (issuecomment-6340144242).
…d other instructions

Marvel's Spider-Man 2 (PPSA03016) still stops at pc 0x8fa0 with the
shared-V# planning alone: its shader moves dwords 0 and 1 of the second
T# read through the pointer-loaded V# into the record pointer's
registers, so those reads have Phi users. The nested branch of
TryMakeTableColumn refused that T#, and the first T# with it, because
the sibling handle's reads were not only descriptor words.

d132754 added the refusal after such a read crashed lavapipe: the
read stayed in the program but went through the V# handle that Run()
rewrites to the column offset and parent pointer words, while the V#'s
own word loads became planning-only and were not emitted, so it read a
garbage address. A planned nested child's T# or S# read with other
users now goes through an unrewritten copy of the V# GetBufferResource.
PlanTableColumnPass keeps a read real while any planned handle using it
has a use that stays real, so the V#'s four loads through the record
pointer are emitted for the copy, and the descriptor handles still take
the snapshot. No kept read goes through a rewritten handle, so the other
users read the guest's V# and descriptor words at dispatch.

The copy needs the V#'s words to be loads through the record pointer
that the program emits. Any other V#, and a data read through a handle
on the V#'s words, remain refused.

The shared-V# reuse test now checks both T#s per group and the word the
later s_load reads behind T#2's dwords 0 and 1, which the test backs
with a snapshot at that address. The T# and S# consumer cases that
d132754 refused now check the real descriptor word. A data read
through a third handle and a T# consumer whose V# comes from a keyed
table record stay refused.

Shape from hugodearaujo's IR on boykopovar#8939 (issuecomment-6340144242).
… the same buffer

Marvel's Spider-Man 2 (PPSA03016) on boykopovar#9790 stops at 135 s in compute
0x11e2b40f00 at ReadConstBuffer@pc=0x9a50, a T# read through a
pointer-loaded V# at (word >> 16) * 32, where the word is a data read
through the same V#, next to an S# read through that V#. hugodearaujo's
run: boykopovar#9790 (comment)

On boykopovar#9790 the T# plans as a nested child with an unkeyed domain, but
the S# is refused: the key read's handle shares the V#'s words with the
S#'s handle, and DescriptorWordReads takes only descriptor words, so the
S# falls to GetHandle and its dword 0 is not a valid runtime value.

A sibling read is now taken as a child key word when it is a scalar
read at an immediate offset through a rereadable V# and its uses only
reach the offsets of T# or S# reads through the same V#, as
scale * ((word >> s) & m) + c. The key read keeps its handle and the
V#'s loads, so the dispatch reads the guest's word. The T# or S# column
gets a child key domain (offset, shift, mask): the snapshot reads that
word from each child buffer and maps only the entry it selects.
possibleU32Bits follows a right shift by a constant, so the child table
spans at most min(num_records / stride, the key's range), 65,536
entries for a 16-bit field. A key the dispatch reads differently from
the snapshot faults outside the key domain, and a key past num_records
reads a null T#, as s_buffer_load_dwordx8 does past num_records.
A store through a handle on the V#'s words, keys from two words or from
a word at a runtime offset, and other data reads through the V# stay
refused.

KeyDomain gains child, shift and mask, so the shader disk cache format
moves to 50.

The test reads a key word at 0x14 and an S# at 0x20 of each child
buffer and checks keys 2, 5, 17, 30 and 47 (the last of the V#'s 48
T#s), both S#s, a moved record pointer, null T#s for keys 48 and 65535,
a fault for a key the dispatch reads differently from the snapshot, and
the refusals above.

This does not make the title pass: the same IR also merges the 0x4c0
T#'s dwords 0 and 1 into the record pointer, which stays refused here.
…ed V#'s record pointer

In hugodearaujo's IR for Marvel's Spider-Man 2 (PPSA03016), compute
0x11e2b40f00 reloads the V# at pc 0x9a3c through a record pointer whose
two words are Phis: record dwords 2 and 3 on most edges, and dwords 0
and 1 of the T# read at 0x4c0 through the same V# on the edge from
$353. boykopovar#9790 (comment)

The T# read at ReadConstBuffer@pc=0x9a50 through that V# is refused
with "GetImageResource dword 0 is not a valid runtime value", whatever
its offset: TryMakeIndirectColumn walked a merged V# pointer with
PointerRecordReads, which takes only the record read and constants on
the low word, and it needed the high word to be the record read itself.

A merged V# pointer now goes through PointerRecordPairs, the edge-paired
walk that a pointer-keyed T# already uses, and a word read as part of a
T# or S# is a pointer-free arm there, like a constant or a lane mask.
The child is looked up by the actual 64-bit pointer, so that arm, which
the snapshot never captures, faults outside the snapshot when a lane
takes it instead of reading a T#. The record reads on every edge must
still be one read per word for a V#.

The test samples the T# at 0x4c0, moves its dwords 0 and 1 into the
record pointer under a condition, reloads the V# behind that Phi, and
reads the key word, the T# at the key and the S# through it, as the IR
does. It checks the three reads per lane with the arm not taken, and a
group that takes the arm faulting outside the snapshot. That last run
replaces the key read with a constant: a data read through a V# loaded
from an unmapped pointer crashes lavapipe on boykopovar#9790 as well, as its
shared-V# reuse shader does with an unmapped record pointer.

On boykopovar#9790, and with the previous commit alone, the test is refused with
the text above. This does not claim the title passes.
Keeps this branch's FormatVersion above main's 45 (boykopovar#7831's barycentric bump).
A scalar memory load ignores the two low bits of its address. The
emitter cleared them in the offset and the immediate of an s_load
through an SGPR pair, but kept them in the 64-bit base, so a base whose
low word ends in 01, 10 or 11 read past the dword the hardware reads.
A record pointer taken from a T#'s first word therefore read up to
three bytes too far and faulted when those bytes were not mapped.

The base pair's low word is now cleared like the offset's. A read
through a user-data anchor translates from the cleared base, and
ImageTableAbi::ScalarAddressDword, which the materializer uses to read
the records behind such pointers and to plan their read ranges, clears
the base the same way. The SRT walker already did.

agc_driver_bda_anchor_reads runs two scalar loads through a user-data
base with low bits 01, 10 and 11, and the scalar address rule in
agc_shader_memory checks the same bases on the CPU. The pointer image
table case that expected a table base off a dword boundary to leave
every record unmapped now expects the records at its dword, the same
as the aligned base.
… every platform

The reuse case builds a record pointer from T#2's first word, the texel
address shifted right by 8, so its low two bits are bits 8 and 9 of
wherever the linker put the texel array: set on macOS, clear on Linux.
The texels now sit 0x100 and 0x300 bytes into a 1024-aligned array, so
the two T#s' first words end in 01 and 11 everywhere and the scalar load
through the pointer always has to ignore them.
@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Nov 3, 2026
@oneandonlydean oneandonlydean self-assigned this Nov 3, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head e358b7a merged onto main 1e65852 · tested 2026-11-03 19:36 UTC · 30 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,793 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,847 of 3,818 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 (958 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.4 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 536 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (536 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 528 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_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 e358b7af22d8023d10fa14f34710bcda0a30e89e 1e658521a0a599872612bb91949311e2956b5283
git checkout 1e658521a0a599872612bb91949311e2956b5283 && git merge --no-ff e358b7af22d8023d10fa14f34710bcda0a30e89e
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.

@hugodearaujo

hugodearaujo commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor Author

A note on the red windows check: the one failure is avplayer_http_patched_modules, in AvPlayerHttpModules.cmake:155, which couldn't copy its client avplayer_http_patched_modules_tests.exe because that executable wasn't built (No such file or directory (input)). This PR changes nothing in AvPlayer or the test runner. It's the selected-test build issue that #15375 describes and fixes, with the same failure on #14794's job. None of the other 3,118 selected Windows tests failed (some were skipped), and the NVIDIA run above passed (0 new failures, no new validation IDs).

@github-actions github-actions Bot added build shader core/shader docs agc libSceAgc* labels Nov 3, 2026
@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ AMD GPU test: passed

PR head e358b7a merged onto main 1e65852 · tested 2026-11-03 19:59 UTC · 39 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,778 passed · 10 failed (0 new, 9 also fail on main, 1 unstable on main) · 59 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,847 of 3,818 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 (958 tests run on the GPU)
Slow tests (>30 s, GPU tests timed with validation layers) ⚠️ agc_driver_pipeline_journal 120.4 s, ⚠️ public_headers 48.2 s, ⚠️ agc_driver_image_sample_unnormalized 43.9 s, ⚠️ agc_driver_stream_copy 38.4 s, ⚠️ agc_driver_lazy_resolved_abi 33.9 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 (9, not counted against this PR)
agc_driver_image_table
agc_driver_native_depth_bda_clear
agc_driver_native_multisample_depth
agc_driver_store_over_untracked
agc_driver_submit_progress
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 536 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (536 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 528 more
VUID-vkCmdCopyImage-srcImage-01548 (4 tests): agc_driver_depth_clear_hle, agc_driver_depth_storage_dispatch, agc_driver_depth_surface_from_storage, agc_driver_dispatch_move_depth
VUID-vkCmdCopyImage-srcImage-01551 (4 tests): agc_driver_depth_clear_hle, 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
Skipped (59)
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_host_import_sparse: skipped, host imports are unavailable: /dev/udmabuf is not accessible
agc_idle_publish_wait: skipped, the device reports 4 of 4 host-imported pages written after a GPU read, so a forced watch of the import reads its submissions as CPU stores
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_storage_pending_key_refresh: skipped, refreshes over a pending key store are not testable here
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 dr
Reproduce
git fetch origin e358b7af22d8023d10fa14f34710bcda0a30e89e 1e658521a0a599872612bb91949311e2956b5283
git checkout 1e658521a0a599872612bb91949311e2956b5283 && git merge --no-ff e358b7af22d8023d10fa14f34710bcda0a30e89e
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.

Reviewed — approved

The PR's own change, three commits on top of #9969's head 9e7ac69470, lets ChildKeyWord accept a key whose T# reads go through a sibling V# loaded through the same record pointer. It is narrowly scoped, it is covered by a test that fails without it, and its gaps are recorded in the debt file.

What I ran

Head e358b7af22d8023d10fa14f34710bcda0a30e89e, main 086c0686c8adff3ee648fdbe34e0b0b647e1d511, merged tree 814f9af6ef17ae7e33d8ac275e0069ffa2cc4d51. Machine: Debian 13 VM (32 vCPU Xeon Gold 6136), GCC 14.2.0, lavapipe (Mesa 26.1.6, LLVM 19).

git diff --check 086c0686c8adff3ee648fdbe34e0b0b647e1d511...e358b7af22d8023d10fa14f34710bcda0a30e89e
python3 tools/check_conventions.py --base 086c0686c8adff3ee648fdbe34e0b0b647e1d511
git diff 9e7ac694706c e358b7af22d8   # the PR's own three commits
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=error,warn,layer \
  ctest --test-dir build -j8 --test-load 32 --output-on-failure -R "agc_driver_(nested_image_table.*|nested_sampler_table|pointer_.*_table|image_table)$"
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=error,warn,layer \
  ctest --test-dir build -V -R "agc_driver_pointer_vsharp_(sibling|child)_key_table$"
# negative control (see below)
git diff 9e7ac694706c e358b7af22d8 -- core/shader/recompiler/Optimization/src/ResourceTracker.cpp | git apply -R
ninja -C build -j32 -l32 agc_driver_image_table_tests
ctest --test-dir build --output-on-failure -R "agc_driver_pointer_vsharp_(sibling|child)_key_table$"
# VUID origin check: every production file of the PR restored from main
ninja -C build -j32 -l32 agc_driver_image_gather_volume_tests
env VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation ANYPS5_NO_SHADER_CACHE=1 ANYPS5_REQUIRE_VULKAN=1 VK_LOADER_DEBUG=error,warn,layer \
  ctest --test-dir build -V -R "^agc_driver_image_gather_volume$"
# files restored from 814f9af6ef17, rebuilt, git status --porcelain empty

Results

Check Result
git diff --check clean
check_conventions.py All conventions checks passed
Configure / build / libs (script) passed
Script's selected test run (2261 tests) 0 new failures, 0 timeouts; 7 known failures also fail on main
21 focused image-table tests with the validation layer 21/21 passed, 0 VUID- lines, 0 "was not found but was requested"
agc_driver_pointer_vsharp_sibling_key_table passed in 0.66 s with the layer loaded
Validation comparison (script) one test with VUIDs not in the baseline: agc_driver_image_gather_volume (VUID-VkSamplerCreateInfo-addressModeU-01079 and -parameter). The test was not run on the baseline. It reports the same VUID with every production file of the PR restored from main, so it comes from main, not this PR. The diff doesn't touch sampler creation.
New test output (merged tree)
1852: pointer V# table with a T# array in one V# indexed by a word read from a sibling V# of the same record pointer: T#s read from the sibling V# at the key read through the first one, with the first one's S#, checked for several keys, the largest inside the sibling V#, keys past it and a moved record pointer
100% tests passed, 0 tests failed out of 2

Negative control

I reverse-applied only the PR's own ResourceTracker.cpp change, the diff from 9e7ac694706c to the head, to the merged tree and rebuilt agc_driver_image_table_tests. The new test then fails with the refusal the description quotes, and #9969's agc_driver_pointer_vsharp_child_key_table still passes:

Output without the change
1/2 Test #1850: agc_driver_pointer_vsharp_child_key_table .....   Passed    0.71 sec
2/2 Test #1852: agc_driver_pointer_vsharp_sibling_key_table ...***Failed    0.12 sec
ShaderRecompiler::Recompile: GetSamplerResource dword 0 is not a valid runtime value; chain: ReadConstBuffer@pc=0x000000c0(GetBufferResource(LoadAddressU32@pc=0x00000090(GetAddressResource(Phi(ReadConstBuffer@pc=0x00000074(...

After I restored the merged file and rebuilt, the test passes again and git status --porcelain is empty.

Findings

Blocking

None.

Non-blocking

  • Unblocks: line has no Game bring-up discussion. The line names PPSA03016 but not its Game bring-up discussion. CONTRIBUTING.md asks for both (Unblocks: PPSA01325 #3232). Suggested fix: add the PPSA03016 discussion number.

Notes on the code, which need no change:

  • SiblingVsharp (ResourceTracker.cpp#L2408-L2422) needs all eight words of the two V#s to be LoadAddressU32 from one, or an equivalent, GetAddressResource.
  • Only DescriptorWordReads passes siblings = true (line 864), and only on its rereadable path. So the key stays the guest's value at dispatch, as the description says.
  • The sibling's T# column is still planned on its own through MatchKeyDomain, because MatchChildKey still requires the same handle. If the sibling can't be planned, the shader is still refused.
  • The debt entry in docs/dev/debt/shader.md states the gap first: the column is not narrowed, and the other forms stay refused.
  • The test's decoy key and swapped S# in the sibling's buffer would catch A's words being read from B.

Not verified

  • Hardware GPUs: I ran only on lavapipe. The author reports RADV RX 9070 XT, and the NVIDIA and AMD CI comments on this head report 0 new failures and no new validation IDs.
  • The title (PPSA03016): I did not launch it.
  • The rest of #9969's chain, which this diff also shows against main. I reviewed only this PR's three commits on top of 9e7ac69470. The chain's tests ran in the script's selection and in the 21 focused tests above.
  • The memory cost of an unnarrowed sibling column. It can bind up to 65,536 entries per distinct child V# within the existing inner key-slot budget. No test covers a large sibling num_records.

@hugodearaujo

Copy link
Copy Markdown
Contributor Author

@XairRrR thanks for the review and the negative control. I added the bring-up discussion to the checklist: Unblocks: PPSA03016 #10195.

@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.
…sharp-reuse

6e403b4 is boykopovar#9457 with the stack's merges of boykopovar#7395's main merge after
boykopovar#7223. FormatVersion stays this branch's 71. In the debt file, boykopovar#7395 adds
a sentence on nested children's registered views to "Nested image
tables", which this branch rewrites. The entry keeps this branch's wording,
and the sentence moves into its own entry after it, since both together
are over the debt files' 1000 characters.
b41beed is boykopovar#9790 with the stack's merges of boykopovar#7395's main merge after
boykopovar#7223. FormatVersion stays this branch's 73, and the debt file keeps this
branch's three entries, with boykopovar#7395's "Nested image table children" entry
added after "Nested image tables".
@hugodearaujo
hugodearaujo force-pushed the fix/shader-nested-sibling-vsharp-key branch from e358b7a to 34213d6 Compare November 4, 2026 13:48
@hugodearaujo

Copy link
Copy Markdown
Contributor Author

Rebased onto #9969's new head c147aa8647, after the chain was rebased on main, and force-pushed (34213d649f). The three commits applied unchanged. On the new base, with the validation layer: with ResourceTracker.cpp from c147aa8647, 20 of the 21 image-table tests pass and the new test fails with the title's refusal; with this change, 21 of 21, with no VUID- line. The 57 ^shader|^agc_shader tests pass. The description now names the new base.

@TechLevelZero

Copy link
Copy Markdown
Contributor

✅ NVIDIA GPU test: passed

PR head 34213d6 merged onto main b11c7bf · tested 2026-11-04 14:37 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,879 passed · 7 failed (0 new, 3 also fail on main, 4 unstable on main) · 49 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,935 of 3,894 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 (1000 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 558 tests)
VUID-VkDeviceCreateInfo-pNext-pNext (558 tests): agc_driver, agc_driver_address_draw_space_reuse, agc_driver_address_passes, agc_driver_alias_copy_label, agc_driver_alpha_to_coverage, agc_driver_array_layer_target, agc_driver_bc_block_copy, agc_driver_bda_anchor_reads, and 550 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 (49)
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_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 av
Reproduce
git fetch origin 34213d649f9b6824cae89cde5061d7a6d1a448ae b11c7bf84f5d2f636ff60166cc3371bd071e24d5
git checkout b11c7bf84f5d2f636ff60166cc3371bd071e24d5 && git merge --no-ff 34213d649f9b6824cae89cde5061d7a6d1a448ae
git submodule update --init --recursive
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON
cmake --build build && cmake --build build --target libs
VK_DRIVER_FILES=/nonexistent/icd.json ctest --test-dir build -E '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 32 --output-on-failure
ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1 VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation \
  ctest --test-dir build -R '^(agc|shader|recompiler|videoout|video_out|guest_video_out|vulkan)|gpu' --timeout 120 --parallel 4 --output-on-failure
# failures are then re-run alone: --timeout 360 --parallel 2; new validation IDs: the test alone, twice, --parallel 1

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

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

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.

5 participants