1

I'm writing shader codes in the GPUImage framework in Android. Then I encounter a problem of array indexing in the fragment shader.

According to Appendix of The OpenGL ES Shading Language, in vertex shader, uniform arrays can be indexed by any integer, and varying arrays can be indexed by constant-index-expression. In fragment shader, both (uniform/varying) arrays can only be indexed by constant-index-expression. Under the definition of constant-index-expression, the for-loop index should be able to used as an array index.

However, things go wrong when I use the loop index as array index in fragment shader. There is no compile error and the shader codes can be run, but it seems that the program treats all index value to 0 during every round in the loop.

Here is my fragment shader codes:

uniform sampler2D inputImageTexture;
uniform highp float sample_weights[9]; // passed by glUniform1fv
varying highp vec2 texture_coordinate;
varying highp vec2 sample_coordinates[9]; // computed in the vertex shader
...
void main()
{
    lowp vec3 sum = vec3(0.0);
    lowp vec4 fragment_color = texture2D(inputImageTexture, texture_coordinate);
    for (int i = 0; i < 9; i++)
    {
        sum += texture2D(inputImageTexture, sample_coordinates[i]).rgb * sample_weights[i];
    }
    gl_FragColor = vec4(sum, fragment_color.a);
}

The result will be correct if I unroll the loop and access [0] to [8] for the arrays. However, when using the loop index, the result is wrong and becomes the same as running

sum += texture2D(inputImageTexture, sample_coordinates[0]).rgb * sample_weights[0];

by 9 times, and there is no compile error reported during the process.

I've only tested one device, which is Nexus 7 with Android version 4.3. The GPUImage framework uses android.opengl.GLES20, but not GLES30.

Is this an additional restriction on shader codes in Android devices, or in OpenGL ES 2.0, or it is a device-dependent issue?

Updated: After testing more Android devices (4.1~4.4), It seems that only that Nexus 7 device has this issue. The results on other devices are correct. It's weird. Is this an implementation issue on individual devices?

1 Answer 1

3

This is a little known fact, but texture lookups inside loops are an undefined thing in GLSL. Specifically the tiny sentence: "Derivatives are undefined within non-uniform control flow", see section 8.9 of the GLSL ES spec. And see section 3.9.2 to find out what non uniform control flow. The fact that this works on other devices is by chance.

Your only option may be to un roll the loop unfortunately.

Sign up to request clarification or add additional context in comments.

1 Comment

You may also be able to change texture2D() to texelFetch() however, this is ES 3.0 only and you did not specify if you are using ES 2.0 or ES 3.0 and you would need to be using GL_NEAREST filtering. This is because this function does not need derivatives to do the filtering on the texture.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.