GS/HW: Predict valid sizes based on repeated draws and scissor

- this should be okay/limited to certain situations like Battlefield 2. Scissor isn't 100% guaranteed to be right, but it's probably better than nothing.
This commit is contained in:
refractionpcsx2 2025-01-25 20:35:32 +00:00
parent 34a0d50c7b
commit 25338fb4f2
1 changed files with 6 additions and 0 deletions

View File

@ -950,6 +950,12 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex)
// e.g. Burnout 3, God of War II, etc.
int height = std::min<int>(m_context->scissor.in.w, m_r.w);
// We can check if the next draw is doing the same from the next page, and assume it's a per line clear.
// Battlefield 2 does this.
int pages = ((GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r) + 1) - m_cached_ctx.FRAME.Block()) >> 5;
if (m_cached_ctx.FRAME.FBW > 1 && m_r.height() <= 64 && (pages % m_cached_ctx.FRAME.FBW) == 0 && m_env.CTXT[m_backed_up_ctx].FRAME.FBP == (m_cached_ctx.FRAME.FBP + pages) && NextDrawMatchesShuffle())
height = std::max<int>(m_context->scissor.in.w, height);
// If the draw is less than a page high, FBW=0 is the same as FBW=1.
const GSLocalMemory::psm_t& frame_psm = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM];
int width = std::min(std::max<int>(m_cached_ctx.FRAME.FBW, 1) * 64, m_context->scissor.in.z);