From ecfbbd4e265f1b58618fa2f7770951956d9a553f Mon Sep 17 00:00:00 2001 From: emiyl Date: Fri, 30 Sep 2022 14:28:56 +0100 Subject: [PATCH] MoltenVK: Workaround for unsupported formats (#315) --- .../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 60 +++++++++++++++---- .../HW/Latte/Renderer/Vulkan/VulkanRenderer.h | 2 + 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index fbc268cb..03ffb7f5 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -1929,6 +1929,20 @@ void VulkanRenderer::QueryAvailableFormats() { m_supportedFormatInfo.fmt_r4g4_unorm_pack = true; } + // R4G4B4A4 + fmtProp = {}; + vkGetPhysicalDeviceFormatProperties(m_physical_device, VK_FORMAT_R4G4B4A4_UNORM_PACK16, &fmtProp); + if (fmtProp.optimalTilingFeatures != 0) + { + m_supportedFormatInfo.fmt_r4g4b4a4_unorm_pack = true; + } + // A1R5G5B5 + fmtProp = {}; + vkGetPhysicalDeviceFormatProperties(m_physical_device, VK_FORMAT_A1R5G5B5_UNORM_PACK16, &fmtProp); + if (fmtProp.optimalTilingFeatures != 0) + { + m_supportedFormatInfo.fmt_a1r5g5b5_unorm_pack = true; + } // print info about unsupported formats to log for (auto& it : requestedFormatList) { @@ -2565,8 +2579,14 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD case Latte::E_GX2SURFFMT::R4_G4_UNORM: if (m_supportedFormatInfo.fmt_r4g4_unorm_pack == false) { - formatInfoOut->vkImageFormat = VK_FORMAT_R4G4B4A4_UNORM_PACK16; - formatInfoOut->decoder = TextureDecoder_R4_G4_UNORM_toRGBA4444_vk::getInstance(); + if (m_supportedFormatInfo.fmt_r4g4b4a4_unorm_pack == false) { + formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UNORM; + formatInfoOut->decoder = nullptr; + } + else { + formatInfoOut->vkImageFormat = VK_FORMAT_R4G4B4A4_UNORM_PACK16; + formatInfoOut->decoder = TextureDecoder_R4_G4_UNORM_toRGBA4444_vk::getInstance(); + } } else { @@ -2618,23 +2638,41 @@ void VulkanRenderer::GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isD formatInfoOut->decoder = TextureDecoder_R5_G6_B5_swappedRB::getInstance(); break; case Latte::E_GX2SURFFMT::R5_G5_B5_A1_UNORM: - // used in Super Mario 3D World for the hidden Luigi sprites - // since order of channels is reversed in Vulkan compared to GX2 the format we need is A1B5G5R5 - formatInfoOut->vkImageFormat = VK_FORMAT_A1R5G5B5_UNORM_PACK16; - formatInfoOut->decoder = TextureDecoder_R5_G5_B5_A1_UNORM_swappedRB::getInstance(); + if (m_supportedFormatInfo.fmt_a1r5g5b5_unorm_pack == false) { + formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UNORM; + formatInfoOut->decoder = nullptr; + } + else { + // used in Super Mario 3D World for the hidden Luigi sprites + // since order of channels is reversed in Vulkan compared to GX2 the format we need is A1B5G5R5 + formatInfoOut->vkImageFormat = VK_FORMAT_A1R5G5B5_UNORM_PACK16; + formatInfoOut->decoder = TextureDecoder_R5_G5_B5_A1_UNORM_swappedRB::getInstance(); + } break; case Latte::E_GX2SURFFMT::A1_B5_G5_R5_UNORM: - // used by VC64 (e.g. Ocarina of Time) - formatInfoOut->vkImageFormat = VK_FORMAT_A1R5G5B5_UNORM_PACK16; // A 15 R 10..14, G 5..9 B 0..4 - formatInfoOut->decoder = TextureDecoder_A1_B5_G5_R5_UNORM_vulkan::getInstance(); + if (m_supportedFormatInfo.fmt_a1r5g5b5_unorm_pack == false) { + formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UNORM; + formatInfoOut->decoder = nullptr; + } + else { + // used by VC64 (e.g. Ocarina of Time) + formatInfoOut->vkImageFormat = VK_FORMAT_A1R5G5B5_UNORM_PACK16; // A 15 R 10..14, G 5..9 B 0..4 + formatInfoOut->decoder = TextureDecoder_A1_B5_G5_R5_UNORM_vulkan::getInstance(); + } break; case Latte::E_GX2SURFFMT::R11_G11_B10_FLOAT: formatInfoOut->vkImageFormat = VK_FORMAT_B10G11R11_UFLOAT_PACK32; // verify if order of channels is still the same as GX2 formatInfoOut->decoder = TextureDecoder_R11_G11_B10_FLOAT::getInstance(); break; case Latte::E_GX2SURFFMT::R4_G4_B4_A4_UNORM: - formatInfoOut->vkImageFormat = VK_FORMAT_R4G4B4A4_UNORM_PACK16; // verify order of channels - formatInfoOut->decoder = TextureDecoder_R4_G4_B4_A4_UNORM::getInstance(); + if (m_supportedFormatInfo.fmt_r4g4b4a4_unorm_pack == false) { + formatInfoOut->vkImageFormat = VK_FORMAT_R8G8B8A8_UNORM; + formatInfoOut->decoder = nullptr; + } + else { + formatInfoOut->vkImageFormat = VK_FORMAT_R4G4B4A4_UNORM_PACK16; + formatInfoOut->decoder = TextureDecoder_R4_G4_B4_A4_UNORM::getInstance(); + } break; // special formats - R10G10B10_A2 case Latte::E_GX2SURFFMT::R10_G10_B10_A2_UNORM: diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h index 6b6abf7a..a1f878e8 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h @@ -15,6 +15,8 @@ struct VkSupportedFormatInfo_t { bool fmt_d24_unorm_s8_uint{}; bool fmt_r4g4_unorm_pack{}; + bool fmt_r4g4b4a4_unorm_pack{}; + bool fmt_a1r5g5b5_unorm_pack{}; }; struct VkDescriptorSetInfo