Unexpected vertex shader behaviour - Android, Galaxy Nexus

I’ve been working on a series of shaders for a game, but have hit a wall and would like some ideas on what could be happening.



I have an effect that sweeps clouds across the screen - 400 tris, all the screen covered by blended sprites. Everything was fine until I came to test against a Galaxy Nexus. Running Android 4.0.1, the Galaxy had frame rates of around 10, where the HTC Desire running Android 4.3 was hitting 80 and the Nexus 7 on Android 4.4 was climbing through 180 fps. On a second Galaxy Nexus with Android 4.3 however, nothing displayed - no errors, just no geometry. Did wonders for the frame-rate, though.



I tried rendering without textures initially, to no avail, and eventually turned to trimming the shader down until I isolated it as appearing to be an issue with initialising too many attributes. Please see below:



Vertex shader in question:

attribute float a_Born;

attribute vec2 a_Origin;

attribute vec2 a_StartPosition;

attribute vec2 a_EndPosition;

attribute vec2 a_BezStartPosition;

attribute vec2 a_BezEndPosition;

attribute vec2 a_TextureCoord;

attribute float a_Lifespan;

attribute float a_Alpha;

attribute float a_AngleDelta;



uniform mat4 u_MVPMatrix;

uniform float u_CurrentTime;



varying float v_Alpha;

varying vec2 v_TexCoord;



void main() {

float elapsedTime = (u_CurrentTime - a_Born) / 1000000.0;



// animated rotation

float angleChange = a_AngleDelta * elapsedTime;

float s = sin(angleChange);

float c = cos(angleChange);



// avoiding matrix maths

vec4 rotated = vec4(0.0, 0.0, 0.0, 1.0);

rotated[0] = dot(vec2(c, -s), a_Origin);

rotated[1] = dot(vec2(s, c), a_Origin);



float progress = clamp(elapsedTime / (a_Lifespan / 1000000.0), 0.0, 1.0);

float progressLeft = 1.0 - progress;



float f1 = progressLeft * progressLeft * progressLeft;

float f2 = 3.0 * progressLeft * progressLeft * progress;

float f3 = 3.0 * progressLeft * progress * progress;

float f4 = progress * progress * progress;



rotated[0] += f1 * a_StartPosition[0];

rotated[0] += f2 * 1.0;//a_BezStartPosition[0];

rotated[0] += f3 * a_BezEndPosition[0];

rotated[0] += f4 * a_EndPosition[0];



rotated[1] += f1 * a_StartPosition[1];

rotated[1] += f2 * 1.0;//a_BezStartPosition[1];

rotated[1] += f3 * a_BezEndPosition[1];

rotated[1] += f4 * a_EndPosition[1];



//rotated[0] += (progressLeft * progressLeft * progressLeft * a_StartPosition[0])

// + (3.0 * progressLeft * progressLeft * progress * a_BezStartPosition[0])

// + (3.0 * progressLeft * progress * progress * a_BezEndPosition[0])

// + (progress * progress * progress * a_EndPosition[0]);



//rotated[1] += (progressLeft * progressLeft * progressLeft * a_StartPosition[1])

// + (3.0 * progressLeft * progressLeft * progress * a_BezStartPosition[1])

// + (3.0 * progressLeft * progress * progress * a_BezEndPosition[1])

// + (progress * progress * progress * a_EndPosition[1]);



gl_Position = u_MVPMatrix * rotated;



v_TexCoord = a_TextureCoord;

v_Alpha = 1.0;//a_Alpha;



}




Simple fragment shader:

precision mediump float;



uniform sampler2D u_Texture;

varying float v_Alpha;

varying vec2 v_TexCoord;



void main() {

gl_FragColor = texture2D(u_Texture, v_TexCoord);

gl_FragColor.a *= v_Alpha;

}




The vertex origin is passed in as an already scaled and initially rotated point (previous iterations that did that on the gpu failed to compile on the Galxy Nexus), and is then rotated over time and moved from its start point to end point along a bezier curve.



The commented out rotated[0] and rotated[1] blocks are the initial implementation of the bezier curve logic, broken down above into each separate summed section to debug.



As it is, it renders as expected (albeit with a badly formed curve). If a_BezStartPosition is called, nothing renders. If a_BezStartPosition is called, and a_BezEndPosition is commented out to there’s no change in the number of attributes used, it renders.



I’ve tried using the PVRShaderEditor tool, which informs me that it is currently using 30 Primary Attributes, and any more seem to prevent it from working. Which is a shame, as I need to enable a_Alpha and a_BezStartPosition, but more than 30 Primary Attributes appears to break the shader, though just on this one platform. I’ve spend a day messing with it, but I’ve not managed to find any relevant information out there :confused:



If anyone out there has any suggestions I am more than open to them - I’m pretty new at all this, but felt I had a handle on what to expect before I ran into issues here.

Hi,



The compiler will not pack attributes for you. By packing your vec2’s into vec4’s, and your floats into a vec4, I was able to reduce the number of Primary Attributes to 18. Can you try using the modified shader below to see if performance improves?


//attribute float a_Born;<br />
attribute vec2 a_Origin;<br />
//attribute vec2 a_StartPosition;<br />
//attribute vec2 a_EndPosition;<br />
attribute vec4 a_Positions; // 0-1 start, 2-3 end<br />
//attribute vec2 a_BezStartPosition;<br />
//attribute vec2 a_BezEndPosition;<br />
attribute vec4 a_BezPositions; // 0-1 start, 2-3 end<br />
attribute vec2 a_TextureCoord;<br />
//attribute float a_Lifespan;<br />
//attribute float a_Alpha;<br />
//attribute float a_AngleDelta;<br />
attribute vec4 a_Properties; //0 born, 1 lifespan, 2 alpha, 3 angle delta<br />
<br />
uniform mat4 u_MVPMatrix;<br />
uniform float u_CurrentTime;<br />
<br />
varying float v_Alpha;<br />
varying vec2 v_TexCoord;<br />
<br />
void main() {<br />
float elapsedTime = (u_CurrentTime - a_Properties[0]) / 1000000.0;<br />
<br />
// animated rotation<br />
float angleChange = a_Properties[3] * elapsedTime;<br />
float s = sin(angleChange);<br />
float c = cos(angleChange);<br />
<br />
// avoiding matrix maths<br />
vec4 rotated = vec4(0.0, 0.0, 0.0, 1.0);<br />
rotated[0] = dot(vec2(c, -s), a_Origin);<br />
rotated[1] = dot(vec2(s, c), a_Origin);<br />
<br />
float progress = clamp(elapsedTime / (a_Properties[1] / 1000000.0), 0.0, 1.0);<br />
float progressLeft = 1.0 - progress;<br />
<br />
float f1 = progressLeft * progressLeft * progressLeft;<br />
float f2 = 3.0 * progressLeft * progressLeft * progress;<br />
float f3 = 3.0 * progressLeft * progress * progress;<br />
float f4 = progress * progress * progress;<br />
<br />
rotated[0] += f1 * a_Positions[0];<br />
rotated[0] += f2 * 1.0;//a_BezPositions[0];<br />
rotated[0] += f3 * a_BezPositions[2];<br />
rotated[0] += f4 * a_Positions[2];<br />
<br />
rotated[1] += f1 * a_Positions[1];<br />
rotated[1] += f2 * 1.0;//a_BezPositions[1];<br />
rotated[1] += f3 * a_BezPositions[3];<br />
rotated[1] += f4 * a_Positions[3];<br />
<br />
//rotated[0] += (progressLeft * progressLeft * progressLeft * a_StartPosition[0])<br />
//            + (3.0 * progressLeft * progressLeft * progress * a_BezStartPosition[0])<br />
//          + (3.0 * progressLeft * progress * progress * a_BezEndPosition[0])<br />
//        + (progress * progress * progress * a_EndPosition[0]);<br />
<br />
//rotated[1] += (progressLeft * progressLeft * progressLeft * a_StartPosition[1])<br />
//            + (3.0 * progressLeft * progressLeft * progress * a_BezStartPosition[1])<br />
//          + (3.0 * progressLeft * progress * progress * a_BezEndPosition[1])<br />
//        + (progress * progress * progress * a_EndPosition[1]);<br />
<br />
gl_Position = u_MVPMatrix * rotated;<br />
<br />
v_TexCoord = a_TextureCoord;<br />
v_Alpha = 1.0;//a_Properties[3];<br />
<br />
}
```<br />
<br />
<blockquote>On a second Galaxy Nexus with Android 4.3 however, nothing displayed - no errors, just no geometry.</blockquote><br />
This sounds like a driver bug. Can you share the graphics driver version of the two Galaxy Nexus' with us? It can be queried with:<br />
<code>adb shell cat /proc/pvr/version</code><br />
Cheers,<br />
Joe

Thanks Joe, packing the attributes got it working! I’ll remember that for next time.



The versioning on the 4.0 device, the one that initially worked, is:

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

System Version String: SGX revision = 1.2.0



Whilst the versioning on the 4.3 device, which didn’t render anything initially, is:

Version CustomerGoogle_Android_ogles1_ogles2_GPL sgxddk 18 1.8@785978 (release) omap4430_android

System Version String: SGX revision = 1.2.0



Hope you can glean anything from that, and thanks again.