ARB_sync 和适当的测试

ARB_sync and proper testing

我偶然发现了 Sync Objects 的概念,并决定对其进行测试。它们似乎按预期工作,但我目前的测试用例有限。

什么是确保这些同步对象按预期执行作为同步 CPU 渲染线程与 GPU 的方法的适当测试?

一个示例用例是 "hook" 进入视频游戏的 OpenGL 上下文的视频捕获程序,或使用 OpenGL 的其他应用程序。

我觉得你的示例用例有点可疑。

FRAPS 是 "hooks" 进入 OpenGL 应用程序以捕获视频的程序示例,它的做法非常不同。 FRAPS 不是强制执行 CPU-GPU 同步,而是在调用 SwapBuffers (...) 之前立即插入一个异步像素缓冲区读取。然后它将尝试读取结果 next 时间 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