Skip to content

feat(agc): implement image_load through image tables - #920

Closed
Celegans12 wants to merge 3 commits into
boykopovar:mainfrom
Celegans12:feat/agc-image-table-image-load
Closed

Celegans12 wants to merge 3 commits into
boykopovar:mainfrom
Celegans12:feat/agc-image-table-image-load

Conversation

@Celegans12

@Celegans12 Celegans12 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

What

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

image_load through a V# or pointer image table throws at planning (image table: ImageRead ... only samples, gathers and queries can); #5's bindless tables accepted it and #757 dropped it.

Tested

  • Windows 11, MinGW-w64 GCC 15.2.0, based on main b3fcd6d with feat(agc): implement image and sampler tables indexed at runtime offsets #757 and feat(agc): implement image tables loaded through 64-bit pointers #758: configure -DBUILD_TESTING=ON, full build, --target libs, ctest:
  • 455/455 tests pass (ctest --output-on-failure)
  • Same build on lavapipe (Mesa 26.2.4 llvmpipe, 8-wide subgroups, VK_DRIVER_FILES): 454/454 pass; agc_driver_flat_store is left out there because it takes several minutes on Windows llvmpipe
  • agc_driver_image_table (GPU) matches table image_loads to direct ones (V# and pointer tables, Float/Uint/Sint, d16), reads per-wave keys on 32-lane subgroups, and checks null, invalid and EXEC-cleared entries; agc_shader_memory plans key * 16 + 8. Both throw without this commit; on main their shaders fail to plan. They pass with -DANYPS5_ENABLE_SPIRV_TOOLS=ON.
  • PPSA26344 v1.008: not run with this commit.
  • Not tested: graphics-stage table reads, PPSA21564 and Dreaming Sarah, Linux (CI), 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 in TechnicalDebt
  • 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 tables loaded through 64-bit pointers #758
  • AI-assisted: yes

@github-actions

github-actions Bot commented Oct 6, 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
#940 core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp L627-629, L968-971
#1074 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L197, L2458
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp L137
core/libs/prx/libSceAgcDriver/Graphics/include/Pipeline.hpp L92
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp L521
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderValidation.cpp L126, L495, L511
#1077 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L197, L2458
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp L137
core/libs/prx/libSceAgcDriver/Graphics/include/Pipeline.hpp L92
core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp L521
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderValidation.cpp L126, L256, L495, L511
#1184 core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp L170-173, L353-355
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L200-249, L276-281, L283-295, L302-308, L379-392, L394-405, L407-408
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/Resources.hpp L82-85
core/shader/recompiler/Optimization/include/Optimization/ResourceMaterializer.hpp L27-29, L60-62
core/shader/recompiler/Optimization/src/BindingAllocator.cpp L128-129, L131-144, L167-171
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp L240-246, L273-279, L283-286, L298, L357-383, L385-392, L394-396, L398-400, L402-404, L406-417, L419-431, L467-470, L474-489, L626-631, L634-651, L703-705, L713-722, L857-870, L1024-1036, L1042
core/shader/recompiler/Optimization/src/ResourceTracker.cpp L304-345, L409-410, L413-421, L423-424
core/shader/recompiler/ShaderDiskCache.cpp L73-75, L83, L422-425, L515-518, L823-825
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp L1007-1045, L1269-1270
#1191 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp L90-108
#1193 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp L90-108
core/shader/recompiler/Optimization/include/Optimization/ResourceMaterializer.hpp L59-62
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp L456-457, L989-990, L1000-1001, L1017, L1023-1036
#1201 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp L90-108
core/shader/recompiler/Optimization/include/Optimization/ResourceMaterializer.hpp L59-62
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp L456-457, L989-990, L1000-1001, L1017, L1023-1036
#1202 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp L10-11, L90-108
core/shader/recompiler/CMakeLists.txt L211
core/shader/recompiler/Optimization/include/Optimization/ResourceMaterializer.hpp L59-62
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp L456-457, L989-990, L1000-1001, L1017, L1023-1036
#1219 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawCapture.cpp L5, L10-11
core/libs/prx/libSceAgcDriver/Execution/src/ShaderMemory.cpp L227-228
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L2458, L3301-3303, L3617
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp L137
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L977-979, L2106-2107, L2646-2652
core/libs/prx/libSceAgcDriver/tests/ShaderDiskCache.cpp L169-176, L233-235, L344-360
core/libs/prx/libSceAgcDriver/tests/ShaderMemory.cpp L200-249, L256-257, L276-281, L283-295, L297-299, L302-308, L344-346, L351-377, L379-392, L394-405, L407-408
core/shader/recompiler/BdaAbi.hpp L30
core/shader/recompiler/IntermediateRepresentation/include/IntermediateRepresentation/IrMetadata/DescriptorBinding.hpp L16-25
core/shader/recompiler/Optimization/include/Optimization/ResourceMaterializer.hpp L11-52, L60-62
core/shader/recompiler/Optimization/src/BindingAllocator.cpp L152-155
core/shader/recompiler/Optimization/src/DescriptorBindingBuilder.cpp L1-2, L134-158, L208, L223-224, L243-271, L351-359
core/shader/recompiler/Optimization/src/ResourceMaterializer.cpp L5, L162-164, L203-207, L209-211, L273-279, L301-320, L326-355, L363-404, L406-407, L409-431, L467-468, L474-489, L535, L575-597, L599-631, L634-657, L667-742, L767-774, L787-831, L835-877, L883-885, L1013, L1016-1017, L1024-1048
core/shader/recompiler/Recompiler.cpp L349-350, L387-391, L537-538
core/shader/recompiler/ShaderDiskCache.cpp L66-68, L70-75, L81-83, L422-426, L492, L515-520, L811-834
core/shader/recompiler/ShaderDiskCache.hpp L15
core/shader/recompiler/SpirvBackend/include/SpirvBackend/SpirvMemory/SpirvDescriptors.hpp L16-17
core/shader/recompiler/SpirvBackend/src/SpirvImageEmitter.cpp L1007-1045, L1052-1053, L1159-1161
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvDescriptors.cpp L5, L55-60, L68-71, L140-141, L153-160, L177-179
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvEmitterHelpers.cpp L0-1, L135-187
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvMemoryInstructions.cpp L1427-1461

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 7, 2026
@Celegans12
Celegans12 force-pushed the feat/agc-image-table-image-load branch from d0520ff to 971bfe0 Compare October 7, 2026 11:08
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 7, 2026
A T# or S# that s_buffer_load reads at key * stride + addend from a
record-time V# was not planned unless it was an r256 T# at key * 32,
and bindless entries that could not be bound sampled zeros.

Such reads are now table columns: each record the offset can reach is
snapshotted at record time, decoded like a direct T# or S# and bound
through runtime descriptor arrays and an offset-to-entry map. An entry
that cannot be bound exactly, such as a min or max S# or an sRGB T# the
shader would have to decode, samples zeros and, if an executing lane
selects it, raises a BDA fault that fails the dispatch. Results with
unmapped records stay out of the dispatch and draw caches. Uint images,
direct or in a table, now sample through the point-filtered S# copy main
gives Sint images, as Vulkan leaves linear filtering of integer formats
undefined. Bindless slots and APS5_BINDLESS_SLOTS are removed, image
samples, gathers and queries carry EXEC, compute pipeline keys include
table sizes and the shader disk cache format becomes 10.
A T# or S# that s_load reads through a 64-bit pointer at a runtime
key * stride + addend offset failed to plan ("GetImageResource dword 0
is not a valid runtime value"). Such loads now form image table
columns when the pointer is known at record time (user data or an SRT
read); a descriptor whose offset is known at record time too stays a
direct binding. The snapshot follows the BDA rule of scalar loads: the
pointer plus the dword-aligned offset and immediate, where a wrapping,
unaligned or unmapped dword makes the entry invalid. It holds the keys
the key's known bits allow (key & 0xff gives 256), else the first
65536; a key past them faults as outside the snapshot when a lane
selects it, because the console would read memory there, not zeros.
Image tables accepted only samples, gathers and queries for a T# read
from a table column, so an image_load through a V# or pointer table
threw at planning ("only samples, gathers and queries can").

The planner now also accepts ImageRead in a table column. The direct
path's EXEC-guarded OpImageFetch becomes ReadValue, which the table
emitter's Float/Uint/Sint switch calls like the sampling ops, so a table
read uses the same sampled-image views, unpacking and per-entry fault.
Packed (_pck) loads, stores and atomics through a table still throw, as
do MSAA and 1D-array dimensions.

Tests: agc_driver_image_table matches V# and pointer table reads (r128
and r256, d16 dmask 0x3) to direct image_loads, reads per-wave keys on
32-lane subgroups and checks null, invalid and EXEC-cleared entries;
agc_shader_memory plans an image_load at key * 16 + 8.
@Celegans12
Celegans12 force-pushed the feat/agc-image-table-image-load branch from 6e5a765 to fd758c0 Compare October 8, 2026 14:52
@github-actions github-actions Bot added needs rebase Conflicts with main, rebase needed and removed needs rebase Conflicts with main, rebase needed labels Oct 8, 2026
@Celegans12

Copy link
Copy Markdown
Contributor Author

Closing this. As boykopovar asked after #639, image_load through image tables is now part of #757 (3b752dc), which replaces the bindless path while keeping image_load working. This PR's tests moved there too.

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

Labels

agc libSceAgc* build docs needs rebase Conflicts with main, rebase needed shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant