Skip to content

fix(agc): find a template's data bindings by binding number - #9564

Merged
adriadam10 merged 3 commits into
boykopovar:mainfrom
EagleBearerYS:port/fable-fix-template-bindings
Oct 25, 2026
Merged

adriadam10 merged 3 commits into
boykopovar:mainfrom
EagleBearerYS:port/fable-fix-template-bindings

Conversation

@EagleBearerYS

@EagleBearerYS EagleBearerYS commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

What

A resource template keeps no binding of its own for an image table: the build hands the shader's image table binding to the table stage. So its binding list is one shorter than the shader's. Yet DataWordsDiffer and refreshData paired the two lists by index and required equal lengths. Every data refresh of a compute template whose shader reads an image table threw "template bindings disagree with the shader". DataWordsDiffer also reported different words for the very shader the template was built from.

This is fable-void's 7bb699b from his fork (wip/new-gpu-path), with his authorship:

  • a00adaa (fable-void): both functions look up the template binding of each data binding by its binding number. His test was adapted to main's image table ABI: its header no longer sets HeaderImageSlots, which main doesn't have, and its mock context gets the image table limits main's imageTableAllocationTests sets.
  • 55e9345 (counter): with APS5_PROFILE_DRAW set, the [rescache] line also counts the template hits refreshed while the template held fewer bindings than the shader, N paired their data bindings by number (no image table binding of their own). Without the profile it costs one test of a static const bool.

fable-void's evidence, from his commit: a title stopped, once its pipelines came from the cache, with "compute shader 0x80003c7100: AGC graphics: template bindings disagree with the shader". The shader listed 9 bindings (guest buffers, three guest image arrays, the fault buffer, the flattened SRT, the sampler table, the image table map, and the image table at 260). The reused template held 8, without binding 260. No open issue carries that text.

Overlap: checked with git merge-tree against every open PR touching these files, on main df2569d. One conflicts:

