私のアプリケーションは、openGL からレンダリングされた結果 (深度マップとレンダリングされた 2D イメージ情報の両方) を CUDA に渡して処理します。
私が行った 1 つの方法は、glReadPixel(..., image_array_HOST/depth_array_Host)* でイメージ/深度マップを取得し、cudaMemcpy(..., cudaMemcpyHostToDevice) で image_HOST/depth_HOST を CUDA に渡すことです。冗長に聞こえますが、この部分は実行しました。(GPU>CPU>GPU から)。*image_array_HOST/depth_array_Host は、ホストで定義する配列です。
別の方法は、openGL<>cuda interpol を使用することです。最初のステップは、openGL で 1 つのバッファーを作成し、そのピクセル バッファーに画像/深度情報を渡すことです。また、1 つの cuda トークンが登録され、そのバッファーにリンクされます。次に、CUDA のマトリックスをその cuda トークンにリンクします。(私が知る限り、ピクセル バッファを cuda マトリックスにリンクする直接的な方法はないようです。openGL が認識する cudatoken が必要です。間違っている場合は修正してください。)
この部分もやりました。CUDA が処理しているデータはどこにも転送されず、openGL 上のどこにでも転送されるため、かなり効率的であると考えられました。デバイス(GPU)内部のデータ処理です。
ただし、2 番目の方法で得た所要時間は、最初の方法よりも (わずかに) 長くなります (GPU>CPU>GPU)。それは本当に私を混乱させます。
見逃した部分があるのか、それとも効率的な方法でやらなかったのかはわかりません。
私もよくわからないことの1つは、glReadPixel(...、* data)です。私の理解では、*data が HOST 上のメモリにリンクするポインタである場合、GPU>CPU からのデータ転送を行います。*data=0 で 1 つのバッファーがバインドされている場合、データはそのバッファーに転送され、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,...);