gpt4 book ai didi

opengl - 内存屏障无法在计算阶段和 CUDA 的数据访问之间同步

转载 作者:行者123 更新时间:2023-12-04 12:46:22 26 4
gpt4 key购买 nike

我有以下管道:

  • 渲染到自定义 FBO 的纹理附件。
  • 将该纹理附件绑定(bind)为图像。
  • 运行计算着色器,使用 imageLoad/Store 从上面的图像中采样。
  • 将结果写入 SSBO 或图像。
  • 将 SSBO(或图像)映射为 CUDA CUgraphicsResource并使用 CUDA 处理来自该缓冲区的数据。

  • 现在,问题在于在第 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..

    此外,我尝试在启动计算之前从上下文中取消绑定(bind) FBO 和取消绑定(bind)纹理,我什至尝试使用 glMemoryBarrier 依次启动一个计算在它们之间设置,并从第一次计算启动中获取目标图像到 CUDA。仍然没有同步。 (嗯,这是有道理的,因为两个计算也彼此不同步)

    在计算着色器阶段之后。不同步!只有当我用 glFinish 替换时,或任何其他完全停止管道的操作。
    点赞 glMapBuffer() , 例如。

    那么我应该只使用glFinish(),还是我在这里遗漏了什么?
    为什么 glMemoryBarrier() 在 CUDA 接管控制之前不同步计算着色器工作?


    更新

    我想稍微重构一下这个问题,因为原来的问题已经很老了。尽管如此,即使使用最新的 CUDA 和视频编解码器 SDK (NVENC),问题仍然存在。所以,我不在乎为什么 glMemoryBarrier不同步。我想知道的是:
  • 如果可以将 OpenGL 计算着色器执行完成与 CUDA 对该共享资源的使用同步,而不会停止整个渲染管道,在我的情况下是 OpenGL 图像。
  • 如果答案是"is",那该怎么做?
  • 最佳答案

    我知道这是一个老问题,但如果有任何可怜的灵魂偶然发现这个......

    一、原因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 支持导入栅栏/信号量并等待以及通过 cuImportExternalSemaphore 从 CUDA 流向它们发出信号, cuWaitExternalSemaphoresAsync , 和 cuSignalExternalSemaphoresAsync .

    关于opengl - 内存屏障无法在计算阶段和 CUDA 的数据访问之间同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37569065/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com