2
votes

I am sharing data between OpenGL and CUDA as follows:

GLuint buffer;
glGenBuffers(1, &buffer);
// Some image is bound to this texture buffer at some point.
...
cudaGraphicsResource_t cgr;
checkCudaErrors(cudaGraphicsGLRegisterBuffer(&cgr, 
                buffer, cudaGraphicsRegisterFlagsNone));
checkCudaErrors(cudaGraphicsMapResources(1, &cgr, 0));
uchar4 * device_ptr = 0;
size_t num_bytes;
checkCudaErrors(cudaGraphicsResourceGetMappedPointer(
               (void **)&device_ptr, &num_bytes, cgr));

This works fine and device_ptr is not a pointer to my CUDA memory. Now, at some point I want to resample this image using bilinear interpolation. It seems that the preferred way to do this in CUDA is map the device data to CUDA texture memory and then perform the interpolation using the tex2D calls.

Now, my question is that the imaging data already exists in OpenGL texture memory and I wonder if there is a way to avoid calling cudaBindTexture2D again and somehow use the OpenGL texture from within CUDA for this interpolation?

1
Why device_ptr is not a pointer to CUDA memory? After calling cudaGraphicsResourceGetMappedPointer, you should be able to treat it like a pointer to an array on device memory and launch a kernel to perform the interpolation. Once the interpolation is done, all you have to do is to call cudaGraphicsUnmapResources(1, &cgr, 0) for it to be displayed by OpenGL. - mty
Sure but can I use it to perform texture interpolation using tex2D calls? Do I need to map it to a texture like regular CUDA memory to do the interpolation? - Luca

1 Answers

7
votes

Yes you can directly read/write opengl texture with tex2D.

  1. Initialize graphic ressource

    struct cudaGraphicsResource *vbo_res;
    cudaGraphicsGLRegisterImage(&vbo_res, gl_buffer,gl_target, cudaGraphicsRegisterFlagsSurfaceLoadStore);
    
  2. Map ressource to array (every frame)

    cudaArray *array;
    cudaGraphicsMapResources(1, &vbo_res, 0);
    cudaGraphicsSubResourceGetMappedArray(&array, vbo_res, 0,0);
    
  3. Bind texture to array

    texture<uchar4, cudaTextureType2D, cudaReadModeNormalizedFloat> texRef;
    cudaBindTextureToArray(texRef, (cudaArray *)array));
    texRef.filterMode = cudaFilterModeLinear;
    

Note:

If texRef resides in global memory it can then be accessed in a cuda kernel with float4 rgba = tex2D( texRef, u,v);