mirror of https://github.com/PCSX2/pcsx2.git
GS-HW: Handle clears with single page width better + use vert color
This commit is contained in:
parent
2b85f96406
commit
15a82e2324
|
@ -1700,22 +1700,19 @@ void GSRendererHW::Draw()
|
|||
&& (m_vt.m_eq.rgba == 0xFFFF) // constant color write
|
||||
&& m_r.x == 0 && m_r.y == 0) // Likely full buffer write
|
||||
{
|
||||
|
||||
// Likely doing a huge single page width clear, which never goes well. (Superman)
|
||||
if ((m_r.w > 1024) && context->FRAME.FBW == 1)
|
||||
{
|
||||
m_r.z = GetResolution().x;
|
||||
m_r.w = GetResolution().y;
|
||||
context->FRAME.FBW = (m_r.z + 63) / 64;
|
||||
}
|
||||
if (OI_GsMemClear() && m_r.w > 1024)
|
||||
{
|
||||
if ((fm & fm_mask) != fm_mask)
|
||||
{
|
||||
m_tc->InvalidateVideoMem(context->offset.fb, m_r, false, true);
|
||||
|
||||
m_tc->InvalidateVideoMemType(GSTextureCache::RenderTarget, context->FRAME.Block());
|
||||
}
|
||||
|
||||
if (zm != 0xffffffff)
|
||||
{
|
||||
m_tc->InvalidateVideoMem(context->offset.zb, m_r, false, false);
|
||||
|
||||
m_tc->InvalidateVideoMemType(GSTextureCache::DepthStencil, context->ZBUF.Block());
|
||||
}
|
||||
m_tc->InvalidateVideoMem(context->offset.fb, m_r, false, true);
|
||||
m_tc->InvalidateVideoMemType(GSTextureCache::RenderTarget, context->FRAME.Block());
|
||||
m_tc->InvalidateVideoMem(context->offset.zb, m_r, false, false);
|
||||
m_tc->InvalidateVideoMemType(GSTextureCache::DepthStencil, context->ZBUF.Block());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4263,21 +4260,26 @@ bool GSRendererHW::OI_GsMemClear()
|
|||
// Note gs mem clear must be tested before calling this function
|
||||
|
||||
// Striped double clear done by Powerdrome and Snoopy Vs Red Baron, it will clear in 32 pixel stripes half done by the Z and half done by the FRAME
|
||||
const bool ZisFrame = m_context->FRAME.FBP == m_context->ZBUF.ZBP && (m_context->FRAME.PSM & 0x30) != (m_context->ZBUF.PSM & 0x30)
|
||||
&& (m_context->FRAME.PSM & 0xF) == (m_context->ZBUF.PSM & 0xF) && (u32)(GSVector4i(m_vt.m_max.p).z) == 0;
|
||||
const bool ZisFrame = m_context->FRAME.FBP == m_context->ZBUF.ZBP && !m_context->ZBUF.ZMSK && (m_context->FRAME.PSM & 0x30) != (m_context->ZBUF.PSM & 0x30)
|
||||
&& (m_context->FRAME.PSM & 0xF) == (m_context->ZBUF.PSM & 0xF) && m_vt.m_eq.z == 1 && m_vertex.buff[1].XYZ.Z == m_vertex.buff[1].RGBAQ.U32[0];
|
||||
|
||||
// Limit it further to a full screen 0 write
|
||||
if (((m_vertex.next == 2) || ZisFrame) && m_vt.m_min.c.eq(GSVector4i(0)))
|
||||
if (((m_vertex.next == 2) || ZisFrame) && m_vt.m_eq.rgba == 0xFFFF)
|
||||
{
|
||||
const GSOffset& off = m_context->offset.fb;
|
||||
const GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
||||
// Limit the hack to a single fullscreen clear. Some games might use severals column to clear a screen
|
||||
GSVector4i r = GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).rintersect(GSVector4i(m_context->scissor.in));
|
||||
|
||||
|
||||
if (r.width() == 32 && ZisFrame)
|
||||
r.z += 32;
|
||||
// Limit the hack to a single full buffer clear. Some games might use severals column to clear a screen
|
||||
// but hopefully it will be enough.
|
||||
if (r.width() <= 128 || r.height() <= 128)
|
||||
if (r.width() < ((static_cast<int>(m_context->FRAME.FBW) - 1) * 64) || r.height() <= 128)
|
||||
return false;
|
||||
|
||||
GL_INS("OI_GsMemClear (%d,%d => %d,%d)", r.x, r.y, r.z, r.w);
|
||||
const int format = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt;
|
||||
const u32 color = (format == 0) ? m_vertex.buff[1].RGBAQ.U32[0] : (m_vertex.buff[1].RGBAQ.U32[0] & ~0xFF000000);
|
||||
|
||||
// FIXME: loop can likely be optimized with AVX/SSE. Pixels aren't
|
||||
// linear but the value will be done for all pixels of a block.
|
||||
|
@ -4291,7 +4293,7 @@ bool GSRendererHW::OI_GsMemClear()
|
|||
|
||||
for (int x = r.left; x < r.right; x++)
|
||||
{
|
||||
*pa.value(x) = 0; // Here the constant color
|
||||
*pa.value(x) = color; // Here the constant color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4305,6 +4307,7 @@ bool GSRendererHW::OI_GsMemClear()
|
|||
for (int x = r.left; x < r.right; x++)
|
||||
{
|
||||
*pa.value(x) &= 0xff000000; // Clear the color
|
||||
*pa.value(x) |= color; // OR in our constant
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue