Dynamic Buffer Templates in D3D11

Published October 13, 2012
Advertisement
Last time, I described a few of the new 'immediate' style rendering classes that I have recently added to Hieroglyph 3. Since then, I have refactored some of the common code used in these classes into a handy set of template classes. I have found them very useful already, so I thought I would describe them here. To get started, we'll quickly discuss what design I started out with, and then discuss what I have now.

The Setup
Hieroglyph 3 uses the concept of a PipelineExecutorDX11 as the interface used to configure the D3D11 rendering pipeline input (through the Input Assembler) and subsequently how to execute the pipeline (via an appropriate draw call). These operations are distinct from the rest of the pipeline configuration (which is handled through a material class) and the pipeline output configuration (which is handled through a 'view' class). Once this concept is encapsulated, it becomes really simple to develop new rendering techniques. For example, trying something out that uses instanced rendering, or an indirect rendering method is quite easy and there is almost no risk of breaking other functionality since you just have to swap out the pipeline executor instance.

By having an object perform the Input Assembler configuration for you, you are essentially letting it perform the mapping between an a renderable object's representation and putting into the pipeline. With this in mind, it probably makes sense to have the same object own whatever buffer resources are going to be used in the implementation of that draw call. Single or multiple vertex buffers, an index buffer, or whatever other type of buffer (like an arguments buffer for indirect rendering) you are going to use should all be owned by the class that is going to use them to configure the pipeline and ultimately do a draw call on them.

Where I was
With this in mind, I implemented three different pipeline executor classes that performed various types of draw calls for my immediate rendering functionality. One used a single vertex buffer, one used a vertex and index buffer, and one used two vertex buffers and an index buffer. While doing this, I found myself copying the code that was used to manage the contents of the buffers. This was a sure sign that I could refactor this code into a reusable component, especially considering that I would be creating other pipeline executors in the future.

When it comes to vertex buffers, you essentially have to create a buffer resource and specify if you want the buffer to be dynamic (i.e. CPU accessible) or not. Then you fill the buffer with data and provide a corresponding input layout and away you go. Since I wanted a simple interface to add vertices to my buffer, I provided a system memory copy of the buffer that can be manipulated by the user. That copy is later loaded into a mapped vertex buffer and used for rendering.

Where I am Now
To keep the interface easy to use, I wanted to be able to add one vertex at a time. However, I wanted this reusable component to be able to handle multiple types of vertices, especially the types that I don't even know about right now. So I came to the conclusion that this component would be a template class, allowing me to provide a simple addVertex( T vertex ) method. Also, dealing with the system memory copy of the classes was also quite easy. The template class covers the management of the buffer, and the template argument provides the custom vertex layout and size - all quite convenient.

The only issue that I encountered was that I couldn't automatically provide an input layout for the template class. In the end, I decided this was ok since whatever class is instantiating the template would have to know what type of vertex it was requesting anyway, so the owner of the template class would need to provide the input layout. In my design, this means that the pipeline executor instantiates the template and creates the corresponding input layout - effectively providing everything that it needs to get its job done.

Wrapping It Up
In the end, the addition of these template classes greatly reduced the amount of code for the pipeline executor classes, commonized their buffer management code (good for maintenance and debugging), and reduces the amount of time needed to create a new one. All of these are good things, so if they sound good to you too, go check out the Hieroglyph code base!

A Personal Note
I also received my Microsoft MVP Award for DirectX in 2012 on October 1st. I am very grateful to have the chance to continue on as an MVP awardee, so thanks to Microsoft for continuing their recognition program!
1 likes 2 comments

Comments

Burnt_Fyr
Congrats on being an MVP again! I've been heavily reading your book in preparation for my eventual move to DX11 from DX9. Speaking of which, the last time I was at the h3 site, I did not find a snapshot of the codebase as it was at the time of the books printing. IIRC you said that you would be putting a link on your main page( as I suggested about a year ago). Your move zink.
October 15, 2012 08:52 PM
Jason Z
Good call :) I went back and checked to see where the code was when the book hit, and I wrote a small wiki entry (with a link from the front page) to discuss the issue. If you are interested, take a look [url="http://hieroglyph3.codeplex.com/wikipage?title=Getting%20the%20codebase%20from%20Practical%20Rendering%20and%20Computation%20with%20Direct3D%2011&referringTitle=Documentation"]here[/url]. Thanks again for reminding me!

Thanks for the flowers - I am genuinely happy to have gotten renewed again, and hope to live up to the award! Especially with all the Win8 stuff that is now here, I think there is lots of work to do...
October 26, 2012 09:44 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement