OpenGL:单独线程上的 glClientWaitSync

use*_*931 5 opengl multithreading synchronization

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

A:避免让 GPU 在 DMA 过程完成之前渲染缓冲区对象:直接在 glUnmapBufferRange 之后,在主线程上调用

GLsync uploadSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
glFlush();
glWaitSync(uploadSync, 0, GL_TIMEOUT_IGNORED);
Run Code Online (Sandbox Code Playgroud)

B:避免在 GPU 完成渲染之前从工作线程写入缓冲区:在 glDrawElements 之后直接调用主线程

GLsync renderSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
Run Code Online (Sandbox Code Playgroud)

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

glClientWaitSync(renderSync,0,100000000);
...start writing to the mapped pointer
Run Code Online (Sandbox Code Playgroud)

1:我的显式同步方法正确吗?

2:第二种情况该如何处理?我想在工作线程中等待(我不想让我的主线程停止),但我无法从工作线程发出 glCommands。除了 gl 调用之外,还有其他方法可以检查 GLsync 是否已发出信号吗?

Jan*_*egg 2

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

\n
\n

在主线程上运行:

\n
GLsync renderSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\nglFlush();\n
Run Code Online (Sandbox Code Playgroud)\n
\n

然后

\n
\n

在工作线程上运行:

\n
glClientWaitSync(renderSync,0,100000000);\n
Run Code Online (Sandbox Code Playgroud)\n
\n

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

\n
\n

4.1.2 信令

\n

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

\n
\n