CUDA-OpenGL Interoperability Accessing all layers of OpenGL array texture in CUDA

Hi all,

I’m just wondering if anyone has any experience using CUDA-OpenGL interoperability, specifically with accessing all layers of a GL_TEXTURE_2D_ARRAY texture in CUDA.

What I’ve done so far is, I created the layered texture in OpenGL, register it using cudaGraphicsGLRegisterImage() with GL_TEXTURE_2D_ARRAY target. When I want to use it I map it using cudaGraphicsMapResources() and then get access to the cudaArray* using cudaGraphicsSubResourceGetMappedArray, specifying 0 for both the array index and the mipmap level.

This set up seems to be working. The issue I’m having is that I only seem to be able to access the base level of the array texture (I guess from specifying 0 for the array index?). Is it possible to be able to access all layers from within the kernel using a bound texture reference?

I assume this is possible because the sample simpleLayeredTexture creates 3D cudaArray which is bound to a texture reference of type cudaTextureType2DLayered and it can access all layers in the kernel.

Since both the simpleLayeredTexture sample and my code are binding the cudaArray* to the texture reference of the same type, I can only think of the cudaGraphicsSubResourceGetMappedArray() call as the one causing the issue. Is there any other way of getting a cudaArray* to the array texture?

texture<float4, cudaTextureType2DLayered, cudaReadModeElementType> texture_reference;

cudaGraphicsResource_t hemicube_resource;

Gluint render_texture_array;

glGenTextures(1, &render_texture_array);

glBindTexture(GL_TEXTURE_2D_ARRAY, render_texture_array);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, internal_format, texture_width, texture_height, texture_depth, 0, format, type, NULL);

cudaError_t status = cudaSuccess;

status = cudaGraphicsGLRegisterImage(&texture_resource, render_texture_array, GL_TEXTURE_2D_ARRAY, cudaGraphicsMapFlagsReadOnly);

// Render to the render_texture_array

cudaError_t status = cudaGraphicsMapResources(1, &texture_resource, 0);

assert(status == cudaSuccess);

cudaArray* texture_array = NULL;

status = cudaGraphicsSubResourceGetMappedArray(&texture_array, texture_resource, 0, 0);

assert(status == NULL);

cudaChannelFormatDesc channel_description = cudaCreateChannelDescHalf4();

cudaError_t status = cudaBindTextureToArray(texture_reference, texture_array, channel_description);

assert(status == cudaSuccess);

// Launch kernel

cudaError_t status = cudaUnbindTexture(texture_reference);

assert(status == cudaSuccess);

status = cudaGraphicsUnmapResources(1, &hemicube_resource, 0);

assert(status == cudaSuccess);

Thank you

Surya

Did you solve this problem?
Did anyone know if it is possible to map the whole texture array to be used by cuda, instead of just one texture layer?

Thanks

Hi Bob,

I found a work around to be able to access all layers of the texture array. What I’ve done is still use the cudaGraphicsSubResourceGetMappedArray() and bind a texture reference for each layer. Then in the kernel I have a function to sample the right texture reference based on the group index, in this case I used a switch case statement.

I’ve read in another post, it’s possible to create an array of function pointer, one function to access each texture reference. I think the main advantage of this is that there’s no conditional statement in the kernel, which should make it faster, but I haven’t tried it. In my case, the texture array is limited to 8 layers, so it’s not too bad. If there’s more layers I think the function pointer array would be better.

Hope it helps.

Surya