Skip to content

fix(agc): resolve and render a multisampled target through its sRGB twin format - #8847

Merged
oneandonlydean merged 3 commits into
boykopovar:mainfrom
JJenkx:fix/agc-msaa-srgb-twin
Oct 22, 2026
Merged

oneandonlydean merged 3 commits into
boykopovar:mainfrom
JJenkx:fix/agc-msaa-srgb-twin

Conversation

@JJenkx

@JJenkx JJenkx commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

A multisampled color target matched a later use only when the use had the same VkFormat. When a surface was rendered as sRGB and then CB-resolved as UNORM, or the other way round, the resolve got a new, cleared multisampled image. It resolved that image instead of the rendered samples, so the destination was all zeros. Both formats are the same bytes on the console. The CB format only says how they are encoded.

Curved Space (PPSA02817) renders its 3D scene into an 8x B8G8R8A8_SRGB target. The CB resolve then decodes the same surface as B8G8R8A8_UNORM. A RenderDoc replay of a gameplay frame on main shows the scene drawn correctly into the 8x sRGB image (event 6961, max 1.0). The resolve pass reads a different 8x B8G8R8A8_UNORM image that nothing drew to. Its 1x destination stays 0, and so do the bloom chain and the composite that read it. Only the HUD is drawn over black.

The change:

  • A multisampled image whose format has an sRGB twin (SrgbTwinFormat, both directions) is created with MUTABLE_FORMAT and a two-entry VkImageFormatListCreateInfo. This happens only when the device can render the twin at the target's sample count.
  • acquire also matches a live target in the twin format. The use is rewritten to the creation format before Recreate, ApplyFastClear and the guard, so fill and CMASK clear values are still computed in the format the image was created in.
  • MultisampleTargetView returns a view in the requested format. ResolveMultisampleTarget resolves through a view and render pass in the source's format, so a UNORM resolve averages the stored bytes as UNORM, as the CB format says.
  • The twin view is retired before its image on storage promotion and destroyed before it on release.

Not changed: sampling a multisampled target (MultisampleTargetTexture) or binding it as a storage image in its twin format still throws as before.

Tested

Linux 7.2.9 (Arch), Ryzen 9 7950X, Radeon RX 6650 XT, RADV Mesa 26.2.4.

Curved Space (PPSA02817) 01.000, converted with --module-dir Media/Modules --module-dir Media/Plugins. Same scripted 100 s run with input, screenshot at 95 s in the first level:

  • main 20de555: HUD over black, 2.1 % of pixels non-black (0.6 % in 3 earlier runs on da5ea87).
  • This PR on 20de555: the arena, ship, enemies and bloom render, 54.7 % non-black (60.4 % on da5ea87).
  • No driver stop in either. No frame-rate claim: the change makes the world draw at all.

Focused tests on main 20de555 (with only the driver source reverted) and on this PR: ctest -R 'multisample|multisampled|^agc_recorder' -V with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1. The Khronos layer 1.4.363 was loaded with VK_ADD_LAYER_PATH, and VK_LOADER_DEBUG=layer shows it inserted in all 20 tests in both logs. Neither log reports was not found but was requested by env var VK_INSTANCE_LAYERS.

  • main: 18/20. The two new tests fail on their asserts: agc_driver_multisample_srgb_twin ("a use of a multisampled surface in its sRGB twin format does not reach the samples rendered in the other format") and agc_driver_multisample_retirement ("an sRGB use of an MSAA surface rendered as UNORM does not reach its samples").
  • This PR: 20/20.
  • VUID- errors: 0 in both logs.

