更新我刚发现我的问题可能与If you call glBufferData after already calling it on a buffer, is there a memory leak?重复了
希望我的问题仍然对某人有用,因为我提供了代码示例,而不仅仅是提及gl函数调用,就像在Q& A中那样。
我不理解glGenBuffers / glBindBuffer / glBufferData
和gldeletebuffers
之间的关系。
考虑绘制一系列线条(线条)。原始序列是在一定数量的帧上绘制的,但随后新的用户输入会增加行数。
我的第一个想法是在大小改变时重用glGenBuffers
指定的缓冲区对象名称。但由于缓冲区大小需要更大,我不能按原样使用现有缓冲区。
注意:此时,我宁愿不假设一些“最大大小”,分配它,然后按我当前需要的大小进行子数据调用。
考虑基于此示例的代码: When should I call glDeleteBuffers()?
如果我在绘制第一帧之前在初始化函数中完成了这些行(代码可能无法编译 - 我关注调用序列,而不是要传递的确切参数 - 我实际上是在C#下工作Xamarin使用OpenTK访问OPENGL ES 2.0,但使用opengl在C ++中查找示例更容易:
GLuint VBO;
void init(int size, float* data) {
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
}
通过以下方式(或应用程序退出时)的许多帧发布:
void destroy() {
glDeleteBuffers(1, &VBO);
}
但是现在我想要一个“re_init”函数来分配不同的大小,我到底需要做什么?
我可以重新分配一个新的VBO缓冲区名称:
void re_init(newSize, newData) {
destroy();
init(newSize, newData);
}
但这看起来有点矫枉过正。我能做的最低工作是什么?这比蛮力破坏/创造一个新的一个更有效吗?
似乎我可以使用任何一组调用,但我不知道结果是否会泄漏内存。我最终需要学习如何在我所处的环境中测试内存泄漏,但是现在我想让理论正确,希望我能编写既高效又无泄漏的代码。
这会泄漏内存吗?
void re_init(newSize, newData) {
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, newSize, newData, GL_STATIC_DRAW);
}
也就是说,我没有对旧缓冲区执行glDeleteBuffers
,因为这样做会释放VBO缓冲区名称,而我正试图找出如何不这样做。
一个问题是,是否有办法重新使用VBO缓冲区名称,数据大小不同?
或者我最好还是坚持每次需要更改缓冲区大小时都要释放缓冲区 及其名称 的简单模型? (这就是glDeleteBuffers似乎所做的。)
答案 0 :(得分:2)
glBufferData
将替换缓冲区对象的内容 - 如spec/doc所示,“在创建新存储时,任何预先存在的数据存储都将被删除” - 所以这不会泄漏记忆。
为了提高效率,需要考虑很多因素,并且没有通用指南 - 我建议您在应用程序中进行配置文件,一旦您对数据有实际用例。
答案 1 :(得分:2)
这里有3个独立的实体:
通过这些定义,我们可以描述每个调用正在做什么:
glGenBuffers()
创建缓冲区名称。glBindBuffer()
在第一次绑定给定名称时创建一个缓冲区对象,并使其成为在缓冲区上运行的其他调用的当前缓冲区。glBufferData()
删除当前缓冲存储区(如果已有),并创建新的缓冲区存储区。glBufferSubData()
修改现有数据存储中的数据。glDeleteBuffers()
删除缓冲区名称,以及相关的缓冲区对象和缓冲区存储(如果存在)。这意味着多次在同一缓冲区对象上调用glBufferData()
完全没问题,并且不会导致任何内存泄漏。
上面列表中的一个细微之处是glGenBuffers()
不会创建缓冲区对象。这只会在第一次绑定名称时发生。这对于缓冲区对象并不重要,但了解具有相同行为的其他类型的对象(如纹理)非常重要。