Skip to content

fix(shader): keep vector selects valid on SPIR-V 1.3 targets - #2191

Merged
adriadam10 merged 2 commits into
boykopovar:mainfrom
tezzgod74:fix/spirv-1.3-no-mesh-targets
Oct 10, 2026
Merged

adriadam10 merged 2 commits into
boykopovar:mainfrom
tezzgod74:fix/spirv-1.3-no-mesh-targets

Conversation

@tezzgod74

Copy link
Copy Markdown
Contributor

What

Fixes #2138. Devices without mesh shaders target SPIR-V 1.3, and 10 execution tests failed validation there since #639.

  • fix(shader): the FMASK identity read in EmitImage selected a uvec4 with the scalar bool condition ctx.Arg(inst, 2). A scalar condition for a vector result needs SPIR-V 1.4. The condition is now splatted into a bvec4, as fix(shader): splat the bindless table hit into a bool vector for SPIR-V 1.3 #574 did for the bindless table hit. This was the source of all nine Expected vector sizes of Result Type and the condition to be equal: Select failures; the module dumped from agc_driver_typed_heaps had %1008 = OpSelect %v4uint %true %1005 %137 with %1005 = uvec4(0x76543210, 0xfedcba98, 0, 0).
  • fix(tests): the geometry pass of agc_driver_prepared_graphics adds the mesh capability and extension to the device target but kept the target's SPIR-V version. On a 1.3 device the mesh module was rejected with module version exceeds requested SPIR-V target. The test now targets 1.4 there, as VulkanDevice does whenever mesh shading is enabled.

Tested

Windows 11 Pro 10.0.26300, MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, -DBUILD_TESTING=ON -DANYPS5_ENABLE_SPIRV_TOOLS=ON, rebased on main at 745b775. Full ctest with ANYPS5_GPU set to each device:

Device mesh / SPIR-V target Result with this change
Ryzen 9 7950X iGPU (RDNA 2, 0x164e), driver 32.0.21045.5002 0 / 1.3 504/508
AMD Radeon RX 9060 XT (RDNA 4, 0x7590), driver 32.0.31041.1004 1 / 1.4 506/508

The 10 tests listed in #2138, which failed on the iGPU at f145139 before this change, pass. The failures left are unrelated and fail the same way without this change: agc_driver_pixel_interlock (#2009), agc_driver_sdwa_float_selectors and agc_driver_sdwa_ldexp_f16 (#1463) on the iGPU, agc_driver_vopc_compare_table (#825) on the RX 9060 XT, and agc_driver_storage_cache_budget on both (vkAllocateMemory returns VK_ERROR_OUT_OF_DEVICE_MEMORY, also on main without these commits). Not tested with a title.

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

🤖 Generated with Claude Code

tezzgod74 and others added 2 commits October 9, 2026 06:09
…IR-V 1.3

