From 2a74cb83d94e10bc32b180f8bafdce62d680afeb Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Mon, 10 Jun 2024 22:46:10 +0100 Subject: [PATCH] GS/HW: Improve detection of upscaling and downscaling --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 36 ++++++++++++++++-------- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 237218d53676a9..410c2940756bc3 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -7141,27 +7141,39 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps) if (GSConfig.UserHacks_NativeScaling == GSNativeScaling::Off) return 0; + if (m_context->TEX1.MMAG != 1 || m_vt.m_primclass < GS_TRIANGLE_CLASS || m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 || + IsMipMapDraw() || GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 8 || !src || !src->m_from_target) + return 0; + const GSVector2i draw_size = GSVector2i(m_vt.m_max.p.x - m_vt.m_min.p.x, m_vt.m_max.p.y - m_vt.m_min.p.y); const GSVector2i tex_size = GSVector2i(m_vt.m_max.t.x - m_vt.m_min.t.x, m_vt.m_max.t.y - m_vt.m_min.t.y); - // Check if we're already downscaled and drawing in current size, try not to rescale it. - if (src && src->m_from_target && (std::abs(draw_size.x - tex_size.x) <= 1 && std::abs(draw_size.y - tex_size.y) <= 1)) - return -1; - // Try to detect if a game is downscaling/upscaling the image in order to do post processing/bloom effects. - const bool is_downscale = (tex_size.x / 2.0f) >= (draw_size.x - 1) && (tex_size.y / 2.0f) >= (draw_size.y - 1); - if (is_downscale && draw_size.x >= PCRTCDisplays.GetResolution().x) + // Try to catch cases of stupid draws like Manhunt and Syphon Filter where they sample a single pixel. + if(tex_size.x == 0 || tex_size.y == 0 || draw_size.x == 0 || draw_size.y == 0) return 0; - const bool is_upscale = (draw_size.x / 2.0f) >= (tex_size.x - 1) && (draw_size.y / 2.0f) >= (tex_size.y - 1); + if (std::abs(draw_size.x - tex_size.x) <= 1 && std::abs(draw_size.y - tex_size.y) <= 1) + return -1; + //const bool is_downscale = (tex_size.x / 2.0f) >= (draw_size.x - 1) && (tex_size.y / 2.0f) >= (draw_size.y - 1); + // Should usually be 2x but some games like Monster House goes from 512x448 -> 128x128 + + const bool is_downscale = draw_size.x <= (tex_size.x - draw_size.x) || draw_size.y <= (tex_size.y - draw_size.y); + + //if (is_downscale != is_downscale2) + // DevCon.Warning("Is down %d down2 is %d draw %d", is_downscale, is_downscale2, s_n); + if (is_downscale && draw_size.x >= PCRTCDisplays.GetResolution().x) + return 0; + const bool is_upscale = (draw_size.x / tex_size.x) >= 4 || (draw_size.y / tex_size.y) >= 4; // DMC does a blit in strips with the scissor to keep it inside page boundaries, so that's not technically full coverage // but good enough for what we want. - const bool no_gaps_or_single_sprite = (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && SpriteDrawWithoutGaps())); - if (no_gaps_or_single_sprite && m_vt.m_primclass >= GS_TRIANGLE_CLASS && m_context->TEX1.MMAG == 1 && src && src->m_from_target && - GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp > 8 && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && !IsMipMapDraw() && - ((is_upscale && !IsDiscardingDstColor()) || (((PRIM->ABE && m_context->ALPHA.C == 2 && m_context->ALPHA.FIX == 255) || IsDiscardingDstColor()) && is_downscale))) + const bool no_gaps_or_single_sprite = (is_downscale || is_upscale) && (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && SpriteDrawWithoutGaps())); + + const bool dst_discarded = IsDiscardingDstColor(); + if (no_gaps_or_single_sprite && ((is_upscale && !dst_discarded) || + (is_downscale && (dst_discarded || (PRIM->ABE && m_context->ALPHA.C == 2 && m_context->ALPHA.FIX == 255))))) { - GL_INS("%s draw detected - from %dx%d to %dx%d", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y); + DevCon.Warning("%s draw detected - from %dx%d to %dx%d draw %d", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y, s_n); return is_upscale ? 2 : 1; } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index d0f7220dfc18c4..f09ccc7f8a7465 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1984,7 +1984,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe dst->m_TEX0.TBP0, dst->m_TEX0.TBW, psm_str(dst->m_TEX0.PSM)); } - if (dst->m_scale != scale && (!preserve_scale || is_shuffle || (dst->m_downscaled && dst->m_scale >= scale))) + if (dst->m_scale != scale && (!preserve_scale || is_shuffle || (dst->m_downscaled && dst->m_scale >= scale) || TEX0.TBW != dst->m_TEX0.TBW)) { calcRescale(dst); GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, clear) :