diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp index 2a49f3d8e7..f4a6d93053 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.cpp +++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp @@ -103,7 +103,7 @@ void GSDevice::RestoreAPIState() { } -GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) +GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format, bool clear) { const GSVector2i size(w, h); @@ -135,10 +135,20 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture: switch (type) { case GSTexture::Type::RenderTarget: - ClearRenderTarget(t, 0); + { + if (clear) + ClearRenderTarget(t, 0); + else + InvalidateRenderTarget(t); + } break; case GSTexture::Type::DepthStencil: - ClearDepth(t); + { + if (clear) + ClearDepth(t); + else + InvalidateRenderTarget(t); + } break; default: break; @@ -212,34 +222,34 @@ void GSDevice::PurgePool() m_pool.clear(); } -GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format) +GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format, bool clear) { - return FetchSurface(HasColorSparse() ? GSTexture::Type::SparseRenderTarget : GSTexture::Type::RenderTarget, w, h, format); + return FetchSurface(HasColorSparse() ? GSTexture::Type::SparseRenderTarget : GSTexture::Type::RenderTarget, w, h, format, clear); } -GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, GSTexture::Format format) +GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear) { - return FetchSurface(HasDepthSparse() ? GSTexture::Type::SparseDepthStencil : GSTexture::Type::DepthStencil, w, h, format); + return FetchSurface(HasDepthSparse() ? GSTexture::Type::SparseDepthStencil : GSTexture::Type::DepthStencil, w, h, format, clear); } -GSTexture* GSDevice::CreateRenderTarget(int w, int h, GSTexture::Format format) +GSTexture* GSDevice::CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear) { - return FetchSurface(GSTexture::Type::RenderTarget, w, h, format); + return FetchSurface(GSTexture::Type::RenderTarget, w, h, format, clear); } -GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format) +GSTexture* GSDevice::CreateDepthStencil(int w, int h, GSTexture::Format format, bool clear) { - return FetchSurface(GSTexture::Type::DepthStencil, w, h, format); + return FetchSurface(GSTexture::Type::DepthStencil, w, h, format, clear); } GSTexture* GSDevice::CreateTexture(int w, int h, GSTexture::Format format) { - return FetchSurface(GSTexture::Type::Texture, w, h, format); + return FetchSurface(GSTexture::Type::Texture, w, h, format, false); } GSTexture* GSDevice::CreateOffscreen(int w, int h, GSTexture::Format format) { - return FetchSurface(GSTexture::Type::Offscreen, w, h, format); + return FetchSurface(GSTexture::Type::Offscreen, w, h, format, false); } GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type) @@ -387,7 +397,7 @@ void GSDevice::ShadeBoost() } } -bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h) +bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h, bool clear) { if (t == NULL) { @@ -402,7 +412,7 @@ bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h) GSTexture::Format fmt = t2 ? t2->GetFormat() : GetDefaultTextureFormat(type); delete t2; - t2 = FetchSurface(type, w, h, fmt); + t2 = FetchSurface(type, w, h, fmt, clear); *t = t2; } @@ -410,9 +420,9 @@ bool GSDevice::ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h) return t2 != NULL; } -bool GSDevice::ResizeTexture(GSTexture** t, int w, int h) +bool GSDevice::ResizeTexture(GSTexture** t, int w, int h, bool clear) { - return ResizeTexture(t, GSTexture::Type::Texture, w, h); + return ResizeTexture(t, GSTexture::Type::Texture, w, h, clear); } bool GSDevice::ResizeTarget(GSTexture** t, int w, int h) diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index 4aacfcb187..f64b97387b 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -546,7 +546,7 @@ protected: FeatureSupport m_features; virtual GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) = 0; - virtual GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format); + virtual GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format, bool clear); virtual void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) = 0; virtual void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset) = 0; @@ -584,13 +584,14 @@ public: virtual void ClearRenderTarget(GSTexture* t, const GSVector4& c) {} virtual void ClearRenderTarget(GSTexture* t, u32 c) {} + virtual void InvalidateRenderTarget(GSTexture* t) {} virtual void ClearDepth(GSTexture* t) {} virtual void ClearStencil(GSTexture* t, u8 c) {} - GSTexture* CreateSparseRenderTarget(int w, int h, GSTexture::Format format); - GSTexture* CreateSparseDepthStencil(int w, int h, GSTexture::Format format); - GSTexture* CreateRenderTarget(int w, int h, GSTexture::Format format); - GSTexture* CreateDepthStencil(int w, int h, GSTexture::Format format); + GSTexture* CreateSparseRenderTarget(int w, int h, GSTexture::Format format, bool clear = true); + GSTexture* CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear = true); + 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, GSTexture::Format format); GSTexture* CreateOffscreen(int w, int h, GSTexture::Format format); GSTexture::Format GetDefaultTextureFormat(GSTexture::Type type); @@ -623,8 +624,8 @@ public: void ShadeBoost(); void ExternalFX(); - bool ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h); - bool ResizeTexture(GSTexture** t, int w, int h); + bool ResizeTexture(GSTexture** t, GSTexture::Type type, int w, int h, bool clear = true); + bool ResizeTexture(GSTexture** t, int w, int h, bool clear = true); bool ResizeTarget(GSTexture** t, int w, int h); bool ResizeTarget(GSTexture** t); diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 670579a2cb..dbc6a4f195 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1297,7 +1297,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con int h = (int)(scale.y * th); GSTexture* sTex = dst->m_texture; - GSTexture* dTex = g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color); + GSTexture* dTex = g_gs_device->CreateTexture(w, h, GSTexture::Format::Color); GSVector4i area(x, y, x + w, y + h); g_gs_device->CopyRect(sTex, dTex, area); @@ -1329,7 +1329,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con // So it could be tricky to put in the middle of the DrawPrims // Texture is created to keep code compatibility - GSTexture* dTex = g_gs_device->CreateRenderTarget(tw, th, GSTexture::Format::Color); + GSTexture* dTex = g_gs_device->CreateTexture(tw, th, GSTexture::Format::Color); // Keep a trace of origin of the texture src->m_texture = dTex; @@ -1496,11 +1496,15 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con } GSVector4 sRect(0, 0, w, h); + const bool texture_completely_overwritten = ((sRect == dRect).alltrue()); + const bool use_texture = (texture_completely_overwritten && shader == ShaderConvert::COPY); // Don't be fooled by the name. 'dst' is the old target (hence the input) // 'src' is the new texture cache entry (hence the output) GSTexture* sTex = dst->m_texture; - GSTexture* dTex = g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color); + GSTexture* dTex = use_texture ? + g_gs_device->CreateTexture(w, h, GSTexture::Format::Color) : + g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, !texture_completely_overwritten); src->m_texture = dTex; // GH: by default (m_paltex == 0) GS converts texture to the 32 bit format @@ -1536,7 +1540,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con // copy. Likely a speed boost and memory usage reduction. bool linear = (TEX0.PSM == PSM_PSMCT32 || TEX0.PSM == PSM_PSMCT24); - if ((sRect == dRect).alltrue() && shader == ShaderConvert::COPY) + if (use_texture) { if (half_right) { diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp index 9d1280e068..7e73dd8e68 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.cpp @@ -752,6 +752,31 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, u32 c) ClearRenderTarget(t, color); } +void GSDeviceOGL::InvalidateRenderTarget(GSTexture* t) +{ + GSTextureOGL* T = static_cast(t); + if (!T || T->HasBeenCleaned()) + return; + + if (GLAD_GL_VERSION_4_3 || GLAD_GL_ES_VERSION_3_0) + { + OMSetFBO(m_fbo); + + if (T->GetType() == GSTexture::Type::DepthStencil || T->GetType() == GSTexture::Type::SparseDepthStencil) + { + OMAttachDs(T); + const GLenum attachments[] = {GL_DEPTH_STENCIL_ATTACHMENT}; + glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, std::size(attachments), attachments); + } + else + { + OMAttachRt(T); + const GLenum attachments[] = {GL_COLOR_ATTACHMENT0}; + glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, std::size(attachments), attachments); + } + } +} + void GSDeviceOGL::ClearDepth(GSTexture* t) { if (!t) diff --git a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h index f10e893190..3b3a2cab7f 100644 --- a/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h +++ b/pcsx2/GS/Renderers/OpenGL/GSDeviceOGL.h @@ -336,6 +336,7 @@ public: void ClearRenderTarget(GSTexture* t, const GSVector4& c) final; void ClearRenderTarget(GSTexture* t, u32 c) final; + void InvalidateRenderTarget(GSTexture* t) final; void ClearDepth(GSTexture* t) final; void ClearStencil(GSTexture* t, u8 c) final; diff --git a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp index 77cb0880cf..ba55af5176 100644 --- a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp +++ b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp @@ -146,7 +146,7 @@ GSTexture* GSRendererSW::GetOutput(int i, int& y_offset) // TODO: round up bottom - if (g_gs_device->ResizeTexture(&m_texture[i], w, h)) + if (g_gs_device->ResizeTexture(&m_texture[i], w, h, false)) { static int pitch = 1024 * 4;