mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Implement PABE(Per pixel alpha blending) on accumulation blend and add optimizations.
PABE accumulation blend: Idea is to achieve final output Cs when As < 1, we do this with manipulating Cd using the src1 output. This can't be done with reverse subtraction as we want Cd to be 0 when As < 1. Blend mix is excluded as no games were found, otherwise it can be added. PABE Disable blending: We can disable blending here as an optimization since alpha max is 128 which if alpha is 1 in the formula Cs*Alpha + Cd*(1 - Alpha) will give us a result of Cs.
This commit is contained in:
parent
fe2a9fc2cd
commit
40d5c78573
|
@ -862,11 +862,17 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
|
|||
// PABE
|
||||
if (PS_PABE)
|
||||
{
|
||||
// As_rgba needed for accumulation blend to manipulate Cd.
|
||||
// No blending so early exit
|
||||
if (As < 1.0f)
|
||||
{
|
||||
As_rgba.rgb = (float3)0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
As_rgba.rgb = (float3)1.0f;
|
||||
}
|
||||
|
||||
float4 RT = SW_BLEND_NEEDS_RT ? RtTexture.Load(int3(pos_xy, 0)) : (float4)0.0f;
|
||||
|
||||
if (PS_SHUFFLE && SW_BLEND_NEEDS_RT)
|
||||
|
|
|
@ -783,9 +783,15 @@ float As = As_rgba.a;
|
|||
|
||||
// PABE
|
||||
#if PS_PABE
|
||||
// As_rgba needed for accumulation blend to manipulate Cd.
|
||||
// No blending so early exit
|
||||
if (As < 1.0f)
|
||||
{
|
||||
As_rgba.rgb = vec3(0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
As_rgba.rgb = vec3(1.0f);
|
||||
#endif
|
||||
|
||||
#if SW_BLEND_NEEDS_RT
|
||||
|
|
|
@ -1050,9 +1050,15 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
|||
|
||||
// PABE
|
||||
#if PS_PABE
|
||||
// As_rgba needed for accumulation blend to manipulate Cd
|
||||
// No blending so early exit
|
||||
if (As < 1.0f)
|
||||
{
|
||||
As_rgba.rgb = vec3(0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
As_rgba.rgb = vec3(1.0f);
|
||||
#endif
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
||||
|
|
|
@ -4420,13 +4420,35 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
|||
// Per pixel alpha blending
|
||||
if (m_draw_env->PABE.PABE && GetAlphaMinMax().min < 128)
|
||||
{
|
||||
// Breath of Fire Dragon Quarter, Strawberry Shortcake, Super Robot Wars, Cartoon Network Racing, Simple 2000 Series Vol.81, SOTC, Super Robot Wars.
|
||||
if (sw_blending)
|
||||
// Breath of Fire Dragon Quarter, Strawberry Shortcake, Super Robot Wars, Cartoon Network Racing, Simple 2000 Series Vol.81, SOTC.
|
||||
if (GetAlphaMinMax().max == 128 && m_conf.ps.blend_a == 0 && ((blend.dst == GSDevice::INV_SRC1_COLOR)
|
||||
|| (blend.dst == GSDevice::INV_DST_ALPHA)
|
||||
|| (blend.dst == GSDevice::INV_CONST_COLOR)))
|
||||
{
|
||||
GL_INS("PABE mode ENABLED");
|
||||
if (features.texture_barrier)
|
||||
// PABE disable blending:
|
||||
// We can disable blending here as an optimization since alpha max is 128
|
||||
// which if alpha is 1 in the formula Cs*Alpha + Cd*(1 - Alpha) will give us a result of Cs.
|
||||
m_conf.blend = {};
|
||||
m_conf.ps.no_color1 = true;
|
||||
m_conf.ps.blend_a = m_conf.ps.blend_b = m_conf.ps.blend_c = m_conf.ps.blend_d = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
else if (sw_blending)
|
||||
{
|
||||
// Disable hw/sw blend and do pure sw blend with reading the framebuffer.
|
||||
if (accumulation_blend && (blend.op != GSDevice::OP_REV_SUBTRACT))
|
||||
{
|
||||
// PABE accumulation blend:
|
||||
// Idea is to achieve final output Cs when As < 1, we do this with manipulating Cd using the src1 output.
|
||||
// This can't be done with reverse subtraction as we want Cd to be 0 when As < 1.
|
||||
// TODO: Blend mix is excluded as no games were found, otherwise it can be added.
|
||||
|
||||
m_conf.ps.pabe = 1;
|
||||
}
|
||||
else if (features.texture_barrier)
|
||||
{
|
||||
// PABE sw blend:
|
||||
// Disable hw/sw mix and do pure sw blend with reading the framebuffer.
|
||||
color_dest_blend = false;
|
||||
accumulation_blend = false;
|
||||
blend_mix = false;
|
||||
|
@ -4441,8 +4463,11 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
|||
}
|
||||
else
|
||||
{
|
||||
// PABE sw blend:
|
||||
m_conf.ps.pabe = !(accumulation_blend || blend_mix);
|
||||
}
|
||||
|
||||
GL_INS("PABE mode %s", m_conf.ps.pabe ? "ENABLED" : "DISABLED");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4516,9 +4541,13 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
|||
m_conf.ps.blend_b = 2;
|
||||
}
|
||||
}
|
||||
else if (m_conf.ps.pabe)
|
||||
{
|
||||
m_conf.blend.dst_factor = GSDevice::SRC1_COLOR;
|
||||
}
|
||||
|
||||
// Dual source output not needed (accumulation blend replaces it with ONE).
|
||||
m_conf.ps.no_color1 = true;
|
||||
m_conf.ps.no_color1 = (m_conf.ps.pabe == 0);
|
||||
}
|
||||
else if (blend_mix)
|
||||
{
|
||||
|
|
|
@ -925,11 +925,17 @@ struct PSMain
|
|||
// PABE
|
||||
if (PS_PABE)
|
||||
{
|
||||
// As_rgba needed for accumulation blend to manipulate Cd.
|
||||
// No blending so early exit
|
||||
if (As < 1.f)
|
||||
{
|
||||
As_rgba.rgb = float3(0.f);
|
||||
return;
|
||||
}
|
||||
|
||||
As_rgba.rgb = float3(1.f);
|
||||
}
|
||||
|
||||
float Ad = PS_RTA_CORRECTION ? trunc(current_color.a * 128.1f) / 128.f : trunc(current_color.a * 255.1f) / 128.f;
|
||||
|
||||
if (PS_SHUFFLE && NEEDS_RT)
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||
/// shaders change, to invalidate the cache.
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 55;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 56;
|
||||
|
|
Loading…
Reference in New Issue