GS-hw: Improve how we handle blending on 24bit with Ad factor in renderer.

This commit is contained in:
lightningterror 2022-08-26 17:07:21 +02:00
parent e89612e5b9
commit edc82d77a5
5 changed files with 20 additions and 29 deletions

View File

@ -66,6 +66,7 @@
#endif #endif
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D) #define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
struct VS_INPUT struct VS_INPUT
{ {
@ -762,9 +763,9 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy)
return; return;
} }
float4 RT = trunc(RtTexture.Load(int3(pos_xy, 0)) * 255.0f + 0.1f); float4 RT = SW_BLEND_NEEDS_RT ? trunc(RtTexture.Load(int3(pos_xy, 0)) * 255.0f + 0.1f) : (float4)0.0f;
float Ad = (PS_DFMT == FMT_24) ? 1.0f : RT.a / 128.0f; float Ad = RT.a / 128.0f;
float3 Cd = RT.rgb; float3 Cd = RT.rgb;
float3 Cs = Color.rgb; float3 Cs = Color.rgb;

View File

@ -709,13 +709,9 @@ void ps_blend(inout vec4 Color, inout float As)
vec4 RT = trunc(texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0) * 255.0f + 0.1f); vec4 RT = trunc(texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0) * 255.0f + 0.1f);
#endif #endif
#if PS_DFMT == FMT_24
float Ad = 1.0f;
#else
// FIXME FMT_16 case // FIXME FMT_16 case
// FIXME Ad or Ad * 2? // FIXME Ad or Ad * 2?
float Ad = RT.a / 128.0f; float Ad = RT.a / 128.0f;
#endif
// Let the compiler do its jobs ! // Let the compiler do its jobs !
vec3 Cd = RT.rgb; vec3 Cd = RT.rgb;

View File

@ -1008,13 +1008,9 @@ void ps_blend(inout vec4 Color, inout float As)
vec4 RT = vec4(0.0f); vec4 RT = vec4(0.0f);
#endif #endif
#if PS_DFMT == FMT_24
float Ad = 1.0f;
#else
// FIXME FMT_16 case // FIXME FMT_16 case
// FIXME Ad or Ad * 2? // FIXME Ad or Ad * 2?
float Ad = RT.a / 128.0f; float Ad = RT.a / 128.0f;
#endif
// Let the compiler do its jobs ! // Let the compiler do its jobs !
vec3 Cd = RT.rgb; vec3 Cd = RT.rgb;

View File

