Skip to content

fix(shader,agc): declare ImageMSArray only for multisampled arrayed storage images - #9978

Open
BKlaasWerkman wants to merge 1 commit into
boykopovar:mainfrom
BKlaasWerkman:fix/image-ms-array-storage-only
Open

BKlaasWerkman wants to merge 1 commit into
boykopovar:mainfrom
BKlaasWerkman:fix/image-ms-array-storage-only

Conversation

@BKlaasWerkman

@BKlaasWerkman BKlaasWerkman commented Oct 23, 2026 •

Copy link
Copy Markdown

What

The recompiler declared ImageMSArray for every multisampled arrayed image, sampled ones included, and the device listed ImageMSArray as supported whether or not shaderStorageImageMultisample is enabled. On a device without that feature, a sampled Dim2DMsaaArray image_load therefore produced a module that Vulkan rejects. The Khronos layer reports it in agc_driver_native_msaa_vertex_input on Intel Arc (Meteor Lake):

vkCreateShaderModule(): SPIR-V Capability ImageMSArray was declared, but one of the following requirements must be met (VkPhysicalDeviceFeatures::shaderStorageImageMultisample).
VUID-VkShaderModuleCreateInfo-pCode-08740

Sources:

  • SPIR-V requires ImageMSArray only for an OpTypeImage with MS 1, Arrayed 1 and Sampled 2. SPIRV-Tools at the pinned submodule commit checks exactly that: validate_image.cpp L699-704.
  • Vulkan requires shaderStorageImageMultisample for a module that declares ImageMSArray (VUID-VkShaderModuleCreateInfo-pCode-08740 and the SPIR-V environment capabilities table it refers to).

Changes:

  • SpirvDescriptors.cpp: ImageMSArray is declared only in the storage-image branch, after the existing StorageImageMultisample check, so a storage multisampled array still fails with storage image multisampling is unavailable on the target device on such a device.
  • VulkanDevice.cpp: ImageMSArray joins the supported capabilities only when shaderStorageImageMultisample is enabled, like StorageImageMultisample.
  • SampleMultisampleTarget.cpp: RunLoad checks that the compiled multisampled image_load declares no ImageMSArray. A sampled load is device-independent (LoadImage is always ImageResourceClass::Sampled), so the check fails on every device, lavapipe included, if the capability comes back.

Tested

Windows 11 Pro 10.0.26300, WinLibs GCC 15.2.0 r7 (UCRT), Release, -DBUILD_TESTING=ON. Two GPUs in the same machine, selected with ANYPS5_GPU:

  • NVIDIA GeForce RTX 3060 Ti, driver 617.42; shaderStorageImageMultisample = true.
  • Intel Arc Graphics (Meteor Lake, 0x7d55), driver 101.9150; shaderStorageImageMultisample = false.

Base main a701f9f, change 6d85dd2. 62 focused tests (ctest -R 'msaa|multisample|sample_order|sampled_cache|shader_device_profile|recompiler|spirv|image_load|image_store|storage_image|agc_shader_memory|native_depth' -V) with ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1 and VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (layer 1.4.363). Neither log has was not found but was requested by env var VK_INSTANCE_LAYERS.

main this PR
RTX 3060 Ti 59/62; 03320 ×3, 00337 ×9 59/62; 03320 ×3, 00337 ×9
Intel Arc 61/62, 4 skipped; 08740 ×1, 03320 ×3, 00337 ×6 61/62, 4 skipped; 03320 ×3, 00337 ×6

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
  • Fixes: none
  • Unblocks: none
  • GPUs tested: NVIDIA GeForce RTX 3060 Ti, driver 617.42, Windows 11 Pro 10.0.26300; Intel Arc Graphics (Meteor Lake), driver 101.9150, Windows 11 Pro 10.0.26300
  • AI-assisted: yes (Claude Code)

🤖 Generated with Claude Code

…torage images

SPIR-V requires ImageMSArray only for an OpTypeImage with MS 1, Arrayed 1
and Sampled 2, and Vulkan requires shaderStorageImageMultisample for a
module that declares it. The recompiler declared it for every
multisampled arrayed image, including sampled ones, and the device listed
it as supported without the feature, so a sampled Dim2DMsaaArray load
produced an invalid module on devices without
shaderStorageImageMultisample (VUID-VkShaderModuleCreateInfo-pCode-08740).

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

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

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
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.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
PR 5925 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6188 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6202 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6804 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6808 core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.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 7275 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7464 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8014 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8223 core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9400 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.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
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
PR 9675 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9676 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.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 9898 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 10046 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 10193 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/shader/recompiler/SpirvBackend/src/SpirvMemory/SpirvDescriptors.cpp
PR 10233 core/libs/prx/libSceAgcDriver/tests/execution/SampleMultisampleTarget.cpp
PR 10435 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 10442 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp

@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 source change is consistent with the SPIR-V condition cited in the PR: ImageMSArray is emitted only for multisampled arrayed storage images, after checking StorageImageMultisample, and the device advertises the related capabilities only when that feature is enabled. The new test inspects the generated module and fails if sampled multisampled image_load declares ImageMSArray. The two-GPU validation comparison reports the original VUID-08740 removed on Intel Arc, with the remaining failures/VUIDs identified on both baseline and change. Required conventions/intake/labels pass; hosted product jobs are not run automatically under repository policy.

@jotitadev jotitadev 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.

