From 77825484a073dd430372dea2166ba59a2753f365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Nov 2023 11:34:55 +0100 Subject: [PATCH] If available, use 16-bit texture formats for MakePixelTexture when appropriate. Optimization for God of War on low-end platforms. Avoids calling a color conversion function that's currently only SIMD-optimized on x86, so will also benefit ARM a little bit. --- Common/Data/Convert/ColorConv.cpp | 1 + GPU/Common/FramebufferManagerCommon.cpp | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Common/Data/Convert/ColorConv.cpp b/Common/Data/Convert/ColorConv.cpp index 01c434e6e5a9..ba32cc098737 100644 --- a/Common/Data/Convert/ColorConv.cpp +++ b/Common/Data/Convert/ColorConv.cpp @@ -617,6 +617,7 @@ void ConvertRGB565ToBGR565(u16 *dst, const u16 *src, u32 numPixels) { u32 i = 0; #endif + // TODO: Add a 64-bit loop too. const u32 *src32 = (const u32 *)src; u32 *dst32 = (u32 *)dst; for (; i < numPixels / 2; i++) { diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 6a8cab187704..ac7a401d794a 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1342,6 +1342,14 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G // No usable single channel format. Can't be bothered. return nullptr; } + } else if (srcPixelFormat == GE_FORMAT_565) { + // Check for supported matching formats. + // This mainly benefits the redundant copies in God of War on low-end platforms. + if ((draw_->GetDataFormatSupport(Draw::DataFormat::B5G6R5_UNORM_PACK16) & Draw::FMT_TEXTURE) != 0) { + texFormat = Draw::DataFormat::B5G6R5_UNORM_PACK16; + } else if ((draw_->GetDataFormatSupport(Draw::DataFormat::R5G6B5_UNORM_PACK16) & Draw::FMT_TEXTURE) != 0) { + texFormat = Draw::DataFormat::R5G6B5_UNORM_PACK16; + } } // TODO: We can just change the texture format and flip some bits around instead of this. @@ -1355,10 +1363,15 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G u8 *dst8 = (u8 *)(data + byteStride * y); switch (srcPixelFormat) { case GE_FORMAT_565: - if (texFormat == Draw::DataFormat::B8G8R8A8_UNORM) + if (texFormat == Draw::DataFormat::B5G6R5_UNORM_PACK16) { + memcpy(dst16, src16, w * sizeof(uint16_t)); + } else if (texFormat == Draw::DataFormat::R5G6B5_UNORM_PACK16) { + ConvertRGB565ToBGR565(dst16, src16, width); // Fast! + } else if (texFormat == Draw::DataFormat::B8G8R8A8_UNORM) { ConvertRGB565ToBGRA8888(dst, src16, width); - else + } else { ConvertRGB565ToRGBA8888(dst, src16, width); + } break; case GE_FORMAT_5551: