Search code examples
androidopengl-esglslopengl-es-2.0sdl-2

Why does this GLSL shader works on some hardware but not on others?


I'm making a game for Mobile (Android) and PC (Linux) using SDL2 and OpenGL ES 2.0. I wrote some shaders for it, and they work perfectly on PC and Xiaomi Redmi Note 9 Pro, but not on my older Motorola Moto G7 Play phone.

After some testing, I managed to come up with a short vertex shader to reproduce the problem:

#version 100
/* 100 = OpenGL ES 2.0... */
attribute vec3 vertex;
void main()
{
    mat4 M = mat4(1.0);
    if (vertex.x == 0.0)    /* doesn't matter if it's true */
        M = mat4(1.0);  /* just set M to identity again */
#define FIX 0
#if FIX
    M[3].w = 1.0;       /* just set M[3][3] to 1.0 again */
#endif
    M[3].x = 0.5;       /* translate right */
    float w = M[3][3];  /* just read M[3][3] */
    gl_Position = M * vec4(vertex, 1.0);
}

The shader is supposed to translate polygons to the right, and this is what happens on PC and Redmi. However, on Moto G, everything is drawn centered on screen, unless FIX is set to 1.

It happens when M is conditionally touched, and then M[3][3] is read, in the order it happens on the example. To me it looks like a weird driver or compiler bug.

Has anyone experienced this type of problem before? What else should I expect to be buggy? How can I write my shaders to avoid this and similar issues? And specially, why does that happen?

And where do you think I should report it? Google? Motorola?

Thanks <3


Solution

  • I agree, it looks like a driver bug. Clearly there's a lot of scope to optimise around M and I imagine the shader compiler is tripping over itself in doing so.

    First thing I'd do is check if the device has any OS updates available. You might find that the issue is fixed already.

    Unfortunately dealing with driver and device specific issues is not unusual on Android and you often won't be able to get close to understanding their cause. Even worse, the pathway to getting a driver bug fixed is not smooth. You should report your reproducible case to the GPU manufacturer (in this case Qualcomm), however few have a proper bug reporting system, so their developer forums are the only point of contact. If they investigate and fix (unlikely unless you have a contact), then they'll fix their drivers which they make available to hardware manufacturers. Motorola might choose to use the updated drivers next time they release an OS update for the device. If they do, then maybe the cellular carriers decide to offer the update to their users. Then with luck your users might update. The whole process take a very long time, and fixes may not reach all the affected end users. I believe Google are aware of the bottleneck and have plans to address it, but I'm not sure how much progress has been made.

    In the end, the best bet for the developer is to find a workaround. In this case maybe simplifying the code and avoiding conditionals would do it. Maybe running an offline optimization step could help reduce the scope for shader compiler errors.

    Sometimes when I run into device specific issues I find it useful to look at this list of workarounds used by Chromium. I don't see anything relevant to this issue on the list though.