From e1a2faf5c24d717a8eccc56897b1d42688bde9b1 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Wed, 2 Sep 2026 02:37:34 +0100 Subject: [PATCH] GS/HW: Fix regression where target updates ignored bilinear --- pcsx2/GS/Renderers/Common/GSDevice.h | 11 +++++++++-- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 16 +++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index 9ef0233ef6..db56528b1a 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -375,6 +375,13 @@ public: return ShaderEntryPoint(Shader()); } + constexpr ShaderConvertSelector SetShader(ShaderConvert shader = ShaderConvert::COPY) + { + ShaderConvertSelector tmp = *this; + tmp.fields.shader = static_cast(shader); + return tmp; + } + constexpr ShaderConvertSelector SetMask(u8 mask = 0xf) const { ShaderConvertSelector tmp = *this; @@ -446,7 +453,7 @@ public: }; static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTexture::Format dst, - u32 src_bpp = 32, u32 dst_bpp = 32, u8 mask = 0xf) + u32 src_bpp = 32, u32 dst_bpp = 32, u8 mask = 0xf, Filter linear = Nearest) { ShaderConvert shader = static_cast(-1); switch (src) @@ -531,7 +538,7 @@ static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTe break; } - return ShaderConvertSelector(shader, mask, dst == GSTexture::Format::DepthStencil); + return ShaderConvertSelector(shader, mask, dst == GSTexture::Format::DepthStencil, linear); } static inline ShaderConvertSelector GetConvertShader(const GSTexture* src, const GSTexture* dst, u32 src_bpp, u32 dst_bpp, u8 mask = 0xf) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index fcc597dde9..d869e54ada 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -7963,8 +7963,9 @@ void GSTextureCache::Target::Update(bool cannot_scale) // Bilinear filtering this is probably not a good thing, at least in native, but upscaling Nearest can be gross and messy. // It's needed for depth, though.. filtering depth doesn't make much sense, but SMT3 needs it.. const bool upscaled = (m_scale != 1.0f); + const bool is_depth = m_type == DepthStencil; const bool override_linear = (upscaled && GSConfig.UserHacks_BilinearHack == GSBilinearDirtyMode::ForceBilinear); - const bool linear = (m_type == RenderTarget && upscaled && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest); + const bool linear = (upscaled && ((!is_depth && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest) || is_depth)); GSDevice::MultiStretchRect* drects = static_cast( alloca(sizeof(GSDevice::MultiStretchRect) * static_cast(m_dirty.size()))); @@ -8028,7 +8029,7 @@ void GSTextureCache::Target::Update(bool cannot_scale) drect.src = t; drect.src_rect = GSVector4(update_r - t_offset) / t_sizef; drect.dst_rect = GSVector4(update_r) * GSVector4(m_scale); - drect.filter = BilnIf(linear && (m_dirty[i].req_linear || override_linear)); + drect.filter = BilnIf(linear && (is_depth || m_dirty[i].req_linear || override_linear)); // Copy the new GS memory content into the destination texture. if (m_type == RenderTarget) @@ -8057,12 +8058,13 @@ void GSTextureCache::Target::Update(bool cannot_scale) m_rt_alpha_scale = true; } - const bool linear = upscaled && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest; - // No need to sort here, it's all the one texture. - const ShaderConvertSelector shader = (m_type == RenderTarget) ? - (m_rt_alpha_scale ? ShaderConvert::RTA_CORRECTION : ShaderConvert::COPY) : - GetConvertShader(GSTexture::Format::Color, m_texture->GetFormat(), bpp, bpp, linear); + ShaderConvertSelector shader = GetConvertShader(GSTexture::Format::Color, m_texture->GetFormat(), bpp, bpp, 0xF, drects[0].filter); + + if (m_type == RenderTarget && m_rt_alpha_scale && shader.Shader() == ShaderConvert::COPY) + { + shader = shader.SetShader(ShaderConvert::RTA_CORRECTION); + } g_gs_device->DrawMultiStretchRects(drects, ndrects, m_texture, shader); }