我遇到了 Sync Objects 的概念,并决定对其进行测试。它们似乎按预期工作,但我目前的测试用例有限。
什么是确保这些同步对象按预期执行作为同步 CPU 渲染线程与 GPU 的方法的适当测试?
这方面的一个示例用例是“ Hook ”到视频游戏的 OpenGL 上下文中的视频捕获程序,或使用 OpenGL 的其他一些应用程序。
最佳答案
我觉得你的示例用例很可疑。
FRAPS 是一个“ Hook ”到 OpenGL 应用程序中以捕获视频的程序示例,它的做法非常不同。 FRAPS 不是强制 CPU-GPU 同步,而是在调用 SwapBuffers (...)
之前立即插入一个异步像素缓冲区读取。然后它将尝试在 下一次 调用 SwapBuffers (...)
时读取结果,而不是在结果可用时停止第一次来。 对于 FRAPS,延迟无关紧要。
然而,即使没有异步 PBO 读取,FRAPS 也没有理由使用同步对象。 glReadPixels (...)
和类似的命令将隐式等待所有挂起的命令完成,然后再读取结果并将控制权返回给 CPU。这确实会损害性能,但 GL 会自动进行同步。
同步对象最简单的用例是同时运行两个或多个渲染上下文。
在 OpenGL 中,您可以跨上下文共享某些资源(包括同步对象),但每个上下文的命令流是完全独立的,并且不强制执行任何类型的同步。因此,如果您要在一个上下文中将数据上传到顶点缓冲区并在另一个上下文中使用它,您将在生产者(上传上下文)中插入栅栏同步并等待它在消费者(绘制上下文)中发出信号。这将确保在上传完成之前不会执行绘制命令 - 如果所有命令都是从同一上下文发出的,GL 实际上会在不使用同步对象的情况下保证这一点。
我刚才给出的例子不需要CPU-GPU同步(只有GPU-GPU),但是你可以使用glClientWaitSync(...)
来阻止你的调用如果您遇到 CPU-GPU 有意义的情况,则线程直到上传完成。
下面是一些伪代码来评估同步对象的有效性:
线程 1:
glBindBuffer (GL_ARRAY_BUFFER, vbo);
glBufferSubData (GL_ARRAY_BUFFER, 0, 4096*4096, foo); // Upload a 16 MiB buffer
GLsync ready =
glFenceSync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
线程 0:
glBindBuffer (GL_ARRAY_BUFFER, vbo);
// Try with and without synchronization
if (sync) {
// Wait up to 1 second for the upload to finish
glClientWaitSync (ready, GL_SYNC_FLUSH_COMMANDS_BIT, 1000000000UL);
}
// Ordinarily mapping a buffer would wait for everything else to finish,
// we need to eliminate that behavior (GL_MAP_UNSYNCHRONIZED_BIT) for this test.
void* bar =
glMapBufferRange (GL_ARRAY_BUFFER, 0, 4096*4096, GL_MAP_UNSYNCHRONIZED_BIT);
// When `sync` is true and the sync object is working, bar should be identical to foo
关于c++ - ARB_sync 和适当的测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28231455/