From 9ec35d1464941747d11777b41df17aafca21f84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Sep 2022 12:34:27 +0200 Subject: [PATCH 1/2] Logic op fix, min filter fix. Also remove some unnecessary indentation. Fixes the water on Adreno (no logic) --- GPU/Common/GPUStateUtils.cpp | 119 +++++++++++++++--------------- GPU/Common/TextureCacheCommon.cpp | 5 +- 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index fb90850cb9b6..04f8240a619e 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -859,66 +859,63 @@ static inline bool blendColorSimilar(uint32_t a, uint32_t b, int margin = 25) { static bool SimulateLogicOpIfNeeded(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &blendEq) { // Note: our shader solution applies logic ops BEFORE blending, not correctly after. // This is however fine for the most common ones, like CLEAR/NOOP/SET, etc. - if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - if (gstate.isLogicOpEnabled()) { - switch (gstate.getLogicOp()) { - case GE_LOGIC_CLEAR: - srcBlend = BlendFactor::ZERO; - dstBlend = BlendFactor::ZERO; - blendEq = BlendEq::ADD; - return true; - case GE_LOGIC_AND: - case GE_LOGIC_AND_REVERSE: - WARN_LOG_REPORT_ONCE(d3dLogicOpAnd, G3D, "Unsupported AND logic op: %x", gstate.getLogicOp()); - break; - case GE_LOGIC_COPY: - // This is the same as off. - break; - case GE_LOGIC_COPY_INVERTED: - // Handled in the shader. - break; - case GE_LOGIC_AND_INVERTED: - case GE_LOGIC_NOR: - case GE_LOGIC_NAND: - case GE_LOGIC_EQUIV: - // Handled in the shader. - WARN_LOG_REPORT_ONCE(d3dLogicOpAndInverted, G3D, "Attempted invert for logic op: %x", gstate.getLogicOp()); - break; - case GE_LOGIC_INVERTED: - srcBlend = BlendFactor::ONE; - dstBlend = BlendFactor::ONE; - blendEq = BlendEq::SUBTRACT; - WARN_LOG_REPORT_ONCE(d3dLogicOpInverted, G3D, "Attempted inverse for logic op: %x", gstate.getLogicOp()); - return true; - case GE_LOGIC_NOOP: - srcBlend = BlendFactor::ZERO; - dstBlend = BlendFactor::ONE; - blendEq = BlendEq::ADD; - return true; - case GE_LOGIC_XOR: - WARN_LOG_REPORT_ONCE(d3dLogicOpOrXor, G3D, "Unsupported XOR logic op: %x", gstate.getLogicOp()); - break; - case GE_LOGIC_OR: - case GE_LOGIC_OR_INVERTED: - // Inverted in shader. - srcBlend = BlendFactor::ONE; - dstBlend = BlendFactor::ONE; - blendEq = BlendEq::ADD; - WARN_LOG_REPORT_ONCE(d3dLogicOpOr, G3D, "Attempted or for logic op: %x", gstate.getLogicOp()); - return true; - case GE_LOGIC_OR_REVERSE: - WARN_LOG_REPORT_ONCE(d3dLogicOpOrReverse, G3D, "Unsupported OR REVERSE logic op: %x", gstate.getLogicOp()); - break; - case GE_LOGIC_SET: - srcBlend = BlendFactor::ONE; - dstBlend = BlendFactor::ONE; - blendEq = BlendEq::ADD; - WARN_LOG_REPORT_ONCE(d3dLogicOpSet, G3D, "Attempted set for logic op: %x", gstate.getLogicOp()); - return true; - } + if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP) && gstate.isLogicOpEnabled()) { + switch (gstate.getLogicOp()) { + case GE_LOGIC_CLEAR: + srcBlend = BlendFactor::ZERO; + dstBlend = BlendFactor::ZERO; + blendEq = BlendEq::ADD; + return true; + case GE_LOGIC_AND: + case GE_LOGIC_AND_REVERSE: + WARN_LOG_REPORT_ONCE(d3dLogicOpAnd, G3D, "Unsupported AND logic op: %x", gstate.getLogicOp()); + break; + case GE_LOGIC_COPY: + // This is the same as off. + break; + case GE_LOGIC_COPY_INVERTED: + // Handled in the shader. + break; + case GE_LOGIC_AND_INVERTED: + case GE_LOGIC_NOR: + case GE_LOGIC_NAND: + case GE_LOGIC_EQUIV: + // Handled in the shader. + WARN_LOG_REPORT_ONCE(d3dLogicOpAndInverted, G3D, "Attempted invert for logic op: %x", gstate.getLogicOp()); + break; + case GE_LOGIC_INVERTED: + srcBlend = BlendFactor::ONE; + dstBlend = BlendFactor::ONE; + blendEq = BlendEq::SUBTRACT; + WARN_LOG_REPORT_ONCE(d3dLogicOpInverted, G3D, "Attempted inverse for logic op: %x", gstate.getLogicOp()); + return true; + case GE_LOGIC_NOOP: + srcBlend = BlendFactor::ZERO; + dstBlend = BlendFactor::ONE; + blendEq = BlendEq::ADD; + return true; + case GE_LOGIC_XOR: + WARN_LOG_REPORT_ONCE(d3dLogicOpOrXor, G3D, "Unsupported XOR logic op: %x", gstate.getLogicOp()); + break; + case GE_LOGIC_OR: + case GE_LOGIC_OR_INVERTED: + // Inverted in shader. + srcBlend = BlendFactor::ONE; + dstBlend = BlendFactor::ONE; + blendEq = BlendEq::ADD; + WARN_LOG_REPORT_ONCE(d3dLogicOpOr, G3D, "Attempted or for logic op: %x", gstate.getLogicOp()); + return true; + case GE_LOGIC_OR_REVERSE: + WARN_LOG_REPORT_ONCE(d3dLogicOpOrReverse, G3D, "Unsupported OR REVERSE logic op: %x", gstate.getLogicOp()); + break; + case GE_LOGIC_SET: + srcBlend = BlendFactor::ONE; + dstBlend = BlendFactor::ONE; + blendEq = BlendEq::ADD; + WARN_LOG_REPORT_ONCE(d3dLogicOpSet, G3D, "Attempted set for logic op: %x", gstate.getLogicOp()); + return true; } } - return false; } @@ -1080,6 +1077,12 @@ static void ConvertBlendState(GenericBlendState &blendState, bool forceReplaceBl case REPLACE_BLEND_NO: // We may still want to do something about stencil -> alpha. ApplyStencilReplaceAndLogicOpIgnoreBlend(replaceAlphaWithStencil, blendState); + + if (forceReplaceBlend) { + // If this is true, the logic and mask replacements will be applied, at least. In that case, + // we should not apply any logic op simulation. + blendState.simulateLogicOpType = LOGICOPTYPE_NORMAL; + } return; case REPLACE_BLEND_BLUE_TO_ALPHA: diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 66d70f7c02f6..ff31455fae59 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -292,11 +292,14 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac SamplerCacheKey TextureCacheCommon::GetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { SamplerCacheKey key = GetSamplingParams(0, nullptr); - // Kill any mipmapping settings. + // Kill any mipmapping settings, and reset min filtering. + int minFilt = gstate.texfilter & 0x7; + key.minFilt = minFilt & 1; key.mipEnable = false; key.mipFilt = false; key.aniso = 0.0; key.maxLevel = 0.0f; + key.lodBias = 0.0f; // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. int w = gstate.getTextureWidth(0); From ac9677dcc045035bc1d428614342a110b5c0149a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Sep 2022 13:14:44 +0200 Subject: [PATCH 2/2] Ah, need to enable the Mali workaround for Outrun's water, too. --- Common/GPU/Vulkan/thin3d_vulkan.cpp | 10 +++++++--- assets/compat.ini | 5 +++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 8420c0145080..91a6f5ff3e97 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -840,15 +840,19 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) // Workaround for Intel driver bug. TODO: Re-enable after some driver version bugs_.Infest(Bugs::DUAL_SOURCE_BLENDING_BROKEN); } else if (caps_.vendor == GPUVendor::VENDOR_ARM) { + int majorVersion = VK_API_VERSION_MAJOR(deviceProps.driverVersion); + // These GPUs (up to some certain hardware version?) have a bug where draws where gl_Position.w == .z // corrupt the depth buffer. This is easily worked around by simply scaling Z down a tiny bit when this case // is detected. See: https://github.com/hrydgard/ppsspp/issues/11937 bugs_.Infest(Bugs::EQUAL_WZ_CORRUPTS_DEPTH); - // At least one driver at the upper end of the range is known to be likely to suffer from the bug causing issue #13833 (Midnight Club map broken). + + // Similar to the Adreno bug, see #13833 (Midnight Club map broken) and other issues. + // Reported fixed in major version 40 - let's add a check once confirmed. bugs_.Infest(Bugs::MALI_STENCIL_DISCARD_BUG); - // This started in driver 31 or 32. - if (VK_API_VERSION_MAJOR(deviceProps.driverVersion) >= 32) { + // This started in driver 31 or 32, fixed in 40 - let's add a check once confirmed. + if (majorVersion >= 32) { bugs_.Infest(Bugs::MALI_CONSTANT_LOAD_BUG); // See issue #15661 } } diff --git a/assets/compat.ini b/assets/compat.ini index f79978e9fd02..c4986ae888a3 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -632,6 +632,11 @@ ULJM05886 = true ULJM08063 = true NPJH50535 = true +# Outrun 2006: Coast to Coast - water +ULES00262 = true +ULUS10064 = true +ULKS46087 = true + [RequireDefaultCPUClock] # GOW : Ghost of Sparta UCUS98737 = true