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"] = "2";
m_default_configuration["extrathreads_height"] = "4"; m_default_configuration["extrathreads_height"] = "4";
m_default_configuration["filter"] = std::to_string(static_cast<s8>(BiFiltering::PS2)); 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["fxaa"] = "0";
m_default_configuration["interlace"] = "7"; m_default_configuration["interlace"] = "7";
m_default_configuration["conservative_framebuffer"] = "1"; m_default_configuration["conservative_framebuffer"] = "1";

View File

@ -66,9 +66,7 @@ GSDevice::GSDevice()
GSDevice::~GSDevice() GSDevice::~GSDevice()
{ {
for (auto t : m_pool) PurgePool();
delete t;
delete m_backbuffer; delete m_backbuffer;
delete m_merge; delete m_merge;
delete m_weavebob; delete m_weavebob;
@ -83,10 +81,7 @@ bool GSDevice::Create(const WindowInfo& wi)
bool GSDevice::Reset(int w, int h) bool GSDevice::Reset(int w, int h)
{ {
for (auto t : m_pool) PurgePool();
delete t;
m_pool.clear();
delete m_backbuffer; delete m_backbuffer;
delete m_merge; delete m_merge;
@ -94,13 +89,13 @@ bool GSDevice::Reset(int w, int h)
delete m_blend; delete m_blend;
delete m_target_tmp; delete m_target_tmp;
m_backbuffer = NULL; m_backbuffer = nullptr;
m_merge = NULL; m_merge = nullptr;
m_weavebob = NULL; m_weavebob = nullptr;
m_blend = NULL; m_blend = nullptr;
m_target_tmp = NULL; 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; return true;
} }
@ -139,19 +134,44 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int w, int h, GSTexture:
{ {
const GSVector2i size(w, h); const GSVector2i size(w, h);
GSTexture* t = nullptr;
for (auto i = m_pool.begin(); i != m_pool.end(); ++i) 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) if (t->GetType() == type && t->GetFormat() == format && t->GetSize() == size)
{ {
m_pool.erase(i); m_pool.erase(i);
break;
return t;
} }
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() void GSDevice::PrintMemoryUsage()
@ -214,13 +234,9 @@ void GSDevice::AgePool()
void GSDevice::PurgePool() void GSDevice::PurgePool()
{ {
// OOM emergency. Let's free this useless pool for (auto t : m_pool)
while (!m_pool.empty()) delete t;
{ m_pool.clear();
delete m_pool.back();
m_pool.pop_back();
}
} }
GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format) 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; break;
} }
GSTexture11* t = NULL; GSTexture11* t = nullptr;
wil::com_ptr_nothrow<ID3D11Texture2D> texture; wil::com_ptr_nothrow<ID3D11Texture2D> texture;
HRESULT hr = m_dev->CreateTexture2D(&desc, nullptr, texture.put()); 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)) if (SUCCEEDED(hr))
{ {
t = new GSTexture11(std::move(texture), format); t = new GSTexture11(std::move(texture), format);
assert(type == t->GetType());
switch (type)
{
case GSTexture::Type::RenderTarget:
ClearRenderTarget(t, 0);
break;
case GSTexture::Type::DepthStencil:
ClearDepth(t);
break;
}
} }
else else
{ {
@ -656,11 +647,6 @@ GSTexture* GSDevice11::CreateSurface(GSTexture::Type type, int w, int h, GSTextu
return t; 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) bool GSDevice11::DownloadTexture(GSTexture* src, const GSVector4i& rect, GSTexture::GSMap& out_map)
{ {
ASSERT(src); ASSERT(src);

View File

@ -397,7 +397,6 @@ private:
int m_d3d_texsize; int m_d3d_texsize;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final; 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 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; 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; FILE* GSDeviceOGL::m_debug_gl_file = NULL;
GSDeviceOGL::GSDeviceOGL() GSDeviceOGL::GSDeviceOGL()
: m_force_texture_clear(0) : m_fbo(0)
, m_fbo(0)
, m_fbo_read(0) , m_fbo_read(0)
, m_apitrace(0) , m_apitrace(0)
, m_palette_ss(0) , m_palette_ss(0)
@ -238,68 +237,9 @@ GSTexture* GSDeviceOGL::CreateSurface(GSTexture::Type type, int w, int h, GSText
{ {
GL_PUSH("Create surface"); 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); 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; return t;
} }
@ -346,8 +286,6 @@ bool GSDeviceOGL::Create(const WindowInfo& wi)
} }
#endif #endif
m_force_texture_clear = theApp.GetConfigI("force_texture_clear");
// WARNING it must be done after the control setup (at least on MESA) // WARNING it must be done after the control setup (at least on MESA)
GL_PUSH("GSDeviceOGL::Create"); GL_PUSH("GSDeviceOGL::Create");

View File

@ -462,7 +462,6 @@ public:
private: private:
std::unique_ptr<GL::Context> m_gl_context; std::unique_ptr<GL::Context> m_gl_context;
int m_force_texture_clear;
int m_mipmap; int m_mipmap;
TriFiltering m_filter; TriFiltering m_filter;
@ -559,7 +558,6 @@ private:
AlignedBuffer<u8, 32> m_download_buffer; AlignedBuffer<u8, 32> m_download_buffer;
GSTexture* CreateSurface(GSTexture::Type type, int w, int h, GSTexture::Format format) final; 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 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; void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;