diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 1df88a118c..ac46c80edd 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -1089,7 +1089,12 @@ bool GSRendererHW::CheckNextDrawForSplitClear(const GSVector4i& r, u32* pages_co { const u32 end_block = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, r); if (pages_covered_by_this_draw) - *pages_covered_by_this_draw = ((end_block - m_cached_ctx.FRAME.Block()) + (BLOCKS_PER_PAGE)) / BLOCKS_PER_PAGE; + { + if (end_block < m_cached_ctx.FRAME.Block()) + *pages_covered_by_this_draw = (((MAX_BLOCKS - end_block) + m_cached_ctx.FRAME.Block()) + (BLOCKS_PER_PAGE)) / BLOCKS_PER_PAGE; + else + *pages_covered_by_this_draw = ((end_block - m_cached_ctx.FRAME.Block()) + (BLOCKS_PER_PAGE)) / BLOCKS_PER_PAGE; + } // must be changing FRAME if (m_backed_up_ctx < 0 || (m_dirty_gs_regs & (1u << DIRTY_REG_FRAME)) == 0) @@ -1848,7 +1853,7 @@ void GSRendererHW::Draw() } const bool process_texture = PRIM->TME && !(PRIM->ABE && m_context->ALPHA.IsBlack() && !m_cached_ctx.TEX0.TCC); - const u32 frame_end_bp = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r); + const u32 frame_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r); bool preserve_rt_color = ((!no_rt && (!IsDiscardingDstColor() || !PrimitiveCoversWithoutGaps() || !all_depth_tests_pass)) || // Using Dst Color or draw has gaps (process_texture && m_cached_ctx.TEX0.TBP0 >= m_cached_ctx.FRAME.Block() && diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index f9abd6bcdb..0864effbd4 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1657,9 +1657,7 @@ void GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons for (iter = GSRendererHW::GetInstance()->m_draw_transfers.begin(); iter != GSRendererHW::GetInstance()->m_draw_transfers.end(); ) { - u32 transfer_end = GSLocalMemory::GetEndBlockAddress(iter->blit.DBP, iter->blit.DBW, iter->blit.DPSM, iter->rect); - if (transfer_end < iter->blit.DBP) - transfer_end += MAX_BLOCKS; + const u32 transfer_end = GSLocalMemory::GetUnwrappedEndBlockAddress(iter->blit.DBP, iter->blit.DBW, iter->blit.DPSM, iter->rect); // If the format, and location doesn't overlap if (transfer_end >= TEX0.TBP0 && iter->blit.DBP <= rect_end && GSUtil::HasCompatibleBits(iter->blit.DPSM, TEX0.PSM)) @@ -2181,7 +2179,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r // Unfortunately sometimes the draw rect is incorrect, and since the end block gets the rect -1, it'll underflow, // so we need to prevent that from happening. Just make it a single block in that case, and hope for the best. const u32 start_bp = GSLocalMemory::GetStartBlockAddress(off.bp(), off.bw(), off.psm(), rect); - const u32 end_bp = rect.rempty() ? start_bp : GSLocalMemory::GetEndBlockAddress(off.bp(), off.bw(), off.psm(), rect); + const u32 end_bp = rect.rempty() ? start_bp : GSLocalMemory::GetUnwrappedEndBlockAddress(off.bp(), off.bw(), off.psm(), rect); // Ideally in the future we can turn this on unconditionally, but for now it breaks too much. const bool check_inside_target = (GSConfig.UserHacks_TargetPartialInvalidation || @@ -2348,7 +2346,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r else { if (GSLocalMemory::m_psm[psm].bpp == GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp || - ((100.0f / static_cast(t->m_end_block - t->m_TEX0.TBP0)) * static_cast(end_bp - bp)) < 20.0f) + ((100.0f / static_cast(t->UnwrappedEndBlock() - t->m_TEX0.TBP0)) * static_cast(end_bp - bp)) < 20.0f) { SurfaceOffset so = ComputeSurfaceOffset(off, r, t); if (so.is_valid) @@ -2421,7 +2419,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r // TODO Use ComputeSurfaceOffset below. if (GSUtil::HasSharedBits(psm, t->m_TEX0.PSM)) { - if (t->m_TEX0.TBP0 >= start_bp && t->m_end_block <= end_bp) + if (t->m_TEX0.TBP0 >= start_bp && t->UnwrappedEndBlock() <= end_bp) { // If we're clearing C24 but the target is C32, then we need to dirty instead. if (rgba._u32 != GSUtil::GetChannelMask(t->m_TEX0.PSM))