GS: Add Auto Flush for Z buffer draws

Adjust Burnout CRC hack
This commit is contained in:
refractionpcsx2 2022-03-08 15:16:19 +00:00
parent d9f914eb7c
commit 90a4a11d49
2 changed files with 23 additions and 20 deletions

View File

@ -2433,10 +2433,14 @@ GSState::PRIM_OVERLAP GSState::PrimitiveOverlap()
__forceinline void GSState::HandleAutoFlush()
{
const bool frame_hit = (m_context->FRAME.Block() == m_context->TEX0.TBP0) && !(m_context->TEST.ATE && m_context->TEST.ATST == 0 && m_context->TEST.AFAIL == 2);
// There's a strange behaviour we need to test on a PS2 here, if the FRAME is a Z format, like Powerdrome something swaps over, and it seems Alpha Fail of "FB Only" writes to the Z.. it's odd.
const bool zbuf_hit = (m_context->ZBUF.Block() == m_context->TEX0.TBP0) && !(m_context->TEST.ATE && m_context->TEST.ATST == 0 && m_context->TEST.AFAIL != 2 && (m_context->ZBUF.PSM & 0x30) == 0x30) && !m_context->ZBUF.ZMSK;
// To briefly explain what's going on here, what we are checking for is draws over a texture when the source and destination are themselves.
// Because one page of the texture gets buffered in the Texture Cache (the PS2's one) if any of those pixels are overwritten, you still read the old data.
// So we need to calculate if a page boundary is being crossed for the format it is in and if the same part of the texture being written and read inside the draw.
if ((m_context->FRAME.Block() == m_context->TEX0.TBP0) && (m_context->TEX0.PSM == m_context->FRAME.PSM) && PRIM->TME && (m_context->FRAME.FBMSK != 0xFFFFFFFF))
if (((frame_hit && ((m_context->TEX0.PSM ^ m_context->FRAME.PSM) & ~0x30) == 0) || (zbuf_hit && ((m_context->TEX0.PSM ^ m_context->ZBUF.PSM) & ~0x30) == 0)) && PRIM->TME && (m_context->FRAME.FBMSK != 0xFFFFFFFF))
{
const int page_mask_x = ~(GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.x - 1);
const int page_mask_y = ~(GSLocalMemory::m_psm[m_context->TEX0.PSM].pgs.y - 1);
@ -2513,12 +2517,20 @@ __forceinline void GSState::HandleAutoFlush()
if(page_crossed)
{
// Update the vertex trace, scissor it (important for Jak 3!) and intersect with the current texture.
if((m_index.tail - 1) == current_tex_end)
m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail - m_vertex.head, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM));
// Make sure the format matches, otherwise the coordinates aren't gonna match, so the draws won't intersect.
if ((frame_hit && (m_context->TEX0.PSM == m_context->FRAME.PSM)) || (zbuf_hit && (m_context->TEX0.PSM == m_context->ZBUF.PSM)))
{
// Update the vertex trace, scissor it (important for Jak 3!) and intersect with the current texture.
if ((m_index.tail - 1) == current_tex_end)
m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail - m_vertex.head, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM));
GSVector4i area_out = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
if (!area_out.rintersect(tex_rect).rempty())
GSVector4i area_out = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
if (!area_out.rintersect(tex_rect).rempty())
{
Flush();
}
}
else // Format of the TEX and FRAME/Z is different, so uhh, just fall back to flushing each page. It's slower, sorry.
{
Flush();
}
@ -2534,29 +2546,19 @@ __forceinline void GSState::VertexKick(u32 skip)
switch (prim)
{
case GS_POINTLIST:
case GS_INVALID:
n = 1;
break;
case GS_LINELIST:
n = 2;
break;
case GS_SPRITE:
case GS_LINESTRIP:
n = 2;
break;
case GS_TRIANGLELIST:
n = 3;
break;
case GS_TRIANGLESTRIP:
n = 3;
break;
case GS_TRIANGLEFAN:
n = 3;
break;
case GS_SPRITE:
n = 2;
break;
case GS_INVALID:
n = 1;
break;
}
if (m_context->FRAME.FBMSK != 0xFFFFFFFF)

View File

@ -18,7 +18,7 @@
bool s_nativeres;
static CRCHackLevel s_crc_hack_level = CRCHackLevel::Full;
bool s_autoflush;
// hacks
#define CRC_Partial (s_crc_hack_level >= CRCHackLevel::Partial)
#define CRC_Full (s_crc_hack_level >= CRCHackLevel::Full)
@ -419,7 +419,7 @@ bool GSC_BurnoutGames(const GSFrameInfo& fi, int& skip)
// 0x01dc0 01c00(MP) ntsc, 0x01f00 0x01d40(MP) ntsc progressive, 0x02200(MP) pal.
// Yellow stripes.
// Multiplayer tested only on Takedown.
skip = 4;
skip = s_autoflush ? 2 : 4;
}
}
@ -950,6 +950,7 @@ void GSState::SetupCrcHack()
s_nativeres = m_nativeres;
s_crc_hack_level = m_crc_hack_level;
s_autoflush = m_userhacks_auto_flush;
memset(lut, 0, sizeof(lut));