GS: Use textures instead of render targets for target copies

Saves the clear.
This commit is contained in:
Connor McLaughlin 2021-12-19 19:41:30 +10:00 committed by refractionpcsx2
parent 4c3df1a963
commit 5976be55f4
6 changed files with 70 additions and 29 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -752,6 +752,31 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, u32 c)
ClearRenderTarget(t, color);
}
void GSDeviceOGL::InvalidateRenderTarget(GSTexture* t)
{
GSTextureOGL* T = static_cast<GSTextureOGL*>(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)

View File

@ -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;

View File

@ -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;