當處理較大數據量的時候,往往會用GPU進行運算,比如OpenGL或者CUDA。在實際的操作中,往往CUDA實現並行計算會比OpenGL更加方便,而OpenGL在進行后期渲染更具有優勢。由於CUDA中的運算結果存儲在GPU中,如果將數據download到CPU,然后再將CPU中的數據上傳到GPU,使用OpenGL進行渲染,中間的GPU與CPU的交互會很耗時,畢竟使用GPU的目的就是為了加速,這樣的數據傳輸會降低效率。
接下來簡要說一下如何使CUDA和OpenGL互操作來實現GPU中數據的交互傳輸,而不用通過主機的CPU。
一、首先是在OpenGL中聲明這樣一個buffer。
cudaGraphicsResource_t cudaBuffer;
然后將Buffer注冊給紋理texture(假定已經提前聲明一個紋理texture)
cudaGraphicsGLRegisterImage(&cudaBuffer, texture, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard);
二、好了,這樣我們只需要把CUDA計算出來的數據寫入cudaBuffer中就行了。如下:
利用Cuda中的兩個API設置cudaBuffer為映射Map,並將一個cuda數組cudaArray綁定到cudaBuffer。
cudaError_t err; err = cudaGraphicsMapResources(1, cudaBuffer, 0); err = cudaGraphicsSubResourceGetMappedArray(&cudaArray, cudaBuffer, 0, 0);
那么接下來的就是把數據寫入cudaArray中的事情了,假設我有一個數據指針pResult指向GPU中的一段內存,這段內存中保存的就是CUDA的運算結果(一幅4通道圖像),我只需要將其copy到cudaArray就行了。注意是cudaMemcpyDeviceToDevice,這個很快的。
創建cudaArray
uchar* cudaArray=NULL; cudaChannelFormatDesc cuDesc = cudaCreateChannelDesc<uchar4>(); cudaMallocArray(&cudaArray, &cuDesc, imgWidth, imgHeight);
將結果數據拷貝至cudaArray
err=cudaMemcpyToArray(cudaArray, 0, 0, pResult, imgWidth*imgHeight * sizeof(uchar4), cudaMemcpyDeviceToDevice);
copy完后要解除映射Map
cudaGraphicsUnmapResources(1, &cudaBuffer, 0);
這樣在OpenGL中就可以直接將buffer中的數據注冊到紋理然后進行渲染了,so easy~