WebGL 2.0:即使 VBO 被删除,Draw 调用也会成功

Posted

技术标签:

【中文标题】WebGL 2.0:即使 VBO 被删除,Draw 调用也会成功【英文标题】:WebGL 2.0: Draw call succeeds even VBO is deleted 【发布时间】:2017-11-14 15:20:59 【问题描述】:

所以我使用 VAO 来存储来自 VBO 的指针。我想测试在绑定 VAO 并调用绘图之前删除数据缓冲区(vbo、ibo 等)时会发生什么。由于 VAO 将指向数据的指针存储在相应的数据缓冲区中,因此我预计渲染器会崩溃。但是,一切都在继续工作。这怎么可能?我正在使用 WebGL 2.0 上下文。该文档指出 VAO 是根据 OpenGL 文档实现的。这是否与 javascript 如何处理对象有关?也许我的 vbo 在我调用 deleteBuffer 之前被缓存在某个地方(不知不觉)。这可能吗?这里发生了什么?

【问题讨论】:

【参考方案1】:

如果gl.DeleteBuffers 尝试删除缓冲区对象,则如果缓冲区对象附加到未绑定的顶点数组对象,则不会删除该缓冲区对象。在这种情况下,对象的名称变得无效,并且它被标记为未使用

gl.bindVertexArray( vao );
gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
gl.vertexAttribPointer( ... );
.....
gl.bindVertexArray( 0 );
gl.deleteBuffers( 1, vbo );

但是如果绑定了顶点数组对象,那么缓冲区对象就被分离删除了:

gl.bindVertexArray( vao );
gl.bindBuffer( gl.ARRAY_BUFFER, vbo );
gl.vertexAttribPointer( ... );
.....
gl.deleteBuffers( 1, vbo );
gl.bindVertexArray( 0 ); 

见OpenGL ES Specification 3.2 - 5.1.3 Deleted Object and Object Name Lifetimes, page 45:

当缓冲区、纹理、变换反馈或渲染缓冲区对象被成功删除时,它会从当前上下文中绑定到的任何绑定点中解除绑定,并与绑定到当前上下文的容器对象的任何附件分离。 ...

对未绑定容器对象的附加,例如删除附加到未绑定到上下文的顶点数组对象的缓冲区,不受影响并继续充当已删除对象的引用 ....

当缓冲区、查询、渲染缓冲区、采样器、同步或纹理对象被删除时,其名称立即变为无效(例如标记为未使用),但在不再使用之前不会删除底层对象。

【讨论】:

另外,仅供参考,OpenGL ES 中的对象删除行为是大多数驱动程序中测试不足的部分。 WebGL 应该做得更好,并且为着色器/程序对已删除着色器和程序的行为进行了广泛的测试。对于 VAO,它也应该经过测试,但对于 WebGL1,它没有经过测试......我们忘记了。对于 WebGL2,它已经过测试,但 Chrome 尚未通过 the test。这是跟踪问题的bug。 @gman 哦,我没有阅读 WebGL 标签,我只阅读了问题,我的错。我现在更改了代码并参考了 OpenGL ES。 很抱歉没有说清楚...该死的,我使用的是 webgl 2.0 上下文,但是我正在使用 chrome 进行测试。感谢您的意见。

以上是关于WebGL 2.0:即使 VBO 被删除,Draw 调用也会成功的主要内容,如果未能解决你的问题,请参考以下文章

在 WebGL 中插入两个 VBO

WebGL 与 WebGPU比对[3]

在 netbeans 7.4 上运行 jogl VBO

安卓 OpenGL ES 2.0 VBO

OpenGL ES 2.0 VBO 问题

OpenGL ES 2.0 vbo 白屏