New tests:

  • MultisampleSrgbTwin: a UNORM/sRGB pair in both directions gets the same image and a separate view, and goes back to the first view. An unrelated format of the same size gets its own image. A guest fill taken as a clear through the twin stores exactly the guest's bytes, read back with vkCmdResolveImage: 0x80808080 on a UNORM-created target used as sRGB, and 0xff0000ff on an sRGB-created target used as UNORM. With the creation-format rewrite removed, the first case fails ("a fill over the color memory of a multisampled target has no exact clear value in its format").
  • MultisampleRetirement::StorageTwin: after storage promotion, the sRGB use views the promoted image. It runs only when context.storageImageMultisample is set, because MultisampleTargetStorageView refuses on devices without shaderStorageImageMultisample (40ed859, after @GiannisG1's report from an HD 630). The fixture now aborts when an image is destroyed while one of its views still exists. With the twin view retired after its image, it fails with "an MSAA image would be destroyed before one of its views". The existing cases pass with this check on main.

tools/check_conventions.py --base origin/main passes. The PR overlap tool finds only adjacent lines in MultisampleTarget.cpp, shared with #6973, #6987, #6989, #6995 and #7002, and in the main() of MultisampleRetirement.cpp, shared with #8604. None of them changes format matching.

Independent check by @simonbbby (comment), at exact head 84854e9116, on Ubuntu 24.04.3 with GCC 13.3:

  • The same focused set passes 20/20 with no skips on an RTX 3090 (NVIDIA 595.99.02), on gfx1036 (RADV Mesa 25.2.8) and on lavapipe (Mesa 25.2.8).
  • With only the parent's MultisampleTarget.cpp restored, both new tests fail on their asserts. With the PR rebuilt, they pass again.
  • A temporary 8-sample variant of the twin fixture passed 3/3 on each physical GPU.
  • That check ran no title, no combination with feat(agc): preserve initial native multisample color contents #6973 and no Khronos validation layer.

Windows check by @ycbuzi (comment), at head 40ed8597fa merged onto main b77bd58 (48c389eb56). Setup: Windows 11 Home 10.0.26200, MinGW-w64 GCC 15.2.0 (ucrt-posix-seh r7), Release, BUILD_TESTING=ON, NVIDIA driver 616.92.

  • libSceAgcDriver and the two test targets this PR changes build with no errors. The two memcmp bound warnings come from Graphics/src/PipelineLibrary.cpp, which this PR does not change, and main prints them the same way.
  • ctest --repeat until-fail:3 on agc_driver_multisample_retirement and agc_driver_multisample_srgb_twin passes all three repeats on an RTX 4070 SUPER and on a GTX 1650 SUPER (ANYPS5_GPU=GTX 1650).
  • Both devices report shaderStorageImageMultisample, so StorageTwin ran on each and the skip branch did not.
  • On the previous head 84854e9116, the two tests also passed twice on the RTX 4070 SUPER.
  • That check ran no title and no validation layer.

Not tested: a device without shaderStorageImageMultisample (the StorageTwin skip branch), a validation layer on Windows, and a CB resolve driven through PM4 in a unit test (covered only by the title run).

Rebased on main 2abfb1beb4 (head 56595793ca).

  • main now creates a multisampled image with MUTABLE_FORMAT | EXTENDED_USAGE and adds storage usage when samples may be reordered (the sample-order view). With those flags, the twin format list is not added, and the twin view relies on MUTABLE_FORMAT.
  • The twin capability check now uses the image's actual flags (orderFlags | MUTABLE_FORMAT) and only the twin view's usage (color attachment and transfer). Otherwise, the added storage usage would have turned the twin off for sRGB targets.
  • release() destroys the order view, the twin view and the resolve passes before the image.

Same focused set, now 24 tests including main's sample-order tests, on the same machine with the Khronos layer:

  • main with only MultisampleTarget.cpp restored: 22/24. The two new tests fail on their asserts.
  • This PR: 24/24.
  • Both logs have the same VUID- lines in the same tests: 12 VkImageMemoryBarrier-image-03320 in agc_driver_sample_order, and 32 VkWriteDescriptorSet-descriptorType-00337 in agc_driver_sample_order, ..._grid_reference and ..._recipe_depth_locations. They come from main's sample-order tests; the PR adds none.

Curved Space at 95 s on the rebased build: the arena, ring, ship and HUD render.

VK_KHR_image_format_list (386d7d0, after @GiannisG1's report):

  • The instance is created with VK_API_VERSION_1_1, where VkImageFormatListCreateInfo belongs to VK_KHR_image_format_list. Validation layers 1.3.275 reported VUID-VkImageCreateInfo-pNext-pNext on an HD 630, a GTX 1050 Ti and llvmpipe.
  • The device now enables VK_KHR_image_format_list when the device lists it (Context::imageFormatList). The twin's format list is chained only then; otherwise the image relies on MUTABLE_FORMAT alone.
  • Rerun on the RX 6650 XT (RADV, which lists the extension) with layer 1.4.363: 24/24, and the same VUID- lines as main, all in its sample-order tests. That layer never reported the pNext VUID here, so I could not reproduce it; the older-layer result needs a rerun on those devices.

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: PPSA02817 Curved Space (PPSA02817) #8691
  • GPUs tested: AMD Radeon RX 6650 XT (RADV NAVI23), Mesa 26.2.4, Linux 7.2.9 (Arch); by @simonbbby without the validation layer: NVIDIA RTX 3090 (595.99.02), AMD gfx1036 (RADV Mesa 25.2.8) and lavapipe (Mesa 25.2.8), Ubuntu 24.04.3; by @ycbuzi without the validation layer, on head 12223bf208 merged onto main a6dcea9279, the full 23-test focused set: NVIDIA RTX 4070 SUPER and GTX 1650 SUPER (616.92) and AMD Radeon Graphics, the Ryzen 9 7900 iGPU (25.10.30.02), Windows 11 Home 10.0.26200 (MinGW-w64 GCC 15.2.0)
  • AI-assisted: yes

🤖 Generated with Claude Code

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 21, 2026
@github-actions

github-actions Bot commented Oct 21, 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 6973 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L103, L489-490
PR 6987 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L103, L489-490
PR 6989 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L103, L489-490
PR 6995 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L103, L489-490, L638
PR 7002 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L103, L489-490, L638
PR 7803 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L338-339, L489-490
PR 8604 core/libs/prx/libSceAgcDriver/tests/execution/MultisampleRetirement.cpp L534-535
PR 8998 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L103, L491-492
PR 9186 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp L612-613
PR 9260 core/libs/prx/libSceAgcDriver/tests/execution/MultisampleRetirement.cpp L516, L534-535

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 2434 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 4072 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 5021 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5431 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 6292 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6481 core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 6615 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6788 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6808 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
PR 6960 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6971 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
PR 7201 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7275 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 7622 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7642 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/tests/execution/MultisampleRetirement.cpp
PR 8014 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8105 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8278 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8658 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 9508 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/tests/execution/MultisampleRetirement.cpp
PR 9533 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.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 9717 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp
PR 9742 core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp

@Amoenus

Amoenus commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Thanks for checking the adjacent stack. Source-only coordination at your 84854e9116 and #6973 419ad899c6: these implement different capabilities, but a direct merge has two conflicts in MultisampleTarget.cpp:

The same constructor/release overlap propagates into #6987/#6989/#6995/#7002 because they retain that parent. All our PRs still merge cleanly with current main; this is a between-PR conflict, not evidence of a duplicated fix. I can adapt our stack if yours lands first. No combined build, GPU qualification, or claim that this fixes Sonic from this source review. AI-assisted: yes (Codex); author responsible.

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, I checked #6973 at 419ad899c6 against 84854e9116. The two changes compose. The conflicts are textual:

  • Constructor: allocate() here adds the two-entry VkImageFormatListCreateInfo only when the caller passes no MUTABLE_FORMAT flag. Your initial allocation passes MUTABLE_FORMAT | EXTENDED_USAGE for the unsigned storage view, so the twin view is then allowed by MUTABLE_FORMAT alone, and no format list restricts your view. A merge keeps your flags and capability checks and adds the twin check after them.
  • release(): destroy initialView, twinView and the per-format resolve passes, then the images. That matches the order here, where the twin view is also retired before its image on storage promotion.

Neither PR depends on the other, so no Depends on. Whichever lands first, the other rebases. If #6973 lands first, I will rebase this one and rerun the focused tests and the Curved Space check. Thanks for offering to adapt your stack otherwise.

@github-actions github-actions Bot added the agc libSceAgc* label Oct 21, 2026
@simonbbby

Copy link
Copy Markdown
Contributor

Independent Linux check at exact head 84854e9116c23e2179f4d67917a5c1a5dffeee98, adding NVIDIA and RADV Mesa 25.2.8 coverage:

ICD Focused suite on exact head Only parent production restored Exact PR restored and rebuilt
RTX 3090 / NVIDIA 595.99.02 20/20 pass, no skips both new regressions fail both pass
gfx1036 (1002:13c0) / RADV Mesa 25.2.8 20/20 pass, no skips both new regressions fail both pass
lavapipe / Mesa 25.2.8, LLVM 20.1.2 20/20 pass, no skips both new regressions fail both pass

The focused command was ctest -V -R 'multisample|multisampled|^agc_recorder', serially per ICD, with ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1. The negative control keeps the PR's tests and restores only Graphics/src/MultisampleTarget.cpp from parent main 20de55550fa0be54794329a23640f73ad134fb6e. multisample_srgb_twin fails because the twin does not reach the original samples; multisample_retirement fails its sRGB-use-of-UNORM assertion. These are assertion failures, not skips or missing devices.

I also tested the twin fixture at 8 samples, matching Curved Space's sample count: the same image/view identity, return-to-original-view, unrelated-format separation and exact clear-byte checks pass 3/3 on each physical GPU. The temporary variant changes target.samples and the capability guard to 8, reserves 256 KiB per guest block, and keeps target.bytes = Side * Side * 4 (the single-sample byte count). This does not add a PM4-driven resolve check; the clear readback still uses the fixture's vkCmdResolveImage path.

Ubuntu 24.04.3, GCC 13.3, Release. No title execution, combined #6973 stack, or Khronos validation-layer A/B was run here; the validation layer is unavailable on this host. All temporary source changes were removed, the exact PR was rebuilt and its two regressions rerun successfully on all three ICDs; checkout is clean.

@GiannisG1

Copy link
Copy Markdown

Heads-up from #8604, which gates StorageRemap in the same main() on context.storageImageMultisample: a device without shaderStorageImageMultisample refuses the storage view (MultisampleTarget.cpp:258). StorageTwin also calls MultisampleTargetStorageView, so once both PRs are in it needs the same guard.

Measured on main e28d386d4 + #8847 84854e911 + #8604 cdf6c2857, agc_driver_multisample_retirement:

Resolution of the main() conflict HD 630, Mesa 25.2.8 (no shaderStorageImageMultisample) GTX 1050 Ti, 580.173.02 llvmpipe, Mesa 25.2.8
run.StorageTwin() after if (storage) run.StorageRemap(); fails: "the device cannot write the multisampled color target's format as a storage image at its sample count" passes passes
if (storage) { run.StorageRemap(); run.StorageTwin(); } skipped passes passes

Whichever lands second takes the second form. If #8847 goes first, I'll rebase #8604 that way.

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, that's right, and it applies to this PR alone, not only after #8604: StorageTwin reaches MultisampleTargetStorageView, which refuses on a device without shaderStorageImageMultisample (MultisampleTarget.cpp:258 on your merge).

40ed859 now runs it only when context.storageImageMultisample is set: if (context.storageImageMultisample) run.StorageTwin();. With #8604, your second form (if (storage) { run.StorageRemap(); run.StorageTwin(); }) is the right resolution, whichever lands second.

Checked on an RX 6650 XT (RADV Mesa 26.2.4), which has the feature: agc_driver_multisample_retirement and agc_driver_multisample_srgb_twin pass with the Khronos validation layer loaded and no VUID- errors. I have no device without the feature, so the skip branch here is covered only by your HD 630 run.

@ycbuzi

ycbuzi commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Windows run of 40ed859 merged onto main b77bd58 (48c389eb56, clean), one of the hosts the description lists as not tested. Windows 11 Home 10.0.26200, MinGW-w64 GCC 15.2.0 (ucrt-posix-seh r7), Release, BUILD_TESTING=ON, NVIDIA driver 616.92.

Built libSceAgcDriver, agc_driver_multisample_retirement_tests and agc_driver_multisample_srgb_twin_tests with no errors; the build prints two memcmp bound warnings, which main prints the same way from Graphics/src/PipelineLibrary.cpp, a file this PR does not change. ctest --repeat until-fail:3 on agc_driver_multisample_retirement and agc_driver_multisample_srgb_twin, on two devices:

Device shaderStorageImageMultisample Result
RTX 4070 SUPER (ANYPS5_GPU unset; the first discrete device listed) 1 both pass all three repeats
GTX 1650 SUPER (ANYPS5_GPU=GTX 1650) 1 both pass all three repeats

Both devices report the feature (vulkaninfo), so the guarded StorageTwin case ran on each; neither covers the skip branch. On the previous head 84854e9 the two tests also passed twice on the RTX 4070 SUPER. Not run: a device without the feature, a validation layer, a title.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@GiannisG1

Copy link
Copy Markdown

Ran 40ed8597fa on the HD 630 (Mesa 25.2.8 ANV, no shaderStorageImageMultisample), a GTX 1050 Ti (580.173.02) and llvmpipe (Mesa 25.2.8); Linux Mint 22.3, GCC 13.3, Release. 3 runs each, plus one with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1.

HD 630 GTX 1050 Ti llvmpipe
main 138182635 + this PR: agc_driver_multisample_srgb_twin passes 3/3 passes 3/3 passes 3/3
main + this PR: agc_driver_multisample_retirement fails 3/3 in StorageRemap, as on main (#8604) passes 3/3 passes 3/3
main + this PR + #8604, resolved as if (storage) { run.StorageRemap(); run.StorageTwin(); }: agc_driver_multisample_retirement skipped 3/3 passes 3/3 passes 3/3

On a device without the feature the guarded StorageTwin is reached only once #8604 is in; with this PR alone, StorageRemap fails first.

One validation difference from main (layers 1.3.275): with this PR both tests report VUID-VkImageCreateInfo-pNext-pNext on all three devices (36–41 times per run of the retirement test, 5 in srgb_twin); main 138182635 reports none:

vkCreateImage(): pCreateInfo->pNext includes a pointer to a VkStructureType (VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO), but its parent extension VK_KHR_image_format_list has not been enabled.

The instance is created with VK_API_VERSION_1_1 (VulkanDevice.cpp:1023), where VkImageFormatListCreateInfo needs VK_KHR_image_format_list enabled (it is core from 1.2), and main does not enable it anywhere. The formatList chain this PR adds in MultisampleTarget.cpp is the only use in the driver.

@JJenkx
JJenkx force-pushed the fix/agc-msaa-srgb-twin branch from 40ed859 to 5659579 Compare October 21, 2026 11:29
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Thanks, you're right. The format list needs VK_KHR_image_format_list on our 1.1 instance, and nothing enabled it. My layer (1.4.363 on RADV) never reported the VUID, so my earlier "no new VUID-" didn't cover this.

386d7d0: the device enables VK_KHR_image_format_list when it is available (Context::imageFormatList), and MultisampleTarget chains the twin's format list only then. Without the extension, the image keeps MUTABLE_FORMAT and the twin view works without a list.

Rerun here (RX 6650 XT, RADV Mesa 26.2.4, which lists the extension; layer 1.4.363; the same 24-test focused set): 24/24, and the same VUID- lines as main, all in its sample-order tests. I can't reproduce the 1.3.275 report on this device, so a rerun of agc_driver_multisample_retirement and agc_driver_multisample_srgb_twin on your three devices would settle it.

On the storage path: agreed. With this PR alone, StorageRemap fails first on the HD 630, and the guarded StorageTwin is only reached with #8604. Your if (storage) { run.StorageRemap(); run.StorageTwin(); } is the resolution for whichever PR lands second.

@GiannisG1

Copy link
Copy Markdown

Reran 386d7d0c4 merged onto main fce8ecf16: HD 630 (Mesa 25.2.8 ANV), GTX 1050 Ti (580.173.02), llvmpipe (Mesa 25.2.8); validation layers 1.3.275. 3 runs each, plus one with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation, ANYPS5_NO_SHADER_CACHE=1, ANYPS5_REQUIRE_VULKAN=1.

HD 630 GTX 1050 Ti llvmpipe
this PR: agc_driver_multisample_srgb_twin passes 3/3 passes 3/3 passes 3/3
this PR: agc_driver_multisample_retirement fails 3/3 in StorageRemap, as on main passes 3/3 passes 3/3
this PR + #8604 (rebased on fce8ecf16), resolved as if (storage) { run.StorageRemap(); run.StorageTwin(); } run.OrderRemap(); then the skip: agc_driver_multisample_retirement skipped 3/3; OrderRemap skips its own case passes 3/3 passes 3/3

The VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO report is gone: 0 in every run, and the VUID- lines match main's (none on the HD 630, VUID-VkDeviceCreateInfo-pNext-pNext on the other two). All three devices list VK_KHR_image_format_list, so this covers the path that enables it, not the one without it.

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for rerunning the refreshed head and separating the baseline failures from this change. I am recording these as your independently run results: the sRGB twin test passes 3/3 on HD 630, GTX 1050 Ti and llvmpipe, and the image-format-list report is absent. The HD 630 retirement failure remains a main baseline issue; the #8604 result is a skip, not a retirement pass. The device-create VUID on NVIDIA/llvmpipe also remains in the baseline. All three devices expose VK_KHR_image_format_list, so the unsupported-extension path remains untested by this set.

JJenkx and others added 3 commits October 21, 2026 14:52
…win format

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

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

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Rebased on main 38d3c0858a (head 12223bf208), because main added Context::storageImageWriteWithoutFormat on the line next to this PR's Context::imageFormatList. git range-diff shows the first two commits unchanged and the third differing only in those Context.hpp context lines. No change to MultisampleTarget.cpp or the tests. I'll rerun the focused set with the validation layer on this head when my GPU slot is free and add the result here.

@JJenkx
JJenkx force-pushed the fix/agc-msaa-srgb-twin branch from 386d7d0 to 12223bf Compare October 21, 2026 19:02
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 21, 2026
@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

Rerun on head 12223bf208 (main 38d3c0858a), clean Release build. Same setup as before: ctest -R 'multisample|multisampled|^agc_recorder' -V with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation (Khronos layer 1.4.363 through VK_ADD_LAYER_PATH), ANYPS5_NO_SHADER_CACHE=1 and ANYPS5_REQUIRE_VULKAN=1, on a Radeon RX 6650 XT with RADV Mesa 26.2.4:

  • 23/23 passed, ctest exit 0. The pattern matches 23 tests on this main, against 24 on the earlier base.
  • VK_LOADER_DEBUG=layer shows the layer inserted in all 23 tests, and no test reports it missing.
  • VUID- errors: 0.

AI-assisted: yes (Claude Code).

@ycbuzi

ycbuzi commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Windows rerun of head 12223bf, merged onto main a6dcea9 (60015ed54c, clean; that main includes #9137). Windows 11 Home 10.0.26200, MinGW-w64 GCC 15.2.0 (ucrt-posix-seh r7), Release, BUILD_TESTING=ON, with ANYPS5_REQUIRE_VULKAN=1 and ANYPS5_NO_SHADER_CACHE=1.

ctest -R 'multisample|multisampled|^agc_recorder' -V, the pattern of your rerun (23 tests here, from 12 executables including the new agc_driver_multisample_srgb_twin_tests), once on each GPU of this machine, selected with ANYPS5_GPU:

GPU Driver shaderStorageImageMultisample VK_KHR_image_format_list Result
NVIDIA GeForce RTX 4070 SUPER 616.92 yes yes 23/23 pass
NVIDIA GeForce GTX 1650 SUPER 616.92 yes yes 23/23 pass
AMD Radeon Graphics (Ryzen 9 7900 iGPU) 25.10.30.02 yes yes 23/23 pass

Each log names the requested device in all 19 of its Selected GPU lines. All three report both features (vulkaninfo), so the twin storage case and the chained format list run on each of them. The build prints the two memcmp bound warnings that main prints from Graphics/src/PipelineLibrary.cpp. The Khronos validation layer is not installed here, so there is no VUID- count. Not run: a title.

@JJenkx

JJenkx commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

@ycbuzi thanks for this. It's the first run of the full 23-test set on Windows, with all three GPUs reporting both shaderStorageImageMultisample and VK_KHR_image_format_list, so the twin storage case and the chained format list ran on each. I've updated the "GPUs tested" line in the description, and noted there that these runs had no validation layer.

@oneandonlydean
oneandonlydean merged commit 8b3e398 into boykopovar:main Oct 22, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants