在帧完成之前删除OpenGL 3.3顶点缓冲区

时间:2017-06-06 16:03:13

标签: opengl vertex-buffer

这是一个高级的OpenGL问题和tbh。它似乎更像是一个驱动程序错误。我知道标准明确指出,删除对象只会删除它的名称,因此生成器函数可以返回相同的名称。但是,如何处理这个问题并不清楚...

情况如下:我有一个所谓的"瞬态" (C ++)对象(从现在开始),生成GL对象,使用它们排列命令,然后删除它们。

现在考虑在调用SwapBuffers()之前我使用多种此类。发生以下情况:

  • TO 1.生成一个名为VBO1的顶点缓冲区,以及一个VAO1和其他东西
  • TO 1.使用VBO1
  • 调用一些映射/绘图命令
  • TO 1.删除VAO1和VBO1(因此释放名称VBO1)
  • TO 2.生成一个顶点缓冲区对象,现在当然具有相同的名称(VBO1),因为名称1被删除并且可用,以及另一个VAO(可能是1)
  • TO 2.使用这个新的VBO1(不同的顶点位置等)调用其他一些映射/绘图命令。
  • TO 2.删除新的VBO1
  • SwapBuffers()

结果是:只有TO 1执行的修改才有效。简而言之:我想渲染一个三角形,然后是一个正方形,但我只得到了三角形。

解决方法:不删除VBO,因此我在TO 2中获得了一个新名称。(VBO2)

我想请求你帮忙解决这个问题;虽然我知道我不应该删除/生成中间对象,但除此之外,这个" buggy"机制真的让我感到不安(我的意思是我怎么能相信GL呢?......简短回答:我不能......)

(sideonote:我从12年开始编程3D图形,但这件事真的给了我毛骨悚然......)

2 个答案:

答案 0 :(得分:0)

我的多线程渲染代码有类似的问题。我使用双缓冲系统来渲染命令,因此当我删除一个对象时,它可能会在下一帧中使用。

缺点是TO不应该直接删除GL对象。它需要将管理器的句柄提交给队列,以便在帧之间进行删除。通过我的双缓冲,我添加了一个小计时器,在释放之前倒数2帧。

对于我的瞬态顶点,我有一大块内存,我写入存储,并跳过VBO提交。我不知道你的设置是什么或你推动了多少个顶点,但如果你1)重新生成每一帧或2)推动小的顶点集,你可能无法从VBO中受益。绝对有和没有VBO的性能测试。

答案 1 :(得分:0)

我找到问题的原因,我认为值得一提(因此其他开发者不会陷入同一个洞)。实际问题是VAO,或者更确切地说是VAO的缓存

在Metal和Vulkan中,输入布局完全独立于实际使用的缓冲区:您只需指定缓冲区所在的绑定点(位置)。

但不是在OpenGL中...... VAO实际上拥有对顶点缓冲区的强引用,顶点缓冲区在创建过程中受到约束。因此发生了以下事情:

  • 创建了VBO1,创建了VAO1
  • VAO1缓存在管道缓存
  • 删除了VBO1,但只释放了名称,而不是对象
  • glGenBuffers()在名称可用时再次返回1
  • 但缓存中的VAO1仍引用旧的VBO1
  • 司机感到困惑,并且不允许我修改新的VBO1

解决方案......好吧......现在当顶点缓冲区被删除时,我删除了引用该缓冲区的所有缓存管道。

从长远来看:我将为输入布局维护一个单独的缓存(即使它是管道状态的一部分),并将瞬态对象进一步向上移动,以便它变为不那么短暂。

欢迎来到OpenGL世界......