From 600ad5f49832a69efe0ebd5ca7a19d3a82f7a319 Mon Sep 17 00:00:00 2001 From: TellowKrinkle Date: Wed, 13 Jul 2022 03:56:33 -0500 Subject: VideoCommon: Better logic op invert approximation --- Source/Core/VideoCommon/ShaderCache.cpp | 38 ++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'Source/Core/VideoCommon/ShaderCache.cpp') diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp index 59ae917686..9b6b1afa9b 100644 --- a/Source/Core/VideoCommon/ShaderCache.cpp +++ b/Source/Core/VideoCommon/ShaderCache.cpp @@ -601,16 +601,6 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig( config.depth_state = depth_state; config.blending_state = blending_state; config.framebuffer_state = g_framebuffer_manager->GetEFBFramebufferState(); - - // We can use framebuffer fetch to emulate logic ops in the fragment shader. - if (config.blending_state.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp && - !g_ActiveConfig.backend_info.bSupportsFramebufferFetch) - { - WARN_LOG_FMT(VIDEO, - "Approximating logic op with blending, this will produce incorrect rendering."); - config.blending_state.ApproximateLogicOpWithBlending(); - } - return config; } @@ -628,6 +618,22 @@ static GXPipelineUid ApplyDriverBugs(const GXPipelineUid& in) ps->ztest = EmulatedZ::Early; } + // If framebuffer fetch is available, we can emulate logic ops in the fragment shader + // and don't need the below blend approximation + if (blend.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp && + !g_ActiveConfig.backend_info.bSupportsFramebufferFetch) + { + if (!blend.LogicOpApproximationIsExact()) + WARN_LOG_FMT(VIDEO, + "Approximating logic op with blending, this will produce incorrect rendering."); + if (blend.LogicOpApproximationWantsShaderHelp()) + { + ps->emulate_logic_op_with_blend = true; + ps->logic_op_mode = static_cast(blend.logicmode.Value()); + } + blend.ApproximateLogicOpWithBlending(); + } + const bool benefits_from_ps_dual_source_off = (!g_ActiveConfig.backend_info.bSupportsDualSourceBlend && g_ActiveConfig.backend_info.bSupportsFramebufferFetch) || @@ -775,6 +781,18 @@ static GXUberPipelineUid ApplyDriverBugs(const GXUberPipelineUid& in) memcpy(&out, &in, sizeof(out)); // Copy padding if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader) out.vertex_format = nullptr; + + // If framebuffer fetch is available, we can emulate logic ops in the fragment shader + // and don't need the below blend approximation + if (out.blending_state.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp && + !g_ActiveConfig.backend_info.bSupportsFramebufferFetch) + { + if (!out.blending_state.LogicOpApproximationIsExact()) + WARN_LOG_FMT(VIDEO, + "Approximating logic op with blending, this will produce incorrect rendering."); + out.blending_state.ApproximateLogicOpWithBlending(); + } + if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch) { // Always blend in shader -- cgit v1.2.3