我掀起了一个简单的C程序(on github),它使用OpenGL从分配了glBufferStorage
的缓冲区中绘制一堆三角形,如下所示:
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLbitfield bufferStorageFlags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
glBufferStorage(GL_ARRAY_BUFFER, vboSize, 0, bufferStorageFlags);
vert *triData = glMapBufferRange(GL_ARRAY_BUFFER, 0, vboSize, bufferStorageFlags);
我知道将glBufferStorage
与MAP_PERSISTENT_BIT
一起使用时,同步是我的责任,但我不确定我需要防范什么。
我唯一一次触摸triData
就是在调用glDrawArrays
之前,并且在调用SDL_GL_SwapWindow
之后,我知道最后一帧的绘制完成了,我还没有打电话给我绘制这个框架即将开始。
即使禁用了vsync,这似乎也能正常工作。
The wiki说:
交换Default Framebuffer上的后缓冲区和前缓冲区可能 导致某种形式的同步......如果还有命令 影响尚未完成的默认帧缓冲区。 交换缓冲区在技术上只需要同步到最后一个命令 这会影响默认的帧缓冲区,但它可能会执行完整的 glfinish在
但我读过的关于此主题的每篇文章都广泛使用GLsync
指针,虽然也许他们只是假设我可能想以更复杂的方式使用缓冲区?
现在,我是否相信SDL_GL_SwapWindow
正在提供足够的同步?
答案 0 :(得分:2)
以前的答案是正确的,即使您使用交换后也需要同步。但我想更清楚地知道这不仅仅是一个理论问题。
交换操作通常不同步。让渲染在显示前提前1-2帧是很常见的。这样做是为了减少GPU暂时进入空闲状态的“气泡”。如果您的交换呼叫是同步的,那么GPU在返回时将不可避免地处于空闲状态,因为之前提交的所有工作都已完成。即使您立即再次开始渲染,也需要一点时间才能真正到达GPU执行。所以你有时间GPU什么都不做,至少只要你的渲染完全受GPU限制就会伤害性能。
现在,您显然不希望渲染在显示之前太远。不希望的副作用是响应用户输入(这对游戏来说是一个大问题)的延迟增加,以及排队的渲染命令的过多内存使用。因此,在此之前需要进行限制。这种限制通常作为交换操作的一部分应用,但几乎任何时候都可能发生。
因此,如果您测量交换呼叫返回所花费的挂钟时间,那么它足够长以表明它正在阻塞是相当常见的。但这并不表示呼叫本身是同步的。它可能只是阻塞,直到前一帧完成,以防止渲染在显示器前面太远。
答案 1 :(得分:1)
这是关于任何多线程/异步代码的favorite advice:
如果多线程代码没有立即显然可证明是正确的,那么它几乎肯定是错误的。
您无法证明OpenGL不会从您正在写入的值中读取。因此,即使没有明显的问题,也是错误的。
是的,您需要进行显式同步。即使您连贯地映射缓冲区,当OpenGL可能正在读取缓冲区时,您仍然无法更改其中的值。您必须等到最后一次从该数据读取的调用之后再次写入该数据。 OpenGL必须等待它完成的唯一方法是glFinish
或glClientWaitSync
。
答案 2 :(得分:0)
我知道使用glBufferStorage时,同步是我的责任,
不,不一定。使用glBufferStorage
创建的缓冲区与使用glBuffer
创建的缓冲区没有什么不同,除非您无法重新指定它。
使用MAP_PERSISTENT_BIT
进行映射时,您只需要进行手动同步(glBufferStorage
包含在<script type="text/javascript">
// Post Form Validate
$(document).ready(function () {
$('#postForm').validate({
errorElement: "div",
rules: {
name: { required: true },
details: { required: true },
category: { required: true }
}
});
$('#restform').click(function(){
$('#postForm')[0].reset();
});
});
// Chosen multi-select
var config = {
'.chosen-select' : {},
'.chosen-select-deselect' : {allow_single_deselect:true},
'.chosen-select-no-single' : {disable_search_threshold:10},
'.chosen-select-no-results': {no_results_text:'Oops, nothing found!'},
'.chosen-select-width' : {width:"95%"}
}
for (var selector in config) {
$(selector).chosen(config[selector]);
}
</script>
,ARB_buffer_storage
)中。