GS: Fix some more draw buffering edgecases

This commit is contained in:
refractionpcsx2
2026-06-07 14:21:48 -04:00
committed by Ty
parent 20721b05fb
commit 3b2962fe1c
+24 -22
View File
@@ -364,9 +364,6 @@ void GSState::ResetDrawBufferIdx()
m_dirty_gs_regs = m_env_buffers[m_current_buffer_idx].m_dirty_regs;
temp_draw_rect = m_env_buffers[m_current_buffer_idx].draw_rect;
}
//DevCon.Warning("New round of draws buffer %d vertex tail %d index tail %d TME %d TBP0 0x%x draw %d", m_current_buffer_idx, m_vertex->tail, m_index->tail, m_env.PRIM.TME, m_env.CTXT[m_env.PRIM.CTXT].TEX0.TBP0, s_n);
}
@@ -405,8 +402,7 @@ void GSState::FlushBuffers(bool flush_base_only, bool use_flush_reason, GSFlushR
else if (m_index_buffers[0].tail == 0)
return;
int max_flushes = flush_base_only ? 1 : m_used_buffers_idx;
//DevCon.Warning("Flushing %d draw buffers from draw %d", m_used_buffers_idx, s_n);
const int max_flushes = flush_base_only ? 1 : m_used_buffers_idx;
for (int i = 0; i < max_flushes; i++)
{
m_current_buffer_idx = i;
@@ -438,7 +434,7 @@ void GSState::FlushBuffers(bool flush_base_only, bool use_flush_reason, GSFlushR
}
else if (restore_env)
memcpy(&m_env, &m_temp_env, sizeof(m_env));
//DevCon.Warning("Flushing position %d ABE is %d TME %d TEX0 TBP %x", i, m_prev_env.PRIM.ABE, m_prev_env.PRIM.TME, m_prev_env.CTXT[m_prev_env.PRIM.CTXT].TEX0.TBP0);
if (use_flush_reason && (i == current_idx || flush_reason == VSYNC))
FlushDraw(flush_reason);
else
@@ -457,8 +453,6 @@ void GSState::FlushBuffers(bool flush_base_only, bool use_flush_reason, GSFlushR
std::memcpy(&m_prev_env.CTXT[1], &m_env_buffers[m_current_buffer_idx].m_env.CTXT[1], 96);
std::memcpy(&m_prev_env.CTXT[ctx].offset, &m_env_buffers[m_current_buffer_idx].m_env.CTXT[ctx].offset, sizeof(m_env_buffers[m_current_buffer_idx].m_env.CTXT[ctx].offset));
std::memcpy(&m_prev_env.CTXT[ctx].scissor, &m_env_buffers[m_current_buffer_idx].m_env.CTXT[ctx].scissor, sizeof(m_env_buffers[m_current_buffer_idx].m_env.CTXT[ctx].scissor));
//DevCon.Warning("Flush complete, draw now %d", s_n);
//UpdateContext();
}
void GSState::PushBuffer()
@@ -466,7 +460,6 @@ void GSState::PushBuffer()
// Just in case it tries to overflow.
if (m_used_buffers_idx >= MAX_DRAW_BUFFERS)
{
//DevCon.Warning("Attempted to add a draw to buffer when full. Flushing");
FlushBuffers(false, false);
ResetDrawBufferIdx();
return;
@@ -508,7 +501,6 @@ void GSState::PushBuffer()
m_dirty_gs_regs = 0;
m_used_buffers_idx++;
m_recent_buffer_switch = true;
//DevCon.Warning("Pushing new buffer %d vertex tail %d index tail %d TME %d TBP0 0x%x draw %d", m_current_buffer_idx, m_vertex->tail, m_index->tail, m_env.PRIM.TME, m_env.CTXT[m_env.PRIM.CTXT].TEX0.TBP0, s_n);
}
}
@@ -522,10 +514,11 @@ bool GSState::CanBufferNewDraw()
// If the base draw isn't writing to the Z buffer, but following draws do, we can't use it.
// Also the base draw needs to be solid, not an alpha blend.
if (base_context.ZBUF.ZMSK || cur_context.FRAME.FBP != base_context.FRAME.FBP || cur_context.ZBUF.ZBP != base_context.ZBUF.ZBP || (m_env_buffers[0].m_env.PRIM.TME && base_context.TEX0.TFX > TFX_DECAL) ||
if (base_context.ZBUF.ZMSK || cur_context.FRAME.FBP != base_context.FRAME.FBP || cur_context.ZBUF.ZBP != base_context.ZBUF.ZBP || (m_env_buffers[0].m_env.PRIM.TME &&
(base_context.TEX0.TFX > TFX_DECAL || (m_env_buffers[0].m_env.PRIM.ABE && !base_context.TEX0.TCC && m_v.RGBAQ.A != 128))) ||
((base_context.TEST.ATE && base_context.TEST.ATST > ATST_ALWAYS && base_context.TEST.AREF != 0) && (base_context.TEST.AFAIL & AFAIL_FB_ONLY) == AFAIL_KEEP))
{
//DevCon.Warning("Flushing, cannot buffer draw due to incompatible base");
// Incompatible base.
return false;
}
@@ -544,6 +537,8 @@ bool GSState::CanBufferNewDraw()
if (!std::memcmp(&m_env_buffers[i].m_env, &m_env, 88))
{
GSDrawingEnvironment& buffered_ctx = m_env_buffers[i].m_env;
if (m_index_buffers[i].tail > m_index_buffers[0].tail)
return false;
if (buffered_ctx.CTXT[ctx].SCISSOR.U64 ^ cur_context.SCISSOR.U64)
continue;
@@ -567,6 +562,9 @@ bool GSState::CanBufferNewDraw()
continue;
if (buffered_ctx.CTXT[ctx].TEX1.U32[0] ^ cur_context.TEX1.U32[0])
continue;
if (buffered_ctx.CTXT[ctx].TEX1.MXL != cur_context.TEX1.MXL)
continue;
if (cur_context.TEX1.MXL)
{
if (buffered_ctx.CTXT[ctx].TEX1.U32[1] ^ cur_context.TEX1.U32[1])
@@ -602,27 +600,32 @@ bool GSState::CanBufferNewDraw()
if (i == 1 && !m_env_buffers[i].draw_rect.eq(m_env_buffers[0].draw_rect))
{
FlushWrite();
FlushBuffers(true, false);
const bool base_only = m_env_buffers[i].draw_rect.rintersect(m_env_buffers[0].draw_rect).rempty();
FlushBuffers(base_only, false);
ResetDrawBufferIdx();
i = -1;
continue;
if (!base_only)
break;
else
{
i = -1;
continue;
}
}
else
return false;
}
/*if (i != (m_current_buffer_idx + 1) && i != 0)
return false;*/
// We found a matching draw
//DevCon.Warning("Matching buffered draw detected in index %d, using", i);
m_index = &m_index_buffers[i];
m_vertex = &m_vertex_buffers[i];
const u32 copy_amt = m_vertex_buffers[m_current_buffer_idx].tail - m_vertex_buffers[m_current_buffer_idx].head;
m_recent_buffer_switch = m_vertex->tail == m_vertex->head;
m_vertex->tail = m_index->buff[m_index->tail - 1] + 1;
if (m_index->tail)
m_vertex->tail = m_index->buff[m_index->tail - 1] + 1;
else
m_vertex->tail = 0;
if (copy_amt)
memcpy(&m_vertex->buff[m_vertex->tail], &m_vertex_buffers[m_current_buffer_idx].buff[m_vertex_buffers[m_current_buffer_idx].head], sizeof(GSVertex) * copy_amt);
@@ -660,7 +663,7 @@ bool GSState::CanBufferNewDraw()
}
m_dirty_gs_regs = 0;
//DevCon.Warning("Picking buffer %d vertex tail %d index tail %d TME %d TBP0 0x%x dirty %x draw %d", m_current_buffer_idx, m_vertex->tail, m_index->tail, m_env.PRIM.TME, m_env.CTXT[m_env.PRIM.CTXT].TEX0.TBP0, m_dirty_gs_regs, s_n);
return true;
}
}
@@ -685,7 +688,6 @@ bool GSState::CanBufferNewDraw()
return false;
PushBuffer();
//DevCon.Warning("Buffering new draw! now buffering %d", m_used_buffers_idx);
return true;
}