From e64c7c7e651c2827c3dc094a313210faa50b4f9d Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Wed, 5 Aug 2026 04:46:15 -0400 Subject: [PATCH] [Fix] (MG_Backend): never back a multisample texture with a one-sample Vulkan image Every one of the sixty direct_state_access.textures_storage_multisample_2d_* and _3d_* cases failed on DirectVulkan, for every internal format, with no GL error anywhere - a pure data mismatch. The CTS asks for glTextureStorage2DMultisample(tex, samples = 1, ...), which is legal GL, and MobileGL carried the 1 faithfully through to VkImageCreateInfo::samples = VK_SAMPLE_COUNT_1_BIT. It then binds that image to the auxiliary program's sampler2DMS, whose SPIR-V is OpTypeImage with MS = 1. VUID-RuntimeSpirv-samples-08726 forbids exactly that pairing: an MS access must come from an image created with more than one sample. The texelFetch therefore read undefined data - which is why it looked format-independent and raised nothing. GL only promises "at least the requested number of samples", so a multisample texture is now floored at two. GL_TEXTURE_SAMPLES still reports what the application asked for; that is read off the texture object, not off the image. The device-capability round below it is bounded at two for the same reason - letting it land back on one sample would recreate the violation silently for any format whose only supported count is one. Takes all 60 textures_storage_multisample_* cases from failing to passing on DirectVulkan, which goes from 296/371 to 356/371. DirectGLES is untouched. --- .../DirectVulkan/Renderer/VkTextureManager.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp index 9306a6d1..fcd1b809 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VkTextureManager.cpp @@ -1518,6 +1518,16 @@ namespace MobileGL::MG_Backend::DirectVulkan { MG_Util::ConvertTextureUploadTargetToString(uploadTarget).c_str()); return false; } + // glTexStorage*Multisample(samples = 1) is legal GL, but a one-sample image cannot back a + // sampler2DMS: VUID-RuntimeSpirv-samples-08726 forbids an OpTypeImage with MS = 1 from + // reading an image created with VK_SAMPLE_COUNT_1_BIT, and the fetch returns undefined data + // rather than an error. GL only promises "at least the requested number of samples", so + // giving a multisample texture two is both legal and the only way to keep the shader's view + // of it honest. GL_TEXTURE_SAMPLES still reports what the application asked for - that is + // read off the texture object, not off the image. + if (isMultisampleTexture && resolvedSampleCount == VK_SAMPLE_COUNT_1_BIT) { + resolvedSampleCount = VK_SAMPLE_COUNT_2_BIT; + } const VkImageAspectFlags aspect = GetAspectMaskForFormat(format); VkFormatProperties formatProperties{}; @@ -1593,7 +1603,11 @@ namespace MobileGL::MG_Backend::DirectVulkan { } } if (rounded == 0) { - for (Uint32 bit = static_cast(resolvedSampleCount) >> 1; bit != 0; bit >>= 1) { + // Never land on one sample: that is the VUID-RuntimeSpirv-samples-08726 + // violation the floor above exists to avoid, and it would come back silently + // for any format whose only supported count is 1. + for (Uint32 bit = static_cast(resolvedSampleCount) >> 1; + bit > static_cast(VK_SAMPLE_COUNT_1_BIT); bit >>= 1) { if ((supported & bit) != 0) { rounded = bit; break;