GS/HW: Centralize new target resizing calls to fix statistics/tidy up

Also add an override for GSVector4i loadl to take a GSVector2i
This commit is contained in:
refractionpcsx2 2025-01-16 10:42:02 +00:00
parent 6c9a115ecc
commit 4f11ea05b5
4 changed files with 34 additions and 36 deletions

View File

@ -1599,6 +1599,11 @@ public:
return loadh(&v); return loadh(&v);
} }
__forceinline static GSVector4i loadl(const GSVector2i& v)
{
return loadl(&v);
}
__forceinline static GSVector4i load(const void* pl, const void* ph) __forceinline static GSVector4i load(const void* pl, const void* ph)
{ {
return loadh(ph, loadl(pl)); return loadh(ph, loadl(pl));

View File

@ -2950,33 +2950,24 @@ void GSRendererHW::Draw()
if (vertical_offset < 0) if (vertical_offset < 0)
{ {
rt->m_TEX0.TBP0 = m_cached_ctx.FRAME.Block(); 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. // 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); int new_offset = std::abs((vertical_offset / frame_psm.pgs.y) * GSLocalMemory::m_psm[rt->m_TEX0.PSM].pgs.y);
texture_offset = new_offset; texture_offset = new_offset;
new_scaled_size.y += new_offset * rt->m_scale; new_size.y += new_offset;
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);
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) 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.y += new_offset;
rt->m_valid.w += new_offset; rt->m_valid.w += new_offset;
rt->m_drawn_since_read.y += new_offset; rt->m_drawn_since_read.y += new_offset;
rt->m_drawn_since_read.w += 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); t_size.y += std::abs(vertical_offset);
vertical_offset = 0; vertical_offset = 0;

View File

@ -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, 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, dst->m_texture->GetWidth(), dst->m_texture->GetHeight(), dst->m_scale, new_scaled_size.x, new_scaled_size.y,
scale); 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) if (src && src->m_from_target && src->m_from_target == dst)
{ {
src->m_texture = dst->m_texture; src->m_texture = dst->m_texture;
src->m_target_direct = false; src->m_target_direct = false;
src->m_shared_texture = false; src->m_shared_texture = false;
dst->ResizeTexture(new_size.x, new_size.y, true, true, GSVector4i(dRect), true);
} }
else else
{ {
m_target_memory_usage -= dst->m_texture->GetMemUsage(); dst->ResizeTexture(new_size.x, new_size.y, true, true, GSVector4i(dRect));
g_gs_device->Recycle(dst->m_texture);
} }
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 // New format or doing a shuffle to a 32bit target that used to be 16bit
@ -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); // 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) if (m_unscaled_size.x == new_unscaled_width && m_unscaled_size.y == new_unscaled_height)
return true; return true;
@ -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. // Only need to copy if it's been written to.
if (m_texture->GetState() == GSTexture::State::Dirty) 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()) if (tex->IsDepthStencil())
{ {
// Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other // Can't do partial copies in DirectX for depth textures, and it's probably not ideal in other
@ -6815,8 +6804,15 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
} }
else else
{ {
// Fast memcpy()-like path for color targets. if (require_new_rect)
g_gs_device->CopyRect(m_texture, tex, rc, 0, 0); {
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); g_perfmon.Put(GSPerfMon::TextureCopies, 1);
@ -6834,12 +6830,18 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
g_gs_device->InvalidateRenderTarget(tex); 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) if (!keep_old)
g_gs_device->Recycle(m_texture); {
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 else
delete m_texture; g_texture_cache->m_target_memory_usage += tex->GetMemUsage();
m_texture = tex; m_texture = tex;
m_unscaled_size = new_unscaled_size; m_unscaled_size = new_unscaled_size;

View File

@ -257,7 +257,7 @@ public:
void UpdateValidChannels(u32 psm, u32 fbmsk); void UpdateValidChannels(u32 psm, u32 fbmsk);
/// Resizes target texture, DOES NOT RESCALE. /// 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: private:
void UpdateTextureDebugName(); void UpdateTextureDebugName();