Shader issue with SGX540 (Samsung Galaxy Nexus)

Hello!



I am having issues with very simple shaders on this device (Samsung Galaxy Nexus running Android 4.3).

One of those shaders is a mask shader which simply gets passed a vec2 and discards the fragment if (x, y) is not between [0, 1].

Here is the vertex shader:



attribute vec4 position;

attribute vec4 inputColor;



varying lowp vec4 colorVarying;



uniform mat4 modelViewProjectionMatrix;



attribute vec2 TexCoord0In;

attribute vec2 TexCoord1In;

varying vec2 TexCoord0Out;

varying vec2 TexCoord1Out;



void main()

{

float tmp = 0.003922;

gl_Position = modelViewProjectionMatrix * position;

TexCoord0Out.x = TexCoord0In.x;

TexCoord0Out.y = 1.0 - TexCoord0In.y;

TexCoord1Out.x = TexCoord1In.x;

TexCoord1Out.y = 1.0 - TexCoord1In.y;



colorVarying = vec4(inputColor.z * tmp, inputColor.y * tmp, inputColor.x * tmp, inputColor.w * tmp);

}



Here is the fragment shader:



varying lowp vec4 colorVarying;

varying lowp vec2 TexCoord0Out;

varying lowp vec2 TexCoord1Out;

uniform sampler2D Texture;



void main()

{

if (TexCoord1Out.x > 1.0 || TexCoord1Out.y > 1.0 || TexCoord1Out.x < 0.0 || TexCoord1Out.y < 0.0)

{

discard;

}



gl_FragColor = colorVarying * texture2D(Texture, TexCoord0Out);

}



On the Galaxy Nexus the masking simply doesn’t work.

Capturing a trace yields this image in the analyser: https://drive.google.com/a/anotherplaceproductions.com/file/d/0B0ugzyFprd1XWFlHNlV4R2NUUkU



Yet the frame buffer captured is like the below: https://drive.google.com/a/anotherplaceproductions.com/file/d/0B0ugzyFprd1XMGZya0p0dUNaZHM



I’ve tried using the trace tool with older compilers, without any luck.

/proc/pvr/version is as follows:



Version CustomerGoogle_Android_ogles1_ogles2_GPL sgxddk 18 1.8.GOOGLENEXUS.ED945322@2198402 (release) omap4430_android

System Version String: SGX revision = 1.2.0



Here is the link to the PVR trace: https://drive.google.com/a/anotherplaceproductions.com/file/d/0B0ugzyFprd1XUUpTOVpCXzB6eFk



This is only one of the issues I have been having with that device: another one is normalising the color from a [0, 256] range to a [0, 1] range only works if I multiply by 0.003922. If I divide by 255.0 it produces incorrect results.

I also have triangle corruptions (geometry being completely wrong) when using a more complicated version of the shader above (one that includes passing down a color intensity alongside multitexturing to use an actual texture mask).



I also tried the above shader without the discard and / or the branching, but to no success. It seems that whatever comes in TexCoord1Out is always between [0, 1].



Similar problems have only been reported on one other device, a Samsung Tab 2 P5100 (4.0.4).



Please let me know if you need more information, I really hope someone can help me!



Thanks,



Guillaume.

Hi Guillaume,



I’ve tried to access the file’s you’ve linked to, but it’s told me I need to bee whitelisted before I can access them.


One of those shaders is a mask shader which simply gets passed a vec2 and discards the fragment if (x, y) is not between [0, 1].

For best performance (and to potentially work around the issue), I would recommend using alpha blending instead of discard. Discard incurs a slow path as fragment depth & stencil values can't be written until fragment visibility is known, which negates many of the benefits of early-z testing.
To do this you can enable blending when rendering the objects that the mask needs to be applied to, then set the alpha value to 0.0 or 1.0 depending on whether or not the fragment should be visible. This blend mode should be suitable:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

This is only one of the issues I have been having with that device: another one is normalising the color from a [0, 256] range to a [0, 1]

I'm not sure why dividing by 255.0 isn't working for you. An alternative solution would be to pass in normalized colour values instead of doing the conversion in your vertex shader.

I also have triangle corruptions (geometry being completely wrong) when using a more complicated version of the shader above (one that includes passing down a color intensity alongside multitexturing to use an actual texture mask).

If you can share an PVRTrace recording of this issue, we can look into it.

Thanks,
Joe

Hi Joe,



Thanks for answering!

I have tried simply changing the alpha, to no avail.



