From 7f0ab1442e88c821aaf42ee60c09e00aec048a74 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 26 Jun 2024 12:34:55 +1000 Subject: [PATCH] GS/HW: Clear instead of invalidating upscaled targets This'll require a little more VRAM bandwidth, but it's better than sampling random garbage because HPO pushes the coordinates down. --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 18 +++++++++--------- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 16 ++++++++++++++-- pcsx2/Pcsx2Config.cpp | 2 +- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 97bd390334a7e..c3b2eab17fe60 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -6002,12 +6002,12 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta // FIXME D3D11 and GL support half pixel center. Code could be easier!!! const GSTextureCache::Target* rt_or_ds = rt ? rt : ds; - const float rtscale = rt_or_ds ? rt_or_ds->GetScale() : 0.0f; - const GSVector2i rtsize = rt_or_ds ? rt_or_ds->GetTexture()->GetSize() : GSVector2i(0, 0); + const float rtscale = rt_or_ds->GetScale(); + const GSVector2i rtsize = rt_or_ds->GetTexture()->GetSize(); float sx, sy, ox2, oy2; const float ox = static_cast(static_cast(m_context->XYOFFSET.OFX)); const float oy = static_cast(static_cast(m_context->XYOFFSET.OFY)); - if (GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native && (!rt || rt->GetScale() > 1.0f)) + if (GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native && rtscale > 1.0f) { sx = 2.0f * rtscale / (rtsize.x << 4); sy = 2.0f * rtscale / (rtsize.y << 4); @@ -6032,12 +6032,12 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta else { // Align coordinates to native resolution framebuffer, hope for the best. - const int scaled_x = rt_or_ds ? rt_or_ds->GetUnscaledWidth() : 0; - const int scaled_y = rt_or_ds ? rt_or_ds->GetUnscaledHeight() : 0; - sx = 2.0f / (scaled_x << 4); - sy = 2.0f / (scaled_y << 4); - ox2 = -1.0f / scaled_x; - oy2 = -1.0f / scaled_y; + const int unscaled_x = rt_or_ds ? rt_or_ds->GetUnscaledWidth() : 0; + const int unscaled_y = rt_or_ds ? rt_or_ds->GetUnscaledHeight() : 0; + sx = 2.0f / (unscaled_x << 4); + sy = 2.0f / (unscaled_y << 4); + ox2 = -1.0f / unscaled_x; + oy2 = -1.0f / unscaled_y; } m_conf.cb_vs.vertex_scale = GSVector2(sx, sy); diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 3646ef1fc925f..55e0e0f92c109 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -2113,8 +2113,20 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe } // And invalidate the target, we're drawing over it so we don't care what's there. - GL_INS("TC: Invalidating target %s[%x] because it's completely overwritten.", to_string(type), dst->m_TEX0.TBP0); - g_gs_device->InvalidateRenderTarget(dst->m_texture); + // We can't do this when upscaling, because of the vertex offset, the top/left rows often aren't drawn. + GL_INS("TC: Invalidating%s target %s[%x] because it's completely overwritten.", to_string(type), + (scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::Native) ? "[clearing] " : "", dst->m_TEX0.TBP0); + if (scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native) + { + if (dst->m_type == RenderTarget) + g_gs_device->ClearRenderTarget(dst->m_texture, 0); + else + g_gs_device->ClearDepth(dst->m_texture, 0.0f); + } + else + { + g_gs_device->InvalidateRenderTarget(dst->m_texture); + } } } } diff --git a/pcsx2/Pcsx2Config.cpp b/pcsx2/Pcsx2Config.cpp index a79a10bd315bb..ccb179f7c3df4 100644 --- a/pcsx2/Pcsx2Config.cpp +++ b/pcsx2/Pcsx2Config.cpp @@ -884,7 +884,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap) SettingsWrapEntryEx(UpscaleMultiplier, "upscale_multiplier"); // ~51x would the upper bound here for 32768x32768 textures, but you'll run out VRAM long before then. - UpscaleMultiplier = std::clamp(UpscaleMultiplier, 0.5f, 50.0f); + UpscaleMultiplier = std::clamp(UpscaleMultiplier, 1.0f, 50.0f); SettingsWrapBitBoolEx(HWMipmap, "hw_mipmap"); SettingsWrapIntEnumEx(AccurateBlendingUnit, "accurate_blending_unit");