Tested

  • Red/green on GitHub's Linux and Windows runners (run). agc_driver_graphics builds a compute template from an image table map, an empty image table and shader data, on its mock Vulkan device. It checks that the template's own words compare equal, refreshes it with other words, then checks the data buffer and the compare.
    • Red: with main's code, it fails ×3 on both runners, with "a template's own words differ from the shader that built it". agc_driver_graphics_maps_fallback, the same executable under the maps fallback, fails with it on Linux.
    • Green: it passes ×10 on both, and so do the other 27-28 tests of the changed executables.
    • The libc and libkernel suites pass on Windows. On Linux, libkernel's passes, and libc's has one failure in the green tree, precise_wait, a timing test that flakes on that runner.
  • Linux, whole tree: both commits are part of a port of twelve of fable-void's fixes, mirrored as CI's Linux job on main cf2c667: 1812/1818, with the same 6 failures as main.
  • Validation layer, main against this PR (CONTRIBUTING's AGC rule), on one GitHub Linux runner (run). Both runs used VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1 and ctest -V, with VK_LOADER_DEBUG=layer to show the layer loading. The device was llvmpipe (LLVM 20.1.2) on Mesa 25.2.8, Ubuntu 24.04.5, Khronos validation layers 1.3.275.
    • This PR's own case runs in agc_driver_graphics on the mock device and creates no Vulkan instance, so the comparison adds real-device tests that reuse a cached draw or dispatch with new data, the RefreshData and DataWordsHash path this PR changes: agc_driver_draw_cache_reuse, agc_driver_draw_cache_reuse_verify, agc_driver_draw_data_hit_user_words, agc_driver_draw_data_hit_user_words_verify, agc_driver_image_table_reuse and agc_driver_buffer_load_store. With the tests whose build inputs this PR touches, that's 35 on each side; main's tree ran them once and this PR's three times.
    • The loader inserted VK_LAYER_KHRONOS_validation 10 times on main and 30 with this PR, and neither log has was not found but was requested by env var VK_INSTANCE_LAYERS.
    • Both logs report the same single message, VUID-VkDeviceCreateInfo-pNext-pNext, for a device-creation structure newer than that layer version. This PR adds no VUID- message.
  • 9cad161, main b7d1d47 merged in (clean; the PR's own diff is unchanged), on GitHub's runners (run):
    • Green: agc_driver_graphics and the other tests pass 10 of 10 on Linux, none skipped. On Windows all 34 build and pass, with 6 skipping without a Vulkan device.
    • Red: on Windows, agc_driver_graphics fails with main's implementation. On Linux this run was in validation mode, whose main arm builds main's whole tree, tests included, so it runs main's agc_driver_graphics without this PR's new case. The Linux red is from the first run.
    • Validation, main against this head, on the Linux runner: the loader inserted VK_LAYER_KHRONOS_validation 10 times on main and 100 with this PR, and neither log has was not found. Both logs report only VUID-VkDeviceCreateInfo-pNext-pNext, so this PR adds no VUID- message.
    • Suites: libc and libkernel pass on both runners. The libc and libkernel suites ran with APS5_SKIP_TIMING_TESTS=1, which relaxes precise_wait's median bounds on GitHub's hosted runners.
  • check_conventions.py passes, with no comment lines added.
  • Not tested: a title. No title we run stops on this text. In Resident Evil Village (PPSA01556), 5 minutes at the static main menu, on the RTX 3070 Laptop GPU (NVIDIA 617.42, Windows 11), on a local tree with this PR and our other two ports of fable-void's shared fixes, with APS5_PROFILE_DRAW=1; no fatal error, [rescache] reports 0 paired their data bindings by number (no image table binding of their own), so this title doesn't reach the case either.

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: none (no order with perf(agc): GPU descriptor heap on VK_EXT_descriptor_heap (APS5_GPU_HEAP) #9508, agreed in its thread; see Overlap)
  • Fixes: none
  • Unblocks: none
  • GPUs tested: the test runs on agc_driver_graphics's mock Vulkan device, on GitHub's Linux (Ubuntu 24.04) and Windows runners; the validation comparison ran on Mesa llvmpipe (LLVM 20.1.2, Mesa 25.2.8), Ubuntu 24.04.5, GitHub's Linux runner.
  • AI-assisted: yes

fable-void and others added 2 commits October 21, 2026 18:39
A resource template keeps no binding of its own for an image table: the
build hands the shader's image table binding to the table stage. Its
binding list is therefore one shorter than the shader's, yet
DataWordsDiffer and refreshData paired the two lists by index and
required equal lengths. Every data refresh of a compute template whose
shader reads an image table threw "template bindings disagree with the
shader", and DataWordsDiffer reported different words for the shader the
template was built from.

Evidence: a title stopped once its pipelines came from the cache with
"compute shader 0x80003c7100: AGC graphics: template bindings disagree
with the shader". The shader listed 9 bindings (guest buffers, three
guest image arrays, the fault buffer, the flattened SRT, the sampler
table, the image table map and the image table at 260); the reused
template held 8, without binding 260.

Both functions now look up the template binding of each data binding by
its binding number.

Tested: agc_driver_graphics builds a compute template from an image
table map, an empty image table and shader data, checks that its own
words compare equal, refreshes it with other words, and checks the data
buffer and the compare afterwards. Without the change it fails with "a
template's own words differ from the shader that built it".

Cherry-picked from fable-void's 7bb699b; conflict in tests/Graphics.cpp resolved to main's image table ABI: the test's header no longer sets HeaderImageSlots, a word main's ABI does not have (main keeps HeaderElementBase at that index), and its mock context gets the image table limits main's imageTableAllocationTests sets (image table capacity and sampled images per set and per stage, 2 each), since main refuses image tables on a context without them.
With APS5_PROFILE_DRAW set, the [rescache] line now counts the template
hits that took a data refresh while the template held fewer bindings
than the shader (no image table binding of its own): the refreshes that
threw "template bindings disagree with the shader" before the bindings
were paired by binding number.
@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 9508 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp L4499-4501, L4524-4526, L4531-4532

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 1395 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 2434 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5021 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5441 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5925 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6192 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6194 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6202 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6223 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6235 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6280 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6412 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6804 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6808 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6960 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6977 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7201 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7256 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7275 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7689 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 7844 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8014 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8246 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8874 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8998 core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9335 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9400 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9431 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9432 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9489 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9592 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9672 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9673 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9674 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 9675 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9676 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9700 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9842 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9891 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9892 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9893 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9895 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9897 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9898 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 10046 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10049 core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
PR 10435 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10442 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/ShaderResources.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp

@MarcZX10

Copy link
Copy Markdown
Contributor

Early review feedback while this remains a draft: the focused test exercises the image-table binding-count mismatch and verifies both the template’s own data words and refreshed dispatch words. Before marking it ready, please coordinate the shared DataWordsDiffer/refreshData changes with #9508’s author and record an agreed merge order; add Depends on if one must land first. The described composition should preserve #9508’s DrawGuestWords source while looking up the held binding by binding number. The repo’s AGC rule also requires a focused same-machine, same-GPU main/change run with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and the Khronos validation layer, confirming the layer loaded and comparing VUIDs. The current mock Vulkan CI evidence is useful for the regression but does not supply that paired validation report. I did not run tests locally.

@MarcZX10 MarcZX10 left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The binding-by-number fix addresses the real image-table template shape: the table binding is consumed by the table stage, so data bindings can no longer be paired safely by vector index. DataWordsDiffer and refreshData now locate each data binding by layout.binding; refresh still validates the single held allocation, size, and shader-data runtime constraints. The regression creates a shader with an image-table map, an empty image table, and shader data, then checks the template's own words, changed words, the refreshed buffer, and the post-refresh comparison. I found no correctness issue in the reviewed change. The hosted Linux/Windows red/green runs include 10 repeats of the focused graphics test and changed executables; the PR also reports the required same-runner Khronos validation comparison with the layer confirmed loaded and no new VUIDs. Hosted eligibility, intake, labels, report and conventions pass; product Linux/Windows and relinker jobs are skipped. I could not run another local build because the workspace filesystem is full, so these are author-reported CI results, not local runs. The branch is 2 ahead / 116 behind current main (94fbb8cea merge base), cleanly mergeable; please refresh before merge. Current main conventions and git diff --check pass. I checked #9508's current branch: it adds DrawGuestWords for descriptor word access, and the authors agree either merge order is fine. This PR's binding-number lookup should be retained together with that source-of-words change when #9508 is integrated; it is not currently in this branch's ancestry. The automated overlap report is partial because many old PR comparisons are uncomparable against main, and it lists the shared files; no competing implementation of this specific image-table refresh fix was found. Approval is for this reviewed head only.

I’ve noticed that holding this PR because of #5239 isn’t necessary. It’s fine for PRs to keep coming in; they’ll be handled in due course. Please disregard my earlier request to hold or defer it.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The binding-number lookup is the right fix for the shorter template binding list, and the reports exercise both DataWordsDiffer and refreshData. The Windows/Linux red/green runs, repeated focused tests, and paired validation-layer run are strong evidence; hosted checks show conventions/eligibility/intake/labels/report pass while product and relinker jobs are skipped. I did not run a local GPU build.

I refreshed current upstream/main to 329efe1bfdaff116c57cdf62718026ee4f5521ae. This head is 2 ahead / 161 behind (merge base 94fbb8cea80af91db62ab6ee7e4da23341675c40). Current-base merge-tree and conventions pass, and git diff --check passes, but main has since changed ShaderResources.cpp and related AGC paths, including HTILE and image-format handling. Please rebase onto current main and rerun the focused template-refresh test plus the relevant paired Vulkan validation selection on the refreshed tree before merge.

#9508 remains open at 9f5e875b95d6a5bbee580b03b36ed7773fd80aa0; pairwise merge-tree currently conflicts in Graphics/src/ShaderResources.cpp. Your description records the author agreement that either can land first and preserves DrawGuestWords with binding-number lookup. Keep that agreed no-wait resolution and both behaviors when integrating; there is no duplicate implementation of this precise binding-index fix.

@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

Thanks, @MarcZX10. main at b7d1d47 is now merged in (9cad161), and the PR's own diff is unchanged. On GitHub's runners (run), the template-refresh test agc_driver_graphics passes 10 of 10 on Linux and Windows, along with the cached draw and dispatch tests from the earlier validation selection, and it fails on Windows with main's implementation. The same run compares main with this head under the validation layer on Linux: the layer loads in both, and both logs report only VUID-VkDeviceCreateInfo-pNext-pNext. It's in Tested. With #9508, the agreed composition stands: either can land first, keeping DrawGuestWords with the binding-number lookup.

@MarcZX10

Copy link
Copy Markdown
Contributor

I’ve noticed that my earlier request to hold this PR based on #5239 was unnecessary. It’s fine to keep submitting PRs; maintainers will handle them in due course. Please disregard that request.

@EagleBearerYS
EagleBearerYS marked this pull request as ready for review October 23, 2026 08:32
@adriadam10 adriadam10 self-assigned this Oct 23, 2026
@EagleBearerYS

Copy link
Copy Markdown
Contributor Author

@MarcZX10 9cad161 merged main b7d1d47 and reran the template-refresh and validation selection (run). Could you re-review?

@adriadam10
adriadam10 dismissed MarcZX10’s stale review October 24, 2026 10:21

Dismissing a stale review: the requested changes were addressed after it (new head and/or updated description with the asked-for runs) and the merge queue blocks on it. Please request changes again if anything is still open.

@adriadam10
adriadam10 merged commit fc41709 into boykopovar:main Oct 25, 2026
16 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the lookup by layout.binding in DataWordsDiffer and refreshData (size and single-buffer requirements kept), the new imageTableTemplateRefreshTests case (fails on main's index pairing) and the author's Linux/Windows red/green runs and validation comparison; merged.

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

Labels

agc libSceAgc*

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants