GS-hw: rework surface fetching.

Factorized code.
Always clear render targets and depth stencils
when being fetched.
"force_texture_clear" OGL only config removed.
This commit is contained in:
iMineLink 2021-12-07 19:47:26 +01:00 committed by lightningterror
parent 0f2768dca4
commit 2e6c5cde29
6 changed files with 44 additions and 108 deletions

View File

@ -1134,7 +1134,6 @@ void GSApp::Init()
m_default_configuration["extrathreads"] = "2";
m_default_configuration["extrathreads_height"] = "4";
m_default_configuration["filter"] = std::to_string(static_cast<s8>(BiFiltering::PS2));
m_default_configuration["force_texture_clear"] = "0";
m_default_configuration["fxaa"] = "0";
m_default_configuration["interlace"] = "7";
m_default_configuration["conservative_framebuffer"] = "1";

View File

@ -66,9 +66,7 @@ GSDevice::GSDevice()
GSDevice::~GSDevice()
{
for (auto t : m_pool)
delete t;
PurgePool();
delete m_backbuffer;
delete m_merge;
delete m_weavebob;
@ -83,10 +81,7 @@ bool GSDevice::Create(const WindowInfo& wi)
bool GSDevice::Reset(int w, int h)
{
for (auto t : m_pool)
delete t;
m_pool.clear();
PurgePool();
delete m_backbuffer;
delete m_merge;
@ -94,13 +89,13 @@ bool GSDevice::Reset(int w, int h)
delete m_blend;
delete m_target_tmp;
m_backbuffer = NULL;
m_merge = NULL;
m_weavebob = NULL;
m_blend = NULL;
m_target_tmp = NULL;
m_backbuffer = nullptr;
m_merge = nullptr;
m_weavebob = nullptr;
m_blend = nullptr;
m_target_tmp = nullptr;
m_current = NULL; // current is special, points to other textures, no need to delete
m_current = nullptr; // current is special, points to other textures, no need to delete
return true;
}
@ -139,19 +134,44 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture:
{
const GSVector2i size(w, h);
GSTexture* t = nullptr;
for (auto i = m_pool.begin(); i != m_pool.end(); ++i)
{
GSTexture* t = *i;
t = *i;
assert(t);
if (t->GetType() == type && t->GetFormat() == format && t->GetSize() == size)
{
m_pool.erase(i);
return t;
break;
}
t = nullptr;
}
return CreateSurface(type, w, h, format);
if (!t)
t = CreateSurface(type, w, h, format);
if (!t)
throw std::bad_alloc();
t->Commit(); // Clear won't be done if the texture isn't committed.
switch (type)
{
case GSTexture::Type::RenderTarget:
ClearRenderTarget(t, 0);
break;
case GSTexture::Type::DepthStencil:
ClearDepth(t);
break;
default:
break;
}
return t;
}
void GSDevice::PrintMemoryUsage()
@ -214,13 +234,9 @@ void GSDevice::AgePool()
void GSDevice::PurgePool()
{
// OOM emergency. Let's free this useless pool
while (!m_pool.empty())
{
delete m_pool.back();
m_pool.pop_back();
}
for (auto t : m_pool)
delete t;
m_pool.clear();
}
GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format)

View File

@ -629,7 +629,7 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTextu
break;
}
GSTexture11* t = NULL;
GSTexture11* t = nullptr;
wil::com_ptr_nothrow<ID3D11Texture2D> texture;
HRESULT hr = m_dev->CreateTexture2D(&desc, nullptr, texture.put());
@ -637,16 +637,7 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTextu
if (SUCCEEDED(hr))
{
t = new GSTexture11(std::move(texture), format);
switch (type)
{
case GSTexture::Type::RenderTarget:
ClearRenderTarget(t, 0);
break;
case GSTexture::Type::DepthStencil:
ClearDepth(t);
break;
}
assert(type == t->GetType());
}
else
{
@ -656,11 +647,6 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTextu
return t;
}
GSTexture* GSDevice11::FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format)
{
return __super::FetchSurface(type, w, h, format);
}
bool GSDevice11::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map)
{
ASSERT(src);

View File

@ -397,7 +397,6 @@ private:
int m_d3d_texsize;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;

View File

@ -49,8 +49,7 @@ int GSDeviceOGL::m_shader_reg = 0;
FILE* GSDeviceOGL::m_debug_gl_file = NULL;
GSDeviceOGL::GSDeviceOGL()
: m_force_texture_clear(0)
, m_fbo(0)
: m_fbo(0)
, m_fbo_read(0)
, m_apitrace(0)
, m_palette_ss(0)
@ -238,68 +237,9 @@ GSTexture* GSDeviceOGL::CreateSurface(GSTexture::Type type, int w, int h, GSText
{
GL_PUSH("Create surface");
// A wrapper to call GSTextureOGL, with the different kind of parameter
// A wrapper to call GSTextureOGL, with the different kind of parameters.
GSTextureOGL* t = new GSTextureOGL(type, w, h, fmt, m_fbo_read, m_mipmap > 1 || m_filter != TriFiltering::None);
// NOTE: I'm not sure RenderTarget always need to be cleared. It could be costly for big upscale.
// FIXME: it will be more logical to do it in FetchSurface. This code is only called at first creation
// of the texture. However we could reuse a deleted texture.
if (m_force_texture_clear == 0)
{
// Clear won't be done if the texture isn't committed. Commit the full texture to ensure
// correct behavior of force clear option (debug option)
t->Commit();
switch (type)
{
case GSTexture::Type::RenderTarget:
ClearRenderTarget(t, 0);
break;
case GSTexture::Type::DepthStencil:
ClearDepth(t);
// No need to clear the stencil now.
break;
default:
break;
}
}
return t;
}
GSTexture* GSDeviceOGL::FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format)
{
GSTexture* t = GSDevice::FetchSurface(type, w, h, format);
if (m_force_texture_clear)
{
// Clear won't be done if the texture isn't committed. Commit the full texture to ensure
// correct behavior of force clear option (debug option)
t->Commit();
const GSVector4 red(1.0f, 0.0f, 0.0f, 1.0f);
switch (type)
{
case GSTexture::Type::RenderTarget:
ClearRenderTarget(t, 0);
break;
case GSTexture::Type::DepthStencil:
ClearDepth(t);
// No need to clear the stencil now.
break;
case GSTexture::Type::Texture:
if (m_force_texture_clear > 1)
static_cast<GSTextureOGL*>(t)->Clear((void*)&red);
else if (m_force_texture_clear)
static_cast<GSTextureOGL*>(t)->Clear(NULL);
break;
default:
break;
}
}
return t;
}
@ -346,8 +286,6 @@ bool GSDeviceOGL::Create(const WindowInfo& wi)
}
#endif
m_force_texture_clear = theApp.GetConfigI("force_texture_clear");
// WARNING it must be done after the control setup (at least on MESA)
GL_PUSH("GSDeviceOGL::Create");

View File

@ -462,7 +462,6 @@ public:
private:
std::unique_ptr<GL::Context> m_gl_context;
int m_force_texture_clear;
int m_mipmap;
TriFiltering m_filter;
@ -559,7 +558,6 @@ private:
AlignedBuffer<u8, 32> m_download_buffer;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
GSTexture* FetchSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final;
void DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex, GSVector4* dRect, const GSRegPMODE& PMODE, const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;