Closed hhromic closed 1 year ago
After taking a look at the GLSL programs for the shaders in libretrodroid, I noticed that textureSize
is defined but actually not used in any of the WORKING (fragment) shaders. In each of the FAILING shaders, textureSize
is used once in this line:
mediump vec2 sharpCoords = (floor(screenCoords) + x) / textureSize;
After researching this problem a bit more, I found this issue mentioning the following:
The GLSL ES Spec (http://www.khronos.org/registry/gles/specs/2.0/GLSL_ES_Specification_1.0.17.pdf) says:
Do precision qualifiers for uniforms need to match? Option 1: Yes. Uniforms are defined to behave as if they are using the same storage in the vertex and fragment processors and may be implemented this way. If uniforms are used in both the vertex and fragment shaders, developers should be warned if the precisions are different. Conversion of precision should never be implicit. Option 2: No. Uniforms may be used by both shaders but the same precision may not be available in both so there is a justification for allowing them to be different. Using the same uniform in the vertex and fragment shaders will always require the precision to be specified in the vertex shader (since the default precision is highp). This is an unnecessary burden on developers. RESOLUTION: Yes, precision qualifiers for uniforms must match.
So, on a device that only supports
mediump
precision in the fragment shader, it is not legal to declare a single uniform ashighp
in the vertex shader (the default) andmediump
in the fragment shader. One way to resolve this is to declare itmediump
everywhere, but this could cause artifacts in some situations. A safer solution is to duplicate the uniform, so the vertex shader gets ahighp
version and the fragment shader gets amediump
version. The Cesium renderer could do this automatically with a little bit of work.We saw this problem in Chrome on a Samsung Galaxy Note 10.1, which has a Mali-400MP GPU. On that device, the shader failed to link as a result of the mismatched precision of the
czm_viewport
uniform (and probably others).
The above seems to suggest that the problem is using the same textureSize
variable name in both, the vertex and fragment programs for the failing shaders, but with different declared precisions.
In libretrodroid, the vertex shader program for the failing shaders is this: https://github.com/Swordfish90/LibretroDroid/blob/d74108e3067764ea02653fc506d9ed9c463f52c7/libretrodroid/src/main/cpp/shadermanager.cpp#L22-L40
As it can be seen, textureSize
does not have an explicit precision, probably defaulting to highp
.
Then, in the failing fragment shader programs, the textureSize
variable is declared like this:
#ifdef GL_FRAGMENT_PRECISION_HIGH
#define HIGHP highp
#else
#define HIGHP mediump
precision mediump float;
#endif
uniform HIGHP vec2 textureSize;
In other words, HIGHP
in Mali-470 MP devices probably gets defined as mediump
causing the mismatch.
According to the referenced issue, the simplest/safest solution would be to rename textureSize
in either the vertex or fragment programs so they do not clash during linking time with different precision.
I would love to test this theory but I lack any experience building libretrodroid/lemuroid :( Hope that at least all the above helps shedding a light to the problem.
The recently added CUTII shader (vertex program) actually seems more correct (uses a #define
set for HIGHP
):
https://github.com/Swordfish90/LibretroDroid/blob/d74108e3067764ea02653fc506d9ed9c463f52c7/libretrodroid/src/main/cpp/shadermanager.cpp#L144-L176
Perhaps the same can be done for defaultShaderVertex
?
Hi @hhromic I honestly can't thank you enough for this report. This is a very thorough analysis and you're definitely spot on with the diagnosis. Precision qualifies are missing on varying and while the majority of drivers are forgiving, some are not.
I'll definitely fix this with the next release of Lemuroid.
Hey @Swordfish90, happy to help where I can! Lemuroid is truly a fantastic frontend for casual retrogaming. I'm glad that all the above made sense to you and that you have a fix in mind for the next version!
Feel free to let me know how can I further help testing and troubleshooting this issue. If you share pre-built APKs with potential fixes, I'm more than happy to sideload them into the affected device for testing. Cheers!
Hi @hhromic . Sorry for the very long delay, but I finally managed to find the time to implement the fix. Are you still up for a test run on your TV? I'm attaching here the apk if you're still interested: https://drive.google.com/file/d/1k1KQWHXsWuF0Ayvmkt01OhKZItxsB7_G/view?usp=share_link
Hi @Swordfish90, no worries about taking your time! Is understandable that you have a life outside of Lemuroid :) I just tested the APK you shared on the following devices I own:
I'm very happy to report that all the shader linking issues are gone now on the Xiaomi MiTV P1 32" device. 🎉 And can also confirm that all my other devices continue to work great as with the regular Lemuroid version.
I tested explicitly every shader independently and all of them are working fine now on the affected device.
Looking forward for this fix to be released officially, and thanks for the great work you have put into this software.
Thank you very much for the investigation and the regression tests. I've merged the changes here #98 . I'll release it on Google Play as soon as Jitpack starts cooperating.
I installed latest Lemuroid
1.14.3
from Google Play on my Xiaomi MiTV P1 32" device running Android TV 9. I tested GB, GC, GBA, NES, SNES and MEGADRIVE games, and everything works nicely except for GB, GBC and GBA games. When starting any GB/GBC/GBA game, Lemuroid simply goes back to the game selection screen without any messages.Using
logcat
, I managed to trace the problem to a shader linking error when starting GB/GBC/GBA games:I further discovered that this error only happens with the
LCD
andSHARP
shaders, and actually the emulated system does not matter. It happens by default with GB/GBC/GBA and not with NES/SNES/MEGADRIVE because theLCD
shader is selected when using the defaultAuto
filter for these systems in Lemuroid. If I forceLCD
orSHARP
shaders in Lemuroid, then any system gives the same linking error and does not start. Likewise, if I force a working shader, e.g.Smooth
, then GB/GBC/GBA games do work as expected.Note: I use Lemuroid on a Samsung Galaxy A70 and an NVIDIA Shield PRO 2019, where this problem has never happened. Therefore, this is likely a GLSL quirk in the Mali-470 MP GPU used by the Xiaomi Mi TV P1 32".