GS: Show VRAM usage in statistics

This commit is contained in:
Stenzek 2023-01-24 13:59:12 +10:00 committed by refractionpcsx2
parent e76afee12d
commit 9d50d44c99
8 changed files with 195 additions and 180 deletions

View File

@ -180,9 +180,14 @@ void ImGuiManager::DrawPerformanceOverlay()
if (GSConfig.OsdShowGSStats)
{
std::string gs_stats;
GSgetStats(gs_stats);
DRAW_LINE(fixed_font, gs_stats.c_str(), IM_COL32(255, 255, 255, 255));
text.clear();
GSgetStats(text);
DRAW_LINE(fixed_font, text.c_str(), IM_COL32(255, 255, 255, 255));
text.clear();
GSgetMemoryStats(text);
if (!text.empty())
DRAW_LINE(fixed_font, text.c_str(), IM_COL32(255, 255, 255, 255));
}
if (GSConfig.OsdShowResolution)

View File

@ -40,6 +40,8 @@
#include "pcsx2/Frontend/InputManager.h"
#include "pcsx2/GS.h"
#include "fmt/format.h"
#ifdef ENABLE_OPENGL
#include "Renderers/OpenGL/GSDeviceOGL.h"
#endif
@ -588,14 +590,12 @@ void GSgetInternalResolution(int* width, int* height)
void GSgetStats(std::string& info)
{
GSPerfMon& pm = g_perfmon;
const char* api_name = HostDisplay::RenderAPIToString(s_render_api);
if (GSConfig.Renderer == GSRendererType::SW)
{
const double fps = GetVerticalFrequency();
const double fillrate = pm.Get(GSPerfMon::Fillrate);
info = StringUtil::StdStringFromFormat("%s SW | %d S | %d P | %d D | %.2f U | %.2f D | %.2f mpps",
fmt::format_to(std::back_inserter(info), "{} SW | {} S | {} P | {} D | {:.2f} U | {:.2f} D | {:.2f} mpps",
api_name,
(int)pm.Get(GSPerfMon::SyncPoint),
(int)pm.Get(GSPerfMon::Prim),
@ -606,35 +606,49 @@ void GSgetStats(std::string& info)
}
else if (GSConfig.Renderer == GSRendererType::Null)
{
info = StringUtil::StdStringFromFormat("%s Null", api_name);
fmt::format_to(std::back_inserter(info), "{} Null", api_name);
}
else
{
if (GSConfig.TexturePreloading == TexturePreloadingLevel::Full)
{
info = StringUtil::StdStringFromFormat("%s HW | HC: %d MB | %d P | %d D | %d DC | %d B | %d RB | %d TC | %d TU",
api_name,
(int)std::ceil(GSRendererHW::GetInstance()->GetTextureCache()->GetTotalHashCacheMemoryUsage() / 1048576.0f),
(int)pm.Get(GSPerfMon::Prim),
(int)pm.Get(GSPerfMon::Draw),
(int)std::ceil(pm.Get(GSPerfMon::DrawCalls)),
(int)std::ceil(pm.Get(GSPerfMon::Barriers)),
(int)std::ceil(pm.Get(GSPerfMon::Readbacks)),
(int)std::ceil(pm.Get(GSPerfMon::TextureCopies)),
(int)std::ceil(pm.Get(GSPerfMon::TextureUploads)));
}
else
{
info = StringUtil::StdStringFromFormat("%s HW | %d P | %d D | %d DC | %d B | %d RB | %d TC | %d TU",
api_name,
(int)pm.Get(GSPerfMon::Prim),
(int)pm.Get(GSPerfMon::Draw),
(int)std::ceil(pm.Get(GSPerfMon::DrawCalls)),
(int)std::ceil(pm.Get(GSPerfMon::Barriers)),
(int)std::ceil(pm.Get(GSPerfMon::Readbacks)),
(int)std::ceil(pm.Get(GSPerfMon::TextureCopies)),
(int)std::ceil(pm.Get(GSPerfMon::TextureUploads)));
}
fmt::format_to(std::back_inserter(info), "{} HW | {} P | {} D | {} DC | {} B | {} RB | {} TC | {} TU",
api_name,
(int)pm.Get(GSPerfMon::Prim),
(int)pm.Get(GSPerfMon::Draw),
(int)std::ceil(pm.Get(GSPerfMon::DrawCalls)),
(int)std::ceil(pm.Get(GSPerfMon::Barriers)),
(int)std::ceil(pm.Get(GSPerfMon::Readbacks)),
(int)std::ceil(pm.Get(GSPerfMon::TextureCopies)),
(int)std::ceil(pm.Get(GSPerfMon::TextureUploads)));
}
}
void GSgetMemoryStats(std::string& info)
{
if (GSConfig.Renderer == GSRendererType::SW || GSConfig.Renderer == GSRendererType::Null)
return;
const u64 targets = GSRendererHW::GetInstance()->GetTextureCache()->GetTargetMemoryUsage();
const u64 sources = GSRendererHW::GetInstance()->GetTextureCache()->GetSourceMemoryUsage();
const u64 hashcache = GSRendererHW::GetInstance()->GetTextureCache()->GetHashCacheMemoryUsage();
const u64 pool = g_gs_device->GetPoolMemoryUsage();
const u64 total = targets + sources + hashcache + pool;
if (GSConfig.TexturePreloading == TexturePreloadingLevel::Full)
{
fmt::format_to(std::back_inserter(info), "VRAM: {} MB | T: {} MB | S: {} MB | H: {} MB | P: {} MB",
(int)std::ceil(total / 1048576.0f),
(int)std::ceil(targets / 1048576.0f),
(int)std::ceil(sources / 1048576.0f),
(int)std::ceil(hashcache / 1048576.0f),
(int)std::ceil(pool / 1048576.0f));
}
else
{
fmt::format_to(std::back_inserter(info), "VRAM: {} MB | T: {} MB | S: {} MB | P: {} MB",
(int)std::ceil(total / 1048576.0f),
(int)std::ceil(targets / 1048576.0f),
(int)std::ceil(sources / 1048576.0f),
(int)std::ceil(pool / 1048576.0f));
}
}

View File

@ -81,6 +81,7 @@ void GSsetGameCRC(u32 crc);
GSVideoMode GSgetDisplayMode();
void GSgetInternalResolution(int* width, int* height);
void GSgetStats(std::string& info);
void GSgetMemoryStats(std::string& info);
void GSgetTitleStats(std::string& info);
/// Converts window position to normalized display coordinates (0..1). A value less than 0 or greater than 1 is

View File

@ -126,6 +126,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
{
if (!prefer_new_texture || t->last_frame_used != m_frame)
{
m_pool_memory_usage -= t->GetMemUsage();
m_pool.erase(i);
break;
}
@ -143,6 +144,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
if (m_pool.size() >= MAX_POOLED_TEXTURES && fallback != m_pool.end())
{
t = *fallback;
m_pool_memory_usage -= t->GetMemUsage();
m_pool.erase(fallback);
}
else
@ -185,19 +187,6 @@ std::unique_ptr<GSDownloadTexture> GSDevice::CreateDownloadTexture(u32 width, u3
return {};
}
void GSDevice::PrintMemoryUsage()
{
#ifdef ENABLE_OGL_DEBUG
u32 pool = 0;
for (auto t : m_pool)
{
if (t)
pool += t->GetMemUsage();
}
GL_PERF("MEM: Surface Pool %dMB", pool >> 20u);
#endif
}
void GSDevice::EndScene()
{
m_vertex.start += m_vertex.count;
@ -208,20 +197,22 @@ void GSDevice::EndScene()
void GSDevice::Recycle(GSTexture* t)
{
if (t)
if (!t)
return;
t->last_frame_used = m_frame;
m_pool.push_front(t);
m_pool_memory_usage += t->GetMemUsage();
//printf("%d\n",m_pool.size());
while (m_pool.size() > MAX_POOLED_TEXTURES)
{
t->last_frame_used = m_frame;
m_pool_memory_usage -= m_pool.back()->GetMemUsage();
delete m_pool.back();
m_pool.push_front(t);
//printf("%d\n",m_pool.size());
while (m_pool.size() > MAX_POOLED_TEXTURES)
{
delete m_pool.back();
m_pool.pop_back();
}
m_pool.pop_back();
}
}
@ -231,6 +222,7 @@ void GSDevice::AgePool()
while (m_pool.size() > 40 && m_frame - m_pool.back()->last_frame_used > 10)
{
m_pool_memory_usage -= m_pool.back()->GetMemUsage();
delete m_pool.back();
m_pool.pop_back();
@ -242,6 +234,7 @@ void GSDevice::PurgePool()
for (auto t : m_pool)
delete t;
m_pool.clear();
m_pool_memory_usage = 0;
}
void GSDevice::ClearSamplerCache()

View File

@ -724,6 +724,7 @@ public:
private:
FastList<GSTexture*> m_pool;
u64 m_pool_memory_usage = 0;
static const std::array<HWBlend, 3*3*3*3> m_blendMap;
static const std::array<u8, 16> m_replaceDualSrcBlendMap;
@ -772,6 +773,7 @@ public:
virtual ~GSDevice();
__fi unsigned int GetFrameNumber() const { return m_frame; }
__fi u64 GetPoolMemoryUsage() const { return m_pool_memory_usage; }
void Recycle(GSTexture* t);
@ -855,8 +857,6 @@ public:
virtual void ClearSamplerCache();
virtual void PrintMemoryUsage();
__fi static constexpr bool IsDualSourceBlendFactor(u8 factor)
{
return (factor == SRC1_ALPHA || factor == INV_SRC1_ALPHA

View File

@ -222,9 +222,6 @@ void GSRendererHW::VSync(u32 field, bool registers_written)
GSConfig.TexturePreloading = TexturePreloadingLevel::Partial;
}
m_tc->PrintMemoryUsage();
g_gs_device->PrintMemoryUsage();
m_skip = 0;
m_skip_offset = 0;
}

View File

@ -24,14 +24,14 @@
#include "common/Align.h"
#include "common/HashCombine.h"
u8* GSTextureCache::m_temp;
static u8* s_unswizzle_buffer;
GSTextureCache::GSTextureCache()
{
// In theory 4MB is enough but 9MB is safer for overflow (8MB
// isn't enough in custom resolution)
// Test: onimusha 3 PAL 60Hz
m_temp = (u8*)_aligned_malloc(9 * 1024 * 1024, 32);
s_unswizzle_buffer = (u8*)_aligned_malloc(9 * 1024 * 1024, 32);
m_surface_offset_cache.reserve(S_SURFACE_OFFSET_CACHE_MAX_SIZE);
}
@ -44,7 +44,7 @@ GSTextureCache::~GSTextureCache()
m_surface_offset_cache.clear();
_aligned_free(m_temp);
_aligned_free(s_unswizzle_buffer);
}
void GSTextureCache::RemovePartial()
@ -74,12 +74,16 @@ void GSTextureCache::RemoveAll()
for (auto it : m_hash_cache)
g_gs_device->Recycle(it.second.texture);
m_hash_cache.clear();
m_hash_cache_memory_usage = 0;
m_hash_cache_replacement_memory_usage = 0;
m_palette_map.Clear();
m_target_heights.clear();
m_source_memory_usage = 0;
m_target_memory_usage = 0;
}
void GSTextureCache::AddDirtyRectTarget(Target* target, GSVector4i rect, u32 psm, u32 bw)
@ -589,6 +593,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(const GIFRegTEX0& TEX0, con
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);
m_target_memory_usage = (m_target_memory_usage - dst->m_texture->GetMemUsage()) + tex->GetMemUsage();
g_gs_device->Recycle(dst->m_texture);
tex->SetScale(new_s);
dst->m_texture = tex;
@ -743,6 +748,7 @@ void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb,
// Fill the new texture with the old data, and discard the old texture.
g_gs_device->StretchRect(old_texture, new_texture, GSVector4(old_texture->GetSize()).zwxy(), ShaderConvert::COPY, false);
m_target_memory_usage = (m_target_memory_usage - old_texture->GetMemUsage()) + new_texture->GetMemUsage();
g_gs_device->Recycle(old_texture);
t->m_texture = new_texture;
@ -1803,6 +1809,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
GSTexture* dTex = outside_target ?
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, true) :
g_gs_device->CreateTexture(w, h, tlevels, GSTexture::Format::Color, true);
m_source_memory_usage += dTex->GetMemUsage();
// copy the rt in
const GSVector4i area(GSVector4i(x, y, x + w, y + h).rintersect(GSVector4i(sTex->GetSize()).zwxy()));
@ -2036,7 +2043,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
GSTexture* dTex = use_texture ?
g_gs_device->CreateTexture(w, h, 1, GSTexture::Format::Color, true) :
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, false);
src->m_texture = dTex;
dTex->SetScale(scale);
m_source_memory_usage += dTex->GetMemUsage();
if (use_texture)
{
@ -2051,10 +2059,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
g_gs_device->StretchRect(sTex, sRectF, dTex, GSVector4(destX, destY, w, h), shader, false);
}
if (src->m_texture)
src->m_texture->SetScale(scale);
else
ASSERT(0);
src->m_texture = dTex;
}
// GH: by default (m_paltex == 0) GS converts texture to the 32 bit format
@ -2101,6 +2106,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
else if (paltex)
{
src->m_texture = g_gs_device->CreateTexture(tw, th, tlevels, GSTexture::Format::UNorm8);
m_source_memory_usage += src->m_texture->GetMemUsage();
if (gpu_clut)
AttachPaletteToSource(src, gpu_clut);
else
@ -2109,6 +2115,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
else
{
src->m_texture = g_gs_device->CreateTexture(tw, th, tlevels, GSTexture::Format::Color);
m_source_memory_usage += src->m_texture->GetMemUsage();
if (gpu_clut)
AttachPaletteToSource(src, gpu_clut);
else if (psm.pal > 0)
@ -2286,6 +2293,7 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(const GIFRegTEX0& TEX0, int
}
t->m_texture->SetScale(static_cast<GSRendererHW*>(g_gs_renderer.get())->GetTextureScaleFactor());
m_target_memory_usage += t->m_texture->GetMemUsage();
m_dst[type].push_front(t);
@ -2486,38 +2494,6 @@ void GSTextureCache::Read(Source* t, const GSVector4i& r)
}
}
void GSTextureCache::PrintMemoryUsage()
{
#ifdef ENABLE_OGL_DEBUG
u32 tex = 0;
u32 tex_rt = 0;
u32 rt = 0;
u32 dss = 0;
for (auto s : m_src.m_surfaces)
{
if (s && !s->m_shared_texture)
{
if (s->m_target)
tex_rt += s->m_texture->GetMemUsage();
else
tex += s->m_texture->GetMemUsage();
}
}
for (auto t : m_dst[RenderTarget])
{
if (t)
rt += t->m_texture->GetMemUsage();
}
for (auto t : m_dst[DepthStencil])
{
if (t)
dss += t->m_texture->GetMemUsage();
}
GL_PERF("MEM: RO Tex %dMB. RW Tex %dMB. Target %dMB. Depth %dMB", tex >> 20u, tex_rt >> 20u, rt >> 20u, dss >> 20u);
#endif
}
// GSTextureCache::Surface
GSTextureCache::Surface::Surface()
@ -2531,13 +2507,7 @@ GSTextureCache::Surface::Surface()
m_TEX0.TBP0 = GSTextureCache::MAX_BP;
}
GSTextureCache::Surface::~Surface()
{
// Shared textures are pointers copy. Therefore no allocation
// to recycle.
if (!m_shared_texture && !m_from_hash_cache && m_texture)
g_gs_device->Recycle(m_texture);
}
GSTextureCache::Surface::~Surface() = default;
void GSTextureCache::Surface::UpdateAge()
{
@ -2560,62 +2530,6 @@ bool GSTextureCache::Surface::Overlaps(u32 bp, u32 bw, u32 psm, const GSVector4i
return overlap;
}
bool GSTextureCache::Surface::ResizeTexture(int new_width, int new_height, bool recycle_old)
{
return ResizeTexture(new_width, new_height, m_texture->GetScale(), recycle_old);
}
bool GSTextureCache::Surface::ResizeTexture(int new_width, int new_height, GSVector2 new_scale, bool recycle_old)
{
const int width = m_texture->GetWidth();
const int height = m_texture->GetHeight();
if (width == new_width && height == new_height)
return true;
// These exceptions *really* need to get lost. This gets called outside of draws, which just crashes
// when it tries to propogate the exception back.
const bool clear = (new_width > width || new_height > height);
GSTexture* tex = nullptr;
try
{
tex = m_texture->IsDepthStencil() ?
g_gs_device->CreateDepthStencil(new_width, new_height, m_texture->GetFormat(), clear) :
g_gs_device->CreateRenderTarget(new_width, new_height, m_texture->GetFormat(), clear);
}
catch (const std::bad_alloc&)
{
}
if (!tex)
{
Console.Error("(ResizeTexture) Failed to allocate %dx%d texture from %dx%d texture", new_width, new_height, width, height);
return false;
}
tex->SetScale(new_scale);
const GSVector4i rc(0, 0, std::min(width, new_width), std::min(height, new_height));
if (tex->IsDepthStencil())
{
// Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other
// APIs either. So use a fullscreen quad setting depth instead.
g_gs_device->StretchRect(m_texture, tex, GSVector4(rc), ShaderConvert::DEPTH_COPY, false);
}
else
{
// Fast memcpy()-like path for color targets.
g_gs_device->CopyRect(m_texture, tex, rc, 0, 0);
}
if (recycle_old)
g_gs_device->Recycle(m_texture);
else
delete m_texture;
m_texture = tex;
return true;
}
// GSTextureCache::Source
GSTextureCache::Source::Source(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, bool dummy_container)
@ -2662,6 +2576,14 @@ GSTextureCache::Source::Source(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, b
GSTextureCache::Source::~Source()
{
_aligned_free(m_write.rect);
// Shared textures are pointers copy. Therefore no allocation
// to recycle.
if (!m_shared_texture && !m_from_hash_cache && m_texture)
{
GSRendererHW::GetInstance()->GetTextureCache()->m_source_memory_usage -= m_texture->GetMemUsage();
g_gs_device->Recycle(m_texture);
}
}
void GSTextureCache::Source::Update(const GSVector4i& rect, int level)
@ -2838,7 +2760,7 @@ void GSTextureCache::Source::Flush(u32 count, int layer)
rtx = psm.rtxP;
}
u8* buff = m_temp;
u8* buff = s_unswizzle_buffer;
for (u32 i = 0; i < count; i++)
{
@ -2916,6 +2838,17 @@ GSTextureCache::Target::Target(const GIFRegTEX0& TEX0, const bool depth_supporte
m_dirty_alpha = GSLocalMemory::m_psm[TEX0.PSM].trbpp != 24;
}
GSTextureCache::Target::~Target()
{
// Targets should never be shared.
pxAssert(!m_shared_texture);
if (m_texture)
{
GSRendererHW::GetInstance()->GetTextureCache()->m_target_memory_usage -= m_texture->GetMemUsage();
g_gs_device->Recycle(m_texture);
}
}
void GSTextureCache::Target::Update(bool reset_age)
{
if(reset_age)
@ -2982,9 +2915,9 @@ void GSTextureCache::Target::Update(bool reset_age)
{
int pitch = ((w + 3) & ~3) * 4;
g_gs_renderer->m_mem.ReadTexture(off, r, m_temp, pitch, TEXA);
g_gs_renderer->m_mem.ReadTexture(off, r, s_unswizzle_buffer, pitch, TEXA);
t->Update(r.rsize(), m_temp, pitch);
t->Update(r.rsize(), s_unswizzle_buffer, pitch);
}
// m_renderer->m_perfmon.Put(GSPerfMon::Unswizzle, w * h * 4);
@ -3042,6 +2975,66 @@ void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect)
// GL_CACHE("UpdateValidity (0x%x->0x%x) from R:%d,%d Valid: %d,%d", m_TEX0.TBP0, m_end_block, rect.z, rect.w, m_valid.z, m_valid.w);
}
bool GSTextureCache::Target::ResizeTexture(int new_width, int new_height, bool recycle_old)
{
return ResizeTexture(new_width, new_height, m_texture->GetScale(), recycle_old);
}
bool GSTextureCache::Target::ResizeTexture(int new_width, int new_height, GSVector2 new_scale, bool recycle_old)
{
const int width = m_texture->GetWidth();
const int height = m_texture->GetHeight();
if (width == new_width && height == new_height)
return true;
// These exceptions *really* need to get lost. This gets called outside of draws, which just crashes
// when it tries to propogate the exception back.
const bool clear = (new_width > width || new_height > height);
GSTexture* tex = nullptr;
try
{
tex = m_texture->IsDepthStencil() ?
g_gs_device->CreateDepthStencil(new_width, new_height, m_texture->GetFormat(), clear) :
g_gs_device->CreateRenderTarget(new_width, new_height, m_texture->GetFormat(), clear);
}
catch (const std::bad_alloc&)
{
}
if (!tex)
{
Console.Error("(ResizeTexture) Failed to allocate %dx%d texture from %dx%d texture", new_width, new_height, width, height);
return false;
}
tex->SetScale(new_scale);
const GSVector4i rc(0, 0, std::min(width, new_width), std::min(height, new_height));
if (tex->IsDepthStencil())
{
// Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other
// APIs either. So use a fullscreen quad setting depth instead.
g_gs_device->StretchRect(m_texture, tex, GSVector4(rc), ShaderConvert::DEPTH_COPY, false);
}
else
{
// Fast memcpy()-like path for color targets.
g_gs_device->CopyRect(m_texture, tex, rc, 0, 0);
}
GSTextureCache* tc = GSRendererHW::GetInstance()->GetTextureCache();
tc->m_target_memory_usage = (tc->m_target_memory_usage - m_texture->GetMemUsage()) + tex->GetMemUsage();
if (recycle_old)
g_gs_device->Recycle(m_texture);
else
delete m_texture;
m_texture = tex;
return true;
}
// GSTextureCache::SourceMap
void GSTextureCache::SourceMap::Add(Source* s, const GIFRegTEX0& TEX0, const GSOffset& off)
@ -3373,7 +3366,12 @@ GSTextureCache::Palette::Palette(u16 pal, bool need_gs_texture)
GSTextureCache::Palette::~Palette()
{
g_gs_device->Recycle(m_tex_palette);
if (m_tex_palette)
{
GSRendererHW::GetInstance()->GetTextureCache()->m_source_memory_usage -= m_tex_palette->GetMemUsage();
g_gs_device->Recycle(m_tex_palette);
}
_aligned_free(m_clut);
}
@ -3398,6 +3396,7 @@ void GSTextureCache::Palette::InitializeTexture()
// and therefore will read texel 15/255 * texture size).
m_tex_palette = g_gs_device->CreateTexture(m_pal, 1, 1, GSTexture::Format::Color);
m_tex_palette->Update(GSVector4i(0, 0, m_pal, 1), m_clut, m_pal * sizeof(m_clut[0]));
GSRendererHW::GetInstance()->GetTextureCache()->m_source_memory_usage += m_tex_palette->GetMemUsage();
}
}
@ -3638,7 +3637,7 @@ GSTextureCache::HashType GSTextureCache::HashTexture(const GIFRegTEX0& TEX0, con
{
BlockHashState hash_st;
BlockHashReset(hash_st);
HashTextureLevel(TEX0, TEXA, hash_st, m_temp);
HashTextureLevel(TEX0, TEXA, hash_st, s_unswizzle_buffer);
return FinishBlockHash(hash_st);
}
@ -3675,7 +3674,7 @@ void GSTextureCache::PreloadTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TE
// Align pitch to 32 bytes for AVX2 if we're going through the temp buffer path.
pitch = Common::AlignUpPow2(pitch, 32);
u8* buff = m_temp;
u8* buff = s_unswizzle_buffer;
rtx(mem, off, block_rect, buff, pitch, TEXA);
tex->Update(rect, buff, pitch, level);
}
@ -3702,7 +3701,7 @@ GSTextureCache::HashCacheKey GSTextureCache::HashCacheKey::Create(const GIFRegTE
BlockHashReset(hash_st);
// base level is always hashed
HashTextureLevel(TEX0, TEXA, hash_st, m_temp);
HashTextureLevel(TEX0, TEXA, hash_st, s_unswizzle_buffer);
if (lod)
{
@ -3712,7 +3711,7 @@ GSTextureCache::HashCacheKey GSTextureCache::HashCacheKey::Create(const GIFRegTE
for (int i = 1; i < nmips; i++)
{
const GIFRegTEX0 MIP_TEX0{g_gs_renderer->GetTex0Layer(basemip + i)};
HashTextureLevel(MIP_TEX0, TEXA, hash_st, m_temp);
HashTextureLevel(MIP_TEX0, TEXA, hash_st, s_unswizzle_buffer);
}
}

View File

@ -92,9 +92,6 @@ public:
void UpdateAge();
bool Inside(u32 bp, u32 bw, u32 psm, const GSVector4i& rect);
bool Overlaps(u32 bp, u32 bw, u32 psm, const GSVector4i& rect);
bool ResizeTexture(int new_width, int new_height, bool recycle_old = true);
bool ResizeTexture(int new_width, int new_height, GSVector2 new_scale, bool recycle_old = true);
};
struct PaletteKey
@ -200,6 +197,7 @@ public:
public:
Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type);
~Target();
void UpdateValidity(const GSVector4i& rect);
@ -207,6 +205,9 @@ public:
/// Updates the target, if the dirty area intersects with the specified rectangle.
void UpdateIfDirtyIntersects(const GSVector4i& rc);
bool ResizeTexture(int new_width, int new_height, bool recycle_old = true);
bool ResizeTexture(int new_width, int new_height, GSVector2 new_scale, bool recycle_old = true);
};
class PaletteMap
@ -298,15 +299,20 @@ public:
protected:
PaletteMap m_palette_map;
SourceMap m_src;
u64 m_source_memory_usage = 0;
std::unordered_map<HashCacheKey, HashCacheEntry, HashCacheKeyHash> m_hash_cache;
u64 m_hash_cache_memory_usage = 0;
u64 m_hash_cache_replacement_memory_usage;
u64 m_hash_cache_replacement_memory_usage = 0;
FastList<Target*> m_dst[2];
FastList<TargetHeightElem> m_target_heights;
static u8* m_temp;
u64 m_target_memory_usage = 0;
constexpr static size_t S_SURFACE_OFFSET_CACHE_MAX_SIZE = std::numeric_limits<u16>::max();
std::unordered_map<SurfaceOffsetKey, SurfaceOffset, SurfaceOffsetKeyHash, SurfaceOffsetKeyEqual> m_surface_offset_cache;
Source* m_temporary_source = nullptr; // invalidated after the draw
std::unique_ptr<GSDownloadTexture> m_color_download_texture;
std::unique_ptr<GSDownloadTexture> m_uint16_download_texture;
std::unique_ptr<GSDownloadTexture> m_uint32_download_texture;
@ -336,6 +342,8 @@ public:
__fi u64 GetHashCacheMemoryUsage() const { return m_hash_cache_memory_usage; }
__fi u64 GetHashCacheReplacementMemoryUsage() const { return m_hash_cache_replacement_memory_usage; }
__fi u64 GetTotalHashCacheMemoryUsage() const { return (m_hash_cache_memory_usage + m_hash_cache_replacement_memory_usage); }
__fi u64 GetSourceMemoryUsage() const { return m_source_memory_usage; }
__fi u64 GetTargetMemoryUsage() const { return m_target_memory_usage; }
void Read(Target* t, const GSVector4i& r);
void Read(Source* t, const GSVector4i& r);
@ -372,8 +380,6 @@ public:
return (type == DepthStencil) ? "Depth" : "Color";
}
void PrintMemoryUsage();
void AttachPaletteToSource(Source* s, u16 pal, bool need_gs_texture);
void AttachPaletteToSource(Source* s, GSTexture* gpu_clut);
SurfaceOffset ComputeSurfaceOffset(const GSOffset& off, const GSVector4i& r, const Target* t);