From 5c3bbf74094135b92a3f912eb67cace29676dcc3 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 3 Dec 2014 00:29:50 -0600 Subject: [PATCH] Works around broken Intel Windows video drivers. Just use regular boolean negation in our pixel shader's depth test everywhere except on Qualcomm. This works around a bug in the Intel Windows driver where comparing a boolean value against true or false fails but boolean negation works fine. Quite silly. Should fix issues #7830 and #7899. --- Source/Core/VideoCommon/DriverDetails.cpp | 1 + Source/Core/VideoCommon/DriverDetails.h | 25 ++++++++++++++++++++++ Source/Core/VideoCommon/PixelShaderGen.cpp | 15 ++++++++----- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 4664f17e16..ccde499071 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -48,6 +48,7 @@ namespace DriverDetails {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true}, {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENTEXTURESIZE, -1.0, 65.0, true}, {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENATTRIBUTELESS, -1.0, 94.0, true}, + {OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, -1, BUG_BROKENNEGATEDBOOLEAN,-1.0, -1.0, true}, {OS_ALL, VENDOR_ARM, DRIVER_ARM_MIDGARD, -1, BUG_BROKENBUFFERSTREAM, -1.0, -1.0, true}, {OS_ALL, VENDOR_MESA, DRIVER_NOUVEAU, -1, BUG_BROKENUBO, 900, 916, true}, {OS_ALL, VENDOR_MESA, DRIVER_R600, -1, BUG_BROKENUBO, 900, 913, true}, diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index 02b56e5d08..49371d3a03 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -178,6 +178,31 @@ namespace DriverDetails // This was fixed in a v66 development version, the first shipping driver version with the release was v95. // To be safe, make v95 the minimum version to work around this issue BUG_BROKENATTRIBUTELESS, + // Bug: Qualcomm has broken boolean negation + // Affected devices: Adreno + // Started Version: -1 + // Ended Version: -1 + // Qualcomm has the boolean negation broken in their shader compiler + // Instead of inverting the boolean value it does a binary negation on the full 32bit register + // This causes a compare against zero to fail in their shader since it is no longer a 0 or 1 value + // but 0xFFFFFFFF or 0xFFFFFFFE depending on what the boolean value was before the negation. + // + // This bug has a secondary issue tied to it unlike other bugs. + // The correction of this bug is to check the boolean value against false which results in us + // not doing a negation of the source but instead checking against the boolean value we want. + // The issue with this is that Intel's Window driver is broken when checking if a boolean value is + // equal to true or false, so one has to do a boolean negation of the source + // + // eg. + // Broken on Qualcomm + // Works on Windows Intel + // if (!cond) + // + // Works on Qualcomm + // Broken on Windows Intel + // if (cond == false) + BUG_BROKENNEGATEDBOOLEAN, + }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 71e534df0a..ae27c3f586 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -13,6 +13,7 @@ #include "VideoCommon/BoundingBox.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/ConstantManager.h" +#include "VideoCommon/DriverDetails.h" #include "VideoCommon/LightingShaderGen.h" #include "VideoCommon/NativeVertexFormat.h" #include "VideoCommon/PixelShaderGen.h" @@ -981,10 +982,10 @@ static inline void WriteAlphaTest(T& out, pixel_shader_uid_data* uid_data, API_T out.SetConstantsUsed(C_ALPHA, C_ALPHA); - // This outputted if statement is not like 'if(!(cond))' for a reason. - // Qualcomm's v95 drivers produce incorrect code using logical not - // Checking against false produces the correct code. - out.Write("\tif(( "); + if (DriverDetails::HasBug(DriverDetails::BUG_BROKENNEGATEDBOOLEAN)) + out.Write("\tif(( "); + else + out.Write("\tif(!( "); uid_data->alpha_test_comp0 = bpmem.alpha_test.comp0; uid_data->alpha_test_comp1 = bpmem.alpha_test.comp1; @@ -999,7 +1000,11 @@ static inline void WriteAlphaTest(T& out, pixel_shader_uid_data* uid_data, API_T // Lookup the second component from the alpha function table compindex = bpmem.alpha_test.comp1; out.Write(tevAlphaFuncsTable[compindex], alphaRef[1]); - out.Write(") == false) {\n"); + + if (DriverDetails::HasBug(DriverDetails::BUG_BROKENNEGATEDBOOLEAN)) + out.Write(") == false) {\n"); + else + out.Write(")) {\n"); out.Write("\t\tocol0 = float4(0.0, 0.0, 0.0, 0.0);\n"); if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)