mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Adjust dither on Blend Mix when Cs-Cd * Af blend.
This commit is contained in:
parent
65649b3cbb
commit
c0e47767b7
|
@ -784,7 +784,7 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
|
|||
}
|
||||
}
|
||||
|
||||
void ps_dither(inout float3 C, float2 pos_xy, float alpha_blend)
|
||||
void ps_dither(inout float3 C, float As, float2 pos_xy)
|
||||
{
|
||||
if (PS_DITHER)
|
||||
{
|
||||
|
@ -800,7 +800,10 @@ void ps_dither(inout float3 C, float2 pos_xy, float alpha_blend)
|
|||
// The idea here is we add on the dither amount adjusted by the alpha before it goes to the hw blend
|
||||
// so after the alpha blend the resulting value should be the same as (Cs - Cd) * As + Cd + Dither.
|
||||
if (PS_DITHER_ADJUST)
|
||||
value *= alpha_blend > 0.0f ? min(1.0f / alpha_blend, 1.0f) : 1.0f;
|
||||
{
|
||||
float Alpha = PS_BLEND_C == 2 ? Af : As;
|
||||
value *= Alpha > 0.0f ? min(1.0f / Alpha, 1.0f) : 1.0f;
|
||||
}
|
||||
|
||||
if (PS_ROUND_INV)
|
||||
C -= value;
|
||||
|
@ -1068,7 +1071,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
|||
}
|
||||
}
|
||||
|
||||
ps_dither(C.rgb, input.p.xy, alpha_blend.a);
|
||||
ps_dither(C.rgb, alpha_blend.a, input.p.xy);
|
||||
|
||||
// Color clamp/wrap needs to be done after sw blending and dithering
|
||||
ps_color_clamp_wrap(C.rgb);
|
||||
|
|
|
@ -720,7 +720,7 @@ void ps_fbmask(inout vec4 C)
|
|||
#endif
|
||||
}
|
||||
|
||||
void ps_dither(inout vec3 C, float alpha_blend)
|
||||
void ps_dither(inout vec3 C, float As)
|
||||
{
|
||||
#if PS_DITHER
|
||||
#if PS_DITHER == 2
|
||||
|
@ -733,7 +733,13 @@ void ps_dither(inout vec3 C, float alpha_blend)
|
|||
// The idea here is we add on the dither amount adjusted by the alpha before it goes to the hw blend
|
||||
// so after the alpha blend the resulting value should be the same as (Cs - Cd) * As + Cd + Dither.
|
||||
#if PS_DITHER_ADJUST
|
||||
value *= alpha_blend > 0.0f ? min(1.0f / alpha_blend, 1.0f) : 1.0f;
|
||||
#if PS_BLEND_C == 2
|
||||
float Alpha = Af;
|
||||
#else
|
||||
float Alpha = As;
|
||||
#endif
|
||||
|
||||
value *= Alpha > 0.0f ? min(1.0f / Alpha, 1.0f) : 1.0f;
|
||||
#endif
|
||||
|
||||
#if PS_ROUND_INV
|
||||
|
|
|
@ -970,7 +970,7 @@ void ps_fbmask(inout vec4 C)
|
|||
#endif
|
||||
}
|
||||
|
||||
void ps_dither(inout vec3 C, float alpha_blend)
|
||||
void ps_dither(inout vec3 C, float As)
|
||||
{
|
||||
#if PS_DITHER
|
||||
ivec2 fpos;
|
||||
|
@ -986,7 +986,13 @@ void ps_dither(inout vec3 C, float alpha_blend)
|
|||
// The idea here is we add on the dither amount adjusted by the alpha before it goes to the hw blend
|
||||
// so after the alpha blend the resulting value should be the same as (Cs - Cd) * As + Cd + Dither.
|
||||
#if PS_DITHER_ADJUST
|
||||
value *= alpha_blend > 0.0f ? min(1.0f / alpha_blend, 1.0f) : 1.0f;
|
||||
#if PS_BLEND_C == 2
|
||||
float Alpha = Af;
|
||||
#else
|
||||
float Alpha = As;
|
||||
#endif
|
||||
|
||||
value *= Alpha > 0.0f ? min(1.0f / Alpha, 1.0f) : 1.0f;
|
||||
#endif
|
||||
|
||||
#if PS_ROUND_INV
|
||||
|
|
|
@ -3769,10 +3769,13 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
|
|||
const bool alpha_c0_one = (m_conf.ps.blend_c == 0 && (GetAlphaMinMax().min == 128) && (GetAlphaMinMax().max == 128));
|
||||
const bool alpha_c0_high_min_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().min > 128);
|
||||
const bool alpha_c0_high_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max > 128);
|
||||
const bool alpha_c0_less_max_one = (m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128);
|
||||
const bool alpha_c2_zero = (m_conf.ps.blend_c == 2 && AFIX == 0u);
|
||||
const bool alpha_c2_one = (m_conf.ps.blend_c == 2 && AFIX == 128u);
|
||||
const bool alpha_c2_less_one = (m_conf.ps.blend_c == 2 && AFIX <= 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_less_one = alpha_c0_less_max_one || alpha_c2_less_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_one))
|
||||
|
@ -3930,8 +3933,6 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
|
|||
// Do not run BLEND MIX if sw blending is already present, it's less accurate.
|
||||
blend_mix &= !sw_blending;
|
||||
sw_blending |= blend_mix;
|
||||
// Disable dithering on blend mix.
|
||||
m_conf.ps.dither &= !blend_mix || (m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128);
|
||||
[[fallthrough]];
|
||||
case AccBlendLevel::Minimum:
|
||||
break;
|
||||
|
@ -3984,8 +3985,6 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
|
|||
// Do not run BLEND MIX if sw blending is already present, it's less accurate.
|
||||
blend_mix &= !sw_blending;
|
||||
sw_blending |= blend_mix;
|
||||
// Disable dithering on blend mix.
|
||||
m_conf.ps.dither &= !blend_mix || (m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128);
|
||||
[[fallthrough]];
|
||||
case AccBlendLevel::Minimum:
|
||||
break;
|
||||
|
@ -4191,6 +4190,14 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
|
|||
}
|
||||
else if (blend_mix)
|
||||
{
|
||||
// Disable dithering on blend mix if needed.
|
||||
if (m_conf.ps.dither)
|
||||
{
|
||||
const bool can_dither = (m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && alpha_less_one);
|
||||
m_conf.ps.dither = can_dither;
|
||||
m_conf.ps.dither_adjust = can_dither;
|
||||
}
|
||||
|
||||
// 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, AFIX};
|
||||
m_conf.ps.blend_mix = (blend.op == GSDevice::OP_REV_SUBTRACT) ? 2 : 1;
|
||||
|
@ -5381,7 +5388,6 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
|||
m_conf.cb_ps.DitherMatrix[1] = GSVector4(DIMX.DM10, DIMX.DM11, DIMX.DM12, DIMX.DM13);
|
||||
m_conf.cb_ps.DitherMatrix[2] = GSVector4(DIMX.DM20, DIMX.DM21, DIMX.DM22, DIMX.DM23);
|
||||
m_conf.cb_ps.DitherMatrix[3] = GSVector4(DIMX.DM30, DIMX.DM31, DIMX.DM32, DIMX.DM33);
|
||||
m_conf.ps.dither_adjust = m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_c == 0 && GetAlphaMinMax().max <= 128;
|
||||
}
|
||||
|
||||
if (PRIM->FGE)
|
||||
|
|
|
@ -843,7 +843,7 @@ struct PSMain
|
|||
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(current_color * 255.5) & cb.fbmask));
|
||||
}
|
||||
|
||||
void ps_dither(thread float4& C, float alpha_blend)
|
||||
void ps_dither(thread float4& C, float As)
|
||||
{
|
||||
if (PS_DITHER == 0)
|
||||
return;
|
||||
|
@ -857,7 +857,10 @@ struct PSMain
|
|||
// The idea here is we add on the dither amount adjusted by the alpha before it goes to the hw blend
|
||||
// so after the alpha blend the resulting value should be the same as (Cs - Cd) * As + Cd + Dither.
|
||||
if (PS_DITHER_ADJUST)
|
||||
value *= alpha_blend > 0.f ? min(1.f / alpha_blend, 1.f) : 1.f;
|
||||
{
|
||||
float Alpha = PS_BLEND_C == 2 ? cb.alpha_fix : As;
|
||||
value *= Alpha > 0.f ? min(1.f / Alpha, 1.f) : 1.f;
|
||||
}
|
||||
|
||||
if (PS_ROUND_INV)
|
||||
C.rgb -= value;
|
||||
|
|
Loading…
Reference in New Issue