[Fix] (DirectVulkan): back legacy low-bit formats (RGB565/RGB5A1/RGBA4/R3G3B2/RGB4/RGBA2/RGB10/12) with their UNorm8/16 canonical shadow layouts and add capability fallbacks - they mapped to VK_FORMAT_UNDEFINED and crashed or wedged the GPU on upload; also admit 2DMSArray/CubeMap/3D color attachment targets in the render pass

This commit is contained in:
2026-07-26 13:28:30 -04:00
parent db01bfa3e8
commit 5e676b338b
3 changed files with 34 additions and 0 deletions
@@ -140,6 +140,20 @@ namespace MobileGL::MG_Backend::DirectVulkan {
case TextureInternalFormat::RGB:
case TextureInternalFormat::RGB8:
return TextureInternalFormat::RGBA8;
// Legacy low-bit-depth formats with no (or rarely supported) native Vulkan
// encoding; a wider normalized fallback keeps at least the required precision.
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5:
case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1:
return TextureInternalFormat::RGBA8;
case TextureInternalFormat::RGB10:
return TextureInternalFormat::RGB10A2;
case TextureInternalFormat::RGB12:
case TextureInternalFormat::RGBA12:
return TextureInternalFormat::RGBA16;
case TextureInternalFormat::SRGB8:
return TextureInternalFormat::SRGB8Alpha8;
case TextureInternalFormat::RGB8Snorm:
@@ -791,6 +791,10 @@ namespace MobileGL::MG_Backend::DirectVulkan {
case TextureTarget::Texture2D:
case TextureTarget::Texture2DArray:
case TextureTarget::Texture2DMultisample:
case TextureTarget::Texture2DMultisampleArray:
case TextureTarget::Texture3D:
case TextureTarget::TextureCubeMap:
case TextureTarget::TextureCubeMapArray:
case TextureTarget::TextureRectangle: {
desc.flags = 0;
desc.format = isDefaultFbo ?
@@ -375,7 +375,23 @@ namespace MobileGL::MG_Backend::DirectVulkan {
switch (format) {
case TextureInternalFormat::RGB:
case TextureInternalFormat::RGB8:
// Legacy low-bit RGB formats share the UNorm8 canonical shadow layout (see
// TextureFormatProcessor), so they upload exactly like RGB8 with an alpha expand.
case TextureInternalFormat::R3G3B2:
case TextureInternalFormat::RGB4:
case TextureInternalFormat::RGB5:
return {VK_FORMAT_R8G8B8A8_UNORM, true, 1, {0xFF, 0x00, 0x00, 0x00}};
// Low-bit RGBA formats: UNorm8x4 canonical shadow, no expansion needed.
case TextureInternalFormat::RGBA2:
case TextureInternalFormat::RGBA4:
case TextureInternalFormat::RGB5A1:
return {VK_FORMAT_R8G8B8A8_UNORM, false, 0, {0, 0, 0, 0}};
// 10/12-bit RGB(A): UNorm16 canonical shadow.
case TextureInternalFormat::RGB10:
case TextureInternalFormat::RGB12:
return {VK_FORMAT_R16G16B16A16_UNORM, true, 2, {0xFF, 0xFF, 0x00, 0x00}};
case TextureInternalFormat::RGBA12:
return {VK_FORMAT_R16G16B16A16_UNORM, false, 0, {0, 0, 0, 0}};
case TextureInternalFormat::SRGB8:
return {VK_FORMAT_R8G8B8A8_SRGB, true, 1, {0xFF, 0x00, 0x00, 0x00}};
case TextureInternalFormat::RGB8Snorm: