From 5bc3b4bf7d20f46c7a4cc9b3ac0683d9cd7669f4 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sat, 10 Dec 2022 23:35:44 +0000 Subject: [PATCH] GS-HW: On memory clear with alpha blend, check if output colour is black --- pcsx2/GS/GSRegs.h | 1 + pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pcsx2/GS/GSRegs.h b/pcsx2/GS/GSRegs.h index f5f9d7c47a..f254ac7e98 100644 --- a/pcsx2/GS/GSRegs.h +++ b/pcsx2/GS/GSRegs.h @@ -540,6 +540,7 @@ REG_END2 __forceinline bool IsOpaque() const { return ((A == B || (C == 2 && FIX == 0)) && D == 0) || (A == 0 && B == D && C == 2 && FIX == 0x80) || (C == 2 && D != 1 && FIX == 0x00); } __forceinline bool IsOpaque(int amin, int amax) const { return ((A == B || amax == 0) && D == 0) || (A == 0 && B == D && amin == 0x80 && amax == 0x80) || (C == 2 && D != 1 && FIX == 0x00); } __forceinline bool IsCd() { return (A == B) && (D == 1); } + __forceinline bool IsBlack() { return ((C == 2 && FIX == 0) || (A == 2 && A == B)) && D == 2; } REG_END2 REG64_(GIFReg, BITBLTBUF) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 9e0f645f54..03f9e85370 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -4213,7 +4213,11 @@ void GSRendererHW::OI_DoubleHalfClear(GSTextureCache::Target*& rt, GSTextureCach // If both buffers are side by side we can expect a fast clear in on-going if (half <= (base + written_pages)) { - const u32 color = v[1].RGBAQ.U32[0]; + // Take the vertex colour, but check if the blending would make it black. + u32 vert_color = v[1].RGBAQ.U32[0]; + if (PRIM->ABE && m_context->ALPHA.IsBlack()) + vert_color &= ~0xFF000000; + const u32 color = vert_color; const bool clear_depth = (m_context->FRAME.FBP > m_context->ZBUF.ZBP); GL_INS("OI_DoubleHalfClear:%s: base %x half %x. w_pages %d h_pages %d fbw %d. Color %x", @@ -4292,7 +4296,13 @@ bool GSRendererHW::OI_GsMemClear() 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); + + // Take the vertex colour, but check if the blending would make it black. + u32 vert_color = m_vertex.buff[1].RGBAQ.U32[0]; + if (PRIM->ABE && m_context->ALPHA.IsBlack()) + vert_color &= ~0xFF000000; + + const u32 color = (format == 0) ? vert_color : (vert_color & ~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.