我想在渲染过程中渲染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缓冲区纹理的正确方法是什么?
答案 0 :(得分:4)
OpenGL上下文与创建它们的进程相关联。您不能在进程之间共享CUDA映射的OpenGL对象,因为OpenGL上下文排序是数据的“所有者”,当您将其映射到CUDA时,您只是将其借出。 OpenGL在幕后进行了大量的簿记和更高级别的管理。
OpenGL中存在某些内部结构,并且在使用OpenGL CUDA互操作时必须遵守约束。例如,您不能主动使用当前映射到CUDA的OpenGL对象作为数据源或目标。例如,对glTexImage2D
或glBufferData
的调用可以重复使用前面的ID,但使用与不同内部ID相关联的不同缓冲区。 glTexSubImage2D
和glBufferSubData
可能需要创建原位副本以满足同步点要求等。如果某个OpenGL状态跟踪器无法访问的进程确实将其内存填满,那么事情就会破裂。
通常的OpenGL CUDA互操作序列是
现在你必须做的是,创建一个在进程之间共享的代理内存区域,而不是OpenGL对象的进程间映射。在使用OpenGL执行某些操作后,将OpenGL对象映射到CUDA,使用cudaMemcpy将数据复制到代理内存中并取消绑定OpenGL对象。