diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 9d4cb69614..e81bdfb2af 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -94,6 +94,8 @@ static BugInfo m_known_bugs[] = { BUG_BROKEN_DUAL_SOURCE_BLENDING, -1.0, -1.0, true}, {API_OPENGL, OS_OSX, VENDOR_INTEL, DRIVER_INTEL, Family::UNKNOWN, BUG_BROKEN_DUAL_SOURCE_BLENDING, -1.0, -1.0, true}, + {API_OPENGL, OS_ALL, VENDOR_IMGTEC, DRIVER_IMGTEC, Family::UNKNOWN, + BUG_BROKEN_BITWISE_OP_NEGATION, -1.0, -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_ATI, DRIVER_ATI, Family::UNKNOWN, BUG_PRIMITIVE_RESTART, -1.0, -1.0, true}, }; diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index 44e492b3a2..009ef1fdd5 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -240,6 +240,13 @@ enum Bug // sometimes this happens in the kernel mode part of the driver resulting in a BSOD. // Disable dual-source blending support for now. BUG_BROKEN_DUAL_SOURCE_BLENDING, + // BUG: ImgTec GLSL shader compiler fails when negating the input to a bitwise operation + // Started version: 1.5 + // Ended version: 1.10 + // Shaders that do something like "variable <<= (-othervariable);" cause the shader to + // fail compilation with no useful diagnostic log. This can be worked around by storing + // the negated value to a temporary variable then using that in the bitwise op. + BUG_BROKEN_BITWISE_OP_NEGATION, }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 9eb0d625cb..335c180b30 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -876,9 +876,19 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i n, mtxidx, n, mtxidx + 1, n); // TODO: should use a shader uid branch for this for better performance - out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", - mtxidx, n, mtxidx); - out.Write("\telse indtevtrans%d <<= (-" I_INDTEXMTX "[%d].w);\n", n, mtxidx); + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_BITWISE_OP_NEGATION)) + { + out.Write("\tint indtexmtx_w_inverse_%d = -" I_INDTEXMTX "[%d].w;\n", n, mtxidx); + out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", + mtxidx, n, mtxidx); + out.Write("\telse indtevtrans%d <<= indtexmtx_w_inverse_%d;\n", n, n); + } + else + { + out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", + mtxidx, n, mtxidx); + out.Write("\telse indtevtrans%d <<= (-" I_INDTEXMTX "[%d].w);\n", n, mtxidx); + } } else if (tevind.mid <= 7 && bHasTexCoord) { // s matrix @@ -888,10 +898,19 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i out.Write("\tint2 indtevtrans%d = int2(fixpoint_uv%d * iindtevcrd%d.xx) >> 8;\n", n, texcoord, n); - - out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", - mtxidx, n, mtxidx); - out.Write("\telse indtevtrans%d <<= (-" I_INDTEXMTX "[%d].w);\n", n, mtxidx); + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_BITWISE_OP_NEGATION)) + { + out.Write("\tint indtexmtx_w_inverse_%d = -" I_INDTEXMTX "[%d].w;\n", n, mtxidx); + out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", + mtxidx, n, mtxidx); + out.Write("\telse indtevtrans%d <<= (indtexmtx_w_inverse_%d);\n", n, n); + } + else + { + out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", + mtxidx, n, mtxidx); + out.Write("\telse indtevtrans%d <<= (-" I_INDTEXMTX "[%d].w);\n", n, mtxidx); + } } else if (tevind.mid <= 11 && bHasTexCoord) { // t matrix @@ -902,9 +921,19 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i out.Write("\tint2 indtevtrans%d = int2(fixpoint_uv%d * iindtevcrd%d.yy) >> 8;\n", n, texcoord, n); - out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", - mtxidx, n, mtxidx); - out.Write("\telse indtevtrans%d <<= (-" I_INDTEXMTX "[%d].w);\n", n, mtxidx); + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_BITWISE_OP_NEGATION)) + { + out.Write("\tint indtexmtx_w_inverse_%d = -" I_INDTEXMTX "[%d].w;\n", n, mtxidx); + out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", + mtxidx, n, mtxidx); + out.Write("\telse indtevtrans%d <<= (indtexmtx_w_inverse_%d);\n", n, n); + } + else + { + out.Write("\tif (" I_INDTEXMTX "[%d].w >= 0) indtevtrans%d >>= " I_INDTEXMTX "[%d].w;\n", + mtxidx, n, mtxidx); + out.Write("\telse indtevtrans%d <<= (-" I_INDTEXMTX "[%d].w);\n", n, mtxidx); + } } else {