From 60a2b246e2e336cb98f0b21835c91f425fedce6b Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Fri, 28 Jul 2023 12:24:34 +0100 Subject: [PATCH] GS: Correct alpha test for RGB Only and non-32bit colours --- pcsx2/GS/GSRegs.h | 1 + pcsx2/GS/GSState.cpp | 7 ++++--- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 10 +++++----- pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp | 2 +- pcsx2/GS/Renderers/SW/GSRendererSW.cpp | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pcsx2/GS/GSRegs.h b/pcsx2/GS/GSRegs.h index a9bc6ad1f0..1bff20cdf8 100644 --- a/pcsx2/GS/GSRegs.h +++ b/pcsx2/GS/GSRegs.h @@ -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) diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index 2003222557..2790bd985a 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -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; diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 6569fbab6d..eb79bfc177 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -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)) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp b/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp index 9df64fc273..38d727104d 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHWMultiISA.cpp @@ -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); diff --git a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp index 641a4e3ee3..3c4e1579ce 100644 --- a/pcsx2/GS/Renderers/SW/GSRendererSW.cpp +++ b/pcsx2/GS/Renderers/SW/GSRendererSW.cpp @@ -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);