diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 64ca6dff7f42..6e97b010e743 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -122,6 +122,10 @@ constexpr BugInfo m_known_bugs[] = { -1.0, -1.0, true}, {API_VULKAN, OS_ALL, VENDOR_QUALCOMM, DRIVER_QUALCOMM, Family::UNKNOWN, BUG_SLOW_CACHED_READBACK_MEMORY, -1.0, -1.0, true}, + {API_OPENGL, OS_ALL, VENDOR_ARM, DRIVER_ARM, Family::UNKNOWN, BUG_BROKEN_VECTOR_BITWISE_AND, + -1.0, -1.0, true}, + {API_VULKAN, OS_ALL, VENDOR_ARM, DRIVER_ARM, Family::UNKNOWN, BUG_BROKEN_VECTOR_BITWISE_AND, + -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 8ea6d40c9cd7..4eceba3d2fac 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -288,6 +288,16 @@ enum Bug // Mali Vulkan driver, causing high CPU usage in the __pi___inval_cache_range kernel // function. This flag causes readback buffers to select the coherent type. BUG_SLOW_CACHED_READBACK_MEMORY, + + // BUG: Apparently ARM Mali GLSL compiler managed to break bitwise AND operations between + // two integers vectors, when one of them is non-constant (though the exact cases of when + // this occurs are still unclear to me). The resulting vector from the operation will be + // the constant vector. + // Easy enough to fix, just do the bitwise AND operation on the vector components first and + // then construct the final vector. + // Started version: -1 + // Ended version: -1 + BUG_BROKEN_VECTOR_BITWISE_AND, }; // Initializes our internal vendor, device family, and driver version diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index b4e99cd3c61d..6db880784ac6 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -1252,12 +1252,23 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i if (ac.dest >= TevOutput::Color0) out.SetConstantsUsed(C_COLORS + u32(ac.dest.Value()), C_COLORS + u32(ac.dest.Value())); - out.Write("\ttevin_a = int4({}, {})&int4(255, 255, 255, 255);\n", - tev_c_input_table[u32(cc.a.Value())], tev_a_input_table[u32(ac.a.Value())]); - out.Write("\ttevin_b = int4({}, {})&int4(255, 255, 255, 255);\n", - tev_c_input_table[u32(cc.b.Value())], tev_a_input_table[u32(ac.b.Value())]); - out.Write("\ttevin_c = int4({}, {})&int4(255, 255, 255, 255);\n", - tev_c_input_table[u32(cc.c.Value())], tev_a_input_table[u32(ac.c.Value())]); + if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VECTOR_BITWISE_AND)) { + out.Write("\ttevin_a = int4({} & 255, {} & 255);\n", + tev_c_input_table[u32(cc.a.Value())], tev_a_input_table[u32(ac.a.Value())]); + out.Write("\ttevin_b = int4({} & 255, {} & 255);\n", + tev_c_input_table[u32(cc.b.Value())], tev_a_input_table[u32(ac.b.Value())]); + out.Write("\ttevin_c = int4({} & 255, {} & 255);\n", + tev_c_input_table[u32(cc.c.Value())], tev_a_input_table[u32(ac.c.Value())]); + } + else + { + out.Write("\ttevin_a = int4({}, {})&int4(255, 255, 255, 255);\n", + tev_c_input_table[u32(cc.a.Value())], tev_a_input_table[u32(ac.a.Value())]); + out.Write("\ttevin_b = int4({}, {})&int4(255, 255, 255, 255);\n", + tev_c_input_table[u32(cc.b.Value())], tev_a_input_table[u32(ac.b.Value())]); + out.Write("\ttevin_c = int4({}, {})&int4(255, 255, 255, 255);\n", + tev_c_input_table[u32(cc.c.Value())], tev_a_input_table[u32(ac.c.Value())]); + } out.Write("\ttevin_d = int4({}, {});\n", tev_c_input_table[u32(cc.d.Value())], tev_a_input_table[u32(ac.d.Value())]);