DEV Community

Cover image for Learning DirectX 12 - Part 3 Initialization Code
NoticeableSmeh
NoticeableSmeh

Posted on

Learning DirectX 12 - Part 3 Initialization Code

I will be using the demo code provided with the book in order to progress in my learning at a relatively quick rate. However, I do plan on returning later on and rewriting this entire thing to really make it my own by the end of this series. I will probably be doing that with SDL, because I like SDL and I know it better than windows programming.

The books source code provides sample framework which hides a lot of boilerplate code that is pretty standard when setting DirectX12 up. This is hidden for us in the file d3dApp. I will be covering how the setup with that code works as I feel that will be great for learning. Although I wont cover every line of code because that would be impossible.

So I will walk through the initialization code essentially linearly and explain each step of the way what happens in each part until we get to the end result which is an empty window with some ImGUI elements.

This is the main way entry point of the program. This code here is more related to windows api and creating applications with windows, the important part here is the initialize function and the run function on the MyApp instance, which is ourApp :)

Going through our MyApp class we call the D3Dapp::initialize (we inherited D3DApp to our MyApp as a form of wrapper for boilerplate stuff). This D3DApp helps with a lot of boilerplate but is quite long so I wont cover it entirely just the really really important bits.

We call the functions to initiate both the window of our application and actually initialize Direct3D here finally.


Here were creating and utilizing a smart pointer for our 3D hardware AKA our graphics card.

This function create the command objects needed for the command process from the cpu to the gpu.

Creating first a command queue which can execute all GPU commands.

Second created hre is the command allocator this serves as a sort of basis of memory in which the our command list created thirdly here us to present itself in our command queue.

A more concrete way of looking at it:

Lets just summarize the difference between these three things, were actually creating these things here in the opposite order of how they would be used.

A command list is an (or multiple) instruction of what the GPU should do. "Draw a box" for example.

A command allocator are what the instructions are written on. It is literal memory that we have access to. We need our command list written down on something tangible, that is what the command allocator is. It allocated memory to record the command list to.

The Command queue is the actual queue, as a person standing in line waiting for their turn, our command lists wait in line for it to be executed.

Think of it this way. We have a command to tell someone to do, this person is very far away so we can't just shout the command at them, so we need to send them a letter. The command we have is "Draw a horse".

So we record our command "Draw a horse" (This is the command list) and record it onto a piece of paper (Command allocator) and we send it of to a person (GPU). This person receives a lot of letters, so people wait in line (Command queue) to give their letter to this person (GPU).

Here were creating the swap chain, the swapchain is what we use to switch between the back buffer and front. Important to note here is that we send in our commandQueue in this argument so its important this stuff is done in the right order.

Descriptor heaps
This is actually very cleverly named because it is exactly what its named. Its heaps of contained information of the related acronyms. RTV (Render target views) tells the GPU where to draw the pixels or vertices, DSV (Depth stencil Views) cover the order in which to draw them.

Lets cover the draw function now. This is a long one so bare with me.

Here we have another big old data heap collection:

CBV - Constant Buffer View: This is very useful as a sort of container for "global variables" accessible for your shaders. Lets say you want to pass the coordinates of a cameras position to a shader, you can put that data in a constant buffer and create a CBV.

SRV - Shader resource view: These are typically for reading textures. If you want to map an image on a 3D model, the sader reads that image through the SRV.

UAV - Unordered access view: This are both read and write buffers. These allow shaders to read and write to a buffer at the same time. Useful for certain things that I do not understand yet.

As you can see these things are more directly related to shader programming and will make more sense later on.

We start of the function by grabbing a reference to our heap we created earlier, the cbvSrvUav heap that is. Then we wipe the old memory allocated on our Cmdlistallocator and same thing with our actual command list.

This is where I think it becomes increasingly obvious how DirectX12 is a state machine because when examining this code here it is very similar to how OpenGL works. You assign what descriptor heap to use then you assign what part of the render target is visible and then what pixels should be draw on the screen. It is really a step by step process.

Finally with the resourceBarrier we are telling the GPU what buffer we want to be written on. We issue a command via our command list to clear the screeen to one colour. Clear depth aswell while we are at it

Transitioning the back buffer to the front buffer and then finally presenting this buffer.

At the end there is a helper function defined in D3DApp that helps force the CPU to wait until the GPU finishes.

When we compile and finally run our application we will finally get this screen.

Really at this point I am very excited, I have probably spent upwards of 30-40 hours reading through taking notes on this book, trying to work through it and to really understand it deeply and finally actually having a window popup feels like a big reward.

See you in the next part we will tackle the chapter on the rendering pipeline!

Top comments (0)