From a32ab4cc978a1bbd543e76c72ef6e8b96b5bd9c8 Mon Sep 17 00:00:00 2001 From: Stenzek <stenzek@gmail.com> Date: Sun, 23 Apr 2023 15:17:08 +1000 Subject: [PATCH] GS: Refactor ResizeTexture() to ResizeRenderTarget() --- pcsx2/GS/Renderers/Common/GSDevice.cpp | 104 ++++++++++------------- pcsx2/GS/Renderers/Common/GSDevice.h | 6 +- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 8 +- pcsx2/GS/Renderers/SW/GSRendererSW.cpp | 2 +- 4 files changed, 52 insertions(+), 68 deletions(-) diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp index ec589655c8..20bf175fdb 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.cpp +++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp @@ -380,14 +380,6 @@ GSTexture* GSDevice::CreateTexture(int w, int h, int mipmap_levels, GSTexture::F return FetchSurface(GSTexture::Type::Texture, w, h, levels, format, false, prefer_reuse); } -GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type) -{ - if (type == GSTexture::Type::DepthStencil) - return GSTexture::Format::DepthStencil; - else - return GSTexture::Format::Color; -} - void GSDevice::StretchRect(GSTexture* sTex, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear) { StretchRect(sTex, GSVector4(0, 0, 1, 1), dTex, dRect, shader, linear); @@ -441,7 +433,7 @@ void GSDevice::ClearCurrent() void GSDevice::Merge(GSTexture* sTex[3], GSVector4* sRect, GSVector4* dRect, const GSVector2i& fs, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) { - if (ResizeTarget(&m_merge, fs.x, fs.y)) + if (ResizeRenderTarget(&m_merge, fs.x, fs.y, false, false)) DoMerge(sTex, sRect, m_merge, dRect, PMODE, EXTBUF, c, GSConfig.PCRTCOffsets); m_current = m_merge; @@ -481,20 +473,20 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse switch (mode) { case 0: // Weave - ResizeTarget(&m_weavebob, ds.x, ds.y); + ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, false, offset, field); m_current = m_weavebob; break; case 1: // Bob // Field is reversed here as we are countering the bounce. - ResizeTarget(&m_weavebob, ds.x, ds.y); + ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); do_interlace(m_merge, m_weavebob, ShaderInterlace::BOB, true, yoffset * (1 - field), 0); m_current = m_weavebob; break; case 2: // Blend - ResizeTarget(&m_weavebob, ds.x, ds.y); + ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); do_interlace(m_merge, m_weavebob, ShaderInterlace::WEAVE, false, offset, field); - ResizeTarget(&m_blend, ds.x, ds.y); + ResizeRenderTarget(&m_blend, ds.x, ds.y, true, false); do_interlace(m_weavebob, m_blend, ShaderInterlace::BLEND, false, 0, 0); m_current = m_blend; break; @@ -503,9 +495,9 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse bufIdx &= ~1; bufIdx |= field; bufIdx &= 3; - ResizeTarget(&m_mad, ds.x, ds.y * 2.0f); + ResizeRenderTarget(&m_mad, ds.x, ds.y * 2.0f, true, false); do_interlace(m_merge, m_mad, ShaderInterlace::MAD_BUFFER, false, offset, bufIdx); - ResizeTarget(&m_weavebob, ds.x, ds.y); + ResizeRenderTarget(&m_weavebob, ds.x, ds.y, true, false); do_interlace(m_mad, m_weavebob, ShaderInterlace::MAD_RECONSTRUCT, false, 0, bufIdx); m_current = m_weavebob; break; @@ -519,9 +511,8 @@ void GSDevice::FXAA() { // Combining FXAA+ShadeBoost can't share the same target. GSTexture*& dTex = (m_current == m_target_tmp) ? m_merge : m_target_tmp; - if (ResizeTexture(&dTex, GSTexture::Type::RenderTarget, m_current->GetWidth(), m_current->GetHeight(), false, true)) + if (ResizeRenderTarget(&dTex, m_current->GetWidth(), m_current->GetHeight(), false, false)) { - InvalidateRenderTarget(dTex); DoFXAA(m_current, dTex); m_current = dTex; } @@ -529,10 +520,8 @@ void GSDevice::FXAA() void GSDevice::ShadeBoost() { - if (ResizeTexture(&m_target_tmp, GSTexture::Type::RenderTarget, m_current->GetWidth(), m_current->GetHeight(), false, true)) + if (ResizeRenderTarget(&m_target_tmp, m_current->GetWidth(), m_current->GetHeight(), false, false)) { - InvalidateRenderTarget(m_target_tmp); - // predivide to avoid the divide (multiply) in the shader const float params[4] = { static_cast<float>(GSConfig.ShadeBoost_Brightness) * (1.0f / 50.0f), @@ -557,7 +546,7 @@ void GSDevice::Resize(int width, int height) s = m_current->GetSize() * GSVector2i(++multiplier); } - if (ResizeTexture(&dTex, GSTexture::Type::RenderTarget, s.x, s.y, false)) + if (ResizeRenderTarget(&dTex, s.x, s.y, false, false)) { const GSVector4 sRect(0, 0, 1, 1); const GSVector4 dRect(0, 0, s.x, s.y); @@ -566,55 +555,48 @@ void GSDevice::Resize(int width, int height) } } -bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h, bool clear, bool prefer_reuse) +bool GSDevice::ResizeRenderTarget(GSTexture** t, int w, int h, bool preserve_contents, bool recycle) { - if (t == NULL) + pxAssert(t); + + GSTexture* orig_tex = *t; + if (orig_tex && orig_tex->GetWidth() == w && orig_tex->GetHeight() == h) { - ASSERT(0); + if (!preserve_contents) + InvalidateRenderTarget(orig_tex); + + return true; + } + + GSTexture* new_tex; + try + { + const GSTexture::Format fmt = orig_tex ? orig_tex->GetFormat() : GSTexture::Format::Color; + new_tex = FetchSurface(GSTexture::Type::RenderTarget, w, h, 1, fmt, !preserve_contents, true); + } + catch (std::bad_alloc&) + { + Console.WriteLn("%dx%d texture allocation failed in ResizeTexture()", w, h); return false; } - GSTexture* t2 = *t; - - if (t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h) + if (preserve_contents && orig_tex) { - const GSTexture::Format fmt = t2 ? t2->GetFormat() : GetDefaultTextureFormat(type); - const int levels = t2 ? (t2->IsMipmap() ? MipmapLevelsForSize(w, h) : 1) : 1; - - GSTexture* new_t = FetchSurface(type, w, h, levels, fmt, clear, prefer_reuse); - if (new_t) - { - if (t2) - { - // TODO: We probably want to make this optional if we're overwriting it... - const GSVector4 sRect(0, 0, 1, 1); - const GSVector4 dRect(0, 0, t2->GetWidth(), t2->GetHeight()); - StretchRect(t2, sRect, new_t, dRect, ShaderConvert::COPY, true); - Recycle(t2); - } - - t2 = new_t; - *t = t2; - } + constexpr GSVector4 sRect = GSVector4::cxpr(0, 0, 1, 1); + const GSVector4 dRect = GSVector4(orig_tex->GetRect()); + StretchRect(orig_tex, sRect, new_tex, dRect, ShaderConvert::COPY, true); } - return t2 != NULL; -} + if (orig_tex) + { + if (recycle) + Recycle(orig_tex); + else + delete orig_tex; + } -bool GSDevice::ResizeTexture(GSTexture** t, int w, int h, bool prefer_reuse) -{ - return ResizeTexture(t, GSTexture::Type::Texture, w, h, false, prefer_reuse); -} - -bool GSDevice::ResizeTarget(GSTexture** t, int w, int h) -{ - return ResizeTexture(t, GSTexture::Type::RenderTarget, w, h); -} - -bool GSDevice::ResizeTarget(GSTexture** t) -{ - GSVector2i s = m_current->GetSize(); - return ResizeTexture(t, GSTexture::Type::RenderTarget, s.x, s.y); + *t = new_tex; + return true; } void GSDevice::SetHWDrawConfigForAlphaPass(GSHWDrawConfig::PSSelector* ps, diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index 569551d697..c365fe3ccd 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -890,7 +890,6 @@ public: GSTexture* CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear = true); GSTexture* CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear = true); GSTexture* CreateTexture(int w, int h, int mipmap_levels, GSTexture::Format format, bool prefer_reuse = false); - GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type); virtual std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) = 0; @@ -929,10 +928,7 @@ public: void CAS(GSTexture*& tex, GSVector4i& src_rect, GSVector4& src_uv, const GSVector4& draw_rect, bool sharpen_only); - bool ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h, bool clear = true, bool prefer_reuse = false); - bool ResizeTexture(GSTexture** t, int w, int h, bool prefer_reuse = false); - bool ResizeTarget(GSTexture** t, int w, int h); - bool ResizeTarget(GSTexture** t); + bool ResizeRenderTarget(GSTexture** t, int w, int h, bool preserve_contents, bool recycle); bool IsRBSwapped() { return m_rbswapped; } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 651d7d88c0..e9050e076b 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1268,7 +1268,13 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, (type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY, false); g_perfmon.Put(GSPerfMon::TextureCopies, 1); m_target_memory_usage = (m_target_memory_usage - dst->m_texture->GetMemUsage()) + tex->GetMemUsage(); - g_gs_device->Recycle(dst->m_texture); + + // If we're changing resolution scale, just toss the texture, it's not going to get reused. + if (!GSConfig.UserHacks_NativePaletteDraw || (dst->m_scale != 1.0f && scale != 1.0f)) + delete dst->m_texture; + else + g_gs_device->Recycle(dst->m_texture); + dst->m_texture = tex; dst->m_scale = scale; dst->m_unscaled_size = new_size; diff --git a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp index ffebf84e9b..2de43a19b0 100644 --- a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp +++ b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp @@ -118,7 +118,7 @@ GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset) int w = curFramebuffer.FBW * 64; int h = framebufferSize.y; - if (g_gs_device->ResizeTarget(&m_texture[index], w, h)) + if (g_gs_device->ResizeRenderTarget(&m_texture[index], w, h, false, false)) { const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[curFramebuffer.PSM]; constexpr int pitch = 1024 * 4;