@ -2481,6 +2481,8 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
// Compute the blending equation to detect special case // Compute the blending equation to detect special case
const GSDevice::FeatureSupport features(g_gs_device->Features()); const GSDevice::FeatureSupport features(g_gs_device->Features());
const GIFRegALPHA& ALPHA = m_context->ALPHA; const GIFRegALPHA& ALPHA = m_context->ALPHA;
// AFIX: Afix factor.
u8 AFIX = ALPHA.FIX;
// Set blending to shader bits // Set blending to shader bits
m_conf.ps.blend_a = ALPHA.A; m_conf.ps.blend_a = ALPHA.A;
@ -2495,15 +2497,21 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
m_conf.ps.fixed_one_a = 1; m_conf.ps.fixed_one_a = 1;
m_conf.ps.blend_c = 0; m_conf.ps.blend_c = 0;
} }
// 24 bits doesn't have an alpha channel so use 128 (1.0f) fix factor as equivalent.
else if (m_conf.ps.dfmt == 1 && m_conf.ps.blend_c == 1)
{
AFIX = 128;
m_conf.ps.blend_c = 2;
}
// Get alpha value // Get alpha value
const bool alpha_c0_zero = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max == 0) && !IsCoverageAlpha(); const bool alpha_c0_zero = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max == 0) && !IsCoverageAlpha();
const bool alpha_c0_one = (m_conf.ps.blend_c == 0 && (GetAlphaMinMax().min == 128) && (GetAlphaMinMax().max == 128)) || IsCoverageAlpha(); const bool alpha_c0_one = (m_conf.ps.blend_c == 0 && (GetAlphaMinMax().min == 128) && (GetAlphaMinMax().max == 128)) || IsCoverageAlpha();
const bool alpha_c0_high_min_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().min > 128) && !IsCoverageAlpha(); const bool alpha_c0_high_min_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().min > 128) && !IsCoverageAlpha();
const bool alpha_c0_high_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max > 128) && !IsCoverageAlpha(); const bool alpha_c0_high_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max > 128) && !IsCoverageAlpha();
const bool alpha_c2_zero = (m_conf.ps.blend_c == 2 && ALPHA.FIX == 0u); const bool alpha_c2_zero = (m_conf.ps.blend_c == 2 && AFIX == 0u);
const bool alpha_c2_one = (m_conf.ps.blend_c == 2 && ALPHA.FIX == 128u); const bool alpha_c2_one = (m_conf.ps.blend_c == 2 && AFIX == 128u);
const bool alpha_c2_high_one = (m_conf.ps.blend_c == 2 && ALPHA.FIX > 128u); const bool alpha_c2_high_one = (m_conf.ps.blend_c == 2 && AFIX > 128u);
const bool alpha_one = alpha_c0_one || alpha_c2_one; const bool alpha_one = alpha_c0_one || alpha_c2_one;
// Optimize blending equations, must be done before index calculation // Optimize blending equations, must be done before index calculation
@ -2832,7 +2840,7 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
{ {
// Require the fix alpha vlaue // Require the fix alpha vlaue
if (m_conf.ps.blend_c == 2) if (m_conf.ps.blend_c == 2)
m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(ALPHA.FIX) / 128.0f; m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(AFIX) / 128.0f;
const HWBlend blend = GSDevice::GetBlend(blend_index, replace_dual_src); const HWBlend blend = GSDevice::GetBlend(blend_index, replace_dual_src);
if (accumulation_blend) if (accumulation_blend)
@ -2874,7 +2882,7 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
else if (blend_mix) else if (blend_mix)
{ {
// For mixed blend, the source blend is done in the shader (so we use CONST_ONE as a factor). // For mixed blend, the source blend is done in the shader (so we use CONST_ONE as a factor).
m_conf.blend = {true, GSDevice::CONST_ONE, blend.dst, blend.op, m_conf.ps.blend_c == 2, ALPHA.FIX}; m_conf.blend = {true, GSDevice::CONST_ONE, blend.dst, blend.op, m_conf.ps.blend_c == 2, AFIX};
m_conf.ps.blend_mix = (blend.op == GSDevice::OP_REV_SUBTRACT) ? 2 : 1; m_conf.ps.blend_mix = (blend.op == GSDevice::OP_REV_SUBTRACT) ? 2 : 1;
// Elide DSB colour output if not used by dest. // Elide DSB colour output if not used by dest.
@ -2970,7 +2978,7 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
else if (m_conf.ps.blend_c == 2) else if (m_conf.ps.blend_c == 2)
{ {
m_conf.ps.blend_c = 2; m_conf.ps.blend_c = 2;
m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(ALPHA.FIX) / 128.0f; m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(AFIX) / 128.0f;
m_conf.ps.clr_hw = 2; m_conf.ps.clr_hw = 2;
} }
else // m_conf.ps.blend_c == 0 else // m_conf.ps.blend_c == 0
@ -2989,18 +2997,8 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
m_conf.ps.clr_hw = 6; m_conf.ps.clr_hw = 6;
m_conf.require_one_barrier |= true; m_conf.require_one_barrier |= true;
} }
if (m_conf.ps.dfmt == 1 && m_conf.ps.blend_c == 1)
{
// 24 bits doesn't have an alpha channel so use 1.0f fix factor as equivalent
const HWBlend blend(GSDevice::GetBlend(blend_index + 3, replace_dual_src)); // +3 <=> +1 on C
m_conf.blend = {true, blend.src, blend.dst, blend.op, true, 128};
}
else
{
const HWBlend blend(GSDevice::GetBlend(blend_index, replace_dual_src)); const HWBlend blend(GSDevice::GetBlend(blend_index, replace_dual_src));
m_conf.blend = {true, blend.src, blend.dst, blend.op, m_conf.ps.blend_c == 2, ALPHA.FIX}; m_conf.blend = {true, blend.src, blend.dst, blend.op, m_conf.ps.blend_c == 2, AFIX};
}
// Remove second color output when unused. Works around bugs in some drivers (e.g. Intel). // Remove second color output when unused. Works around bugs in some drivers (e.g. Intel).
m_conf.ps.no_color1 |= !GSDevice::IsDualSourceBlendFactor(m_conf.blend.src_factor) && m_conf.ps.no_color1 |= !GSDevice::IsDualSourceBlendFactor(m_conf.blend.src_factor) &&

View File

@ -823,7 +823,7 @@ struct PSMain
return; return;
} }
float Ad = PS_DFMT == FMT_24 ? 1.f : trunc(current_color.a * 255.5f) / 128.f; float Ad = trunc(current_color.a * 255.5f) / 128.f;
float3 Cd = trunc(current_color.rgb * 255.5f); float3 Cd = trunc(current_color.rgb * 255.5f);
float3 Cs = Color.rgb; float3 Cs = Color.rgb;