The FMASK identity read selected a uvec4 with a scalar bool condition,
which needs SPIR-V 1.4. Devices without mesh shaders target 1.3, so
every image test that reaches the path failed validation with
ANYPS5_ENABLE_SPIRV_TOOLS (boykopovar#2138), as in boykopovar#574.

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

The geometry pass adds the mesh capability and extension to the device
target but kept its SPIR-V version. On a device without mesh shaders
that is 1.3, and the mesh module was rejected as exceeding the target.
VulkanDevice targets 1.4 whenever mesh shading is enabled.

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

rmz-24 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

I reached the same fix independently and confirmed it on a mesh-capable GPU by forcing meshShader off locally (RTX 5060 Ti, NVIDIA 617.42, Windows 11, MinGW GCC 15.2.0 r7, -DANYPS5_ENABLE_SPIRV_TOOLS=ON). With this change the full ctest passes 510/510, with mesh forced off and with it on.

One suggestion: CI can't catch a regression of this class, since lavapipe exposes mesh shaders and every CI module targets 1.4. A 3-line guard in ImageSint8.cpp's Run also compiles each shader for a 1.3 target, so the SPIRV-Tools job validates the 1.3 module on any device:

    request.useCache = false;
    auto withoutMesh = request;
    withoutMesh.target.spirvVersion = 0x00010300u;
    static_cast<void>(ShaderRecompiler::Recompile(withoutMesh));
    const auto result = ShaderRecompiler::Recompile(request);

On the RTX 5060 Ti (mesh=1, so the device itself targets 1.4), agc_driver_image_sint8 fails without your emitter change:

level=2 word=1444: Expected vector sizes of Result Type and the condition to be equal: Select
  %1019 = OpSelect %v4uint %true %1016 %148

and passes with it. All 26 agc_driver_image* tests pass with the guard. Feel free to take it into this PR; otherwise I can send it as a separate test PR after this one merges.

AI-assisted: yes

@tezzgod74

Copy link
Copy Markdown
Contributor Author

Thanks for confirming it on NVIDIA with mesh forced off, and for the guard. It closes the gap where CI can't see 1.3-only failures. Please send it as its own PR after this one merges so it carries your name; I'll test it on the RDNA 2 iGPU here (mesh=0, so it targets 1.3 natively) when it's up.

AI-assisted: yes

@danielradosa

Copy link
Copy Markdown
Contributor

Windows run with a title for this PR. Astro Bot PPSA21567 v01.018 (retail, owned; eboot.bin and sce_module unwrapped from their SELF containers, relinked with --windows). Windows 11 Pro 10.0.26300, MinGW-w64 GCC 15.2.0 (WinLibs r7), Release, -DANYPS5_ENABLE_SPIRV_TOOLS=ON. GPU: Ryzen 5 7600 iGPU (RDNA 2, 0x164e), driver 32.0.21045.5002, selected with ANYPS5_GPU="Radeon(TM) Graphics". The device reports mesh=0, so programs target SPIR-V 1.3.

Tree: main d70b899 plus the #2340 stack (#1836, #1837, #2257, CouchRiv's fix-shader-sampled-heap-capacity) and other open PRs; none of them touch SpirvImageEmitter.cpp. On main alone the title stops earlier, at the #1817 s_swappc_b64 registration stop.

  • Without this PR (warm shader cache): 689 programs registered (606 from the disk cache, 83 compiled) and 96 deferred by fix(agc): defer shaders that cannot be prepared at registration to their first use #1836, then the title ends at about 2 minutes with
    terminate called after throwing an instance of 'std::runtime_error'
      what():  ShaderRecompiler::Recompile: SPIR-V validation before optimization failed:
    level=2 word=764: Expected vector sizes of Result Type and the condition to be equal: Select
      %622 = OpSelect %v4uint %true %619 %134
    
    the same shape as the agc_driver_typed_heaps module in the description.
  • With this PR (cold cache, new source version): 723 programs compiled and 96 deferred, no validation failure. The run was ended by APS5_HANG_DUMP_SECS=450 while the main thread was still registering shaders; no frame is presented yet.

agc_driver_prepared_graphics and agc_driver_typed_heaps pass on this iGPU with the PR.

AI-assisted: yes (Claude Code).

@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the FMASK select now uses a bvec4 condition (valid on SPIR-V 1.3, same per-component result), the prepared graphics test targets 1.4 where it adds mesh, and agc_driver_prepared_graphics plus the Agc/AgcDriver ctest pass (296/296). Note that the tests can't fail without the change on CI, which targets 1.4; the 1.3 guard suggested in the thread is a good follow-up. Merging.

@adriadam10
adriadam10 merged commit 87be948 into boykopovar:main Oct 10, 2026
6 checks passed
SleglJan pushed a commit to SleglJan/AnyPS5 that referenced this pull request Oct 10, 2026
…sh-targets

fix(shader): keep vector selects valid on SPIR-V 1.3 targets
@tezzgod74
tezzgod74 deleted the fix/spirv-1.3-no-mesh-targets branch October 11, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* shader core/shader

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AGC: since #639, devices without mesh shaders (SPIR-V 1.3 target) get modules that fail validation

4 participants