OpenGL:glClientWaitSync在单独的线程上

时间:2015-11-10 22:16:02

标签: multithreading opengl synchronization

我使用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调用?

1 个答案:

答案 0 :(得分:2)

您可以做的是在工作线程中创建一个OpenGL上下文,然后与主线程共享它。下一个:

  

在主线程上运行:

     

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

然后

  

在工作线程上运行:

     

glClientWaitSync(renderSync,0,100000000);

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

  

4.1.2信令

     

脚注3 :在等待在另一个上下文的命令流中发出的fence命令完成时,SYNC_FLUSH_COMMANDS_BIT定义的简单刷新行为将无济于事。阻止围栏同步对象的应用程序必须采取其他步骤,以确保发出相应fence命令的上下文已将该命令刷新到图形   管道