The ARM Mali GPU driver miscompiles a fragment shader that uses the bitwise not operation on a uvec2 variable. The shader is expected to render a black color, but the Mali GPU renders a white color instead.
uvec2
The source code of the fragment shader is as follows:
#version 300 es
precision highp float;precision highp int;
precision highp float;
precision highp int;
uniform int input1; // input1 = 0
layout(location = 0) out vec4 color;
void main() { uvec2 a = uvec2(input1, 2u) | 1u; // a = (1, 3) uint b = ~a.y; // b = 4294967292 float c = float(b % 2u); // c = 0.0 color = vec4(c, c, c, 1.0); // color = (0.0, 0.0, 0.0, 1.0) a.k.a. black}
void main() {
uvec2 a = uvec2(input1, 2u) | 1u; // a = (1, 3)
uint b = ~a.y; // b = 4294967292
float c = float(b % 2u); // c = 0.0
color = vec4(c, c, c, 1.0); // color = (0.0, 0.0, 0.0, 1.0) a.k.a. black
}
The input uniform is set to 0 during runtime. The variable `a` is set to `(uvec2(0, 2) | 1) = (1, 3)`. The variable `b` is set to `~3 = 4294967292`. The variable `c` is thus `4294967292 % 2 = 0`. The expected color is black `(0.0, 0.0, 0.0, 1.0)`, but the Mali GPU renders the color as white.
I prepared an HTML file that can be simply opened in browser to reproduce this issue. The HTML webpage contains a minimal JS script that executes the fragment shader and outputs the color to the canvas. Also, I prepared a detailed README file describing the environment and steps to reproduce the issue. You can download them all here
Thanks for the bug report - the compiler team have confirmed that we can reproduce the problem.
(MPGCOMP-22174)
Thanks for your prompt reply!
I find that this bug impacts any shader program containing a "uvec bit_op variable" pattern, and it causes incorrect results for multiple shaders that I am currently developing.
uvec bit_op variable"
I would greatly appreciate it if you could fix such issues soon.
Even if we fix the issue in the driver, it will take time for drivers to make their way into devices and even then not all OEMs will take a driver update.
The bug seems to impact vector operations, as a workaround can you try scalarizing these paths - e.g.:
uvec2 a = uvec2(input1, 2u); a.y |= 1u;
Thanks for your checking of this issue! The code snippet that I provided is just a minimal example for demonstration. The problem is that my project have multiple shaders, each containing dozens to hundreds lines of code. Since this issue affects any vector operands, I have to scalarize all of the vector variables into scalars. The refactoring efforts are non-trivial and the code could be less readable.
I understand that it takes time to fix the bug (and thank you for your efforts for debugging and fixing!), I can do the refactoring as a temporary workaround. But as I am developing more shaders, I am looking forward to seeing the fixes in the near future.
Thank you again for your time in investigating this issue.