Question

I'm drawing a simple triangle using opengl-es 2.0 on android (tests on nexus4).

On continuous draw mode i'm rotating this triangle using a rotation matrix and setting the uMVPMatrix inside the vertex shader.

The Problem

I'm new to open gl but this is quite basic and works good, but after around 30 seconds the garbage collector kicks in:

05-05 19:12:23.359  26333-26357/com.x.app V/Renderer﹕ Surface created
05-05 19:12:23.369  26333-26357/com.x.app V/Renderer﹕ Changed surface width:1196 height: 768
05-05 19:12:59.307  26333-26357/com.x.app D/dalvikvm﹕ GC_FOR_ALLOC freed 436K, 5% free 9121K/9588K, paused 64ms, total 65ms
05-05 19:13:48.910  26333-26357/com.x.app D/dalvikvm﹕ GC_FOR_ALLOC freed 522K, 6% free 9105K/9664K, paused 31ms, total 31ms
05-05 19:14:39.144  26333-26357/com.x.app D/dalvikvm﹕ GC_FOR_ALLOC freed 512K, 6% free 9104K/9664K, paused 13ms, total 13ms

After the second GC Round there is another Rectangle on the screen, sometimes a Line. Vertex bug after second garbage collector run Another image here

After one or two garbage collector runs, it's gone again and this happens over and over again.

I guess there's some binding between the shader code and java that i did horribly wrong.

My Code

My triangle draw method:

 public void draw(float[] mMVPMatrix) {
    GLES20.glUseProgram(mProgram);
    int mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
    GLES20.glEnableVertexAttribArray(mPositionHandle);
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);
    mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
    GLES20.glUniform4fv(mColorHandle, 1, color, 0);
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
    GLES20.glDisableVertexAttribArray(mPositionHandle);
}

The vertex buffer (Triangle constructor):

    ByteBuffer bb = ByteBuffer.allocateDirect(
            triangleCoords.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(triangleCoords);
    vertexBuffer.position(0);
    vertexCount=triangleCoords.length;
Was it helpful?

Solution

You should use DDMS 'Start Tracking' and 'Get Allocations' buttons to track memory allocations. It will show you all your allocations. More information here: http://developer.android.com/tools/debugging/ddms.html#alloc

Looking at your code, I'd strongly recommend you to call GLES20.glGetUniformLocation only once right after you've compiled shader and store these values in int variables. Finding uniforms/attributes by string identifier quite is time-consuming and my wild guess is that it also allocates some memory (not much but you do it each frame). Don't do that on each draw call.

Other than that, this question is not relevant to OpenGL ES, it is a common garbage collection issue which you can easily track in DDMS.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top