I have added your email to the permissions to the 3 files - have you still not been able to access them?



Thanks,



G.

Hi Guillaume,



Looking at your shader code and render, it seems that glScissor() would provide a more efficient and cleaner solution to clipping the elements in your application’s GUI. have you considered applying scissor regions to your render?


I also have triangle corruptions (geometry being completely wrong) when using a more complicated version of the shader above (one that includes passing down a color intensity alongside multitexturing to use an actual texture mask).

I'm not sure what you mean here. Are you seeing the corrupt on device, or when replaying the frame in PVRTraceGUI? Can you share screenshots and a PVRTrace recording of this issue so we can investigate?

Thanks,
Joe

Hi Joe,



Sorry I took so long to answer!

Thanks a lot for the feedback - glScissor was a great call as we actually didn’t use the texture mask, so we were able to get that working on that device.

I haven’t been able to capture a trace of the corruption (we’ve been rushing to submit this build on the play store), but I’ve shared a screenshot of it with you.

Hopefully I’ll get you a trace at some point too. I assume that similarly to the masking issue, the trace tool will not exhibit the problem.



Here is the shader code responsible for what’s on the screenshot:



VSH:



attribute vec4 position;

attribute vec4 inputColor;



varying lowp vec4 colorVarying;



uniform mat4 modelViewProjectionMatrix;



attribute vec2 TexCoord0In;

attribute vec2 TexCoord1In;

varying vec2 TexCoord0Out;

varying vec2 TexCoord1Out;





attribute lowp float Intensity;

varying lowp float IntensityOut;



void main()

{

gl_Position = modelViewProjectionMatrix * position;

TexCoord0Out.x = TexCoord0In.x;

TexCoord0Out.y = 1.0 - TexCoord0In.y;

TexCoord1Out.x = TexCoord1In.x;

TexCoord1Out.y = 1.0 - TexCoord1In.y;

IntensityOut = Intensity;

colorVarying = vec4(inputColor.z / 255.0, inputColor.y / 255.0, inputColor.x / 255.0, inputColor.w / 255.0);

}



FSH:



varying lowp vec4 colorVarying;

varying lowp vec2 TexCoord0Out;

varying lowp vec2 TexCoord1Out;

uniform sampler2D Texture;

uniform sampler2D Texture2;

varying lowp float IntensityOut;



void main()

{

if (TexCoord1Out.x > 1.0 || TexCoord1Out.y > 1.0 || TexCoord1Out.x < 0.0 || TexCoord1Out.y < 0.0)

{

discard;

}



mediump vec4 blah_1;

mediump vec4 tmpvar_2;

tmpvar_2 = (colorVarying * texture2D (Texture, TexCoord0Out));

blah_1.w = tmpvar_2.w;

blah_1.xyz = mix (vec3(dot (tmpvar_2.xyz, vec3(0.3, 0.59, 0.11))), tmpvar_2.xyz, IntensityOut);



gl_FragColor = vec4(colorVarying.rgb * blah_1.rgb, colorVarying.w * texture2D(Texture, TexCoord0Out).w * texture2D(Texture2, TexCoord1Out).w);

}



The problem disappears when we get rid of the intensity variables. The problem seems to be about passing that IntensityOut from the vertex shader to the fragment shader, as even setting gl_FragColor to a flat color still exhibits the problem.



Thanks,



G.

Hi Guillaume,



I’m not sure where to view your latest screenshot. Can you share a link to it?



If you increase the precision of the “IntensityOut” varying, does it affect the result?



Joe

Sorry I thought you would have received the google drive invite. Here is the link:

https://drive.google.com/a/anotherplaceproductions.com/file/d/0B0ugzyFprd1XTm1XQTJMUjZaR1E

Ah - my mistake. I did receive the invite. Thanks for the link anyway.



Sorry for going quiet on this chain. I haven’t had a chance to look into it again. I’ll see if one of the other support guys can follow up.



Joe

No worries Joe! I’ve gone quiet too as your suggestion allowed us to work around the issue (glScissor + simplifying the shader to not pass down that intensity float from vertex to fragment). That’s why I didn’t capture the trace as I moved onto something else (we actually managed to release the game on the store).



There is definitely something wrong with this device though, as the same code has always worked on all iOS platforms as well as all but one other android devices we tested it on (that’s 30+ devices).



Thanks again for your help and the great turnaround!



G.

Could this be a precision issue ?



varying lowp vec2 TexCoord1Out;



Try increasing this to mediump or highp.



K-