mirror of https://github.com/PCSX2/pcsx2.git
GS: Use pixel format mask for FBMSK checks
This commit is contained in:
parent
224863fbd5
commit
9721ed0fb3
|
@ -2730,7 +2730,7 @@ __forceinline void GSState::VertexKick(u32 skip)
|
|||
break;
|
||||
}
|
||||
|
||||
if (m_context->FRAME.FBMSK != 0xFFFFFFFF)
|
||||
if ((m_context->FRAME.FBMSK & GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk) != GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk)
|
||||
m_mem.m_clut.Invalidate(m_context->FRAME.Block());
|
||||
|
||||
if (auto_flush && m_index.tail >= n)
|
||||
|
@ -3206,12 +3206,14 @@ void GSState::CalcAlphaMinMax()
|
|||
m_vt.m_alpha.valid = true;
|
||||
}
|
||||
|
||||
bool GSState::TryAlphaTest(u32& fm, u32& zm)
|
||||
bool GSState::TryAlphaTest(u32& fm, const u32 fm_mask, u32& zm)
|
||||
{
|
||||
// Shortcut for the easy case
|
||||
if (m_context->TEST.ATST == ATST_ALWAYS)
|
||||
return true;
|
||||
|
||||
const u32 framemask = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
const u32 framemaskalpha = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk & 0xFF000000;
|
||||
// Alpha test can only control the write of some channels. If channels are already masked
|
||||
// the alpha test is therefore a nop.
|
||||
switch (m_context->TEST.AFAIL)
|
||||
|
@ -3223,11 +3225,11 @@ bool GSState::TryAlphaTest(u32& fm, u32& zm)
|
|||
return true;
|
||||
break;
|
||||
case AFAIL_ZB_ONLY:
|
||||
if (fm == 0xFFFFFFFF)
|
||||
if ((fm & framemask) == framemask)
|
||||
return true;
|
||||
break;
|
||||
case AFAIL_RGB_ONLY:
|
||||
if (zm == 0xFFFFFFFF && ((fm & 0xFF000000) == 0xFF000000 || GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt == 1))
|
||||
if (zm == 0xFFFFFFFF && ((fm & framemaskalpha) == framemaskalpha || GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt == 1))
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -212,7 +212,7 @@ protected:
|
|||
u8 uses_boundary; ///< Whether or not the usage touches the left, top, right, or bottom edge (and therefore needs wrap modes preserved)
|
||||
};
|
||||
TextureMinMaxResult GetTextureMinMax(const GIFRegTEX0& TEX0, const GIFRegCLAMP& CLAMP, bool linear);
|
||||
bool TryAlphaTest(u32& fm, u32& zm);
|
||||
bool TryAlphaTest(u32& fm, const u32 fm_mask, u32& zm);
|
||||
bool IsOpaque();
|
||||
bool IsMipMapDraw();
|
||||
bool IsMipMapActive();
|
||||
|
|
|
@ -1249,13 +1249,14 @@ void GSRendererHW::Draw()
|
|||
|
||||
u32 fm = context->FRAME.FBMSK;
|
||||
u32 zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0;
|
||||
const u32 fm_mask = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
|
||||
// Note required to compute TryAlphaTest below. So do it now.
|
||||
if (PRIM->TME && tex_psm.pal > 0)
|
||||
m_mem.m_clut.Read32(context->TEX0, env.TEXA);
|
||||
|
||||
// Test if we can optimize Alpha Test as a NOP
|
||||
context->TEST.ATE = context->TEST.ATE && !GSRenderer::TryAlphaTest(fm, zm);
|
||||
context->TEST.ATE = context->TEST.ATE && !GSRenderer::TryAlphaTest(fm, fm_mask, zm);
|
||||
|
||||
context->FRAME.FBMSK = fm;
|
||||
context->ZBUF.ZMSK = zm != 0;
|
||||
|
@ -1271,7 +1272,7 @@ void GSRendererHW::Draw()
|
|||
// Depth is always pass/fail (no read) and write are discarded (tekken 5). (Note: DATE is currently implemented with a stencil buffer => a depth/stencil buffer)
|
||||
(zm != 0 && m_context->TEST.ZTST <= ZTST_ALWAYS && !m_context->TEST.DATE) ||
|
||||
// Depth will be written through the RT
|
||||
(context->FRAME.FBP == context->ZBUF.ZBP && !PRIM->TME && zm == 0 && fm == 0 && context->TEST.ZTE)
|
||||
(context->FRAME.FBP == context->ZBUF.ZBP && !PRIM->TME && zm == 0 && (fm & fm_mask) == 0 && context->TEST.ZTE)
|
||||
);
|
||||
|
||||
if (no_rt && no_ds)
|
||||
|
@ -1504,7 +1505,7 @@ void GSRendererHW::Draw()
|
|||
&& draw_sprite_tex && m_src->m_32_bits_fmt;
|
||||
|
||||
// Okami mustn't call this code
|
||||
if (m_texture_shuffle && m_vertex.next < 3 && PRIM->FST && (m_context->FRAME.FBMSK == 0))
|
||||
if (m_texture_shuffle && m_vertex.next < 3 && PRIM->FST && ((m_context->FRAME.FBMSK & fm_mask) == 0))
|
||||
{
|
||||
// Avious dubious call to m_texture_shuffle on 16 bits games
|
||||
// The pattern is severals column of 8 pixels. A single sprite
|
||||
|
@ -1741,7 +1742,7 @@ void GSRendererHW::Draw()
|
|||
|
||||
//
|
||||
|
||||
if (fm != 0xffffffff && rt)
|
||||
if ((fm & fm_mask) != fm_mask && rt)
|
||||
{
|
||||
//rt->m_valid = rt->m_valid.runion(r);
|
||||
rt->UpdateValidity(m_r);
|
||||
|
|
|
@ -230,7 +230,7 @@ void GSRendererNew::EmulateTextureShuffleAndFbmask()
|
|||
|
||||
// Please bang my head against the wall!
|
||||
// 1/ Reduce the frame mask to a 16 bit format
|
||||
const u32& m = m_context->FRAME.FBMSK;
|
||||
const u32 m = m_context->FRAME.FBMSK & GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
const u32 fbmask = ((m >> 3) & 0x1F) | ((m >> 6) & 0x3E0) | ((m >> 9) & 0x7C00) | ((m >> 16) & 0x8000);
|
||||
// FIXME GSVector will be nice here
|
||||
const u8 rg_mask = fbmask & 0xFF;
|
||||
|
@ -301,7 +301,7 @@ void GSRendererNew::EmulateTextureShuffleAndFbmask()
|
|||
// Don't allow only unused bits on 16bit format to enable fbmask,
|
||||
// let's set the mask to 0 in such cases.
|
||||
int fbmask = static_cast<int>(m_context->FRAME.FBMSK);
|
||||
const int fbmask_r = m_conf.ps.dfmt == 2 ? 0x80F8F8F8 : m_conf.ps.dfmt == 1 ? 0x00FFFFFF : 0xFFFFFFFF;
|
||||
const int fbmask_r = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
fbmask &= fbmask_r;
|
||||
const GSVector4i fbmask_v = GSVector4i::load(fbmask);
|
||||
const GSVector4i fbmask_vr = GSVector4i::load(fbmask_r);
|
||||
|
@ -1329,7 +1329,8 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
// Detect framebuffer read that will need special handling
|
||||
if (g_gs_device->Features().texture_barrier && (m_context->FRAME.Block() == m_context->TEX0.TBP0) && PRIM->TME && GSConfig.AccurateBlendingUnit != AccBlendLevel::Minimum)
|
||||
{
|
||||
if ((m_context->FRAME.FBMSK == 0x00FFFFFF) && (m_vt.m_primclass == GS_TRIANGLE_CLASS))
|
||||
const u32 fb_mask = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
if (((m_context->FRAME.FBMSK & fb_mask) == (fb_mask & 0x00FFFFFF)) && (m_vt.m_primclass == GS_TRIANGLE_CLASS))
|
||||
{
|
||||
// This pattern is used by several games to emulate a stencil (shadow)
|
||||
// Ratchet & Clank, Jak do alpha integer multiplication (tfx) which is mostly equivalent to +1/-1
|
||||
|
|
|
@ -962,6 +962,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
|||
|
||||
u32 fm = context->FRAME.FBMSK;
|
||||
u32 zm = context->ZBUF.ZMSK || context->TEST.ZTE == 0 ? 0xffffffff : 0;
|
||||
const u32 fm_mask = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
|
||||
|
||||
// When the format is 24bit (Z or C), DATE ceases to function.
|
||||
// It was believed that in 24bit mode all pixels pass because alpha doesn't exist
|
||||
|
@ -988,7 +989,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
|||
|
||||
if (context->TEST.ATE)
|
||||
{
|
||||
if (!TryAlphaTest(fm, zm))
|
||||
if (!TryAlphaTest(fm, fm_mask, zm))
|
||||
{
|
||||
gd.sel.atst = context->TEST.ATST;
|
||||
gd.sel.afail = context->TEST.AFAIL;
|
||||
|
@ -1009,7 +1010,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
|||
}
|
||||
}
|
||||
|
||||
bool fwrite = fm != 0xffffffff;
|
||||
bool fwrite = (fm & fm_mask) != fm_mask;
|
||||
bool ftest = gd.sel.atst != ATST_ALWAYS || context->TEST.DATE && context->FRAME.PSM != PSM_PSMCT24;
|
||||
|
||||
bool zwrite = zm != 0xffffffff;
|
||||
|
@ -1302,12 +1303,13 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
|
|||
gd.afix = GSVector4i((int)context->ALPHA.FIX << 7).xxzzlh();
|
||||
}
|
||||
|
||||
const u32 masked_fm = fm & fm_mask;
|
||||
if (gd.sel.date
|
||||
|| gd.sel.aba == 1 || gd.sel.abb == 1 || gd.sel.abc == 1 || gd.sel.abd == 1
|
||||
|| gd.sel.atst != ATST_ALWAYS && gd.sel.afail == AFAIL_RGB_ONLY
|
||||
|| gd.sel.fpsm == 0 && fm != 0 && fm != 0xffffffff
|
||||
|| gd.sel.fpsm == 1 && (fm & 0x00ffffff) != 0 && (fm & 0x00ffffff) != 0x00ffffff
|
||||
|| gd.sel.fpsm == 2 && (fm & 0x80f8f8f8) != 0 && (fm & 0x80f8f8f8) != 0x80f8f8f8)
|
||||
|| gd.sel.fpsm == 0 && masked_fm != 0 && masked_fm != fm_mask
|
||||
|| gd.sel.fpsm == 1 && masked_fm != 0 && masked_fm != fm_mask
|
||||
|| gd.sel.fpsm == 2 && masked_fm != 0 && masked_fm != fm_mask)
|
||||
{
|
||||
gd.sel.rfb = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue