多线程 – OpenGL:glClientWaitSync在单独的线程上

我使用glMapBufferRange和GL_MAP_UNSYNCHRONIZED_BIT来映射缓冲区对象.然后,我将返回的指针传递给工作线程,以异步计算新的顶点.对象是双重缓冲的,因此我可以渲染一个对象,而另一个对象被写入.使用GL_MAP_UNSYNCHRONIZED_BIT给了我明显更好的性能(主要是因为glUnmapBuffer更快返回),但我得到了一些视觉工件(尽管有双缓冲) – 所以我假设GPU在DMA上传仍在进行时开始渲染,或者工作线程太早开始写顶点.

如果我正确理解glFenceSync,glWaitSync和glClientWaitSync,那么我应该通过以下方式解决这些问题:

答:避免GPU在DMA过程完成之前呈现缓冲区对象:
直接在glUnmapBufferRange之后,调用主线程

GLsync uploadSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
glWaitSync(uploadSync, 0, GL_TIMEOUT_IGNORED);

B:避免在GPU完成呈现之前从工作线程写入缓冲区:
在glDrawElements之后的direclty,调用主线程

GLsync renderSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);

在工作线程上,就在开始将数据写入之前从glMapBufferRange返回的指针之前

glClientWaitSync(renderSync,0,100000000);
...start writing to the mapped pointer

1:我对显式同步的处理方法是否正确?

2:我该如何处理第二种情况?我想在工作线程中等待(我不想让我的主线程失速),但我无法从工作线程发出glCommands.还有另一种方法来检查GLsync是否已经发出信号而不是gl调用吗?

最佳答案 你可以做的是在工作线程中创建一个OpenGL上下文,然后与主线程共享它.下一个:

Run on the main thread:

GLsync renderSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();

然后

Run on the worker thread:

glClientWaitSync(renderSync,0,100000000);

主线程上的glFlush很重要,否则你可能会无限期等待.另见OpenGL docs

4.1.2 Signaling

Footnote 3: The simple flushing behavior defined by SYNC_FLUSH_COMMANDS_BIT will not help when waiting for a fence command issued in another context’s command stream to complete. Applications which block on a fence sync object must take additional steps to assure that the context from which the corresponding fence command was issued has flushed that command to the graphics
pipeline.

点赞