From bad0283ff7fdd389fae76144c57953033167a7b1 Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Sat, 25 Dec 2021 00:27:53 -0500 Subject: [PATCH 1/5] VKPipeline: Add shader blending support --- .../Core/VideoBackends/Vulkan/VKPipeline.cpp | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp b/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp index 716f7be530..77ac29b4c6 100644 --- a/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp @@ -132,53 +132,64 @@ static VkPipelineDepthStencilStateCreateInfo GetVulkanDepthStencilState(const De }; } -static VkPipelineColorBlendAttachmentState GetVulkanAttachmentBlendState(const BlendingState& state) +static VkPipelineColorBlendAttachmentState +GetVulkanAttachmentBlendState(const BlendingState& state) { VkPipelineColorBlendAttachmentState vk_state = {}; - vk_state.blendEnable = static_cast(state.blendenable); - vk_state.colorBlendOp = state.subtract ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD; - vk_state.alphaBlendOp = state.subtractAlpha ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD; bool use_dual_source = state.usedualsrc && g_ActiveConfig.backend_info.bSupportsDualSourceBlend && (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || state.dstalpha); + bool use_shader_blend = !use_dual_source && state.usedualsrc && state.dstalpha && + g_ActiveConfig.backend_info.bSupportsFramebufferFetch; - if (use_dual_source) + if (use_shader_blend) { - static constexpr std::array src_factors = { - {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR, - VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; - static constexpr std::array dst_factors = { - {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR, - VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; - - vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())]; - vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())]; - vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())]; - vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())]; + vk_state.blendEnable = VK_FALSE; } else { - static constexpr std::array src_factors = { - {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR, - VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; + vk_state.blendEnable = static_cast(state.blendenable); + vk_state.colorBlendOp = state.subtract ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD; + vk_state.alphaBlendOp = state.subtractAlpha ? VK_BLEND_OP_REVERSE_SUBTRACT : VK_BLEND_OP_ADD; - static constexpr std::array dst_factors = { - {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR, - VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, - VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; + if (use_dual_source) + { + static constexpr std::array src_factors = { + {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; + static constexpr std::array dst_factors = { + {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC1_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; - vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())]; - vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())]; - vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())]; - vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())]; + vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())]; + vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())]; + vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())]; + vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())]; + } + else + { + static constexpr std::array src_factors = { + {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_DST_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; + + static constexpr std::array dst_factors = { + {VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_SRC_COLOR, + VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, + VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA}}; + + vk_state.srcColorBlendFactor = src_factors[u32(state.srcfactor.Value())]; + vk_state.srcAlphaBlendFactor = src_factors[u32(state.srcfactoralpha.Value())]; + vk_state.dstColorBlendFactor = dst_factors[u32(state.dstfactor.Value())]; + vk_state.dstAlphaBlendFactor = dst_factors[u32(state.dstfactoralpha.Value())]; + } } if (state.colorupdate) From c1d87db6fa12cdc95fa5c7775faa49ea24743729 Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Thu, 6 Jan 2022 04:15:07 -0500 Subject: [PATCH 2/5] PixelShaderGen: Add support for non-dual source shader blending --- Source/Core/VideoCommon/PixelShaderGen.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 837001c118..4d0996e814 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -2018,8 +2018,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data) "float3(1,1,1);", // ONE "initial_ocol0.rgb;", // DSTCLR "float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR - "ocol1.aaa;", // SRCALPHA - "float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA + "src_color.aaa;", // SRCALPHA + "float3(1,1,1) - src_color.aaa;", // INVSRCALPHA "initial_ocol0.aaa;", // DSTALPHA "float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA }; @@ -2028,8 +2028,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data) "1.0;", // ONE "initial_ocol0.a;", // DSTCLR "1.0 - initial_ocol0.a;", // INVDSTCLR - "ocol1.a;", // SRCALPHA - "1.0 - ocol1.a;", // INVSRCALPHA + "src_color.a;", // SRCALPHA + "1.0 - src_color.a;", // INVSRCALPHA "initial_ocol0.a;", // DSTALPHA "1.0 - initial_ocol0.a;", // INVDSTALPHA }; @@ -2038,8 +2038,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data) "float3(1,1,1);", // ONE "ocol0.rgb;", // SRCCLR "float3(1,1,1) - ocol0.rgb;", // INVSRCCLR - "ocol1.aaa;", // SRCALHA - "float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA + "src_color.aaa;", // SRCALHA + "float3(1,1,1) - src_color.aaa;", // INVSRCALPHA "initial_ocol0.aaa;", // DSTALPHA "float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA }; @@ -2048,12 +2048,14 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data) "1.0;", // ONE "ocol0.a;", // SRCCLR "1.0 - ocol0.a;", // INVSRCCLR - "ocol1.a;", // SRCALPHA - "1.0 - ocol1.a;", // INVSRCALPHA + "src_color.a;", // SRCALPHA + "1.0 - src_color.a;", // INVSRCALPHA "initial_ocol0.a;", // DSTALPHA "1.0 - initial_ocol0.a;", // INVDSTALPHA }; - out.Write("\tfloat4 blend_src;\n"); + out.Write("\tfloat4 src_color = {};\n" + "\tfloat4 blend_src;", + uid_data->useDstAlpha ? "ocol1" : "ocol0"); out.Write("\tblend_src.rgb = {}\n", blend_src_factor[uid_data->blend_src_factor]); out.Write("\tblend_src.a = {}\n", blend_src_factor_alpha[uid_data->blend_src_factor_alpha]); out.Write("\tfloat4 blend_dst;\n"); From 80dfefb32ee811794bbf9e46cf01339668dd5e08 Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Thu, 6 Jan 2022 04:15:21 -0500 Subject: [PATCH 3/5] UberShaderPixel: Add support for non-dual source shader blending --- Source/Core/VideoCommon/UberShaderPixel.cpp | 22 +++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp index 7bb4eb4210..e3917e90e6 100644 --- a/Source/Core/VideoCommon/UberShaderPixel.cpp +++ b/Source/Core/VideoCommon/UberShaderPixel.cpp @@ -1194,8 +1194,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, "blend_src.rgb = float3(1,1,1);", // ONE "blend_src.rgb = initial_ocol0.rgb;", // DSTCLR "blend_src.rgb = float3(1,1,1) - initial_ocol0.rgb;", // INVDSTCLR - "blend_src.rgb = ocol1.aaa;", // SRCALPHA - "blend_src.rgb = float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA + "blend_src.rgb = src_color.aaa;", // SRCALPHA + "blend_src.rgb = float3(1,1,1) - src_color.aaa;", // INVSRCALPHA "blend_src.rgb = initial_ocol0.aaa;", // DSTALPHA "blend_src.rgb = float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA }; @@ -1204,8 +1204,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, "blend_src.a = 1.0;", // ONE "blend_src.a = initial_ocol0.a;", // DSTCLR "blend_src.a = 1.0 - initial_ocol0.a;", // INVDSTCLR - "blend_src.a = ocol1.a;", // SRCALPHA - "blend_src.a = 1.0 - ocol1.a;", // INVSRCALPHA + "blend_src.a = src_color.a;", // SRCALPHA + "blend_src.a = 1.0 - src_color.a;", // INVSRCALPHA "blend_src.a = initial_ocol0.a;", // DSTALPHA "blend_src.a = 1.0 - initial_ocol0.a;", // INVDSTALPHA }; @@ -1214,8 +1214,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, "blend_dst.rgb = float3(1,1,1);", // ONE "blend_dst.rgb = ocol0.rgb;", // SRCCLR "blend_dst.rgb = float3(1,1,1) - ocol0.rgb;", // INVSRCCLR - "blend_dst.rgb = ocol1.aaa;", // SRCALHA - "blend_dst.rgb = float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA + "blend_dst.rgb = src_color.aaa;", // SRCALHA + "blend_dst.rgb = float3(1,1,1) - src_color.aaa;", // INVSRCALPHA "blend_dst.rgb = initial_ocol0.aaa;", // DSTALPHA "blend_dst.rgb = float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA }; @@ -1224,13 +1224,19 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, "blend_dst.a = 1.0;", // ONE "blend_dst.a = ocol0.a;", // SRCCLR "blend_dst.a = 1.0 - ocol0.a;", // INVSRCCLR - "blend_dst.a = ocol1.a;", // SRCALPHA - "blend_dst.a = 1.0 - ocol1.a;", // INVSRCALPHA + "blend_dst.a = src_color.a;", // SRCALPHA + "blend_dst.a = 1.0 - src_color.a;", // INVSRCALPHA "blend_dst.a = initial_ocol0.a;", // DSTALPHA "blend_dst.a = 1.0 - initial_ocol0.a;", // INVDSTALPHA }; out.Write(" if (blend_enable) {{\n" + " float4 src_color;\n" + " if (bpmem_dstalpha != 0u) {{\n" + " src_color = ocol1;\n" + " }} else {{\n" + " src_color = ocol0;\n" + " }}" " float4 blend_src;\n"); WriteSwitch(out, api_type, "blend_src_factor", blendSrcFactor, 4, true); WriteSwitch(out, api_type, "blend_src_factor_alpha", blendSrcFactorAlpha, 4, true); From e7f5e5172c60a5e844fd121ee595dd5a77b0301e Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Fri, 30 Jul 2021 04:02:51 -0400 Subject: [PATCH 4/5] DriverDetails: Introduce new VENDOR_APPLE for Apple GPUs --- Source/Core/VideoBackends/Vulkan/VulkanContext.cpp | 5 +++++ Source/Core/VideoCommon/DriverDetails.h | 1 + 2 files changed, 6 insertions(+) diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index 8e0f0ed513..50cae2b6a8 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -922,6 +922,11 @@ void VulkanContext::InitDriverDetails() vendor = DriverDetails::VENDOR_IMGTEC; driver = DriverDetails::DRIVER_IMGTEC; } + else if (device_name.find("Apple") != std::string::npos) + { + vendor = DriverDetails::VENDOR_APPLE; + driver = DriverDetails::DRIVER_PORTABILITY; + } else { WARN_LOG_FMT(VIDEO, "Unknown Vulkan driver vendor, please report it to us."); diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index d03a920abd..f902f31ed3 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -43,6 +43,7 @@ enum Vendor VENDOR_TEGRA, VENDOR_VIVANTE, VENDOR_MESA, + VENDOR_APPLE, VENDOR_UNKNOWN }; From 259a5fc7c02d48f21d2479d8e259519bc4ed443e Mon Sep 17 00:00:00 2001 From: OatmealDome Date: Sat, 25 Dec 2021 00:27:43 -0500 Subject: [PATCH 5/5] DriverDetails: Add broken discard with early-Z bug on Apple Silicon GPUs --- .../Core/VideoBackends/Vulkan/VKPipeline.cpp | 7 +++-- .../VideoBackends/Vulkan/VulkanContext.cpp | 7 +++++ Source/Core/VideoCommon/DriverDetails.cpp | 2 ++ Source/Core/VideoCommon/DriverDetails.h | 10 +++++- Source/Core/VideoCommon/PixelShaderGen.cpp | 31 ++++++++++++++++--- Source/Core/VideoCommon/UberShaderPixel.cpp | 29 ++++++++++++----- 6 files changed, 70 insertions(+), 16 deletions(-) diff --git a/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp b/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp index 77ac29b4c6..61c51b5d34 100644 --- a/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp +++ b/Source/Core/VideoBackends/Vulkan/VKPipeline.cpp @@ -133,7 +133,7 @@ static VkPipelineDepthStencilStateCreateInfo GetVulkanDepthStencilState(const De } static VkPipelineColorBlendAttachmentState -GetVulkanAttachmentBlendState(const BlendingState& state) +GetVulkanAttachmentBlendState(const BlendingState& state, AbstractPipelineUsage usage) { VkPipelineColorBlendAttachmentState vk_state = {}; @@ -143,7 +143,8 @@ GetVulkanAttachmentBlendState(const BlendingState& state) bool use_shader_blend = !use_dual_source && state.usedualsrc && state.dstalpha && g_ActiveConfig.backend_info.bSupportsFramebufferFetch; - if (use_shader_blend) + if (use_shader_blend || (usage == AbstractPipelineUsage::GX && + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z))) { vk_state.blendEnable = VK_FALSE; } @@ -349,7 +350,7 @@ std::unique_ptr VKPipeline::Create(const AbstractPipelineConfig& con VkPipelineDepthStencilStateCreateInfo depth_stencil_state = GetVulkanDepthStencilState(config.depth_state); VkPipelineColorBlendAttachmentState blend_attachment_state = - GetVulkanAttachmentBlendState(config.blending_state); + GetVulkanAttachmentBlendState(config.blending_state, config.usage); VkPipelineColorBlendStateCreateInfo blend_state = GetVulkanColorBlendState(config.blending_state, &blend_attachment_state, 1); diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp index 50cae2b6a8..d074b09c1f 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.cpp @@ -371,6 +371,13 @@ void VulkanContext::PopulateBackendInfoFeatures(VideoConfig* config, VkPhysicalD // with depth clamping. Fall back to inverted depth range for these. if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_REVERSED_DEPTH_RANGE)) config->backend_info.bSupportsReversedDepthRange = false; + + // Calling discard when early depth test is enabled can break on some Apple Silicon GPU drivers. + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) + { + // We will use shader blending, so disable hardware dual source blending. + config->backend_info.bSupportsDualSourceBlend = false; + } } void VulkanContext::PopulateBackendInfoMultisampleModes( diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 829d050549..6d7749c949 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -140,6 +140,8 @@ constexpr BugInfo m_known_bugs[] = { -1.0, -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM, Family::UNKNOWN, BUG_PRIMITIVE_RESTART, -1.0, -1.0, true}, + {API_VULKAN, OS_OSX, VENDOR_APPLE, DRIVER_PORTABILITY, Family::UNKNOWN, + BUG_BROKEN_DISCARD_WITH_EARLY_Z, -1.0, -1.0, true}, }; static std::map m_bugs; diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index f902f31ed3..70c39450c9 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -319,7 +319,15 @@ enum Bug // BUG: Multi-threaded shader pre-compilation sometimes crashes // Used primarily in Videoconfig.cpp's GetNumAutoShaderPreCompilerThreads() // refer to https://github.com/dolphin-emu/dolphin/pull/9414 for initial validation coverage - BUG_BROKEN_MULTITHREADED_SHADER_PRECOMPILATION + BUG_BROKEN_MULTITHREADED_SHADER_PRECOMPILATION, + + // BUG: Some driver and Apple Silicon GPU combinations have problems with fragment discard when + // early depth test is enabled. Discarded fragments may appear corrupted (Super Mario Sunshine, + // Sonic Adventure 2: Battle, Phantasy Star Online Epsiodes 1 & 2, etc). + // Affected devices: Apple Silicon GPUs of Apple family 4 and newer. + // Started version: -1 + // Ended version: -1 + BUG_BROKEN_DISCARD_WITH_EARLY_Z, }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 4d0996e814..3aeb77d747 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -321,7 +321,9 @@ PixelShaderUid GetPixelShaderUid() BlendingState state = {}; state.Generate(bpmem); - if (state.usedualsrc && state.dstalpha && g_ActiveConfig.backend_info.bSupportsFramebufferFetch && + if (((state.usedualsrc && state.dstalpha) || + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) && + g_ActiveConfig.backend_info.bSupportsFramebufferFetch && !g_ActiveConfig.backend_info.bSupportsDualSourceBlend) { uid_data->blend_enable = state.blendenable; @@ -944,10 +946,15 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DUAL_SOURCE_BLENDING) || uid_data->useDstAlpha); const bool use_shader_blend = - !use_dual_source && uid_data->useDstAlpha && host_config.backend_shader_framebuffer_fetch; + !use_dual_source && + (uid_data->useDstAlpha || + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) && + host_config.backend_shader_framebuffer_fetch; const bool use_shader_logic_op = !host_config.backend_logic_op && uid_data->logic_op_enable && host_config.backend_shader_framebuffer_fetch; - const bool use_framebuffer_fetch = use_shader_blend || use_shader_logic_op; + const bool use_framebuffer_fetch = + use_shader_blend || use_shader_logic_op || + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z); if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) { @@ -1869,9 +1876,23 @@ static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_dat // ZCOMPLOC HACK: if (!uid_data->alpha_test_use_zcomploc_hack) { - out.Write("\t\tdiscard;\n"); - if (api_type == APIType::D3D) +#ifdef __APPLE__ + if (uid_data->forced_early_z && + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) + { + // Instead of using discard, fetch the framebuffer's color value and use it as the output + // for this fragment. + out.Write("\t\t{} = float4(initial_ocol0.xyz, 1.0);\n", + use_dual_source ? "real_ocol0" : "ocol0"); out.Write("\t\treturn;\n"); + } + else +#endif + { + out.Write("\t\tdiscard;\n"); + if (api_type == APIType::D3D) + out.Write("\t\treturn;\n"); + } } out.Write("\t}}\n"); diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp index e3917e90e6..161f40146a 100644 --- a/Source/Core/VideoCommon/UberShaderPixel.cpp +++ b/Source/Core/VideoCommon/UberShaderPixel.cpp @@ -57,7 +57,9 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, const bool use_shader_blend = !use_dual_source && host_config.backend_shader_framebuffer_fetch; const bool use_shader_logic_op = !host_config.backend_logic_op && host_config.backend_shader_framebuffer_fetch; - const bool use_framebuffer_fetch = use_shader_blend || use_shader_logic_op; + const bool use_framebuffer_fetch = + use_shader_blend || use_shader_logic_op || + DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z); const bool early_depth = uid_data->early_depth != 0; const bool per_pixel_depth = uid_data->per_pixel_depth != 0; const bool bounding_box = host_config.bounding_box; @@ -1007,8 +1009,21 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, out.Write(" depth = float(zbuffer_zCoord) / 16777216.0;\n"); } - out.Write(" // Alpha Test\n" - " if (bpmem_alphaTest != 0u) {{\n" + out.Write(" // Alpha Test\n"); + + if (early_depth && DriverDetails::HasBug(DriverDetails::BUG_BROKEN_DISCARD_WITH_EARLY_Z)) + { + // Instead of using discard, fetch the framebuffer's color value and use it as the output + // for this fragment. + out.Write(" #define discard_fragment {{ {} = float4(initial_ocol0.xyz, 1.0); return; }}\n", + use_shader_blend ? "real_ocol0" : "ocol0"); + } + else + { + out.Write(" #define discard_fragment discard\n"); + } + + out.Write(" if (bpmem_alphaTest != 0u) {{\n" " bool comp0 = alphaCompare(TevResult.a, " I_ALPHA ".r, {});\n", BitfieldExtract<&AlphaTest::comp0>("bpmem_alphaTest")); out.Write(" bool comp1 = alphaCompare(TevResult.a, " I_ALPHA ".g, {});\n", @@ -1019,13 +1034,13 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config, " switch ({}) {{\n", BitfieldExtract<&AlphaTest::logic>("bpmem_alphaTest")); out.Write(" case 0u: // AND\n" - " if (comp0 && comp1) break; else discard; break;\n" + " if (comp0 && comp1) break; else discard_fragment; break;\n" " case 1u: // OR\n" - " if (comp0 || comp1) break; else discard; break;\n" + " if (comp0 || comp1) break; else discard_fragment; break;\n" " case 2u: // XOR\n" - " if (comp0 != comp1) break; else discard; break;\n" + " if (comp0 != comp1) break; else discard_fragment; break;\n" " case 3u: // XNOR\n" - " if (comp0 == comp1) break; else discard; break;\n" + " if (comp0 == comp1) break; else discard_fragment; break;\n" " }}\n" " }}\n" "\n");