我注意到我的程序中有一个奇怪的错误,当我在调用glVertexArrayVertexBuffer
后多次绑定VAO时会发生这种错误。在我的帧循环中,我通常有一个VAO用于一次绘制调用,但有时我想使用相同的VAO用于具有不同着色器的多个绘制调用。但这在我的实现中不起作用:
while(RUN){
updateBuffers();//updates VAO
drawThis();//binds and unbinds VAO
drawThat();//binds and unbinds VAO -> OpenGL Invalid Operation error at draw call
}
虽然这有效:
while(RUN){
updateBuffers();//updates VAO
drawThis();//binds and unbinds VAO
updateBuffers();//updates VAO
drawThat();//binds and unbinds VAO -> works
}
这也行不通:
updateBuffers();
while(RUN){
drawThis();//OpenGL Invalid Operation error in second frame
}
但这可行
updateBuffers();
glBindVertexArray(VAO);
while(RUN){
drawThis();//only makes the draw call
}
glBindVertexArray(0);
...但这不是一个选项,因为我也想在我的帧循环中使用其他VAO(我希望保持灵活的顺序)。
那么这些功能在内部是做什么的?
draw
函数只需绑定VAO和着色器,进行绘制调用(通常为glDrawElementsInstanced
),然后取消绑定着色器和VAO。
updateBuffers
函数通常通过指针写入缓冲区对象(使用glNamedBufferStorage
初始化),该指针使用GL_MAP_WRITE_BIT
,GL_MAP_PERSISTENT_BIT
和{{1}映射整个缓冲区标志。为了确保我不会覆盖仍然由GPU使用的任何数据,我总是写入缓冲区的不同分区。因此,在每次更新之前,我将写入偏移量增加先前更新的大小(如果更新超过存储大小,则将其设置为0)。
因为着色器应该可以看到更新后的数据,所以我还必须更新着色器绑定的绑定点。我通过调用glBindBufferRange
为均匀缓冲区(由均匀块使用)和glVertexArrayVertexBuffer
为每个更新的顶点缓冲区(对于顶点属性)执行此操作,以使每个缓冲区的绑定偏移量从位置开始更新的数据。
这总是适用于统一缓冲区绑定(偏移量用glBindBufferRange
更新)但是当我更新VAO的顶点缓冲区的绑定(使用glVertexArrayVertexBuffer
)然后绑定并取消绑定该VAO在再次致电glVertexArrayVertexBuffer
之前不止一次,我收到GL_MAP_COHERENT_BIT
错误。
为什么glVertexArrayVertexBuffer
导致VAO表现得像这样?更新VAO绑定到顶点缓冲区的偏移量的正确方法是什么?