diff --git a/pcsx2/GS/Renderers/HW/GSTextureReplacements.cpp b/pcsx2/GS/Renderers/HW/GSTextureReplacements.cpp index 0accf065cf..2592c56547 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureReplacements.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureReplacements.cpp @@ -117,6 +117,8 @@ namespace GSTextureReplacements static std::optional ParseReplacementName(const std::string& filename); static std::string GetGameTextureDirectory(); static std::string GetDumpFilename(const TextureName& name, u32 level); + template + std::pair GetBCAlphaMinMax(ReplacementTexture& rtex); static void SetReplacementTextureAlphaMinMax(ReplacementTexture& rtex); static std::optional LoadReplacementTexture(const TextureName& name, const std::string& filename, bool only_base_image); static void QueueAsyncReplacementTextureLoad(const TextureName& name, const std::string& filename, bool mipmap, bool cache_only); @@ -485,61 +487,80 @@ GSTexture* GSTextureReplacements::LookupReplacementTexture(const GSTextureCache: } } -void GSTextureReplacements::SetReplacementTextureAlphaMinMax(ReplacementTexture& rtex) +template +std::pair GSTextureReplacements::GetBCAlphaMinMax(ReplacementTexture& rtex) { - if (rtex.format >= GSTexture::Format::BC1 && rtex.format <= GSTexture::Format::BC7) + constexpr u32 BC_BLOCK_SIZE = 4; + constexpr u32 BC_BLOCK_BYTES = (format == GSTexture::Format::BC1) ? 8 : 16; + + const u32 blocks_wide = (rtex.width + (BC_BLOCK_SIZE - 1)) / BC_BLOCK_SIZE; + const u32 blocks_high = (rtex.height + (BC_BLOCK_SIZE - 1)) / BC_BLOCK_SIZE; + + GSVector4i minc = GSVector4i::xffffffff(); + GSVector4i maxc = GSVector4i::zero(); + + for (u32 y = 0; y < blocks_high; y++) { - constexpr u32 BC_BLOCK_SIZE = 4; - constexpr u32 BC_BLOCK_BYTES = 16; + const u8* block_in = rtex.data.data() + y * rtex.pitch; + alignas(16) u8 block_pixels_out[BC_BLOCK_SIZE * BC_BLOCK_SIZE * sizeof(u32)]; - const u32 blocks_wide = (rtex.width + (BC_BLOCK_SIZE - 1)) / BC_BLOCK_SIZE; - const u32 blocks_high = (rtex.height + (BC_BLOCK_SIZE - 1)) / BC_BLOCK_SIZE; - - GSVector4i minc = GSVector4i::xffffffff(); - GSVector4i maxc = GSVector4i::zero(); - - for (u32 y = 0; y < blocks_high; y++) + for (u32 x = 0; x < blocks_wide; x++, block_in += BC_BLOCK_BYTES) { - const u8* block_in = rtex.data.data() + y * rtex.pitch; - alignas(16) u8 block_pixels_out[BC_BLOCK_SIZE * BC_BLOCK_SIZE * sizeof(u32)]; - - for (u32 x = 0; x < blocks_wide; x++, block_in += BC_BLOCK_BYTES) + switch (format) { - switch (rtex.format) - { - case GSTexture::Format::BC1: - DecompressBlockBC1(0, 0, sizeof(u32) * BC_BLOCK_SIZE, block_in, block_pixels_out); - break; - case GSTexture::Format::BC2: - DecompressBlockBC2(0, 0, sizeof(u32) * BC_BLOCK_SIZE, block_in, block_pixels_out); - break; - case GSTexture::Format::BC3: - DecompressBlockBC3(0, 0, sizeof(u32) * BC_BLOCK_SIZE, block_in, block_pixels_out); - break; + case GSTexture::Format::BC1: + DecompressBlockBC1(0, 0, sizeof(u32) * BC_BLOCK_SIZE, block_in, block_pixels_out); + break; + case GSTexture::Format::BC2: + DecompressBlockBC2(0, 0, sizeof(u32) * BC_BLOCK_SIZE, block_in, block_pixels_out); + break; + case GSTexture::Format::BC3: + DecompressBlockBC3(0, 0, sizeof(u32) * BC_BLOCK_SIZE, block_in, block_pixels_out); + break; - case GSTexture::Format::BC7: - bc7decomp::unpack_bc7(block_in, reinterpret_cast(block_pixels_out)); - break; - } + case GSTexture::Format::BC7: + bc7decomp::unpack_bc7(block_in, reinterpret_cast(block_pixels_out)); + break; + } - const u8* out_ptr = block_pixels_out; - for (u32 i = 0; i < ((BC_BLOCK_SIZE * BC_BLOCK_SIZE * sizeof(u32)) / sizeof(GSVector4i)); i++) - { - const GSVector4i v = GSVector4i::load(out_ptr); - out_ptr += sizeof(GSVector4i); - minc = minc.min_u32(v); - maxc = maxc.max_u32(v); - } + const u8* out_ptr = block_pixels_out; + for (u32 i = 0; i < ((BC_BLOCK_SIZE * BC_BLOCK_SIZE * sizeof(u32)) / sizeof(GSVector4i)); i++) + { + const GSVector4i v = GSVector4i::load(out_ptr); + out_ptr += sizeof(GSVector4i); + minc = minc.min_u32(v); + maxc = maxc.max_u32(v); } } - - rtex.alpha_minmax = - std::make_pair(static_cast(minc.minv_u32() >> 24), static_cast(maxc.maxv_u32() >> 24)); } - else + + return std::make_pair(static_cast(minc.minv_u32() >> 24), static_cast(maxc.maxv_u32() >> 24)); +} + +void GSTextureReplacements::SetReplacementTextureAlphaMinMax(ReplacementTexture& rtex) +{ + switch (rtex.format) { - pxAssert(rtex.format == GSTexture::Format::Color); - rtex.alpha_minmax = GSGetRGBA8AlphaMinMax(rtex.data.data(), rtex.width, rtex.height, rtex.pitch); + case GSTexture::Format::BC1: + rtex.alpha_minmax = GetBCAlphaMinMax(rtex); + break; + + case GSTexture::Format::BC2: + rtex.alpha_minmax = GetBCAlphaMinMax(rtex); + break; + + case GSTexture::Format::BC3: + rtex.alpha_minmax = GetBCAlphaMinMax(rtex); + break; + + case GSTexture::Format::BC7: + rtex.alpha_minmax = GetBCAlphaMinMax(rtex); + break; + + default: + pxAssert(rtex.format == GSTexture::Format::Color); + rtex.alpha_minmax = GSGetRGBA8AlphaMinMax(rtex.data.data(), rtex.width, rtex.height, rtex.pitch); + break; } }