我有以下管道:
现在,问题在于在阶段4和5之间同步数据。以下是我尝试过的同步解决方案。
glFlush - 不能真正起作用,因为它不能保证所有命令执行的完整性。
glFinish - 这个有效。但不建议这样做,因为它最终确定了提交给驱动程序的所有命令。
ARB_sync Here it is said建议不要这样做,因为它会严重影响性能。
glMemoryBarrier 这个很有意思。但它根本行不通。
以下是代码示例:
glMemoryBarrier(GL_ALL_BARRIER_BITS);
还尝试过:
glTextureBarrierNV()
代码执行如下:
//rendered into the fbo...
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindImageTexture(imageUnit1, fboTex, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA8);
glBindImageTexture(imageUnit2, imageTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8));
glDispatchCompute(16, 16, 1);
glFinish(); // <-- must sync here,otherwise cuda buffer doesn't receive all the data
//cuda maps the image to CUDA buffer here..
此外,在启动计算之前,我尝试从上下文中取消绑定FBO和取消绑定纹理,我甚至尝试在它们之间设置glMemoryBarrier
之后启动一个计算,并从第一次计算启动到目标图像CUDA。仍然没有同步。 (嗯,这是有道理的,因为两个计算也彼此不同步)
在计算着色器阶段之后。它没有同步!只有当我用glFinish
替换时,或者用任何其他完全停止管道的操作。
例如,像glMapBuffer()
一样。
我应该只使用glFinish(),还是我在这里遗漏了什么?
为什么glMemoryBarrier()在CUDA接管控制之前不同步计算着色器工作?
更新
我想稍微重构这个问题,因为原来的问题已经很久了。然而,即使使用最新的CUDA和视频编解码器SDK(NVENC),问题仍然存在。所以,我不关心为什么glMemoryBarrier
不同步。我想知道的是:
如果可以将OpenGL计算着色器执行完成与CUDA对该共享资源的使用同步,而不会拖延整个渲染管道,这就是我的OpenGL图像。
如果答案为“是”,那该怎么办?
答案 0 :(得分:2)
我知道这是一个古老的问题,但是是否有可怜的灵魂偶然发现了这个问题...
首先,原因glMemoryBarrier
不起作用:它需要 OpenGL驱动程序将障碍插入管线。 CUDA根本不关心OpenGL管道。
第二,glFinish
之外的另一种方法是将glFenceSync
与glClientWaitSync
结合使用:
....
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindImageTexture(imageUnit1, fboTex, 0, GL_FALSE, 0, GL_READ_ONLY,GL_RGBA8);
glBindImageTexture(imageUnit2, imageTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8));
glDispatchCompute(16, 16, 1);
GLsync fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
... other work you might want to do that does not impact the buffer...
GLenum res = glClientWaitSync(fence, GL_SYNC_FLUSH_COMMANDS_BIT, timeoutInNs);
if(res == GL_TIMEOUT_EXPIRED || res == GL_WAIT_FAILED) {
...handle timeouts and failures
}
cudaGraphicsMapResources(1, &gfxResource, stream);
...
这将导致CPU阻塞,直到所有命令执行完GPU为止。这包括内存传输和计算操作。
不幸的是,无法告诉CUDA在OpenGL内存屏障/栅栏上等待。如果您确实需要额外的异步性,则必须切换到DirectX 12,CUDA为此支持DirectX 12导入篱笆/信号量并等待并通过cuImportExternalSemaphore
,{{1 }}和cuWaitExternalSemaphoresAsync
。