mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Handle more double-half clear edge cases
Spiderman: Web of Shadows clears its depth buffer with 32-bit FRAME and 24-bit Z. So the upper 8 bits of half the depth buffer are not cleared, yay. We can't turn this into a 32-bit clear, because then it'll zero out those bits, which other games need (e.g. Jak 2). We can't do a 24-bit clear, because something might rely on half those bits actually getting zeroed. So, instead, we toss the depth buffer, and let the mem clear path write out FRAME and Z separately, with their associated masks. Limit it to black to avoid false positives. Also fixes FBW getting blown out to 20 for a horizontal double-half clear in Wakeboarding Unleashed.
This commit is contained in:
parent
e1c9987059
commit
fa2f578900
|
@ -5912,8 +5912,12 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
|
|||
return false;
|
||||
|
||||
// Z and color must be constant and the same
|
||||
GSVertex* v = &m_vertex.buff[0];
|
||||
if (m_vt.m_eq.rgba != 0xFFFF || !m_vt.m_eq.z || v[1].XYZ.Z != v[1].RGBAQ.U32[0])
|
||||
if (m_vt.m_eq.rgba != 0xFFFF || !m_vt.m_eq.z)
|
||||
return false;
|
||||
|
||||
const u32 write_color = GetConstantDirectWriteMemClearColor();
|
||||
const u32 write_depth = GetConstantDirectWriteMemClearDepth();
|
||||
if (write_color != write_depth)
|
||||
return false;
|
||||
|
||||
// Frame and depth pointer can be inverted
|
||||
|
@ -5946,8 +5950,30 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
|
|||
if ((!enough_bits && frame_psm.fmt != zbuf_psm.fmt && m_cached_ctx.FRAME.FBMSK != ((zbuf_psm.fmt == 1) ? 0xFF000000u : 0)) ||
|
||||
!GSUtil::HasCompatibleBits(m_cached_ctx.FRAME.PSM & ~0x30, m_cached_ctx.ZBUF.PSM & ~0x30)) // Bit depth is not the same (i.e. 32bit + 16bit).
|
||||
{
|
||||
GL_INS("Inconsistent FRAME [%s, %08x] and ZBUF [%s] formats, not using double-half clear.",
|
||||
GL_INS("DetectDoubleHalfClear(): Inconsistent FRAME [%s, %08x] and ZBUF [%s] formats, not using double-half clear.",
|
||||
psm_str(m_cached_ctx.FRAME.PSM), m_cached_ctx.FRAME.FBMSK, psm_str(m_cached_ctx.ZBUF.PSM));
|
||||
|
||||
// Spiderman: Web of Shadows clears its depth buffer with 32-bit FRAME and 24-bit Z. So the upper 8 bits of half
|
||||
// the depth buffer are not cleared, yay. We can't turn this into a 32-bit clear, because then it'll zero out
|
||||
// those bits, which other games need (e.g. Jak 2). We can't do a 24-bit clear, because something might rely
|
||||
// on half those bits actually getting zeroed. So, instead, we toss the depth buffer, and let the mem clear
|
||||
// path write out FRAME and Z separately, with their associated masks. Limit it to black to avoid false positives.
|
||||
if (write_color == 0)
|
||||
{
|
||||
const GSTextureCache::Target* base_tgt = g_texture_cache->GetExactTarget(base * BLOCKS_PER_PAGE,
|
||||
m_cached_ctx.FRAME.FBW, clear_depth ? GSTextureCache::DepthStencil : GSTextureCache::RenderTarget,
|
||||
GSLocalMemory::GetEndBlockAddress(half * BLOCKS_PER_PAGE, m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r));
|
||||
if (base_tgt)
|
||||
{
|
||||
GL_INS("DetectDoubleHalfClear(): Invalidating targets at 0x%x/0x%x due to different formats, and clear to black.",
|
||||
base * BLOCKS_PER_PAGE, half * BLOCKS_PER_PAGE);
|
||||
g_texture_cache->InvalidateVideoMemType(GSTextureCache::RenderTarget, base * BLOCKS_PER_PAGE);
|
||||
g_texture_cache->InvalidateVideoMemType(GSTextureCache::RenderTarget, half * BLOCKS_PER_PAGE);
|
||||
g_texture_cache->InvalidateVideoMemType(GSTextureCache::DepthStencil, base * BLOCKS_PER_PAGE);
|
||||
g_texture_cache->InvalidateVideoMemType(GSTextureCache::DepthStencil, half * BLOCKS_PER_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6035,9 +6061,15 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
|
|||
if (horizontal)
|
||||
{
|
||||
const int width = m_r.width();
|
||||
m_cached_ctx.FRAME.FBW *= 2;
|
||||
m_r.z = (w_pages * frame_psm.pgs.x);
|
||||
m_r.z += m_r.x + width;
|
||||
|
||||
const u32 new_w_pages = (m_r.z + 63) / 64;
|
||||
if (new_w_pages > m_cached_ctx.FRAME.FBW)
|
||||
{
|
||||
GL_INS("DetectDoubleHalfClear(): Doubling FBW because %u pages wide is less than FBW %u", new_w_pages, m_cached_ctx.FRAME.FBW);
|
||||
m_cached_ctx.FRAME.FBW *= 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -523,7 +523,7 @@ public:
|
|||
|
||||
void IncAge();
|
||||
|
||||
const char* to_string(int type)
|
||||
static const char* to_string(int type)
|
||||
{
|
||||
return (type == DepthStencil) ? "Depth" : "Color";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue