can't bind Surface to CudaArray obtained via Interop

I have an application that renders graphics using CUDA and displays them on Windows 7 via DX11. In CUDA 3.0, I accomplish this by rendering to a linear pixel array, then using cudaMemcpyToArray to copy the pixels to a DX11 render buffer (texture) that has been mapped to a CUDA Array. This works fine, but (1) is slow, and (2) requires interaction with the CPU to issue the copy command.

CUDA 3.1 adds the ability to bind a CUDA array to a Surface reference, which can be written directly, avoiding the memcpy. Unfortunately, only arrays allocated by cudaMallocArray with a special “cudaArraySurfaceLoadStore” flag appear to be eligible for Surface binding. In particular, attempting to bind an array obtained via cudaGraphicsSubResourceGetMappedArray returns cudaErrorInvalidValue. Is there any way to make the mapped array acceptable to the Surface binding code? Thanks!

In the code below, only the final assert fails…

[codebox]

// set up CUDA view of DX backbuffer on device

ID3D11Texture2D *backBuffer; // omitting initialization for brevity

D3D11_TEXTURE2D_DESC d;

backBuffer->GetDesc(&d);

int err;

cudaGraphicsResource *backBufferResource = NULL;

err = cudaGraphicsD3D11RegisterResource(&backBufferResource, backBuffer, cudaGraphicsRegisterFlagsNone);

assert(err == CUDA_SUCCESS);

cudaArray *backBufferCudaArray = NULL;

err = cudaGraphicsResourceSetMapFlags(backBufferResource, cudaGraphicsMapFlagsNone);

assert(err == CUDA_SUCCESS);

err = cudaGraphicsMapResources(1, &backBufferResource, (cudaStream_t)0);

assert(err == CUDA_SUCCESS);

err = cudaGraphicsSubResourceGetMappedArray(&backBufferCudaArray, backBufferResource, 0, 0);

assert(err == CUDA_SUCCESS);

struct cudaChannelFormatDesc chDesc = cudaCreateChannelDesc(8, 8, 8, 8, cudaChannelFormatKindUnsigned);

struct surfaceReference *drawingSurfaceReference;

err = cudaGetSurfaceReference((const struct surfaceReference **)&drawingSurfaceReference, “drawingSurface”);

assert(err == CUDA_SUCCESS);

// the following returns err=11

err= cudaBindSurfaceToArray(drawingSurfaceReference, backBufferCudaArray, &chDesc);

assert(err == CUDA_SUCCESS); [/codebox]

I’m pretty sure that this is a limitation of the current driver - it needs that “cudaArraySurfaceLoadStore” flag to be set when creating the array to use it with a surface. I’ll check.

Shouldn’t you be using Direct Compute? :)

I’m pretty sure that this is a limitation of the current driver - it needs that “cudaArraySurfaceLoadStore” flag to be set when creating the array to use it with a surface. I’ll check.

Shouldn’t you be using Direct Compute? :)

I’d be interested in writing to mapped arrays via Surfaces as well(mapped arrays from OpenGL textures, to be more specific).

Currently it is possible only to read OpenGL/Direct3D textures in Cuda without copy(by binding a Cuda texture to the mapped array).

I’d be interested in writing to mapped arrays via Surfaces as well(mapped arrays from OpenGL textures, to be more specific).

Currently it is possible only to read OpenGL/Direct3D textures in Cuda without copy(by binding a Cuda texture to the mapped array).

I stumble upon similar problems while changing from CUDA 2.3 to 3.1, using D3D9 though.

Previously, I used [font=“Courier New”]cudaD3D9ResourceGetMappedPointer()[/font] on a registered [font=“Courier New”]IDirect3DTexture9[/font] and wrote my kernel results into the memory returned by [font=“Courier New”]cudaD3D9ResourceGetMappedPointer()[/font]. Now I discovered that [font=“Courier New”]cudaGraphicsResourceGetMappedPointer()[/font] only works for buffer resources (and obviously NOT for textures). If I’m not mistaken, I need to use [font=“Courier New”]cudaGraphicsSubResourceGetMappedArray()[/font] instead.

But how do I use the obtained [font=“Courier New”]cudaArray[/font] for writing data?!?!

For now you have to write your data to (temporary) linear memory first, and then use cudaMemcpyToArray to transfer it to the mapped array(as vxRenderer said).

Thanks for the reply. And that’s necessary although 3.1 supports surface writes?

So, basically I need the memory twice, once created with cudaMallocPitch() or something and once comming from the D3D texture as cudaArray?

I stumbled upon the same problem just now: trying to cudaBindSurfaceToArray() with an array that was obtained through cudaGraphicsSubResourceGetMappedArray() yields an invalid parameter error. The graphics resource I’ve mapped is an OpenGL framebuffer with a renderbuffer attachment though.

Has there been any change in this issue, or is it still a driver limitation? I’m using driver version 260.99.

Now it should probably work using [font=“Courier New”]cudaGraphicsD3D11RegisterResource[/font] with [font=“Courier New”]cudaGraphicsRegisterFlagsSurfaceLoadStore[/font].