2015-11-10 94 views
3

我正在使用glMapBufferRange和GL_MAP_UNSYNCHRONIZED_BIT来映射缓冲区对象。然后,我将返回的指针传递给工作线程以异步计算新顶点。对象是双重缓冲的,所以我可以渲染一个对象而另一个被写入。使用GL_MAP_UNSYNCHRONIZED_BIT给了我明显更好的性能(主要是因为glUnmapBuffer更快地返回),但是我得到了一些视觉工件(尽管有双重缓冲) - 所以我假设GPU在DMA上传仍在进行时开始渲染,或者工作线程开始写入顶点太早。 如果我理解glFenceSync,glWaitSync和glClientWaitSync正确的,那么我应该解决以下方式将这些问题:OpenGL:单独线程上的glClientWaitSync

答:避免在GPU渲染缓存对象的DMA过程完成之前:glUnmapBufferRange后直接 ,通话在主线程

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

B:避免在工作者线程写入缓冲区中的GPU呈现完毕之前:glDrawElements后 照片直接,调用主线程

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呼叫?

+0

您可以为上传线程使用单独的GL上下文,该上下文线程将所有对象与主要上下文共享以进行绘制。在这种情况下,您也可以共享同步对象,并且可以通过这种方式同步这些线程。 – derhass

+0

我理解GLsync对象的方式是它们没有绑定到上下文,所以我猜这些上下文甚至不需要共享。如果可能的话,我想避免为工作线程分开上下文。在Android上,似乎可以通过eglDupNativeFenceFDANDROID从GLsync生成本地栅栏 - 如果Windows也有类似的东西,或者与平台无关,那就太棒了。 – user1282931

+0

同步对象与GL上下文(或多个共享的上下文)相关联的对象与任何其他GL对象一样,所以如果没有共享上下文,您就无法离开。 – derhass

回答

1

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

运行:

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

那么工作线程

运行:

glClientWaitSync(renderSync,0,100000000);

主线程上的glFlush非常重要,否则您可能会无限等待。又见OpenGL docs

4.1.2信令

脚注3:等待在另一种情况下的命令流发出的围篱命令完成时SYNC_FLUSH_COMMANDS_BIT定义的简单冲洗行为将不利于。阻挡栅栏同步对象的应用程序必须执行额外的步骤,以确保发出相应栅栏命令的上下文已将该命令刷新到管道图形处理器。

+0

我想避免为工作线程设置单独的上下文,但似乎没有办法绕过它 – user1282931