GS: Purge sparse texture

Only worked on a limited number of drivers, not reliable, and not
necessary now that we're reducing target sizes, which works better
anyway.
This commit is contained in:
Connor McLaughlin 2022-07-28 23:43:17 +10:00 committed by refractionpcsx2
parent 63b3646e73
commit 742a929966
20 changed files with 36 additions and 379 deletions

View File

@ -1477,8 +1477,6 @@ void GSApp::Init()
m_default_configuration["override_GL_ARB_draw_buffers_blend"] = "-1";
m_default_configuration["override_GL_ARB_gpu_shader5"] = "-1";
m_default_configuration["override_GL_ARB_shader_image_load_store"] = "-1";
m_default_configuration["override_GL_ARB_sparse_texture"] = "-1";
m_default_configuration["override_GL_ARB_sparse_texture2"] = "-1";
m_default_configuration["override_GL_ARB_texture_barrier"] = "-1";
m_default_configuration["OverrideTextureBarriers"] = "-1";
m_default_configuration["OverrideGeometryShaders"] = "-1";

View File

@ -161,12 +161,10 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
}
t->SetScale(GSVector2(1, 1)); // Things seem to assume that all textures come out of here with scale 1...
t->Commit(); // Clear won't be done if the texture isn't committed.
switch (type)
{
case GSTexture::Type::RenderTarget:
case GSTexture::Type::SparseRenderTarget:
{
if (clear)
ClearRenderTarget(t, 0);
@ -175,7 +173,6 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
}
break;
case GSTexture::Type::DepthStencil:
case GSTexture::Type::SparseDepthStencil:
{
if (clear)
ClearDepth(t);
@ -215,12 +212,6 @@ void GSDevice::Recycle(GSTexture* t)
{
if (t)
{
#ifdef _DEBUG
// Uncommit saves memory but it means a futur allocation when we want to reuse the texture.
// Which is slow and defeat the purpose of the m_pool cache.
// However, it can help to spot part of texture that we forgot to commit
t->Uncommit();
#endif
t->last_frame_used = m_frame;
m_pool.push_front(t);
@ -259,16 +250,6 @@ void GSDevice::ClearSamplerCache()
{
}
GSTexture* GSDevice::CreateSparseRenderTarget(int w, int h, GSTexture::Format format, bool clear)
{
return FetchSurface(HasColorSparse() ? GSTexture::Type::SparseRenderTarget : GSTexture::Type::RenderTarget, w, h, 1, format, clear, true);
}
GSTexture* GSDevice::CreateSparseDepthStencil(int w, int h, GSTexture::Format format, bool clear)
{
return FetchSurface(HasDepthSparse() ? GSTexture::Type::SparseDepthStencil : GSTexture::Type::DepthStencil, w, h, 1, format, clear, true);
}
GSTexture* GSDevice::CreateRenderTarget(int w, int h, GSTexture::Format format, bool clear)
{
return FetchSurface(GSTexture::Type::RenderTarget, w, h, 1, format, clear, true);
@ -292,7 +273,7 @@ GSTexture* GSDevice::CreateOffscreen(int w, int h, GSTexture::Format format)
GSTexture::Format GSDevice::GetDefaultTextureFormat(GSTexture::Type type)
{
if (type == GSTexture::Type::DepthStencil || type == GSTexture::Type::SparseDepthStencil)
if (type == GSTexture::Type::DepthStencil)
return GSTexture::Format::DepthStencil;
else
return GSTexture::Format::Color;

View File

@ -729,9 +729,6 @@ public:
virtual void BeginScene() {}
virtual void EndScene();
virtual bool HasDepthSparse() { return false; }
virtual bool HasColorSparse() { return false; }
virtual void ClearRenderTarget(GSTexture* t, const GSVector4& c) {}
virtual void ClearRenderTarget(GSTexture* t, u32 c) {}
virtual void InvalidateRenderTarget(GSTexture* t) {}
@ -742,8 +739,6 @@ public:
virtual void PopDebugGroup() {}
virtual void InsertDebugMessage(DebugMessageCategory category, const char* fmt, ...) {}
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, bool mipmap, GSTexture::Format format, bool prefer_reuse = false);

View File

@ -22,13 +22,10 @@
GSTexture::GSTexture()
: m_scale(1, 1)
, m_size(0, 0)
, m_committed_size(0, 0)
, m_gpu_page_size(0, 0)
, m_mipmap_levels(0)
, m_type(Type::Invalid)
, m_format(Format::Invalid)
, m_state(State::Dirty)
, m_sparse(false)
, m_needs_mipmaps_generated(true)
, last_frame_used(0)
, OffsetHack_modxy(0.0f)
@ -73,12 +70,10 @@ void GSTexture::Swap(GSTexture* tex)
{
std::swap(m_scale, tex->m_scale);
std::swap(m_size, tex->m_size);
std::swap(m_committed_size, tex->m_committed_size);
std::swap(m_mipmap_levels, tex->m_mipmap_levels);
std::swap(m_type, tex->m_type);
std::swap(m_format, tex->m_format);
std::swap(m_state, tex->m_state);
std::swap(m_sparse, tex->m_sparse);
std::swap(m_needs_mipmaps_generated, tex->m_needs_mipmaps_generated);
std::swap(last_frame_used, tex->last_frame_used);
std::swap(OffsetHack_modxy, tex->OffsetHack_modxy);
@ -133,55 +128,3 @@ void GSTexture::GenerateMipmapsIfNeeded()
m_needs_mipmaps_generated = false;
GenerateMipmap();
}
void GSTexture::CommitRegion(const GSVector2i& region)
{
if (!m_sparse)
return;
GSVector2i aligned_region = RoundUpPage(region);
aligned_region.x = std::max(m_committed_size.x, aligned_region.x);
aligned_region.y = std::max(m_committed_size.y, aligned_region.y);
if (aligned_region != m_committed_size)
CommitPages(aligned_region, true);
}
void GSTexture::Commit()
{
if (!m_sparse)
return;
if (m_committed_size != m_size)
CommitPages(m_size, true);
}
void GSTexture::Uncommit()
{
if (!m_sparse)
return;
GSVector2i zero = GSVector2i(0, 0);
if (m_committed_size != zero)
CommitPages(m_committed_size, false);
}
void GSTexture::SetGpuPageSize(const GSVector2i& page_size)
{
pxAssert(std::bitset<32>(page_size.x + 1).count() == 1);
pxAssert(std::bitset<32>(page_size.y + 1).count() == 1);
m_gpu_page_size = page_size;
}
GSVector2i GSTexture::RoundUpPage(GSVector2i v)
{
v.x = std::min(m_size.x, v.x);
v.y = std::min(m_size.y, v.y);
v.x += m_gpu_page_size.x;
v.y += m_gpu_page_size.y;
v.x &= ~m_gpu_page_size.x;
v.y &= ~m_gpu_page_size.y;
return v;
}

View File

@ -33,8 +33,6 @@ public:
DepthStencil,
Texture,
Offscreen,
SparseRenderTarget,
SparseDepthStencil,
};
enum class Format : u8
@ -63,25 +61,16 @@ public:
protected:
GSVector2 m_scale;
GSVector2i m_size;
GSVector2i m_committed_size;
GSVector2i m_gpu_page_size;
int m_mipmap_levels;
Type m_type;
Format m_format;
State m_state;
bool m_sparse;
bool m_needs_mipmaps_generated;
public:
GSTexture();
virtual ~GSTexture() {}
virtual operator bool()
{
pxAssert(0);
return false;
}
// Returns the native handle of a texture.
virtual void* GetNativeHandle() const = 0;
@ -113,16 +102,15 @@ public:
bool IsRenderTargetOrDepthStencil() const
{
return (m_type >= Type::RenderTarget && m_type <= Type::DepthStencil) ||
(m_type >= Type::SparseRenderTarget && m_type <= Type::SparseDepthStencil);
return (m_type >= Type::RenderTarget && m_type <= Type::DepthStencil);
}
bool IsRenderTarget() const
{
return (m_type == Type::RenderTarget || m_type == Type::SparseRenderTarget);
return (m_type == Type::RenderTarget);
}
bool IsDepthStencil() const
{
return (m_type == Type::DepthStencil || m_type == Type::SparseDepthStencil);
return (m_type == Type::DepthStencil);
}
State GetState() const { return m_state; }
@ -131,14 +119,6 @@ public:
void GenerateMipmapsIfNeeded();
void ClearMipmapGenerationFlag() { m_needs_mipmaps_generated = false; }
virtual void CommitPages(const GSVector2i& region, bool commit) {}
void CommitRegion(const GSVector2i& region);
void Commit();
void Uncommit();
GSVector2i GetCommittedSize() const { return m_committed_size; }
void SetGpuPageSize(const GSVector2i& page_size);
GSVector2i RoundUpPage(GSVector2i v);
// frame number (arbitrary base) the texture was recycled on
// different purpose than texture cache ages, do not attempt to merge
unsigned last_frame_used;
@ -146,7 +126,7 @@ public:
float OffsetHack_modxy;
// Typical size of a RGBA texture
virtual u32 GetMemUsage() { return m_size.x * m_size.y * (m_format == Format::UNorm8 ? 1 : 4); }
u32 GetMemUsage() const { return m_size.x * m_size.y * (m_format == Format::UNorm8 ? 1 : 4); }
// Helper routines for formats/types
static bool IsCompressedFormat(Format format) { return (format >= Format::BC1 && format <= Format::BC7); }

View File

@ -1370,7 +1370,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
const GSVector4 dRect(config.drawarea);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::FloatColor);
hdr_rt->CommitRegion(GSVector2i(config.drawarea.z, config.drawarea.w));
// Warning: StretchRect must be called before BeginScene otherwise
// vertices will be overwritten. Trust me you don't want to do that.
StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::COPY, false);

View File

@ -319,8 +319,7 @@ void GSDevice12::LookupNativeFormat(GSTexture::Format format, DXGI_FORMAT* d3d_f
GSTexture* GSDevice12::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
{
pxAssert(type != GSTexture::Type::Offscreen && type != GSTexture::Type::SparseRenderTarget &&
type != GSTexture::Type::SparseDepthStencil);
pxAssert(type != GSTexture::Type::Offscreen);
const u32 clamped_width = static_cast<u32>(std::clamp<int>(1, width, D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION));
const u32 clamped_height = static_cast<u32>(std::clamp<int>(1, height, D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION));

View File

@ -3520,12 +3520,6 @@ void GSRendererHW::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sourc
SetupIA(sx, sy);
if (rt)
rt->CommitRegion(GSVector2i(m_conf.drawarea.z, m_conf.drawarea.w));
if (ds)
ds->CommitRegion(GSVector2i(m_conf.drawarea.z, m_conf.drawarea.w));
m_conf.alpha_second_pass.enable = ate_second_pass;
if (ate_second_pass)
@ -4226,9 +4220,6 @@ void GSRendererHW::OI_DoubleHalfClear(GSTextureCache::Target*& rt, GSTextureCach
// If both buffers are side by side we can expect a fast clear in on-going
const u32 color = v[1].RGBAQ.U32[0];
const GSVector4i commitRect = ComputeBoundingBox(rt->m_texture->GetScale(), rt->m_texture->GetSize());
rt->m_texture->CommitRegion(GSVector2i(commitRect.z, commitRect.w));
g_gs_device->ClearRenderTarget(rt->m_texture, color);
}
}
@ -4513,8 +4504,6 @@ bool GSRendererHW::OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source*
{
// random battle transition (z buffer written directly, clear it now)
GL_INS("OI_FFX ZB clear");
if (ds)
ds->Commit(); // Don't bother to save few MB for a single game
g_gs_device->ClearDepth(ds);
}
@ -4566,7 +4555,6 @@ bool GSRendererHW::OI_RozenMaidenGebetGarden(GSTexture* rt, GSTexture* ds, GSTex
if (GSTextureCache::Target* tmp_rt = m_tc->LookupTarget(TEX0, GetTargetSize(), GSTextureCache::RenderTarget, true))
{
GL_INS("OI_RozenMaidenGebetGarden FB clear");
tmp_rt->m_texture->Commit(); // Don't bother to save few MB for a single game
g_gs_device->ClearRenderTarget(tmp_rt->m_texture, 0);
}
@ -4585,7 +4573,6 @@ bool GSRendererHW::OI_RozenMaidenGebetGarden(GSTexture* rt, GSTexture* ds, GSTex
if (GSTextureCache::Target* tmp_ds = m_tc->LookupTarget(TEX0, GetTargetSize(), GSTextureCache::DepthStencil, true))
{
GL_INS("OI_RozenMaidenGebetGarden ZB clear");
tmp_ds->m_texture->Commit(); // Don't bother to save few MB for a single game
g_gs_device->ClearDepth(tmp_ds->m_texture);
}
@ -4705,8 +4692,6 @@ bool GSRendererHW::OI_SuperManReturns(GSTexture* rt, GSTexture* ds, GSTextureCac
ASSERT((v->RGBAQ.A << 24 | v->RGBAQ.B << 16 | v->RGBAQ.G << 8 | v->RGBAQ.R) == (int)v->XYZ.Z);
// Do a direct write
if (rt)
rt->Commit(); // Don't bother to save few MB for a single game
g_gs_device->ClearRenderTarget(rt, GSVector4(m_vt.m_min.c));
m_tc->InvalidateVideoMemType(GSTextureCache::DepthStencil, ctx->FRAME.Block());
@ -4743,8 +4728,6 @@ bool GSRendererHW::OI_ArTonelico2(GSTexture* rt, GSTexture* ds, GSTextureCache::
if (m_vertex.next == 2 && !PRIM->TME && m_context->FRAME.FBW == 10 && v->XYZ.Z == 0 && m_context->TEST.ZTST == ZTST_ALWAYS)
{
GL_INS("OI_ArTonelico2");
if (ds)
ds->Commit(); // Don't bother to save few MB for a single game
g_gs_device->ClearDepth(ds);
}

View File

@ -521,8 +521,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
if (new_s != old_s)
{
calcRescale(dst->m_texture);
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateSparseRenderTarget(new_size.x, new_size.y, GSTexture::Format::Color, clear) :
g_gs_device->CreateSparseDepthStencil(new_size.x, new_size.y, GSTexture::Format::DepthStencil, clear);
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_size.x, new_size.y, GSTexture::Format::Color, clear) :
g_gs_device->CreateDepthStencil(new_size.x, new_size.y, GSTexture::Format::DepthStencil, clear);
g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, (type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY, false);
g_gs_device->Recycle(dst->m_texture);
tex->SetScale(new_s);
@ -1878,13 +1878,13 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int
if (type == RenderTarget)
{
t->m_texture = g_gs_device->CreateSparseRenderTarget(w, h, GSTexture::Format::Color, clear);
t->m_texture = g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, clear);
t->m_used = true; // FIXME
}
else if (type == DepthStencil)
{
t->m_texture = g_gs_device->CreateSparseDepthStencil(w, h, GSTexture::Format::DepthStencil, clear);
t->m_texture = g_gs_device->CreateDepthStencil(w, h, GSTexture::Format::DepthStencil, clear);
}
t->m_texture->SetScale(static_cast<GSRendererHW*>(g_gs_renderer.get())->GetTextureScaleFactor());
@ -2078,8 +2078,8 @@ void GSTextureCache::Surface::ResizeTexture(int new_width, int new_height, GSVec
const bool clear = (new_width > width || new_height > height);
GSTexture* tex = m_texture->IsDepthStencil() ?
g_gs_device->CreateSparseDepthStencil(new_width, new_height, m_texture->GetFormat(), clear) :
g_gs_device->CreateSparseRenderTarget(new_width, new_height, m_texture->GetFormat(), clear);
g_gs_device->CreateDepthStencil(new_width, new_height, m_texture->GetFormat(), clear) :
g_gs_device->CreateRenderTarget(new_width, new_height, m_texture->GetFormat(), clear);
if (!tex)
{
Console.Error("(GSTextureCache::Surface::ResizeTexture) Failed to allocate %dx%d texture", new_width, new_height);

View File

@ -402,7 +402,6 @@ GSTexture* GSDeviceMTL::CreateSurface(GSTexture::Type type, int width, int heigh
[desc setUsage:MTLTextureUsageRenderTarget];
break;
case GSTexture::Type::RenderTarget:
case GSTexture::Type::SparseRenderTarget:
if (m_dev.features.slow_color_compression)
[desc setUsage:MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget | MTLTextureUsagePixelFormatView]; // Force color compression off by including PixelFormatView
else

View File

@ -122,7 +122,7 @@ namespace Emulate_DSA
// Replace function pointer to emulate DSA behavior
void Init()
{
fprintf(stderr, "DSA is not supported. Expect slower performance\n");
Console.Warning("DSA is not supported. Expect slower performance");
glBindTextureUnit = BindTextureUnit;
glCreateTextures = CreateTexture;
glTextureStorage2D = TextureStorage;
@ -139,15 +139,6 @@ namespace Emulate_DSA
namespace GLLoader
{
#define fprintf_once(out, ...) \
do \
if (s_first_load) \
fprintf(out, __VA_ARGS__); \
while (0);
bool s_first_load = true;
bool vendor_id_amd = false;
bool vendor_id_nvidia = false;
bool vendor_id_intel = false;
@ -162,10 +153,6 @@ namespace GLLoader
bool found_GL_ARB_gpu_shader5 = false; // Require IvyBridge
bool found_GL_ARB_shader_image_load_store = false; // Intel IB. Nvidia/AMD miss Mesa implementation.
// In case sparse2 isn't supported
bool found_compatible_GL_ARB_sparse_texture2 = false;
bool found_compatible_sparse_depth = false;
static bool mandatory(const std::string& ext)
{
if (!GLExtension::Has(ext))
@ -183,11 +170,11 @@ namespace GLLoader
if (!found)
{
fprintf_once(stdout, "INFO: %s is NOT SUPPORTED\n", name.c_str());
DevCon.Warning("INFO: %s is NOT SUPPORTED", name.c_str());
}
else
{
fprintf_once(stdout, "INFO: %s is available\n", name.c_str());
DevCon.WriteLn("INFO: %s is available", name.c_str());
}
std::string opt("override_");
@ -276,9 +263,6 @@ namespace GLLoader
// Extra
{
// Bonus
optional("GL_ARB_sparse_texture");
optional("GL_ARB_sparse_texture2");
// GL4.0
found_GL_ARB_gpu_shader5 = optional("GL_ARB_gpu_shader5");
// GL4.2
@ -302,30 +286,30 @@ namespace GLLoader
if (vendor_id_amd)
{
fprintf_once(stderr, "The OpenGL hardware renderer is slow on AMD GPUs due to an inefficient driver.\n"
Console.Warning("The OpenGL hardware renderer is slow on AMD GPUs due to an inefficient driver.\n"
"Check out the link below for further information.\n"
"https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-AMD-GPUs---All-you-need-to-know\n");
"https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-AMD-GPUs---All-you-need-to-know");
}
if (vendor_id_intel && (!GLExtension::Has("GL_ARB_texture_barrier") || !GLExtension::Has("GL_ARB_direct_state_access")))
{
// Assume that driver support is good when texture barrier and DSA is supported, disable the log then.
fprintf_once(stderr, "The OpenGL renderer is inefficient on Intel GPUs due to an inefficient driver.\n"
Console.Warning("The OpenGL renderer is inefficient on Intel GPUs due to an inefficient driver.\n"
"Check out the link below for further information.\n"
"https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-Intel-GPUs-All-you-need-to-know\n");
"https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-Intel-GPUs-All-you-need-to-know");
}
if (!GLExtension::Has("GL_ARB_viewport_array"))
{
glScissorIndexed = ReplaceGL::ScissorIndexed;
glViewportIndexedf = ReplaceGL::ViewportIndexedf;
fprintf_once(stderr, "GL_ARB_viewport_array is not supported! Function pointer will be replaced\n");
Console.Warning("GL_ARB_viewport_array is not supported! Function pointer will be replaced");
}
if (!GLExtension::Has("GL_ARB_texture_barrier"))
{
glTextureBarrier = ReplaceGL::TextureBarrier;
fprintf_once(stderr, "GL_ARB_texture_barrier is not supported! Blending emulation will not be supported\n");
Console.Warning("GL_ARB_texture_barrier is not supported! Blending emulation will not be supported");
}
#ifdef _WIN32
@ -339,70 +323,6 @@ namespace GLLoader
return true;
}
bool is_sparse2_compatible(const char* name, GLenum internal_fmt, int x_max, int y_max)
{
GLint index_count = 0;
glGetInternalformativ(GL_TEXTURE_2D, internal_fmt, GL_NUM_VIRTUAL_PAGE_SIZES_ARB, 1, &index_count);
if (!index_count)
{
fprintf_once(stdout, "%s isn't sparse compatible. No index found\n", name);
return false;
}
GLint x, y;
glGetInternalformativ(GL_TEXTURE_2D, internal_fmt, GL_VIRTUAL_PAGE_SIZE_X_ARB, 1, &x);
glGetInternalformativ(GL_TEXTURE_2D, internal_fmt, GL_VIRTUAL_PAGE_SIZE_Y_ARB, 1, &y);
if (x > x_max && y > y_max)
{
fprintf_once(stdout, "%s isn't sparse compatible. Page size (%d,%d) is too big (%d, %d)\n",
name, x, y, x_max, y_max);
return false;
}
return true;
}
static void check_sparse_compatibility()
{
if (!GLExtension::Has("GL_ARB_sparse_texture") ||
!GLExtension::Has("GL_EXT_direct_state_access") ||
theApp.GetConfigI("override_GL_ARB_sparse_texture") != 1)
{
found_compatible_GL_ARB_sparse_texture2 = false;
found_compatible_sparse_depth = false;
return;
}
found_compatible_GL_ARB_sparse_texture2 = true;
if (!GLExtension::Has("GL_ARB_sparse_texture2"))
{
// Only check format from GSTextureOGL
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_R8", GL_R8, 256, 256);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_R16UI", GL_R16UI, 256, 128);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_R32UI", GL_R32UI, 128, 128);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_R32I", GL_R32I, 128, 128);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_RGBA8", GL_RGBA8, 128, 128);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_RGBA16", GL_RGBA16, 128, 64);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_RGBA16I", GL_RGBA16I, 128, 64);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_RGBA16UI", GL_RGBA16UI, 128, 64);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_RGBA16F", GL_RGBA16F, 128, 64);
found_compatible_GL_ARB_sparse_texture2 &= is_sparse2_compatible("GL_RGBA32F", GL_RGBA32F, 64, 64);
}
// Can fit in 128x64 but 128x128 is enough
// Disable sparse depth for AMD. Bad driver strikes again.
// driver reports a compatible sparse format for depth texture but it isn't attachable to a frame buffer.
found_compatible_sparse_depth = !vendor_id_amd && is_sparse2_compatible("GL_DEPTH32F_STENCIL8", GL_DEPTH32F_STENCIL8, 128, 128);
fprintf_once(stdout, "INFO: sparse color texture is %s\n", found_compatible_GL_ARB_sparse_texture2 ? "available" : "NOT SUPPORTED");
fprintf_once(stdout, "INFO: sparse depth texture is %s\n", found_compatible_sparse_depth ? "available" : "NOT SUPPORTED");
}
bool check_gl_requirements()
{
if (!check_gl_version(3, 3))
@ -411,12 +331,6 @@ namespace GLLoader
if (!check_gl_supported_extension())
return false;
// Bonus for sparse texture
check_sparse_compatibility();
fprintf_once(stdout, "\n");
s_first_load = false;
return true;
}
} // namespace GLLoader

View File

@ -45,7 +45,4 @@ namespace GLLoader
extern bool found_GL_ARB_gpu_shader5;
extern bool found_GL_ARB_shader_image_load_store;
extern bool found_GL_ARB_clear_texture;
extern bool found_compatible_GL_ARB_sparse_texture2;
extern bool found_compatible_sparse_depth;
} // namespace GLLoader

View File

@ -774,7 +774,7 @@ void GSDeviceOGL::InvalidateRenderTarget(GSTexture* t)
{
OMSetFBO(m_fbo);
if (T->GetType() == GSTexture::Type::DepthStencil || T->GetType() == GSTexture::Type::SparseDepthStencil)
if (T->GetType() == GSTexture::Type::DepthStencil)
{
OMAttachDs(T);
const GLenum attachments[] = {GL_DEPTH_STENCIL_ATTACHMENT};
@ -1192,7 +1192,6 @@ void GSDeviceOGL::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r
PSSetShaderResource(6, sTex);
#endif
dTex->CommitRegion(GSVector2i(r.z, r.w));
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
ASSERT(GLExtension::Has("GL_ARB_copy_image") && glCopyImageSubData);
@ -1242,7 +1241,6 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
BeginScene();
GL_PUSH("StretchRect from %d to %d", sTex->GetID(), dTex->GetID());
dTex->CommitRegion(GSVector2i((int)dRect.z + 1, (int)dRect.w + 1));
if (draw_in_depth)
OMSetRenderTargets(NULL, dTex);
else
@ -1885,7 +1883,6 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
{
GSVector2i size = config.rt->GetSize();
hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::FloatColor, false);
hdr_rt->CommitRegion(GSVector2i(config.drawarea.z, config.drawarea.w));
OMSetRenderTargets(hdr_rt, config.ds, &config.scissor);
// save blend state, since BlitRect destroys it

View File

@ -377,9 +377,6 @@ public:
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
void OMSetColorMaskState(OMColorMaskSelector sel = OMColorMaskSelector());
bool HasColorSparse() final { return GLLoader::found_compatible_GL_ARB_sparse_texture2; }
bool HasDepthSparse() final { return GLLoader::found_compatible_sparse_depth; }
bool CreateTextureFX();
std::string GetShaderSource(const std::string_view& entry, GLenum type, const std::string_view& common_header, const std::string_view& glsl_h_code, const std::string_view& macro_sel);
std::string GenGlslHeader(const std::string_view& entry, GLenum type, const std::string_view& macro);

View File

@ -181,7 +181,6 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
m_type = type;
m_fbo_read = fbo_read;
m_texture_id = 0;
m_sparse = false;
m_mipmap_levels = 1;
int gl_fmt = 0;
@ -287,56 +286,9 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
ASSERT(0);
}
switch (m_type)
{
case Type::Texture:
// Only 32 bits input texture will be supported for mipmap
m_mipmap_levels = levels;
break;
case Type::SparseRenderTarget:
case Type::SparseDepthStencil:
m_sparse = true;
break;
default:
break;
}
switch (m_format)
{
case Format::UInt16:
case Format::UNorm8:
m_sparse &= GLLoader::found_compatible_GL_ARB_sparse_texture2;
SetGpuPageSize(GSVector2i(255, 255));
break;
case Format::Color:
case Format::UInt32:
case Format::PrimID:
m_sparse &= GLLoader::found_compatible_GL_ARB_sparse_texture2;
SetGpuPageSize(GSVector2i(127, 127));
break;
case Format::FloatColor:
m_sparse &= GLLoader::found_compatible_GL_ARB_sparse_texture2;
SetGpuPageSize(GSVector2i(63, 63));
break;
case Format::DepthStencil:
m_sparse &= GLLoader::found_compatible_sparse_depth;
SetGpuPageSize(GSVector2i(127, 127));
break;
case GSTexture::Format::BC1:
case GSTexture::Format::BC2:
case GSTexture::Format::BC3:
case GSTexture::Format::BC7:
m_sparse = false;
SetGpuPageSize(GSVector2i(127, 127));
break;
case Format::Invalid:
ASSERT(0);
}
// Only 32 bits input texture will be supported for mipmap
if (m_type == Type::Texture)
m_mipmap_levels = levels;
// Create a gl object (texture isn't allocated here)
glCreateTextures(GL_TEXTURE_2D, 1, &m_texture_id);
@ -347,26 +299,8 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
glTextureParameteri(m_texture_id, GL_TEXTURE_SWIZZLE_A, GL_RED);
}
if (m_sparse)
{
GSVector2i old_size = m_size;
m_size = RoundUpPage(m_size);
if (m_size != old_size)
{
fprintf(stderr, "Sparse texture size (%dx%d) isn't a multiple of gpu page size (%dx%d)\n",
old_size.x, old_size.y, m_gpu_page_size.x, m_gpu_page_size.y);
}
glTextureParameteri(m_texture_id, GL_TEXTURE_SPARSE_ARB, true);
}
else
{
m_committed_size = m_size;
}
m_mem_usage = (m_committed_size.x * m_committed_size.y) << m_int_shift;
static int every_512 = 0;
GLState::available_vram -= m_mem_usage;
GLState::available_vram -= GetMemUsage();
if ((GLState::available_vram < 0) && (every_512 % 512 == 0))
{
fprintf(stderr, "Available VRAM is very low (%lld), a crash is expected! Enable conservative buffer allocation or reduce upscaling!\n", GLState::available_vram);
@ -394,7 +328,7 @@ GSTextureOGL::~GSTextureOGL()
glDeleteTextures(1, &m_texture_id);
GLState::available_vram += m_mem_usage;
GLState::available_vram += GetMemUsage();
}
void* GSTextureOGL::GetNativeHandle() const
@ -560,44 +494,6 @@ void GSTextureOGL::GenerateMipmap()
glGenerateTextureMipmap(m_texture_id);
}
void GSTextureOGL::CommitPages(const GSVector2i& region, bool commit)
{
GLState::available_vram += m_mem_usage;
if (commit)
{
if (m_committed_size.x == 0)
{
// Nothing allocated so far
GL_INS("CommitPages initial %dx%d of %u", region.x, region.y, m_texture_id);
glTexturePageCommitmentEXT(m_texture_id, GL_TEX_LEVEL_0, 0, 0, 0, region.x, region.y, 1, commit);
}
else
{
GL_INS("CommitPages extend %dx%d to %dx%d of %u", m_committed_size.x, m_committed_size.y, region.x, region.y, m_texture_id);
int w = region.x - m_committed_size.x;
int h = region.y - m_committed_size.y;
// Extend width
glTexturePageCommitmentEXT(m_texture_id, GL_TEX_LEVEL_0, m_committed_size.x, 0, 0, w, m_committed_size.y, 1, commit);
// Extend height
glTexturePageCommitmentEXT(m_texture_id, GL_TEX_LEVEL_0, 0, m_committed_size.y, 0, region.x, h, 1, commit);
}
m_committed_size = region;
}
else
{
// Release everything
GL_INS("CommitPages release of %u", m_texture_id);
glTexturePageCommitmentEXT(m_texture_id, GL_TEX_LEVEL_0, 0, 0, 0, m_committed_size.x, m_committed_size.y, 1, commit);
m_committed_size = GSVector2i(0, 0);
}
m_mem_usage = (m_committed_size.x * m_committed_size.y) << m_int_shift;
GLState::available_vram -= m_mem_usage;
}
GSTexture::GSMap GSTextureOGL::Read(const GSVector4i& r, AlignedBuffer<u8, 32>& buffer)
{
GSMap m;
@ -625,8 +521,8 @@ GSTexture::GSMap GSTextureOGL::Read(const GSVector4i& r, AlignedBuffer<u8, 32>&
bool GSTextureOGL::Save(const std::string& fn)
{
// Collect the texture data
u32 pitch = 4 * m_committed_size.x;
u32 buf_size = pitch * m_committed_size.y * 2; // Note *2 for security (depth/stencil)
u32 pitch = 4 * m_size.x;
u32 buf_size = pitch * m_size.y * 2; // Note *2 for security (depth/stencil)
std::unique_ptr<u8[]> image(new u8[buf_size]);
#ifdef PCSX2_DEVBUILD
GSPng::Format fmt = GSPng::RGB_A_PNG;
@ -634,12 +530,12 @@ bool GSTextureOGL::Save(const std::string& fn)
GSPng::Format fmt = GSPng::RGB_PNG;
#endif
if (IsDepth())
if (IsDepthStencil())
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_texture_id, 0);
glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image.get());
glReadPixels(0, 0, m_size.x, m_size.y, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image.get());
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
@ -648,7 +544,6 @@ bool GSTextureOGL::Save(const std::string& fn)
else if (m_format == Format::PrimID)
{
// Note: 4.5 function used for accurate DATE
// barely used outside of dev and not sparse anyway
glGetTextureImage(m_texture_id, 0, GL_RED_INTEGER, GL_INT, buf_size, image.get());
fmt = GSPng::R32I_PNG;
@ -661,24 +556,24 @@ bool GSTextureOGL::Save(const std::string& fn)
if (m_format == Format::Color)
{
glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image.get());
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image.get());
}
else if (m_format == Format::UInt16)
{
glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, image.get());
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, image.get());
fmt = GSPng::R16I_PNG;
}
else if (m_format == Format::UNorm8)
{
fmt = GSPng::R8I_PNG;
glReadPixels(0, 0, m_committed_size.x, m_committed_size.y, GL_RED, GL_UNSIGNED_BYTE, image.get());
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_BYTE, image.get());
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
int compression = theApp.GetConfigI("png_compression_level");
return GSPng::Save(fmt, fn, image.get(), m_committed_size.x, m_committed_size.y, pitch, compression);
return GSPng::Save(fmt, fn, image.get(), m_size.x, m_size.y, pitch, compression);
}
void GSTextureOGL::Swap(GSTexture* tex)
@ -696,10 +591,4 @@ void GSTextureOGL::Swap(GSTexture* tex)
std::swap(m_int_format, static_cast<GSTextureOGL*>(tex)->m_int_format);
std::swap(m_int_type, static_cast<GSTextureOGL*>(tex)->m_int_type);
std::swap(m_int_shift, static_cast<GSTextureOGL*>(tex)->m_int_shift);
std::swap(m_mem_usage, static_cast<GSTextureOGL*>(tex)->m_mem_usage);
}
u32 GSTextureOGL::GetMemUsage()
{
return m_mem_usage;
}

View File

@ -54,9 +54,6 @@ private:
GLenum m_int_type;
u32 m_int_shift;
// Allow to track size of allocated memory
u32 m_mem_usage;
public:
explicit GSTextureOGL(Type type, int width, int height, int levels, Format format, GLuint fbo_read);
virtual ~GSTextureOGL();
@ -71,7 +68,6 @@ public:
void Swap(GSTexture* tex) final;
GSMap Read(const GSVector4i& r, AlignedBuffer<u8, 32>& buffer);
bool IsDepth() { return (m_type == Type::DepthStencil || m_type == Type::SparseDepthStencil); }
bool IsIntegerFormat() const
{
return (m_int_format == GL_RED_INTEGER || m_int_format == GL_RGBA_INTEGER);
@ -88,8 +84,4 @@ public:
void Clear(const void* data);
void Clear(const void* data, const GSVector4i& area);
void CommitPages(const GSVector2i& region, bool commit) final;
u32 GetMemUsage() final;
};

View File

@ -405,8 +405,7 @@ VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
{
pxAssert(type != GSTexture::Type::Offscreen && type != GSTexture::Type::SparseRenderTarget &&
type != GSTexture::Type::SparseDepthStencil);
pxAssert(type != GSTexture::Type::Offscreen);
const u32 clamped_width = static_cast<u32>(std::clamp<int>(1, width, g_vulkan_context->GetMaxImageDimension2D()));
const u32 clamped_height = static_cast<u32>(std::clamp<int>(1, height, g_vulkan_context->GetMaxImageDimension2D()));

View File

@ -172,9 +172,6 @@ const char* dialog_message(int ID, bool* updateText)
return cvtString("Allows advanced atomic operations to speed up Accurate DATE.\n"
"Only disable this if using Accurate DATE causes (GPU driver) issues.\n\n"
"Note: This option is only supported by GPUs which support at least Direct3D 11.");
case IDC_SPARSE_TEXTURE:
return cvtString("Allows to reduce VRAM usage on the GPU.\n\n"
"Note: Feature is currently experimental and works only on Nvidia GPUs.");
case IDC_LINEAR_PRESENT:
return cvtString("Use bilinear filtering when Upscaling/Downscaling the image to the screen. Disable it if you want a sharper/pixelated output.");
// Exclusive for Hardware Renderer

View File

@ -89,7 +89,6 @@ enum
// OpenGL Advanced Settings
IDC_GEOMETRY_SHADER_OVERRIDE,
IDC_IMAGE_LOAD_STORE,
IDC_SPARSE_TEXTURE,
// On-screen Display
IDC_OSD_LOG,
IDC_OSD_MONITOR,

View File

@ -588,7 +588,6 @@ DebugTab::DebugTab(wxWindow* parent)
m_ui.addComboBoxAndLabel(ogl_grid, "Texture Barriers:", "OverrideTextureBarriers", &theApp.m_gs_generic_list, -1, vk_ogl_hw_prereq);
m_ui.addComboBoxAndLabel(ogl_grid, "Geometry Shader:", "OverrideGeometryShaders", &theApp.m_gs_generic_list, IDC_GEOMETRY_SHADER_OVERRIDE, vk_ogl_hw_prereq);
m_ui.addComboBoxAndLabel(ogl_grid, "Image Load Store:", "override_GL_ARB_shader_image_load_store", &theApp.m_gs_generic_list, IDC_IMAGE_LOAD_STORE, ogl_hw_prereq);
m_ui.addComboBoxAndLabel(ogl_grid, "Sparse Texture:", "override_GL_ARB_sparse_texture", &theApp.m_gs_generic_list, IDC_SPARSE_TEXTURE, ogl_hw_prereq);
m_ui.addComboBoxAndLabel(ogl_grid, "Dump Compression:", "GSDumpCompression", &theApp.m_gs_dump_compression, -1);
ogl_box->Add(ogl_grid);