[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.
This commit is contained in:
BZLZHH
2026-08-05 04:46:15 -04:00
parent dd60ff39ce
commit e64c7c7e65
@@ -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<Uint32>(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<Uint32>(resolvedSampleCount) >> 1;
bit > static_cast<Uint32>(VK_SAMPLE_COUNT_1_BIT); bit >>= 1) {
if ((supported & bit) != 0) {
rounded = bit;
break;