GS/HW: Rewrite invalidation and fix up surrounding behaviour.

This commit is contained in:
refractionpcsx2 2023-07-12 01:00:49 +01:00
parent dfba3c51fb
commit 9292bbcd1b
5 changed files with 587 additions and 641 deletions

View File

@ -62,16 +62,16 @@ GSVector4i GSDirtyRectList::GetTotalRect(GIFRegTEX0 TEX0, const GSVector2i& size
{ {
if (!empty()) if (!empty())
{ {
GSVector4i r(INT_MAX, INT_MAX, 0, 0); GSVector4i r = GSVector4i::cxpr(INT_MAX, INT_MAX, 0, 0);
for (auto& dirty_rect : *this) for (auto& dirty_rect : *this)
{ {
r = r.runion(dirty_rect.GetDirtyRect(TEX0)); r = r.runion(dirty_rect.GetDirtyRect(TEX0));
} }
const GSVector2i bs = GSLocalMemory::m_psm[TEX0.PSM].bs; const GSVector2i& bs = GSLocalMemory::m_psm[TEX0.PSM].bs;
return r.ralign<Align_Outside>(bs).rintersect(GSVector4i(0, 0, size.x, size.y)); return r.ralign<Align_Outside>(bs).rintersect(GSVector4i::loadh(size));
} }
return GSVector4i::zero(); return GSVector4i::zero();

View File

@ -996,6 +996,7 @@ bool GSHwHack::OI_RozenMaidenGebetGarden(GSRendererHW& r, GSTexture* rt, GSTextu
{ {
GL_INS("OI_RozenMaidenGebetGarden FB clear"); GL_INS("OI_RozenMaidenGebetGarden FB clear");
g_gs_device->ClearRenderTarget(tmp_rt->m_texture, 0); g_gs_device->ClearRenderTarget(tmp_rt->m_texture, 0);
tmp_rt->UpdateDrawn(tmp_rt->m_valid);
tmp_rt->m_alpha_max = 0; tmp_rt->m_alpha_max = 0;
tmp_rt->m_alpha_min = 0; tmp_rt->m_alpha_min = 0;
} }
@ -1061,9 +1062,10 @@ bool GSHwHack::OI_SonicUnleashed(GSRendererHW& r, GSTexture* rt, GSTexture* ds,
{ {
GSVector2i new_size = GSVector2i(std::max(rt_again->m_unscaled_size.x, src->m_unscaled_size.x), GSVector2i new_size = GSVector2i(std::max(rt_again->m_unscaled_size.x, src->m_unscaled_size.x),
std::max(rt_again->m_unscaled_size.y, src->m_unscaled_size.y)); std::max(rt_again->m_unscaled_size.y, src->m_unscaled_size.y));
rt_again->ResizeTexture(new_size.x, new_size.y); rt_again->ResizeTexture(new_size.x, new_size.y);
rt = rt_again->m_texture; rt = rt_again->m_texture;
rt_size = new_size; rt_size = new_size;
rt_again->UpdateDrawn(GSVector4i::loadh(rt_size));
} }
} }
@ -1318,6 +1320,9 @@ static bool GetMoveTargetPair(GSRendererHW& r, GSTextureCache::Target** src, GIF
*src = tsrc; *src = tsrc;
*dst = tdst; *dst = tdst;
tdst->UpdateDrawn(tdst->m_valid);
return true; return true;
} }

View File

@ -2274,7 +2274,7 @@ void GSRendererHW::Draw()
const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && PrimitiveCoversWithoutGaps(); const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && PrimitiveCoversWithoutGaps();
const bool is_clear = is_possible_mem_clear && is_square; const bool is_clear = is_possible_mem_clear && is_square;
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true, rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true,
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, unclamped_draw_rect); fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, unclamped_draw_rect, IsPossibleChannelShuffle());
// Draw skipped because it was a clear and there was no target. // Draw skipped because it was a clear and there was no target.
if (!rt) if (!rt)
@ -2588,9 +2588,10 @@ void GSRendererHW::Draw()
rt->ResizeDrawn(rt->GetUnscaledRect()); rt->ResizeDrawn(rt->GetUnscaledRect());
} }
const GSVector4i update_rect = m_r.rintersect(GSVector4i::loadh(new_size));
// Limit to 2x the vertical height of the resolution (for double buffering) // Limit to 2x the vertical height of the resolution (for double buffering)
rt->UpdateValidity(m_r, can_update_size || (m_r.w <= (resolution.y * 2) && !m_texture_shuffle)); rt->UpdateValidity(update_rect, can_update_size || (m_r.w <= (resolution.y * 2) && !m_texture_shuffle));
rt->UpdateDrawn(m_r, can_update_size || (m_r.w <= (resolution.y * 2) && !m_texture_shuffle)); rt->UpdateDrawn(update_rect, can_update_size || (m_r.w <= (resolution.y * 2) && !m_texture_shuffle));
// Probably changing to double buffering, so invalidate any old target that was next to it. // Probably changing to double buffering, so invalidate any old target that was next to it.
// This resolves an issue where the PCRTC will find the old target in FMV's causing flashing. // This resolves an issue where the PCRTC will find the old target in FMV's causing flashing.
// Grandia Xtreme, Onimusha Warlord. // Grandia Xtreme, Onimusha Warlord.
@ -2781,7 +2782,11 @@ void GSRendererHW::Draw()
// Temporary source *must* be invalidated before normal, because otherwise it'll be double freed. // Temporary source *must* be invalidated before normal, because otherwise it'll be double freed.
g_texture_cache->InvalidateTemporarySource(); g_texture_cache->InvalidateTemporarySource();
// // Set the RT format back to 32bits after the shuffle.
if (rt && m_texture_shuffle && rt->m_32_bits_fmt)
{
rt->m_TEX0.PSM = PSMCT32;
}
// Invalidation of old targets when changing to double-buffering. // Invalidation of old targets when changing to double-buffering.
if (old_rt) if (old_rt)
@ -5670,6 +5675,7 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
const u32 base = clear_depth ? m_cached_ctx.ZBUF.ZBP : m_cached_ctx.FRAME.FBP; const u32 base = clear_depth ? m_cached_ctx.ZBUF.ZBP : m_cached_ctx.FRAME.FBP;
const u32 half = clear_depth ? m_cached_ctx.FRAME.FBP : m_cached_ctx.ZBUF.ZBP; const u32 half = clear_depth ? m_cached_ctx.FRAME.FBP : m_cached_ctx.ZBUF.ZBP;
const bool enough_bits = clear_depth ? (frame_psm.trbpp >= zbuf_psm.trbpp) : (zbuf_psm.trbpp >= frame_psm.trbpp); const bool enough_bits = clear_depth ? (frame_psm.trbpp >= zbuf_psm.trbpp) : (zbuf_psm.trbpp >= frame_psm.trbpp);
// Size of the current draw // Size of the current draw
const u32 w_pages = (m_r.z + (frame_psm.pgs.x - 1)) / frame_psm.pgs.x; const u32 w_pages = (m_r.z + (frame_psm.pgs.x - 1)) / frame_psm.pgs.x;
const u32 h_pages = (m_r.w + (frame_psm.pgs.y - 1)) / frame_psm.pgs.y; const u32 h_pages = (m_r.w + (frame_psm.pgs.y - 1)) / frame_psm.pgs.y;

File diff suppressed because it is too large Load Diff

View File

@ -479,7 +479,7 @@ public:
Target* FindTargetOverlap(Target* target, int type, int psm); Target* FindTargetOverlap(Target* target, int type, int psm);
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0, Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true, bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
const GSVector4i draw_rc = GSVector4i::zero()); const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false);
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0, Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0,
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true, bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true,
const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr); const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr);