WPF DirectX Cuda Interop

May 17, 2014 at 10:00 PM
I'm sorry to say that I've been working on this on and off for several weeks now thinking that if I keep coming back to it, I will eventually figure it out...but this hasn't worked for me as of yet. I started using ManagedCuda a few months ago and have had great success with it. I'm using it to process images in various ways with incredible efficiency...until it comes to displaying the images. Currently, I read a image (byte array) from a camera, load it into a CudaDeviceVariable<byte> m_d_InputImage, run a cuda kernel against it, where the results are stored in CudaDeviceVariable<byte> m_d_OutputImage. Then I unload m_d_OutputImage and then copy to a WriteableBitmapEx object which is assigned as the source for an Image control. Works great, but lots of wasted moving around of the data.
I have no experience with DirectX, but I know that an interop to a D3DImage control is probably the fastest solution. I've studied your FluidsWPF example (with SlimDX), but quickly get lost in all the fluid physics stuff thats going on and can't seem to filter out what I'd need to do just to get my m_d_OutputImage displayed on the D3DImage control. Is there a simple example of how to do this somewhere? Or can you point me in the right direction?

I can live with what I have, but would really like to take full advantage of the GPU in this way. Regardless, thank you for providing ManagedCUDA! It has thus far been an excellent tool for me.
Coordinator
May 18, 2014 at 2:13 PM
Sorry, I don’t know of a direct example doing this. But I can point you in the right direction:
  1. You’ll need to know the fundamental basics of DirectX like projection matrix, device context, textures, vertices and indices, etc. Just google for “DirectX 9 introduction” and you’ll find a lot. Doesn’t matter if it’s a C++ or C# tutorial, you only need to get the ideas behind DirectX... (I guess DirectX 9 is best for this use case, as device handling is simpler as in Direct 10/11),
  2. Once you have this basic understanding, you’ll create a square or rectangle out of two triangles and a texture. This texture will be you image. Also for this step you’ll find many samples to get the texture on the triangles.
  3. Interop with Cuda: a texture in DirectX has a counterpart in CUDA which is a CudaArray. Do the interop magic to get a reference to the texture and either copy the CudaDeviceVariable to it (which is fast as it is a device to device copy) or directly write to the CudaArray using surface references / surface objects inside your kernel. For the interop stuff you can use the Fluids sample.
But before you wonder too much, Fluids doesn’t render an image in Cuda, all it does manipulating hundreds of spikes/dots and DirectX is used to render an image of them.

Hope it helps!