Ran this on Apple silicon, a third vendor and a second device without shaderStorageImageMultisample (MoltenVK reports it as false on the M2 Max, like the Intel Arc in the description).

Setup: Apple M2 Max (32 GB), macOS 27.2, x86_64 build under Rosetta, Release, BUILD_TESTING=ON. Method: #8658 (feat/macos-port) @ dc0c8db500 plus this PR's diff (head 6d85dd2b5b), not main, since main does not build on macOS yet. Two drivers: Vulkan SDK 1.4.363.0 MoltenVK 1.4.2, and MoltenVK main with SPIRV-Cross #2704. ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ctest -j1 --timeout 30 -V.

Focused set: ctest -R 'multisample|msaa|sample_order|storage_image|image_load|image_store|shader_device_profile' (42 entries).

SDK MoltenVK 1.4.2 MoltenVK main + #2704
test change only (red) 38/42; agc_driver_native_msaa_vertex_input fails with the multisampled image_load declared ImageMSArray, which only multisampled arrayed storage images need same
this PR (green) 39/42 39/42
  • The 3 failures left on both sides are agc_driver_multisample_retirement, agc_driver_sample_mask_multisample and agc_driver_sample_order. They fail the same way on the #8658 base without this PR, so they are not from this change.
  • The tests that need shaderStorageImageMultisample skip on both sides (agc_driver_sample_multisample_target, agc_driver_multisample_centered_lines, the sample-order checkerboard).
  • Validation layer: the same VUID counts on both sides (04451 from the port's missing VK_KHR_portability_subset, 03320, 00337, 09582). The layer reported no 08740 on MoltenVK, either with or without the fix.
  • Whole ^agc suite with this PR, SDK driver: 852/870, the same 18 failures as the base.

GPUs tested: Apple M2 Max (MoltenVK 1.4.2 from Vulkan SDK 1.4.363.0, and MoltenVK main + SPIRV-Cross #2704), macOS 27.2.

Written with AI assistance (Claude Code). I ran the builds and tests above on my machine.

@blawesom

Copy link
Copy Markdown
Contributor

Third-vendor column for the paired protocol — AMD RADV, where neither of the two GPUs above sits:

Machine: CachyOS, kernel 7.2.10, GCC 16.2.1, Ninja, Release, BUILD_TESTING=ON, AMD Radeon RX 9070 XT, RADV (Mesa 26.2.4, GFX1201). This branch rebases clean onto main f075f91737.

Paired run — main and this branch, ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ctest -V, the msaa/multisample slice of your focused set (29 tests: the agc_driver_msaa_*, agc_driver_multisample*, agc_driver_native_multisample_depth, agc_driver_sample_multisample_target, agc_driver_native_msaa_vertex_input, agc_driver_sampled_cache_budget_without_storage_image_multisample, agc_multisample_guest_access, agc_driver_cached_image_multisample_guard, agc_driver_multisampled_pass_order, image_msaa_load and neighbours):

  • 29/29 pass on both, identical per-test results.
  • Neither log contains was not found but was requested by env var VK_INSTANCE_LAYERS, and neither has a VUID- line. RADV exposes shaderStorageImageMultisample, so the 08740 rejection itself is not reachable here — the useful part on this device is the new device-independent check below.

Old code, new test — SpirvDescriptors.cpp/VulkanDevice.cpp from main, SampleMultisampleTarget.cpp from this branch: both agc_driver_native_msaa_vertex_input and agc_driver_sample_multisample_target fail with AGC graphics: the multisampled image_load declared ImageMSArray, which only multisampled arrayed storage images need — so the regression check fires on a third vendor too, exactly as the description's "every device, lavapipe included" predicts.

AI-assisted: yes (OpenCode); both runs and the old-code cross-check were executed on this machine.

@BKlaasWerkman

BKlaasWerkman commented Oct 23, 2026 •

Copy link
Copy Markdown
Author

Rechecked on today's main f2a4fb1, which is 400+ commits past the base above. Head 6d85dd2 still merges cleanly, and the same 62 focused tests give the same results as in the description:

Full ctest of that main on both GPUs has no failure besides those and agc_storage_write_back on Intel Arc (#10126).

AI-assisted: yes (Claude Code)

Edited: the VUID- counts were halved; the first version counted each validation message twice. No conclusion changes.

@brummilab

Copy link
Copy Markdown

Tested on AMD under Windows, the case this PR is about (the driver does not expose shaderStorageImageMultisample): Radeon RX 6600 XT (Navi 23, 0x73ff), AMD driver 32.0.21045.16010, Windows 11 Pro 26300, WinLibs GCC 15.2.0 r7, Release, Vulkan SDK 1.4.363. main 30be9b428 and this PR (head 6d85dd2b5) merged onto it, same machine, ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1, VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, tests matching multisample|msaa|sample_order|storage_image|image_load|image_store|shader_device_profile, each run on its own with VK_KHRONOS_VALIDATION_LOG_FILENAME so the layer's log confirms it loaded:

Tests Passed Failed Skipped Layer loaded VUID- messages
main 44 43 1 0 39 4
this PR 44 43 1 0 39 4

The one failure is the same on both: agc_driver_sample_order_grid_reference, the AMD Windows device loss #9503 fixes; its 4 VUIDs (VUID-VkSubmitInfo-pSignalSemaphores-03242 x2, VUID-vkDestroyDevice-device-05137 x2) follow from that loss and are identical on both arms. No new failures and no new validation errors.

AI-assisted: yes

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants