Skip to content

feat(agc): implement image tables loaded through 64-bit pointers - #758

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
Celegans12:feat/agc-image-tables-global
Oct 14, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
Celegans12:feat/agc-image-tables-global

Conversation

@Celegans12

@Celegans12 Celegans12 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

What

Stacked on #757; please review the last commit only.

Image and sampler descriptors loaded by s_load at runtime offsets through a 64-bit pointer still fail planning. This enumerates offsets from an independently resolvable base, preserving registration-time compilation and keeping invocation data out of shader and pipeline keys.

Consecutive descriptor reads must share one heap/address handle and an affine offset. Alignment, signed immediates and bounded keys are preserved; invalid, unmapped or overflowing selected entries fault. Each table records its consumed descriptor spans, read in runs like #757's buffer tables. Overlapping buffer or storage-image writes poison that table, while gaps and unrelated tables remain usable.

Pointer columns share #757's column rules: reads with the same access shape share one column, whose key bound is the widest of their keys and whose stored plan keeps the pointer flag and bound. Records that hold a pointer to the T#, and a T# split over two loads of its record, are not planned here; #4475 (stacked on this) adds both. #5466 needs a table-aware rule when it meets this, which its author described there. Persisted invocation ranges advance disk format 32 to 33; runtime ABI 12 is unchanged.

Tested

Based on main 066b58f with #757. Windows 11 (MinGW-w64 GCC 15.2.0) and Linux: configure -DBUILD_TESTING=ON, full build, --target libs, ctest.

  • Windows, NVIDIA: 1188/1189 tests pass; log_macros also fails on main here.
  • Linux (upstream's job on WSL, lavapipe), merged with main 84b01f9: 1171/1173; agc_driver_bc_block_copy and agc_driver_depth_compare_copy also fail on main there.

The pointer cases in agc_driver_image_table (masked keys, null and invalid entries, key cap, unmapped entries, overlapping storage writes, two-table isolation), agc_shader_memory and agc_shader_disk_cache (a pointer table's plan round trips) pass on both; they fail to build without this commit. Windows ran counted reuse with write watch; WSL skips it and the two subgroup-32 per-wave cases.

Not tested: graphics-stage pointer tables, native RADV, console behaviour.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: feat(agc): implement image and sampler tables indexed at runtime offsets #757
  • Unblocks: PPSA26344 Ghost of Yōtei (PPSA26344) #675
  • GPUs tested: NVIDIA GeForce RTX 3080 Laptop GPU, driver 610.62, Windows 11; llvmpipe (Mesa 25.2.8), WSL Ubuntu 24.04
  • AI-assisted: yes

@github-actions github-actions Bot added build shader core/shader docs agc libSceAgc* labels Oct 5, 2026
@Celegans12
Celegans12 force-pushed the feat/agc-image-tables-global branch from b7993a2 to 5b655e5 Compare October 6, 2026 00:19
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 6, 2026
@Celegans12
Celegans12 force-pushed the feat/agc-image-tables-global branch from 5b655e5 to 68e13e7 Compare October 6, 2026 02:50
@Celegans12

Copy link
Copy Markdown
Contributor Author

The Linux failure here (agc_driver_flat_store timing out at 120 s) is the llvmpipe slowdown from #757 that I reported in this comment. The fix is in progress on #757, and this branch will be restacked onto it.

RINNECODER added a commit to RINNECODER/AnyPS5 that referenced this pull request Oct 14, 2026
* fix(shader): plan a table T# that several image operations share

TryMakeTableImage planned a T# read from a bindless image table only when
its eight scalar reads had no user other than that one GetImageResource.
Descriptor-phi splitting gives each image operation its own copy of the
T# over the same reads, so a table entry that is both queried and sampled
was refused, and GetHandle then rejected the scalar reads.

Accept reads whose every user is a GetImageResource built from exactly
those eight reads; each copy is planned as the same table.

A shipped title stops on such a shader at start-up:
image_get_resinfo and image_sample_lz on one s_buffer_load_dwordx8 T#.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit e015772)

* test(shader): check that a queried and sampled table T# is one image

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit cd1757e)

* test(shader): check uniform table images after the descriptor phis

boykopovar#757 and boykopovar#758 add their image table checks where this check was, after
verifyBindlessTable, so the pull requests conflicted.

(cherry picked from commit e092d2a)

* feat(recompiler): reuse pure IR values recomputed in dominated blocks

The front end rebuilds operand flushes, NaN checks and bitcasts for every
use of a register, and nothing merged them when SPIRV-Tools is off. A
dominator-scoped value numbering pass before SPIR-V emission replaces a
pure value with an earlier identical one in the same or a dominating
block. Only operations that are functions of their operands are merged;
loads, stores, atomics, barriers, phis and cross-lane reads are left
alone. A block the entry does not reach throws.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit f0f920a)

