From e7ea1da99f6a96977670b0603e3a40409718640c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 26 Mar 2016 13:17:17 -0700 Subject: [PATCH] Vulkan: Swizzle instead of converting colors. --- Common/Vulkan/VulkanImage.cpp | 14 +++++--- Common/Vulkan/VulkanImage.h | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 58 +++++++++++++++++++------------ 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/Common/Vulkan/VulkanImage.cpp b/Common/Vulkan/VulkanImage.cpp index 205c360bb4..86484b0547 100644 --- a/Common/Vulkan/VulkanImage.cpp +++ b/Common/Vulkan/VulkanImage.cpp @@ -240,7 +240,7 @@ void VulkanTexture::Wipe() { } } -void VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkImageUsageFlags usage) { +void VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkImageUsageFlags usage, const VkComponentMapping *mapping) { Wipe(); VkCommandBuffer cmd = vulkan_->GetInitCommandBuffer(); @@ -294,10 +294,14 @@ void VulkanTexture::CreateDirect(int w, int h, int numMips, VkFormat format, VkI view_info.image = VK_NULL_HANDLE; view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; view_info.format = format_; - view_info.components.r = VK_COMPONENT_SWIZZLE_R; - view_info.components.g = VK_COMPONENT_SWIZZLE_G; - view_info.components.b = VK_COMPONENT_SWIZZLE_B; - view_info.components.a = VK_COMPONENT_SWIZZLE_A; + if (mapping) { + view_info.components = *mapping; + } else { + view_info.components.r = VK_COMPONENT_SWIZZLE_R; + view_info.components.g = VK_COMPONENT_SWIZZLE_G; + view_info.components.b = VK_COMPONENT_SWIZZLE_B; + view_info.components.a = VK_COMPONENT_SWIZZLE_A; + } view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; view_info.subresourceRange.baseMipLevel = 0; view_info.subresourceRange.levelCount = numMips; diff --git a/Common/Vulkan/VulkanImage.h b/Common/Vulkan/VulkanImage.h index fe2dbe6dbd..3b0a3ece81 100644 --- a/Common/Vulkan/VulkanImage.h +++ b/Common/Vulkan/VulkanImage.h @@ -26,7 +26,7 @@ public: void Unlock(); // Fast uploads from buffer. Mipmaps supported. Usage must at least include VK_IMAGE_USAGE_TRANSFER_DST_BIT in order to use UploadMip. - void CreateDirect(int w, int h, int numMips, VkFormat format, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + void CreateDirect(int w, int h, int numMips, VkFormat format, VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, const VkComponentMapping *mapping = nullptr); void UploadMip(int mip, int mipWidth, int mipHeight, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels void EndCreate(); int GetNumMips() const { return numMips_; } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 9672c8efbc..04d0b1785c 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -69,13 +69,17 @@ #define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in GL #define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024 -// TODO: Except for color swizzle, exact matches are available. -// So we can get rid of the conversion functions entirely. -#define VULKAN_4444_FORMAT VK_FORMAT_R4G4B4A4_UNORM_PACK16 -#define VULKAN_1555_FORMAT VK_FORMAT_R5G5B5A1_UNORM_PACK16 -#define VULKAN_565_FORMAT VK_FORMAT_R5G6B5_UNORM_PACK16 +// Note: some drivers prefer B4G4R4A4_UNORM_PACK16 over R4G4B4A4_UNORM_PACK16. +#define VULKAN_4444_FORMAT VK_FORMAT_B4G4R4A4_UNORM_PACK16 +#define VULKAN_1555_FORMAT VK_FORMAT_A1R5G5B5_UNORM_PACK16 +#define VULKAN_565_FORMAT VK_FORMAT_B5G6R5_UNORM_PACK16 #define VULKAN_8888_FORMAT VK_FORMAT_R8G8B8A8_UNORM +static const VkComponentMapping VULKAN_4444_SWIZZLE = { VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B }; +static const VkComponentMapping VULKAN_1555_SWIZZLE = { VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A }; +static const VkComponentMapping VULKAN_565_SWIZZLE = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; +static const VkComponentMapping VULKAN_8888_SWIZZLE = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; + // Hack! extern int g_iNumVideos; @@ -620,14 +624,10 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, VkFormat dstFmt, int u32 *dst = (u32 *)dstBuf; switch (dstFmt) { case VULKAN_4444_FORMAT: - ConvertRGBA4444ToABGR4444((u16 *)dst, (const u16 *)src, numPixels); - break; - // Final Fantasy 2 uses this heavily in animated textures. case VULKAN_1555_FORMAT: - ConvertRGBA5551ToABGR1555((u16 *)dst, (const u16 *)src, numPixels); - break; case VULKAN_565_FORMAT: - ConvertRGB565ToBGR565((u16 *)dst, (const u16 *)src, numPixels); + if (dst != src) + memcpy(dst, src, numPixels * sizeof(u16)); break; default: // No need to convert RGBA8888, right order already @@ -680,15 +680,7 @@ void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutB const u32 clutExtendedBytes = std::min(clutTotalBytes_ + clutBaseBytes, clutMaxBytes_); clutHash_ = DoReliableHash32((const char *)clutBufRaw_, clutExtendedBytes, 0xC0108888); - - // Avoid a copy when we don't need to convert colors. - if (clutFormat != GE_CMODE_32BIT_ABGR8888) { - const int numColors = clutFormat == GE_CMODE_32BIT_ABGR8888 ? (clutMaxBytes_ / sizeof(u32)) : (clutMaxBytes_ / sizeof(u16)); - ConvertColors(clutBufConverted_, clutBufRaw_, getClutDestFormatVulkan(clutFormat), numColors); - clutBuf_ = clutBufConverted_; - } else { - clutBuf_ = clutBufRaw_; - } + clutBuf_ = clutBufRaw_; // Special optimization: fonts typically draw clut4 with just alpha values in a single color. clutAlphaLinear_ = false; @@ -1405,7 +1397,27 @@ void TextureCacheVulkan::SetTexture(VulkanPushBuffer *uploadBuffer) { entry->vkTex = new CachedTextureVulkan(); entry->vkTex->texture_ = new VulkanTexture(vulkan_); VulkanTexture *image = entry->vkTex->texture_; - image->CreateDirect(w * scaleFactor, h * scaleFactor, maxLevel + 1, dstFmt); + + const VkComponentMapping *mapping; + switch (dstFmt) { + case VULKAN_4444_FORMAT: + mapping = &VULKAN_4444_SWIZZLE; + break; + + case VULKAN_1555_FORMAT: + mapping = &VULKAN_1555_SWIZZLE; + break; + + case VULKAN_565_FORMAT: + mapping = &VULKAN_565_SWIZZLE; + break; + + default: + mapping = &VULKAN_8888_SWIZZLE; + break; + } + + image->CreateDirect(w * scaleFactor, h * scaleFactor, maxLevel + 1, dstFmt, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, mapping); } lastBoundTexture = entry->vkTex; @@ -1647,10 +1659,10 @@ TextureCacheVulkan::TexCacheEntry::Status TextureCacheVulkan::CheckAlpha(const u CheckAlphaResult res; switch (dstFmt) { case VULKAN_4444_FORMAT: - res = CheckAlphaABGR4444Basic(pixelData, stride, w, h); + res = CheckAlphaRGBA4444Basic(pixelData, stride, w, h); break; case VULKAN_1555_FORMAT: - res = CheckAlphaABGR1555Basic(pixelData, stride, w, h); + res = CheckAlphaRGBA5551Basic(pixelData, stride, w, h); break; case VULKAN_565_FORMAT: // Never has any alpha.