From edc82d77a5b8a2c5c464420535807dadcb0ebda1 Mon Sep 17 00:00:00 2001 From: lightningterror <18107717+lightningterror@users.noreply.github.com> Date: Fri, 26 Aug 2022 17:07:21 +0200 Subject: [PATCH] GS-hw: Improve how we handle blending on 24bit with Ad factor in renderer. --- bin/resources/shaders/dx11/tfx.fx | 5 ++-- bin/resources/shaders/opengl/tfx_fs.glsl | 4 --- bin/resources/shaders/vulkan/tfx.glsl | 4 --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 34 +++++++++++------------- pcsx2/GS/Renderers/Metal/tfx.metal | 2 +- 5 files changed, 20 insertions(+), 29 deletions(-) diff --git a/bin/resources/shaders/dx11/tfx.fx b/bin/resources/shaders/dx11/tfx.fx index e699e2d864..a739e124c6 100644 --- a/bin/resources/shaders/dx11/tfx.fx +++ b/bin/resources/shaders/dx11/tfx.fx @@ -66,6 +66,7 @@ #endif #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 { @@ -762,9 +763,9 @@ void ps_blend(inout float4 Color, inout float As, float2 pos_xy) 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 Cs = Color.rgb; diff --git a/bin/resources/shaders/opengl/tfx_fs.glsl b/bin/resources/shaders/opengl/tfx_fs.glsl index a552b0fa85..0bf7b41951 100644 --- a/bin/resources/shaders/opengl/tfx_fs.glsl +++ b/bin/resources/shaders/opengl/tfx_fs.glsl @@ -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); #endif -#if PS_DFMT == FMT_24 - float Ad = 1.0f; -#else // FIXME FMT_16 case // FIXME Ad or Ad * 2? float Ad = RT.a / 128.0f; -#endif // Let the compiler do its jobs ! vec3 Cd = RT.rgb; diff --git a/bin/resources/shaders/vulkan/tfx.glsl b/bin/resources/shaders/vulkan/tfx.glsl index 72fe16bc63..d746d78a50 100644 --- a/bin/resources/shaders/vulkan/tfx.glsl +++ b/bin/resources/shaders/vulkan/tfx.glsl @@ -1008,13 +1008,9 @@ void ps_blend(inout vec4 Color, inout float As) vec4 RT = vec4(0.0f); #endif - #if PS_DFMT == FMT_24 - float Ad = 1.0f; - #else // FIXME FMT_16 case // FIXME Ad or Ad * 2? float Ad = RT.a / 128.0f; - #endif // Let the compiler do its jobs ! vec3 Cd = RT.rgb; diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index fbe1e9c13e..49807e2673 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -2481,6 +2481,8 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& // Compute the blending equation to detect special case const GSDevice::FeatureSupport features(g_gs_device->Features()); const GIFRegALPHA& ALPHA = m_context->ALPHA; + // AFIX: Afix factor. + u8 AFIX = ALPHA.FIX; // Set blending to shader bits 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.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 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_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_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_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_high_one = (m_conf.ps.blend_c == 2 && AFIX > 128u); const bool alpha_one = alpha_c0_one || alpha_c2_one; // 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 if (m_conf.ps.blend_c == 2) - m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast(ALPHA.FIX) / 128.0f; + m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast(AFIX) / 128.0f; const HWBlend blend = GSDevice::GetBlend(blend_index, replace_dual_src); if (accumulation_blend) @@ -2874,7 +2882,7 @@ void GSRendererHW::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool& else if (blend_mix) { // 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; // 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) { m_conf.ps.blend_c = 2; - m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast(ALPHA.FIX) / 128.0f; + m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast(AFIX) / 128.0f; m_conf.ps.clr_hw = 2; } 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.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)); - m_conf.blend = {true, blend.src, blend.dst, blend.op, m_conf.ps.blend_c == 2, ALPHA.FIX}; - } + 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, AFIX}; // 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) && diff --git a/pcsx2/GS/Renderers/Metal/tfx.metal b/pcsx2/GS/Renderers/Metal/tfx.metal index b6c12eb1ce..36370b131f 100644 --- a/pcsx2/GS/Renderers/Metal/tfx.metal +++ b/pcsx2/GS/Renderers/Metal/tfx.metal @@ -823,7 +823,7 @@ struct PSMain 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 Cs = Color.rgb;