【发布时间】:2013-04-04 23:35:02
【问题描述】:
我的应用程序将从 openGL 获取渲染结果(深度图和渲染的 2D 图像信息) 到 CUDA 进行处理。
我做的一种方法是通过 glReadPixel(..., image_array_HOST/depth_array_Host)* 检索图像/深度图,然后将 image_HOST/depth_HOST 传递给 CUDA 通过 cudaMemcpy(..., cudaMemcpyHostToDevice)。我已经完成了这部分,虽然这听起来是多余的。 (从 GPU>CPU>GPU)。 *image_array_HOST/depth_array_Host 是我在主机上定义的数组。
另一种方法是使用openGLcuda interpol。 第一步是在 openGL 中创建一个缓冲区,然后将图像/深度信息传递给该像素缓冲区。 还注册了一个 cuda 令牌并将其链接到该缓冲区。然后将 CUDA 上的矩阵链接到该 cuda 令牌。 (据我所知,似乎没有直接的方法将像素缓冲区链接到 cuda 矩阵,应该有一个 cudatoken 供 openGL 识别。如果我错了,请纠正我。)
这部分我也做过。它认为它应该相当有效,因为 CUDA 正在处理的数据是 没有转移到任何地方,而只是转移到它在openGL上的位置。它是设备(GPU)内部的数据处理。
但是,我从第二种方法获得的花费时间甚至(略)长于第一种方法(GPU>CPU>GPU)。 这真的让我很困惑。
我不确定我是否遗漏了任何部分,或者我没有以有效的方式做到这一点。
我也不确定的一件事是 glReadPixel(...,*data)。 在我的理解中,如果 *data 是指向 HOST 上内存的指针,那么它将执行从 GPU>CPU 传输的数据。 如果 *data=0,并且绑定了一个缓冲区,那么数据将被传输到该缓冲区,它应该是 GPU>GPU 的东西。
也许其他方法可以比 glReadPixel(..,0) 更有效地传递数据。
希望有人能解释我的问题。
以下是我的代码:
--
// openGL has finished its rendering, and the data are all save in the openGL. It is ready to go.
...
// declare one pointer and memory location on cuda for later use.
float *depth_map_Device;
cudaMalloc((void**) &depth_map_Device, sizeof(float) * size);
// inititate cuda<>openGL
cudaGLSetGLDevice(0);
// generate a buffer, and link the cuda token to it -- buffer <>cuda token
GLuint gl_pbo;
cudaGraphicsResource_t cudaToken;
size_t data_size = sizeof(float)*number_data; // number_data is defined beforehand
void *data = malloc(data_size);
glGenBuffers(1, &gl_pbo);
glBindBuffer(GL_ARRAY_BUFFER, gl_pbo);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
cudaGraphicsGLRegisterBuffer(&cudaToken, gl_pbo, cudaGraphicsMapFlagsNone); // now there is a link between gl_buffer and cudaResource
free(data);
// now it start to map(link) the data on buffer to cuda
glBindBuffer(GL_PIXEL_PACK_BUFFER, gl_pbo);
glReadPixels(0, 0, width, height, GL_RED, GL_FLOAT, 0);
// map the rendered data to buffer, since it is glReadPixels(..,0), it should be still fast? (GPU>GPU)
// width & height are defined beforehand. It can be GL_DEPTH_COMPONENT or others as well, just an example here.
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, gl_pbo);
cudaGraphicsMapResources(1, &cudaToken, 0); // let cufaResource which has a link to gl_buffer to the the current CUDA windows
cudaGraphicsResourceGetMappedPointer((void **)&depth_map_Device, &data_size, cudaToken); // transfer data
cudaGraphicsUnmapResources(1, &cudaToken, 0); // unmap it, for the next round
// CUDA kernel
my_kernel <<<block_number, thread_number>>> (...,depth_map_Device,...);
【问题讨论】:
-
由于没有人回复,我再次来到这里,希望有人能看到。非常感谢