GS: Use accumulation blend when alpha is known to be 1

This commit is contained in:
TellowKrinkle 2022-08-28 00:21:27 -05:00 committed by lightningterror
parent 9150e69783
commit e89612e5b9
1 changed files with 26 additions and 4 deletions

View File

@ -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;