Skip to content

Commit

Permalink
GS/HW: Centralize new target resizing calls to fix statistics/tidy up
Browse files Browse the repository at this point in the history
Also add an override for GSVector4i loadl to take a GSVector2i
  • Loading branch information
refractionpcsx2 committed Jan 16, 2025
1 parent f4a9783 commit a508d4e
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 36 deletions.
5 changes: 5 additions & 0 deletions pcsx2/GS/GSVector4i.h
Original file line number Diff line number Diff line change
Expand Up @@ -1599,6 +1599,11 @@ class alignas(16) GSVector4i
return loadh(&v);
}

__forceinline static GSVector4i loadl(const GSVector2i& v)
{
return loadl(&v);
}

__forceinline static GSVector4i load(const void* pl, const void* ph)
{
return loadh(ph, loadl(pl));
Expand Down
17 changes: 4 additions & 13 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2939,33 +2939,24 @@ void GSRendererHW::Draw()
if (vertical_offset < 0)
{
rt->m_TEX0.TBP0 = m_cached_ctx.FRAME.Block();
GSVector2i new_scaled_size = rt->m_unscaled_size * rt->m_scale;
GSVector2i new_size = rt->m_unscaled_size;
// Make sure to use the original format for the offset.
int new_offset = std::abs((vertical_offset / frame_psm.pgs.y) * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.y);
texture_offset = new_offset;

new_scaled_size.y += new_offset * rt->m_scale;
GSTexture* tex = g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, true);
//if (!tex)
// return nullptr;
//m_target_memory_usage += tex->GetMemUsage();
GSVector4i dRect = GSVector4i(0, new_offset * rt->m_scale, new_scaled_size.x, new_scaled_size.y);
g_gs_device->StretchRect(rt->m_texture, GSVector4(0,0,1,1), tex, GSVector4(dRect), ShaderConvert::COPY, false);
new_size.y += new_offset;

rt->ResizeTexture(new_size.x, new_size.y, true, true, GSVector4i::loadh(new_size * rt->m_scale).loadl(GSVector2i(0, new_offset * rt->m_scale)));

if (src && src->m_from_target && src->m_from_target == rt && src->m_target_direct)
{
src->m_texture = tex;
src->m_texture = rt->m_texture;
}

g_gs_device->Recycle(rt->m_texture);

rt->m_valid.y += new_offset;
rt->m_valid.w += new_offset;
rt->m_drawn_since_read.y += new_offset;
rt->m_drawn_since_read.w += new_offset;
rt->m_texture = tex;
rt->m_unscaled_size = new_scaled_size / rt->m_scale;

t_size.y += std::abs(vertical_offset);
vertical_offset = 0;
Expand Down
46 changes: 24 additions & 22 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2173,30 +2173,19 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
GL_INS("TC Convert to 16bit: %dx%d: %dx%d @ %f -> %dx%d @ %f", dst->m_unscaled_size.x, dst->m_unscaled_size.y,
dst->m_texture->GetWidth(), dst->m_texture->GetHeight(), dst->m_scale, new_scaled_size.x, new_scaled_size.y,
scale);
//DevCon.Warning("Scale %s draw %d", scale_down ? "down" : "up", GSState::s_n);
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, true) :
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, true);
if (!tex)
return nullptr;
m_target_memory_usage += tex->GetMemUsage();

g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, (type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY, false);


if (src && src->m_from_target && src->m_from_target == dst)
{
src->m_texture = dst->m_texture;
src->m_target_direct = false;
src->m_shared_texture = false;

dst->ResizeTexture(new_size.x, new_size.y, true, true, GSVector4i(dRect), true);
}
else
{
m_target_memory_usage -= dst->m_texture->GetMemUsage();
g_gs_device->Recycle(dst->m_texture);
dst->ResizeTexture(new_size.x, new_size.y, true, true, GSVector4i(dRect));
}

dst->m_texture = tex;
dst->m_unscaled_size = new_size;
}

// New format or doing a shuffle to a 32bit target that used to be 16bit
Expand Down Expand Up @@ -6782,7 +6771,7 @@ void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect, bool can_res
// 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_unscaled_width, int new_unscaled_height, bool recycle_old)
bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unscaled_height, bool recycle_old, bool require_new_rect, GSVector4i new_rect, bool keep_old)
{
if (m_unscaled_size.x == new_unscaled_width && m_unscaled_size.y == new_unscaled_height)
return true;
Expand All @@ -6806,7 +6795,7 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
// Only need to copy if it's been written to.
if (m_texture->GetState() == GSTexture::State::Dirty)
{
const GSVector4i rc = GSVector4i::loadh(size.min(new_size));
const GSVector4i rc = require_new_rect ? new_rect : GSVector4i::loadh(size.min(new_size));
if (tex->IsDepthStencil())
{
// Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other
Expand All @@ -6815,8 +6804,15 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
}
else
{
// Fast memcpy()-like path for color targets.
g_gs_device->CopyRect(m_texture, tex, rc, 0, 0);
if (require_new_rect)
{
g_gs_device->StretchRect(m_texture, tex, GSVector4(rc), ShaderConvert::COPY, false);
}
else
{
// Fast memcpy()-like path for color targets.
g_gs_device->CopyRect(m_texture, tex, rc, 0, 0);
}
}

g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Expand All @@ -6834,12 +6830,18 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
g_gs_device->InvalidateRenderTarget(tex);
}

g_texture_cache->m_target_memory_usage = (g_texture_cache->m_target_memory_usage - m_texture->GetMemUsage()) + tex->GetMemUsage();

if (recycle_old)
g_gs_device->Recycle(m_texture);
if (!keep_old)
{
g_texture_cache->m_target_memory_usage = (g_texture_cache->m_target_memory_usage - m_texture->GetMemUsage()) + tex->GetMemUsage();

if (recycle_old)
g_gs_device->Recycle(m_texture);
else
delete m_texture;
}
else
delete m_texture;
g_texture_cache->m_target_memory_usage += tex->GetMemUsage();

m_texture = tex;
m_unscaled_size = new_unscaled_size;
Expand Down
2 changes: 1 addition & 1 deletion pcsx2/GS/Renderers/HW/GSTextureCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ class GSTextureCache
void UpdateValidChannels(u32 psm, u32 fbmsk);

/// Resizes target texture, DOES NOT RESCALE.
bool ResizeTexture(int new_unscaled_width, int new_unscaled_height, bool recycle_old = true);
bool ResizeTexture(int new_unscaled_width, int new_unscaled_height, bool recycle_old = true, bool require_offset = false, GSVector4i offset = GSVector4i::zero(), bool keep_old = false);

private:
void UpdateTextureDebugName();
Expand Down

0 comments on commit a508d4e

Please sign in to comment.