我差不多完成了我的应用。其中一个视图使用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);
}
有什么建议吗? 非常感谢你的帮助!
答案 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中运行静态分析器?
非常擅长指出未发布的已分配内存等等。
要使用它,请在“运行”按钮上按住鼠标,然后从下拉列表中选择“分析”。
如果它确实找到了任何东西,它通常会将它们指向蓝色,你可以看到线条追溯到内存分配和未释放的位置等等......
如果有任何影响,请告诉我。