Question

I've almost finished my app. One of the views uses GLKit. I just have a problem with memory. Basically what happens is that when GLKView is displayed, the memory consumption constantly rises (seen with Instruments). At a certain point it obviously crashes. I don't know much about GLKit, so I hope you can help me.

The problem is a 3d arrow that I'm displaying. If I don't draw it, all the other things don't create any problem. This is the header file that contains the arrow vertex data:

#import <GLKit/GLKit.h>

struct arrowVertexData
{
    GLKVector3      vertex;
    GLKVector3      normal;
    GLKVector2      texCoord;
};
typedef struct arrowVertexData arrowVertexData;
typedef arrowVertexData* vertexDataPtr;


static const arrowVertexData MeshVertexData[] = {
    {/*v:*/{{-0.000004, 0.0294140, -0.0562387}}, /*n:*/{{0.000000, 1.000000, 0.000000}}, /*t:*/{{0.500000, 0.333333}}},
... etc...

And this is the draw code:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    [self.arrowEffect prepareToDraw];
    //glGenVertexArraysOES(1, &arrowVertexArray);
    //glBindVertexArrayOES(arrowVertexArray);

    glGenBuffers(1, &arrowVertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, arrowVertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(MeshVertexData), MeshVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(arrowVertexData), 0);
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_TRUE, sizeof(arrowVertexData), (void *)offsetof(arrowVertexData, normal));
    glBindVertexArrayOES(arrowVertexArray);

    // Render the object with GLKit

    glDrawArrays(GL_TRIANGLES, 0, sizeof(MeshVertexData) / sizeof(arrowVertexData));

    //reset buffers
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    //disable atttributes
    glDisableVertexAttribArray(GLKVertexAttribNormal);
    glDisableVertexAttribArray(GLKVertexAttribPosition);
}

Any suggestion? Thank you very much for you help!

Was it helpful?

Solution

You are creating a new vertex buffer (VBO) each time drawInRect is called, and never deleting them. GLGenBuffers and GLBindBuffer set up and a new buffer and make it current, but the real damage is done with GLBufferData, which copies the data into the new buffer.

glBindBuffer(GL_ARRAY_BUFFER, 0); resets GL to not use the buffer, and glDisableVertexAttribArray(GLKVertexAttribPosition); tells GL not to look for position data in a buffer anymore, but neither of these calls does anything to free the memory. If you wanted to free the memory each time, you would need to call GLDeleteBuffers(1, &arrowVertexBuffer); to free the memory.

A better approach would be to generate the buffer once at startup and delete it when terminating, and hang on to arrowVertexBuffer, rebinding and unbinding it each time through as needed, as sell as reseting the pointers, assuming other parts of your program are modifying GL state.

It looks like you also started down the path of using a Vertex Array Object (VAO), which would be another way to capture state once for reuse, although it may be better to wait until you have the VBO working correctly before attempting that. Both VBOs and VAOs are methods for caching state that evolved over time to reduce the load each time through your rendering loop, but VAOs cast a much broader net, which could make it trickier to get it right.

As a general suggestion, you may be able to get more attention for a question like this by adding a more general and popular tag, such as [Open GL].

Another debugging tool you should definitely try is OpenGL Profiler. If you did not install it with XCode, look it up in the documentation and you should find a link to download the graphic tools package. The resources window will allow you to track the buffer objects in use.

OTHER TIPS

Have you tried running the static analyzer in Xcode?

It's very good at pointing out allocated memory that isn't released and that kind of thing.

To use it hold the mouse down on the "Run" button and select "Analyze" from the drop down list.

If it does find anything it usually points them out in blue and you can see the lines tracing back to where memory is being allocated and not released, etc...

Let me know if that has any effect.

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