* fix(shader): size per-invocation LDS by the append counter's offset

FunctionLdsDwords bounds every LDS access by its address argument and
gives up on opcodes without a dword count. DataAppend and DataConsume
have neither: their first argument is M0, which only places GDS
counters, and the emitter addresses the LDS counter by the instruction
offset alone. Any pixel or vertex-path program with ds_append or
ds_consume therefore declared the full 8192-dword Function array per
invocation. LLVM 20 llvmpipe needs about 6 s to compile that array in
the new pixel LDS read-modify-write test, which ran past the 5 s
graphics fence on CI. The counter now takes the dword at its offset.

(cherry picked from commit 13cc3a9)

* fix(shader): record BDA faults in hull programs instead of refusing them

Every hull program with a BDA access was refused with "BDA fault
termination requires a barrier-safe tessellation-control execution
protocol". The refusal predates BdaInvocationsMayStop: a program with
s_barrier no longer stops a faulting invocation; the fault is recorded,
the read returns zero and every invocation reaches the barrier. In a
hull, s_barrier is the only control barrier the backend emits after the
guest code starts, so that rule already covers it, and a hull without
one can stop an invocation without stranding a barrier.

The tessellation test draws hulls that scale their levels by a BDA read,
with and without s_barrier, and requires an unmapped read to report a
tessellation-control fault (not on llvmpipe, which runs hull loads that
the unmapped-address check skips). The contract test now accepts a hull
with s_barrier.

(cherry picked from commit c1e4a0b)

* fix(shader): normalize reserved buffer bits before scalar binding

(cherry picked from commit bfab566)

---------

Co-authored-by: milescoviello <kitslayer29@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Yunus Shaikh <75296019+EagleBearerYS@users.noreply.github.com>
Co-authored-by: fdfawef324 <287205748+fdfawef324@users.noreply.github.com>
Co-authored-by: Dean Galvin <dean.galvin@live.com>
Co-authored-by: Celegans12 <53881228+Celegans12@users.noreply.github.com>
Co-authored-by: eljackjoestar-cmd <eljackjoestar@gmail.com>
Materialize runtime-indexed image and sampler records into descriptor
tables while keeping descriptor selection in the shader. Report invalid
active entries through the existing deferred fault buffer.

Bind fragment tables in the fragment set when pipeline libraries split it,
and reserve a physical descriptor for empty tables. Reject unsupported
sampler, border, cube and anisotropic pairings per entry. Keep one column
per heap access shape, one T# shared by several image operations included
(milescoviello's boykopovar#5550 case), and narrow it to the union of its keys'
domains when every key has one (SleglJan's key-domain changes). Plan
columns read at (key << n) & mask over their whole domain (tibzejoker's
fix). Read records in runs through SleglJan's bulk reader, and reject
entries whose surface has no mapped byte, as Tamalero proposed. Store
table columns in disk plans; update the runtime ABI and disk format. Bound
table-sized entries in the resource cache (65,536 table elements) and the
dispatch cache (256 MiB of captured words), evicting LRU.
Plan runtime-indexed T# and S# columns read through a 64-bit pointer.
Preserve the console offset alignment, signed immediate and key bounds.
Track the descriptor dwords consumed by each table in its invocation.
Reject table reads when a writable buffer or storage image overlaps them.
Cover the overlapping-storage fault and isolated second-table behavior.
@Celegans12
Celegans12 force-pushed the feat/agc-image-tables-global branch from a5c63d5 to 34525fd Compare October 14, 2026 15:14
@Celegans12

Copy link
Copy Markdown
Contributor Author

I've restacked this on #757's new head d9e47d1 (rebased onto main 066b58f), so the head is now 34525fd. Its own diff hasn't changed, and the disk format is still 33. On this head, Windows NVIDIA passes 1,188 of 1,189 tests, and upstream's Linux job merged with main 84b01f9 passes 1,171 of 1,173; the failures there (log_macros, agc_driver_bc_block_copy, agc_driver_depth_compare_copy) are the same ones main has.

@adriadam10 adriadam10 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Stacked on #757, reviewed together: see the review there (#758 head 34525fd merged with #757 onto main 84b01f9, Linux RADV 572/573, the one failure also fails on main). The pointer cases in agc_driver_image_table, agc_shader_memory and agc_shader_disk_cache pass. Approving; it goes in after #757, each with the full Build dispatched on its final head.

@adriadam10
adriadam10 merged commit e34c479 into boykopovar:main Oct 14, 2026
8 of 9 checks passed
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants