Hi.
It looks like the Adreno 330 driver for Google Nexus 5 does not correctly support non constant indexing of uniform arrays in a vertex shader.
Below is an example - my Java code generates part of the vertex shader source like this:
String vertexSource=
"#version 300 es\n\n"
+"#define ENTITY_COUNT "+meshEntitiesPerDraw+"\n"+"const int c_zero_int = 0;\n"+"const int c_one_int = 1;\n"+"const int c_two_int = 2;\n"+"const float c_zero = 0.0;\n"+"const float c_one = 1.0;\n"+"uniform mat4 viewMatrix;\n"+"uniform vec4 miscData;\n"+"uniform mat4 modelMatrixList[ENTITY_COUNT];\n";+"uniform vec4 lightDiffuseList[ENTITY_COUNT];\n";+"uniform vec4 lightSpecularList[ENTITY_COUNT];\n";+"uniform vec4 lightDirectionList[ENTITY_COUNT];\n";+"uniform vec4 lightLocationList[ENTITY_COUNT];\n";
... some other stuff here ...
+" int instanceID = gl_InstanceID;\n"
... some other stuff here ...+" diffuse = lightDiffuseList[instanceID];\n"+" specular = lightSpecularList[instanceID];\n"+" directionUniform = lightDirectionList[instanceID];\n"+" locationUniform = lightLocationList[instanceID];\n"
... some other stuff here ...
This works fine on all modern Android devices I've tested with except for those running Adreno.
For those running Adreno (such as Nexus 5), my lighting ends up with unpredictable results.
Note 'meshEntitiesPerDraw' is equal to 20 on Nexus 5 (obtained by dividng GL_MAX_VERTEX_UNIFORM_COMPONENTS based on the unform arrays).
However, if I change the last bit of quoted code to:
for(int x=0; x<20; x++){vertexSource=vertexSource+"if(instanceID=="+x+")\n"+"{\n"+" diffuse = lightDiffuseList["+x+"];\n"+" specular = lightSpecularList["+x+"];\n"+" directionUniform = lightDirectionList["+x+"];\n"+" locationUniform = lightLocationList["+x+"];\n"+"}\n";}
It works fine.
This means when I'm attempting to access the uniform arrays using an integer variable (obtained from gl_InstanceID) I'm getting strange results, but when I access the arrays using a constant integer (using an if statement on the instanceID) it works fine.
Does Adreno support uniform array indexing using non-constants?
According to the OpenGL ES 3.0 spec, vertex shaders should support not constant indexing of uniform arrays.
Note also that if I decrease meshEntitiesPerDraw to 11 (instead of 20), it works fine as well. This is odd because with a value of 20 I should still have plenty of spare uniforms left over.
At first glance, the accessing of the uniform arrays using an integer variable should work as you have coded them.
1) Is it possible the problem lies with gl_InstanceID? - can you set the integer variable by using another value
2) Would it be possible to provide the exact shader code - Are you able to share apks with both techniques of accessing the arrays?
3) Could you provide a few more of the Adreno devices that you have tried (are they all usingAdreno 330)?
thanks
I changed to
instanceID = 0;
and it worked.
I also changed to
instanceID = int(inPosition.x*0.0)
and it worked.
I then changed it to
instanceID = int(inPosition.x*0.0)+gl_InstanceID
and got the wrong lighting (same as just using gl_InstanceID).
I then changed it to
instanceID = int(inPosition.x*0.0)*gl_InstanceID
and got the wrong lighting - but different results to just using gl_InstanceID.
I've attached screen shots of all 3 scenarios (using gl_InstanceID, using a constant or inPosition.x*0.0, and the *gl_InstanceID).
The shader source is below.
Vertex shader:
Please excuse the poor formatting (copy/paste issues).
I did some more testing and found that if I removed all the branching (if statements) from the vertex shader source, it worked fine with gl_InstanceID. Could it be something to do with the compiler's optimisation that is causing issues?
I'm currently waiting on some colleagues to provide me the list of tested devices - but I've confirmed it with the Nexus 5 myself.
Thanks for looking into this.
Attached screenshots:
Working lights (using a constant or an attribute multiplied by 0.0):
https://drive.google.com/file/d/0B9XpTXH7iwk-VjNSMHlUc250a1U/edit?usp=sh...
https://drive.google.com/file/d/0B9XpTXH7iwk-QS0zSEY1QjJ2ZGc/edit?usp=sh...
Not working but different results (using an attribute multipled by 0.0 then multiplied by gl_instanceID):
By the way when I said I changed the value of instanceID, it was after this line:
mat4 modelMatrix = modelMatrixList[instanceID];
THanks for the additional testing.
1) It's possible that the compiler's optimization is having some problems with this shader. Are you able to provide us with a sample apk (with shader simplied as much as possible, yet producing incorrect results) and bitmap of expected result?
2) Have you updated your Nexus 5 to the latest build (and thus, graphics drivers)? What is the build version/date currently loaded on your Nexus 5?
Thanks for the reply.
The Nexus 5 is updated to the latest version:
Android: 4.4.4
Baseband: M8974A-2.0.50.1.16
Build number: KTU84P
We decided to remove all branching from the shader (to improve performance) and that fixed the problem with using gl_InstanceID to access the arrays. So the bug appears to still be there but we aren't worried about it now.
We are, however, having more issues as discussed in post 28107.
Thanks for the reply.
The Nexus 5 is updated to the latest version:
Android: 4.4.4
Baseband: M8974A-2.0.50.1.16
Build number: KTU84P
We decided to remove all branching from the shader (to improve performance) and that fixed the problem with using gl_InstanceID to access the arrays. So the bug appears to still be there but we aren't worried about it now.
We are, however, having more issues as discussed in post 28107.