Skip to content

feat(agc): bind storage buffers update-after-bind above the per-stage limit - #1580

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
Zheorgyan:feat/storage-buffers-update-after-bind
Oct 10, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
Zheorgyan:feat/storage-buffers-update-after-bind

Conversation

@Zheorgyan

@Zheorgyan Zheorgyan commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

What

agc_driver_many_buffers fails on Apple GPUs with "shader descriptors exceed per-stage limits". MoltenVK reports maxPerStageDescriptorStorageBuffers 31 and maxDescriptorSetStorageBuffers 155 on every Apple GPU, while the test binds 124 buffers in one stage. its update-after-bind limits are 1000000, and the guest buffers are one constant-indexed array binding, so the shaders don't need to change

when a stage's storage buffers or resources go above the regular per-stage limit, or the set's storage buffers above the per-set limit, and the device has descriptorBindingStorageBufferUpdateAfterBind, the set now uses the update-after-bind limits instead of throwing

  • VulkanDevice enables descriptorBindingStorageBufferUpdateAfterBind when available and passes VkPhysicalDeviceDescriptorIndexingProperties through the context. without the feature those limits stay 0 and the old error is thrown
  • such a set's layout gets UPDATE_AFTER_BIND_POOL with UPDATE_AFTER_BIND on its storage-buffer bindings, and is allocated from a separate chain of pools created with UPDATE_AFTER_BIND. the layout key carries the flag. the two places that created layouts share CreateSetLayout now, and the two that created single-set pools share CreateSetPool
  • a set within the regular limits takes the same path as before, so devices with large limits, like the AMD, NVIDIA and lavapipe ones, are unchanged
  • image bindings after an update-after-bind buffer binding are checked against the update-after-bind resource limit
  • ValidateDescriptorLayout, added on main since this PR was opened, takes the same flag and checks such a set against maxPerStageUpdateAfterBindResources instead of maxPerStageResources

Tested

  • macOS 15.6.1 on an M1 Pro, MoltenVK from Vulkan SDK 1.4.363.0, on top of mugurc's macos-port branch, before the rebase. agc_driver_many_buffers fails before and passes after. the rest of the suite ran with -j1 --timeout 30 without the flip and display tests and agc_driver_lds_atomics64. 427 tests, and the 2 that fail, agc_driver_pixel_interlock and agc_driver_sdwa_float_selectors, fail the same way without this change
  • agc_driver_graphics has a new case on the mock device. 17 buffers over a per-stage limit of 16 get the update-after-bind layout, binding flag and pool, an update-after-bind limit of 16 still throws, and one buffer keeps the regular layout. with the switch to update-after-bind removed, the new case fails
  • Linux, Ubuntu 24.04 in Docker, GCC 14.2, lavapipe, after the rebase on a8b032b2. builds, agc_driver_graphics, agc_driver_many_buffers, agc_driver_typed_heaps, agc_driver_oversized_descriptor_sets and agc_driver_prepared_graphics pass. 26 of the 207 agc_driver tests fail, with illegal instruction and segfault crashes of this x86-64 emulated container and wrong values in image_sint8 and shader_clock, none of them in descriptor code
  • the upstream run is waiting for approval, so the same Build ran in my fork on 910a777f and passed on linux and windows: https://github.com/Zheorgyan/AnyPS5/actions/runs/37902941264
  • tools/check_conventions.py passes

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: none
  • AI-assisted: yes

@yahya308

yahya308 commented Oct 8, 2026

Copy link
Copy Markdown

Tested on top of main 9e2ffe0d, Windows 11, MinGW-w64 GCC 16.2.0, full ctest with ANYPS5_REQUIRE_VULKAN=1 --repeat until-fail:3, NVIDIA RTX 4070 Laptop (32.0.16.1074) and AMD Radeon 780M (32.0.31041.1004). vopc_compare_table fails on the 780M on main too (#825, #1473).

Head cb7bb927: no change from main on either GPU. many_buffers passes on both.

AI-assisted: yes (Claude Code).

@github-actions github-actions Bot added agc libSceAgc* needs rebase Conflicts with main, rebase needed labels Oct 8, 2026
utkuhalis added a commit to utkuhalis/AnyPS5-ARM that referenced this pull request Oct 9, 2026
…bind above the per-stage limit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp
utkuhalis added a commit to utkuhalis/AnyPS5-ARM that referenced this pull request Oct 9, 2026
…settings

Without argument buffers MoltenVK caps every stage at 31 storage buffers,
including update-after-bind ones, so the update-after-bind path from boykopovar#1580
could not help (agc_driver_many_buffers). With them the update-after-bind
limits rise to 1000000. The instance now asks MoltenVK for argument buffers
through VK_EXT_layer_settings when the loader offers it, unless
MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS is set by the user.

Full suite on an M3 Pro: 471 of 483; Breakout still runs at about 60 fps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Zheorgyan
Zheorgyan force-pushed the feat/storage-buffers-update-after-bind branch from cb7bb92 to 910a777 Compare October 9, 2026 08:06
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 9, 2026
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the limit logic (per-stage, per-set, ValidateDescriptorLayout), the layout key, the separate update-after-bind pool chain and cleanup; agc_driver_graphics and agc_driver_prepared_graphics pass on the PR merged onto main, and the new case doesn't build without the change. The red linux/windows jobs were agc_shader_fusion_tests missing spirv/unified1/spirv.hpp, a main breakage fixed in 37bc6f2, not this PR.

Rebased onto current main (no code changes) to get a clean CI run; merging once it's green. Not verified here: MoltenVK/Apple at runtime.

@adriadam10
adriadam10 force-pushed the feat/storage-buffers-update-after-bind branch from 910a777 to 27e6ad1 Compare October 10, 2026 00:18
@adriadam10
adriadam10 merged commit a9ac7bc into boykopovar:main Oct 10, 2026
8 checks passed
SleglJan pushed a commit to SleglJan/AnyPS5 that referenced this pull request Oct 10, 2026
…s-update-after-bind

feat(agc): bind storage buffers update-after-bind above the per-stage limit
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.

3 participants