diff --git a/pcsx2/GS/GSVector4i.h b/pcsx2/GS/GSVector4i.h index cbcb6f420c435..cdd3f02c6fdae 100644 --- a/pcsx2/GS/GSVector4i.h +++ b/pcsx2/GS/GSVector4i.h @@ -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)); diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index f933bf6efaa93..8d64b1e6ee2f4 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -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; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 01a585779f060..43c53657ae7cf 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -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 @@ -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; @@ -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 @@ -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); @@ -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; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index 3997698761335..f8f5cf4fd0a0b 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -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();