diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 08f216eaa5..fbe1e9c13e 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -2504,9 +2504,10 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& const bool alpha_c2_zero = (m_conf.ps.blend_c == 2 && ALPHA.FIX == 0u); const bool alpha_c2_one = (m_conf.ps.blend_c == 2 && ALPHA.FIX == 128u); const bool alpha_c2_high_one = (m_conf.ps.blend_c == 2 && ALPHA.FIX > 128u); + const bool alpha_one = alpha_c0_one || alpha_c2_one; // Optimize blending equations, must be done before index calculation - if ((m_conf.ps.blend_a == m_conf.ps.blend_b) || ((m_conf.ps.blend_b == m_conf.ps.blend_d) && (alpha_c0_one || alpha_c2_one))) + if ((m_conf.ps.blend_a == m_conf.ps.blend_b) || ((m_conf.ps.blend_b == m_conf.ps.blend_d) && alpha_one)) { // Condition 1: // A == B @@ -2546,7 +2547,8 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& blend_ad_alpha_masked = false; u8 blend_index = u8(((m_conf.ps.blend_a * 3 + m_conf.ps.blend_b) * 3 + m_conf.ps.blend_c) * 3 + m_conf.ps.blend_d); - const int blend_flag = GSDevice::GetBlendFlags(blend_index); + const HWBlend blend_preliminary = GSDevice::GetBlend(blend_index, false); + const int blend_flag = blend_preliminary.flags; // Re set alpha, it was modified, must be done after index calculation if (blend_ad_alpha_masked) @@ -2557,6 +2559,11 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& // Do the multiplication in shader for blending accumulation: Cs*As + Cd or Cs*Af + Cd bool accumulation_blend = !!(blend_flag & BLEND_ACCU); + // If alpha == 1.0, almost everything is an accumulation blend! + // Ones that use (1 + Alpha) can't guarante the mixed sw+hw blending this enables will give an identical result to sw due to clamping + // But enable for everything else that involves dst color + if (alpha_one && (m_conf.ps.blend_a != m_conf.ps.blend_d) && blend_preliminary.dst != GSDevice::CONST_ZERO) + accumulation_blend = true; // Blending doesn't require barrier, or sampling of the rt const bool blend_non_recursive = !!(blend_flag & BLEND_NO_REC); @@ -2832,6 +2839,23 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& { // Keep HW blending to do the addition/subtraction m_conf.blend = {true, GSDevice::CONST_ONE, GSDevice::CONST_ONE, blend.op, false, 0}; + // Remove Cd from sw blend, it's handled in hw + if (m_conf.ps.blend_a == 1) + m_conf.ps.blend_a = 2; + if (m_conf.ps.blend_b == 1) + m_conf.ps.blend_b = 2; + if (m_conf.ps.blend_d == 1) + m_conf.ps.blend_d = 2; + + if (m_conf.ps.blend_a == 2) + { + // Accumulation blend is only available in (Cs - 0)*Something + Cd, or with alpha == 1 + ASSERT(m_conf.ps.blend_d == 2 || alpha_one); + // A bit of normalization + m_conf.ps.blend_a = m_conf.ps.blend_d; + m_conf.ps.blend_d = 2; + } + if (m_conf.ps.blend_a == 2) { // The blend unit does a reverse subtraction so it means @@ -2840,8 +2864,6 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& m_conf.ps.blend_a = m_conf.ps.blend_b; m_conf.ps.blend_b = 2; } - // Remove the addition/substraction from the SW blending - m_conf.ps.blend_d = 2; // Dual source output not needed (accumulation blend replaces it with ONE). m_conf.ps.no_color1 = true;