GS/HW: Reduce sw/hdr colclip in more cases.

When doing `Cs*Alpha + Cd*(1 - Alpha)` or `Cd*Alpha + Cs*(1 - Alpha)` with an alpha of 128 or lower
we don't really need to hdr or sw colclip blend it because colour range of the result will be
between 0-1 (0-255) without it overflowing.

Also update previous optimizations to include Ad cases when RTA is already scaled.
This commit is contained in:
lightningterror 2024-09-13 06:46:21 +02:00
parent f50083e47a
commit e8e0b97f6d
1 changed files with 10 additions and 3 deletions

View File

@ -4149,6 +4149,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
const bool alpha_c0_eq_less_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128); const bool alpha_c0_eq_less_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128);
const bool alpha_c1_high_min_one = (m_conf.ps.blend_c == 1 && rt_alpha_min > 128); const bool alpha_c1_high_min_one = (m_conf.ps.blend_c == 1 && rt_alpha_min > 128);
const bool alpha_c1_high_max_one = (m_conf.ps.blend_c == 1 && rt_alpha_max > 128); const bool alpha_c1_high_max_one = (m_conf.ps.blend_c == 1 && rt_alpha_max > 128);
const bool alpha_c1_eq_less_max_one = (m_conf.ps.blend_c == 1 && rt_alpha_max <= 128);
bool alpha_c1_high_no_rta_correct = m_conf.ps.blend_c == 1 && !(new_rt_alpha_scale || can_scale_rt_alpha); bool alpha_c1_high_no_rta_correct = m_conf.ps.blend_c == 1 && !(new_rt_alpha_scale || can_scale_rt_alpha);
const bool alpha_c2_eq_zero = (m_conf.ps.blend_c == 2 && AFIX == 0u); const bool alpha_c2_eq_zero = (m_conf.ps.blend_c == 2 && AFIX == 0u);
const bool alpha_c2_eq_one = (m_conf.ps.blend_c == 2 && AFIX == 128u); const bool alpha_c2_eq_one = (m_conf.ps.blend_c == 2 && AFIX == 128u);
@ -4233,8 +4234,12 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// HW blend can handle Cd output. // HW blend can handle Cd output.
bool color_dest_blend = !!(blend_flag & BLEND_CD); bool color_dest_blend = !!(blend_flag & BLEND_CD);
// HW blend can handle it, no need for sw blend or hdr, Cd*Alpha or Cd*(1 - Alpha) where Alpha <= 128, Alpha is As or Af. // HW blend can handle it, no need for sw or hdr colclip, Cd*Alpha or Cd*(1 - Alpha) where Alpha <= 128.
bool color_dest_blend2 = alpha_eq_less_one && ((blend_flag & BLEND_HW2) || (m_conf.ps.blend_b == m_conf.ps.blend_d == 1 && m_conf.ps.blend_a == 2)); bool color_dest_blend2 = !m_draw_env->PABE.PABE && ((m_conf.ps.blend_a == 1 && m_conf.ps.blend_b == 2 && m_conf.ps.blend_d == 2) || ((m_conf.ps.blend_b == m_conf.ps.blend_d == 1) && m_conf.ps.blend_a == 2)) &&
(alpha_eq_less_one || (alpha_c1_eq_less_max_one && new_rt_alpha_scale));
// HW blend can handle it, no need for sw or hdr colclip, Cs*Alpha + Cd*(1 - Alpha) or Cd*Alpha + Cs*(1 - Alpha) where Alpha <= 128.
bool blend_zero_to_one_range = !m_draw_env->PABE.PABE && (((m_conf.ps.blend_b == m_conf.ps.blend_d == 1) && m_conf.ps.blend_a == 0) || (blend_flag & BLEND_MIX3)) &&
(alpha_eq_less_one || (alpha_c1_eq_less_max_one && new_rt_alpha_scale));
// Do the multiplication in shader for blending accumulation: Cs*As + Cd or Cs*Af + Cd // Do the multiplication in shader for blending accumulation: Cs*As + Cd or Cs*Af + Cd
bool accumulation_blend = !!(blend_flag & BLEND_ACCU); bool accumulation_blend = !!(blend_flag & BLEND_ACCU);
@ -4311,6 +4316,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// Prefer sw blend if possible. // Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend; color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend; color_dest_blend2 &= !prefer_sw_blend;
blend_zero_to_one_range &= !prefer_sw_blend;
accumulation_blend &= !prefer_sw_blend; accumulation_blend &= !prefer_sw_blend;
// Enable sw blending for barriers. // Enable sw blending for barriers.
sw_blending |= blend_requires_barrier; sw_blending |= blend_requires_barrier;
@ -4351,6 +4357,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// Prefer sw blend if possible. // Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend; color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend; color_dest_blend2 &= !prefer_sw_blend;
blend_zero_to_one_range &= !prefer_sw_blend;
accumulation_blend &= !prefer_sw_blend; accumulation_blend &= !prefer_sw_blend;
// Enable sw blending for reading fb. // Enable sw blending for reading fb.
sw_blending |= prefer_sw_blend; sw_blending |= prefer_sw_blend;
@ -4384,7 +4391,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
const bool free_colclip = features.framebuffer_fetch || no_prim_overlap || blend_non_recursive; const bool free_colclip = features.framebuffer_fetch || no_prim_overlap || blend_non_recursive;
GL_DBG("COLCLIP Info (Blending: %u/%u/%u/%u, OVERLAP: %d)", m_conf.ps.blend_a, m_conf.ps.blend_b, m_conf.ps.blend_c, m_conf.ps.blend_d, m_prim_overlap); GL_DBG("COLCLIP Info (Blending: %u/%u/%u/%u, OVERLAP: %d)", m_conf.ps.blend_a, m_conf.ps.blend_b, m_conf.ps.blend_c, m_conf.ps.blend_d, m_prim_overlap);
if (color_dest_blend || color_dest_blend2) if (color_dest_blend || color_dest_blend2 || blend_zero_to_one_range)
{ {
// No overflow, disable colclip. // No overflow, disable colclip.
GL_INS("COLCLIP mode DISABLED"); GL_INS("COLCLIP mode DISABLED");