GS: Correct alpha test for RGB Only and non-32bit colours

This commit is contained in:
refractionpcsx2 2023-07-28 12:24:34 +01:00
parent ebd60d93f3
commit 60a2b246e2
5 changed files with 12 additions and 10 deletions

View File

@ -792,6 +792,7 @@ REG_END2
__forceinline bool DoFirstPass() const { return !ATE || ATST != ATST_NEVER; } // not all pixels fail automatically
__forceinline bool DoSecondPass() const { return ATE && ATST != ATST_ALWAYS && AFAIL != AFAIL_KEEP; } // pixels may fail, write fb/z
__forceinline bool NoSecondPass() const { return ATE && ATST != ATST_ALWAYS && AFAIL == AFAIL_KEEP; } // pixels may fail, no output
__forceinline u32 GetAFAIL(u32 fpsm) const { return (AFAIL == AFAIL_RGB_ONLY && (fpsm & 0xF) != 0) ? AFAIL_FB_ONLY : AFAIL; } // FB Only when not 32bit Framebuffer
REG_END2
REG64_(GIFReg, TEX0)

View File

@ -3788,9 +3788,10 @@ bool GSState::TryAlphaTest(u32& fm, const u32 fm_mask, u32& zm)
const u32 framemask = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk;
const u32 framemaskalpha = GSLocalMemory::m_psm[m_context->FRAME.PSM].fmsk & 0xFF000000;
const u32 fail_type = m_context->TEST.GetAFAIL(m_context->FRAME.PSM);
// 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)
switch (fail_type)
{
case AFAIL_KEEP:
break;
@ -3803,7 +3804,7 @@ bool GSState::TryAlphaTest(u32& fm, const u32 fm_mask, u32& zm)
return true;
break;
case AFAIL_RGB_ONLY:
if (zm == 0xFFFFFFFF && ((fm & framemaskalpha) == framemaskalpha || GSLocalMemory::m_psm[m_context->FRAME.PSM].fmt == 1))
if (zm == 0xFFFFFFFF && (fm & framemaskalpha) == framemaskalpha)
return true;
break;
default:
@ -3887,7 +3888,7 @@ bool GSState::TryAlphaTest(u32& fm, const u32 fm_mask, u32& zm)
if (!pass)
{
switch (m_context->TEST.AFAIL)
switch (fail_type)
{
case AFAIL_KEEP:
fm = zm = 0xffffffff;

View File

@ -4933,8 +4933,8 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
const bool commutative_depth = (m_conf.depth.ztst == ZTST_GEQUAL && m_vt.m_eq.z) || (m_conf.depth.ztst == ZTST_ALWAYS);
const bool commutative_alpha = (m_context->ALPHA.C != 1); // when either Alpha Src or a constant
ate_RGBA_then_Z = (m_cached_ctx.TEST.AFAIL == AFAIL_FB_ONLY) && commutative_depth;
ate_RGB_then_ZA = (m_cached_ctx.TEST.AFAIL == AFAIL_RGB_ONLY) && commutative_depth && commutative_alpha;
ate_RGBA_then_Z = m_cached_ctx.TEST.GetAFAIL(m_cached_ctx.FRAME.PSM) == AFAIL_FB_ONLY && commutative_depth;
ate_RGB_then_ZA = m_cached_ctx.TEST.GetAFAIL(m_cached_ctx.FRAME.PSM) == AFAIL_RGB_ONLY && commutative_depth && commutative_alpha;
}
if (ate_RGBA_then_Z)
@ -5030,8 +5030,8 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
bool g = m_conf.colormask.wg;
bool b = m_conf.colormask.wb;
bool a = m_conf.colormask.wa;
switch (m_cached_ctx.TEST.AFAIL)
const int fail_type = m_cached_ctx.TEST.GetAFAIL(m_cached_ctx.FRAME.PSM);
switch (fail_type)
{
case AFAIL_KEEP: z = r = g = b = a = false; break; // none
case AFAIL_FB_ONLY: z = false; break; // rgba
@ -5159,7 +5159,7 @@ GSRendererHW::CLUTDrawTestResult GSRendererHW::PossibleCLUTDraw()
return CLUTDrawTestResult::NotCLUTDraw;
// Keep the draws simple, no alpha testing, blending, mipmapping, Z writes, and make sure it's flat.
const bool fb_only = m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.AFAIL == 1 && m_cached_ctx.TEST.ATST == ATST_NEVER;
const bool fb_only = m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.GetAFAIL(m_cached_ctx.FRAME.PSM) == AFAIL_FB_ONLY && m_cached_ctx.TEST.ATST == ATST_NEVER;
// No Z writes, unless it's points, then it's quite likely to be a palette and they left it on.
if (!m_cached_ctx.ZBUF.ZMSK && !fb_only && !(m_vt.m_primclass == GS_POINT_CLASS))

View File

@ -132,7 +132,7 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc, b
if (!hw.TryAlphaTest(fm, fm_mask, zm))
{
gd.sel.atst = context->TEST.ATST;
gd.sel.afail = context->TEST.AFAIL;
gd.sel.afail = context->TEST.GetAFAIL(context->FRAME.PSM);
gd.aref = GSVector4i((int)context->TEST.AREF);

View File

@ -990,7 +990,7 @@ bool GSRendererSW::GetScanlineGlobalData(SharedData* data)
if (!TryAlphaTest(fm, fm_mask, zm))
{
gd.sel.atst = context->TEST.ATST;
gd.sel.afail = context->TEST.AFAIL;
gd.sel.afail = context->TEST.GetAFAIL(context->FRAME.PSM);
gd.aref = GSVector4i((int)context->TEST.AREF);