【问题标题】:CUDA GL interop - Reading mapped buffer texture from another processCUDA GL 互操作 - 从另一个进程读取映射的缓冲区纹理
【发布时间】:2014-06-21 05:47:00
【问题描述】:

我想在渲染进程中将某些东西渲染到 GL 缓冲区纹理,然后在另一个进程中通过 CUDA 读取它。目前我不希望将两个进程合并为一个。我的代码如下所示:

//Note: this code runs under Linux
int svMain();
int main() {
    //Tons of variable definitions vomited
    float* dptr;    //pointer to mapped device mem
    size_t map_size;    //size of mapped mem
    cudaGraphicsResource_t cuda_res;
    cudaIpcMemHandle_t memhdl;
    if( !fork() )
        return svMain();
    else {
        initGL();
        genGLBufferTextureAndUploadSomeData();
        cudaGLSetGLDevice(0);
        cudaGraphicsGLRegisterBuffer( &cuda_res, buf_id, cudaGraphicsRegisterFlagsNone );
        cudaGraphicsMapResources( 1, &cuda_res, &map_size, 0 );
        cudaGraphicsGetMappedPointer( (void**)&dptr, &map_size, cuda_res );
        cudaIpcGetMemHandle( &memhdl, dptr );
        sendToServerProcViaSocket( memhdl );
    }
    return 0;
}
int svMain() {
    cudaIpcMemHandle_t memhdl;
    float* dptr;
    cudaGLSetGLDevice(0);
    recvFromClientProc( memhdl );
    if( cudaSuccess != cudaIpcOpenMemHandle( (void**)&dptr, memhdl ) ) {
        fprintf( stderr, "SV: cannot open CUDA mem handle!\n" );
        return -1;
    } else
        launchSomeKernel( dptr );
    return 0;
}

问题是cudaIpcOpenMemHandle 总是返回错误。但是,如果我通过cudaMalloc(不涉及 GL)分配设备内存,然后发送相应的内存句柄,上面的代码就可以工作。如果我在一个进程中完成所有工作(涉及 GL,不涉及 IPC),它也可以工作。

我的操作系统是 Ubuntu 13.04 LTS

CUDA 工具包中的“simpleIPC”示例在我的系统中运行良好。 这是我的设备查询输出的一部分:

Device 0: "GeForce GT 650M"
  CUDA Driver Version / Runtime Version          6.0 / 5.5
  CUDA Capability Major/Minor version number:    3.0
  Total amount of global memory:                 2048 MBytes (2147287040 bytes)
  ( 2) Multiprocessors, (192) CUDA Cores/MP:     384 CUDA Cores
  Texture alignment:                             512 bytes
  Concurrent copy and kernel execution:          Yes with 1 copy engine(s)
  Run time limit on kernels:                     Yes
  Integrated GPU sharing Host Memory:            No
  Support host page-locked memory mapping:       Yes
  Alignment requirement for Surfaces:            Yes
  Device has ECC support:                        Disabled
  Device supports Unified Addressing (UVA):      Yes
  Device PCI Bus ID / PCI location ID:           1 / 0
  Compute Mode:
     < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

那么,从另一个进程访问 GL 缓冲区纹理的正确方法是什么?

【问题讨论】:

  • 您隐含地假设 OpenGL 缓冲区在进程之间是可移植的。是什么让您认为是这样的?
  • 根据this,GL 缓冲区可以在上下文之间共享(嗯,我不太确定进程间可移植性)。我只是不明白为什么 CUDA IPC 设施只适用于通过cudaMalloc 分配的内存而不是 GL 缓冲区。

标签: opengl cuda ipc


【解决方案1】:

OpenGL 上下文与创建它们的进程相关联。您不能在进程之间共享 CUDA 映射的 OpenGL 对象,因为 OpenGL 上下文是数据的“所有者”,当您将其映射到 CUDA 时,您只是将其借出。 OpenGL 在幕后做了很多簿记和更高级别的管理。

在使用 OpenGL CUDA 互操作时必须遵守 OpenGL 中的某些内部结构和约束。例如,您不得主动使用当前映射到 CUDA 的 OpenGL 对象作为数据源或目标。例如,对glTexImage2DglBufferData 的调用可能会重用正面ID,但会使用与不同内部ID 相关联的不同缓冲区。 glTexSubImage2DglBufferSubData 可能需要创建原位副本以满足同步点要求等。如果 OpenGL 状态跟踪器无法访问的某个进程填充了它的内存,事情就会中断。

通常的 OpenGL CUDA 互操作序列是

  1. 在 OpenGL 中做一些事情
  2. 在 OpenGL 中解除对象的活动使用
  3. 将对象映射到 CUDA
  4. 在 CUDA 中做点什么
  5. 从 CUDA 取消映射对象
  6. 回到 1

现在你必须做的是,创建一个在进程之间共享的代理内存区域,而不是 OpenGL 对象的进程间映射。使用 OpenGL 完成某些操作后,将 OpenGL 对象映射到 CUDA,使用 cudaMemcpy 将数据复制到代理内存中并取消绑定 OpenGL 对象。

【讨论】:

  • 感谢您的详细回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 2013-01-15
  • 2013-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多