内存使用量随着时间的推移不断增加(GLKit - iOS)

时间:2012-10-03 19:00:10

标签: ios memory glkit vertex-buffer glkbaseeffect

我差不多完成了我的应用。其中一个视图使用GLKit。我刚才有记忆问题。基本上会发生的是,当显示GLKView时,内存消耗不断增加(用仪器看到)。在某一点上,它显然会崩溃。 我对GLKit了解不多,所以我希望你能帮助我。

问题是我正在显示的3D箭头。如果我不绘制它,所有其他的东西都不会产生任何问题。 这是包含箭头顶点数据的头文件:

#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...

这是绘图代码:

- (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);
}

有什么建议吗? 非常感谢你的帮助!

2 个答案:

答案 0 :(得分:2)

每次调用drawInRect时都会创建一个新的顶点缓冲区(VBO),并且永远不会删除它们。 GLGenBuffers和GLBindBuffer设置了一个新缓冲区并使其成为当前状态,但真正的损坏是通过GLBufferData完成的,其中数据复制到新缓冲区中。

glBindBuffer(GL_ARRAY_BUFFER,0);重置GL不使用缓冲区,glDisableVertexAttribArray(GLKVertexAttribPosition);告诉GL不再在缓冲区中查找位置数据,但这些调用都没有做任何事情来释放内存。如果你想每次释放内存,你需要调用GLDeleteBuffers(1,&amp; arrowVertexBuffer);释放记忆。

更好的方法是在启动时生成一次缓冲区并在终止时删除它,然后依赖于arrowVertexBuffer,每次重新绑定和取消绑定它,如同重置指针一样,假定程序的其他部分正在修改GL状态。

看起来你也开始使用顶点阵列对象(VAO)的路径,这是另一种捕获状态一次以便重用的方法,尽管在尝试之前让VBO正常工作可能会更好那。 VBO和VAO都是用于缓存状态的方法,随着时间的推移逐渐演变以减少每次通过渲染循环的负载,但是VAO投射了更广泛的网络,这可能使得纠正它变得更加棘手。

作为一般性建议,您可以通过添加更通用且更受欢迎的标记(例如[Open GL])来获得更多关注这样的问题。

你应该尝试的另一个调试工具是OpenGL Profiler。如果你没有用XCode安装它,请在文档中查找,你应该找到一个下载图形工具包的链接。资源窗口允许您跟踪正在使用的缓冲区对象。

答案 1 :(得分:0)

您是否尝试在Xcode中运行静态分析器?

非常擅长指出未发布的已分配内存等等。

要使用它,请在“运行”按钮上按住鼠标,然后从下拉列表中选择“分析”。

如果它确实找到了任何东西,它通常会将它们指向蓝色,你可以看到线条追溯到内存分配和未释放的位置等等......

如果有任何影响,请告诉我。