In this blog post, I will share a C++ AMP implementation of a fractal generator, rendering 4 dimensional Quaternion Julia fractals. I’ll show you screenshots of the app, then we’ll dive into the code, and then I’ll share a pointer of where you can get the Visual Studio project.
The original sample was written using DirectCompute by Jan Vlietinck. The shader code in the DirectCompute version was a port of a Cg version written by Keenan Crane. I have ported the DirectCompute portions to use C++ AMP.
The application presents an animation of Julia fractals by changing the generation parameters by a small amount at each time quantum. Here are some snapshots of the fractal animation.
- Use the mouse wheel to zoom in and out
- Hold down the left mouse button to select and rotate the fractal
- Use ‘space’ to turn the animation ‘on’ or ‘off’
You can also change the parameters to the Julia fractal during the animation.
- Use w/x to increase/decrease the x component of the quaternion constant (MuC.x)
- Use q/z to increase/decrease the y component of the quaternion constant (MuC.y)
- Use a/d to increase/decrease the z component of the quaternion constant (MuC.z)
- Use e/c to increase/decrease the w component of the quaternion constant (MuC.w)
- Use -/+ to increase/decrease the precision of intersection (epsilon)
Porting to C++ AMP
The porting of this sample was achieved using the guide C++ AMP for DirectCompute programmer. The main win32 application is implemented in QJulia4D.cpp.
We first start by removing most of the boilerplate code to create constant buffers, resource views and to compile and launch the shader since this is not needed when using C++ AMP. C++ AMP containers automatically take care of creating the buffers and resource views on the accelerator. Constants can be directly captured into the parallel_for_each. This takes care of creating and setting the required constant buffers. Finally the code to explicitly compile and launch the shader is not required when using C++ AMP. This is automatically taken care by the call to parallel_for_each.
The shader was ported to use C++ AMP in julia4DAMP.cpp. The compute shader is replaced with a parallel_for_each call as shown below.
Original Compute Shader:
C++ AMP kernel:
Any exceptions from launch and execution of the shader, including TDR, are bubbled up to the user using C++ AMP runtime exceptions. The rest of the shader code remains unchanged in this port. Note that you can also use other C++ constructs when porting since C++ AMP allows us to express the kernel using C++ with some restrictions. You are welcome to try this out, I just did a vanilla port instead of writing the code in C++ the way I would if I was writing it from scratch.
And that’s it! We now have a sample that is written entirely in C++.
As always, please feel free to share your thoughts and ask questions below or in our MSDN concurrency forum.