I was very upset when I had to remove this part of book during the page counts. Honestly, writing about all new features of DirectX 11.1 in just 146 pages was really hard, especially when the target audiences of our book were armatures and professionals.
In chapter 5 of DirectX 11.1 Game Programming book, I explained, what is C++AMP technology and how and when we can use it in our application, but for those who have’t read the book yet and unfamiliar with C++AMP technology, I going to demonstrate it in short sentences.
“C++ Amp or C++ Accelerated Massive Parallelism is a small extension library that enables heterogeneous computing, which brings “GPGPU” programming for developers by taking advantage of GPU. C++ AMP fairly looked like an extension. It is C++, not C, and is used for implementing data parallelism directly in C++, it also integrated with direct3D for accelerating your code, if the code cannot be run on GPUs, it will fall back onto CPUs.“
For getting more information about C++AMP, please check see this link out.
The following are some essential prerequisites that should be considered before developing an application using DirectX 11.2:
- The first important requirement is a personal computer or tablet running on Windows 8.1.
- You need to set up Microsoft Visual Studio Express 2013 for Windows 8.1 as a developer environment.
- Make sure you set up the Windows Software Development Kit (SDK) for Windows 8.1. The Windows SDK for Windows 8.1 contains headers, libraries, and tools that can be used when creating Windows 8.1 applications.
- Download the source code of this project which uploaded by me on MSDN Code Gallery.
In Chapter 05 of DirectX 11.1 Game Programming, my main concern was that C++AMP & Compute Shader results in good gains. Also I compare performances of both on Windows Store app. We learned how & when we must each technology.
Now let’s assume some collision detection on C++AMP:
- The data is on the CPU, so it has to be transferred to the GPU, if GPU is not available it has to fall back on the CPU.
- The commands will be queued in the GPU queue, and will be processed asynchronously, so it might take a full frame until the results are available.
- The results have to be transferred back to the CPU
In this case, the GPU can process the collisions faster than CPU, but transferring data back to the CPU might obtain bottleneck of your application. The results on CPU might be more quickly if you have a spare thread to do the computations, so make sure run your code on GPU when you think it is really the efficient way.
In this section, we are going to extend our collision detection with C++Amp, which means we can check more collision detection in one frame. We want to check collision between player’s spaceship and other spaceships, if collision happened, then player must go back to initial position.
Open “manager.cpp” from “Graphics\cpp” folder of the solution. Make sure get the project and source codes from here. Let’s take a look at the UpdateModels method of this class.
void Manager::UpdateModels( float time )
int size = this->models.size();
if (size == 0) return;
We stored position and rotation of models in vectors;
Furthermore, we stored three float number in "infos",
which are a random float number between "100" and "500",
a random angle between "0" and "360" degree and finally,
a random number between "0.005f" and "0.015f" which is
used for velocity.
array_view<XMFLOAT3, 1> p(size, this->positions);
array_view<XMFLOAT3, 1> r(size, this->rotations);
array_view<XMFLOAT3, 1> _infos(size, this->infos);
array_view<XMFLOAT4X4, 1> w(size, this->worlds);
We stored positions, rotations, information and
world matrices into "array_views".
#pragma region Create World Matrix
parallel_for_each(w.extent, [=](index<1> i) restrict(amp)
using namespace Concurrency::fast_math;
We want to move all spaceships around a circle,
except a player's spaceship.
The center of the circle located at the zero coordinate,
and radius is the value of infos[i].x.
if (i != 0)//If not player
//teta + velocity
_infos[i].y = fmodf(_infos[i].y + _infos[i].z, 360);
//Calculate position of each model
p[i].z = _infos[i].x * sin(_infos[i].y);
p[i].x = _infos[i].x * cos(_infos[i].y);
//Apply rotation for each model
r[i].y = _infos[i].y;
Before creating the world matrix, first calculate
shared mathematical functions. The following code
will show For calculating rotation we have Rx,Ry and Rz
which are rotation matrices around world X, Y and Z axis.
auto cosX = cos(r[i].x);
auto sinX = sin(r[i].x);
auto cosY = cos(r[i].y);
auto sinY = sin(r[i].y);
auto cosZ = cos(r[i].z);
auto sinZ = sin(r[i].z);
auto sinXY = sinX * sinY;
auto cosXsinY = cosX * sinY;
#pragma region Apply rotation
w[i]._11 = cosY * cosZ;
w[i]._12 = -cosY * sinZ;
w[i]._13 = sinY;
w[i]._21 = sinXY * cosZ + cosX * sinZ;
w[i]._22 = -sinXY * sinZ + cosX * cosZ;
w[i]._23 = -sinX * cosY;
w[i]._31 = -cosXsinY * cosZ + sinX * sinZ;
w[i]._32 = cosXsinY * sinZ + sinX * cosZ;
w[i]._33 = cosX * cosY;
Elements M14, M24 and M34 are vector of position of world matrix.
#pragma region Apply position
w[i]._14 = p[i].x;
w[i]._24 = p[i].y;
w[i]._34 = p[i].z;
w[i]._41 = w[i]._42 = w[i]._43 = 0;
w[i]._44 = 1;
Call "synchronize" method for synchronizing "array_view"
with related vector, and then check collision detections
#pragma region Check collisions
const float debounce = 10.0f;
float radius = this->models->Radius;
parallel_for_each(p.extent, [=](index<1> i) restrict(amp)
using namespace Concurrency::fast_math;
if (i == 0)//if is player
for ( int j = 1 ; j < size; j++)
// Check collision between player and others
auto normalVectorX = p[i].x - p[j].x;
auto normalVectorY = p[i].y - p[j].y;
auto normalVectorZ = p[i].z - p[j].z;
auto distance = fabsf(sqrt( powf(normalVectorX, 2) +
powf(normalVectorY, 2) + powf(normalVectorZ, 2)));
if (distance < (radius * 2) - debounce)
//Reset player position
p[i].x = p[i].y = p[i].z = 0;
When collision happened, we’ve reset the position of the player’s spaceship. the following image shows the result of project.
For getting more samples about C++AMP, make sure check this link.