opengl - 将间接命令绑定为 draw_indirect_buffer 和原子计数器会导致崩溃
问题描述
我发现在使用 OpenGL 4.3 时我无法弄清楚的驱动程序的奇怪行为。
我glDrawArraysIndirect()
在默认的 FBO 上绘制了一些三角形。
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, command);
glBindVertexArray(VAO);
glDrawArraysIndirect(GL_TRIANGLES, nullptr);
glBindVertexArray(0);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
是这样定义的command
:
struct DrawArraysIndirectCommand
{
GLuint count;
GLuint primCount;
GLuint first;
GLuint baseInstance;
};
它在屏幕外 FBO 上进行的先前绘制调用的片段着色器中进行了更新,它被绑定为原子计数器:
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, command);
在片段着色器中,它以这种方式更新:
layout(binding = 0, offset = 0) uniform atomic_uint vertex_count;
main() {
...
if(some condition) { atomicCounterIncrement(vertex_count); }
...
}
问题源于 nvidia 驱动程序和 intel 驱动程序之间的不同行为。起初,我command
在程序开始时将其绑定为原子计数器,在任何绘图调用之前,直到程序结束我才解除绑定:
init() {
// Generation of the buffer
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, command); // <--- FIX
}
draw() {
glBindFramebuffer(GL_FRAMEBUFFER, offscreen_FBO);
// Clear indirect draw command buffer
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, command);
glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawArraysIndirectCommand),
&clearedCommand);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
glBindVertexArray(VAO2);
// Draw call in which the command is updated from the fragment shader
glDrawArrays(GL_TRIANGLES, 0, another_vertex_count);
glBindVertexArray(0);
//use of the updated command in another draw call...
}
通过这种方式,它与 nvidia 驱动程序配合得很好。但是当我使用英特尔驱动程序测试该应用程序时,它只工作了几分钟然后就崩溃了(崩溃源于图形驱动程序,但没有产生错误)。我通过每次在绘图调用之前绑定原子计数器来解决这个问题:
draw() {
glBindFramebuffer(GL_FRAMEBUFFER, offscreen_FBO);
// Clear indirect draw command buffer
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, command);
glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, sizeof(DrawArraysIndirectCommand),
&clearedCommand);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, command); // <--- FIX
glBindVertexArray(VAO2);
// Draw call in which the command is updated from the fragment shader
glDrawArrays(GL_TRIANGLES, 0, another_vertex_count);
glBindVertexArray(0);
//use of the updated command in another draw call...
}
通过这种方式,它在英特尔驱动程序上也可以正常工作。但为什么?为什么每次都需要重新绑定?这就像驱动程序有时会丢失绑定,但没有任何其他glBindBufferBase()
绑定在同一索引处。command
我认为问题与用作原子计数器和间接命令缓冲区的事实有关,但我无法理解链接。
解决方案
推荐阅读
- c# - 如何触发
的状态 在 Blazor WASM 中 - python - Django - 仅当登录用户是添加项目的用户或者他是超级用户时才具有编辑权限
- php - 如何在 laravel 数据表中呈现列?
- typescript - List.flat 方法的类型?
- c# - 如何编辑我的代码以在控制台而不是 GUI 中运行
- angular - Angular 客户端无法访问 Google Compute Engine 中的 Localhost
- java - 无法执行包含 Junit Appium 脚本和库的 Jar
- java - 如何加快google news word2vec模型的加载速度
- genetic-algorithm - 什么是有效的非自适应人口规模调整方法?
- python - 覆盖键时,什么是 Open Parenthesis 键(PyQt5)