androidcompute-shaderopengl-es-3.1

Using compute shader in Android 5 (Open GL ES 3.1)


I am learning about OpenGL ES and in particular, compute shaders in OpenGL ES 3.1, specifically, in Android 5.0.1.

I have 3 shaders defined (compute, vertex, and fragment) and attached to two different programs, one for the compute shader and one for the vertex and fragment shaders.

I have no problem when I only use the vertex and fragment shaders but now that I added the compute shader I get the following error:

02-11 20:02:10.375  13243-13264/com.example.daan.daggl2 I/VERSION﹕ OpenGL ES 3.1 NVIDIA 349.00
02-11 20:02:10.472  13243-13264/com.example.daan.daggl2 A/libc﹕ Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 13264 (GLThread 9847)

I'm trying to figure out what I'm missing but I'm new to this topic and I'm not sure where to begin looking for the problem.

The object's constructor is:

public Triangle() {
        buffers = new int[1];
        GLES31.glGenBuffers(1, buffers, 0);
        gVBO = buffers[0];

        // set up the vertex and fragment shaders
        int vertexShader = MyGLRenderer.loadShader(
            GLES31.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = MyGLRenderer.loadShader(
            GLES31.GL_FRAGMENT_SHADER, fragmentShaderCode);

        program = GLES31.glCreateProgram();    
        GLES31.glAttachShader(program, vertexShader);
        GLES31.glAttachShader(program, fragmentShader);
        GLES31.glLinkProgram(program);
        checkGLError("LinkProgram/program");

        // set up the compute shader
        int computeShader = MyGLRenderer.loadShader(
            GLES31.GL_COMPUTE_SHADER, computeShaderCode);
        computeProgram = GLES31.glCreateProgram();
        GLES31.glAttachShader(computeProgram, computeShader);
        GLES31.glLinkProgram(computeProgram);
        checkGLError("LinkProgram/computeProgram");
    }

The draw function:

public void draw(float[] mvpMatrix, float[] color) {

        GLES31.glUseProgram(computeProgram);
        checkGLError("UseProgram/computeProgram");
        int radiusId = GLES31.glGetUniformLocation(
            computeProgram, "radius");
        indexBufferBinding = 0;
        GLES31.glUniform1f(radiusId, (float) radius);
        GLES31.glBindBufferBase(
            GLES31.GL_SHADER_STORAGE_BUFFER, indexBufferBinding, gVBO);
        checkGLError("glBindBuffer/gVBO");
        GLES31.glDispatchCompute(2, 2, 1);
        GLES31.glBindBufferBase(
            GLES31.GL_SHADER_STORAGE_BUFFER, indexBufferBinding, 0);
        // See note 1 below
        //GLES31.glMemoryBarrier(
        //    GLES31.GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
        GLES31.glMemoryBarrier(
            GLES31.GL_SHADER_STORAGE_BARRIER_BIT);
        checkGLError("glMemoryBarrier/1");
        GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, gVBO);
        checkGLError("glBindBuffer/gVBO");

        GLES31.glUseProgram(program);

        int posId = GLES31.glGetAttribLocation(
            program, "a_v4Position");
        int fillId = GLES31.glGetAttribLocation(
            program, "a_v4FillColor");
        int mvpMatrixId = GLES31.glGetUniformLocation(
            program, "mvp_matrix");

        GLES31.glEnableVertexAttribArray(posId);
        GLES31.glEnableVertexAttribArray(fillId);
        GLES31.glUniformMatrix4fv(mvpMatrixId, 1, false, mvpMatrix, 0);
        // See note 2 below
        GLES31.glDrawArrays(GLES31.GL_POINTS, 0, 3);
    }

For reference, the shaders are at the end of the post.

Notes:

  1. I can't find GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT in the Android documentation. Shouldn't it be there? The documentation mentions it.
  2. The draw call crashes the application. Up until before glDrawArrays() everything seems fine.

Any ideas on what to look for are appreciated.

Vertex Shader:

private final String vertexShaderCode =
            "uniform mat4 mvp_matrix;" +
            "attribute vec4 a_v4Position;" +
            "attribute vec4 a_v4FillColor;" +
            "varying vec4 v_v4FillColor;" +
            "void main(void) {" +
            " v_v4FillColor = a_v4FillColor;" +
            " gl_Position = mvp_matrix * a_v4Position;" +
            "}";

Fragment Shader:

    private final String fragmentShaderCode =
            "precision mediump float;" +
            "varying vec4 v_v4FillColor;" +
            "void main(void) {" +
            " gl_FragColor = v_v4FillColor;" +
            "}";

Compute Shader:

    private final String computeShaderCode =
            "#version 310 es" +
            "\n" +
            "uniform float radius;" +
            "struct Vector3f { float x; float y; float z; float w; };" +
            "struct AttribData { Vector3f v; Vector3f c; };" +
            "layout(std140, binding = 0) buffer destBuffer { AttribData data[]; } outBuffer;" +
            "layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" +
            "void main() {" +
            " ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);" +
            " uint gWidth = gl_WorkGroupSize.x * gl_NumWorkGroups.x;" +
            " uint gHeigth = gl_WorkGroupSize.y * gl_NumWorkGroups.y;" +
            " uint gSize = uint(gWidth) * uint(gHeigth);" +
            " uint offset = uint(storePos.y)*gWidth + uint(storePos.x);" +
            " float alpha = 2.0 * 3.1159265359 * (float(offset) / float(gSize));" +
            " outBuffer.data[offset].v.x = float(sin(alpha)) * float(radius);" +
            " outBuffer.data[offset].v.y = float(cos(alpha)) * float(radius);" +
            " outBuffer.data[offset].v.z = 0.0;" +
            " outBuffer.data[offset].v.w = 1.0;" +
            " outBuffer.data[offset].c.x = float(storePos.x) / float(gWidth);" +
            " outBuffer.data[offset].c.y = 0.0;" +
            " outBuffer.data[offset].c.z = 1.0;" +
            " outBuffer.data[offset].c.w = 1.0;" +
            "}";

Solution

  • Yes, GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT is missing in the Android Java bindings. There's a tradition of the Java OpenGL bindings in Android being incomplete. There are still things missing from the 3.0 bindings as well.

    In this case, since it's just an enum value, you can easily work around it by defining the value itself. The C/C++ definition is:

    #define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
    

    So in Java, you can add a definition like this to your code:

    static final int GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT = 0x00000001;
    

    As for the crash, I'm not totally sure. I notice that there's no glVertexAttribPointer() calls in the posted code. If they are indeed not in your code, that would certainly be a problem.