Posted by Jason Z, 18 July 2010 · 160 views
In the first steps towards adding multithreading support into Hieroglyph (as discussed here) I have been quite busy with a major surgery on my renderer - and I'm beginning to make some good progress. I decided that I was going to split the functionality of my current renderer into three distinct section. Here's the split:
1. Resource Manager: Used to create and store resources (by resources I mean all D3D resources, including state objects). This roughly follows the device interface for D3D11.
2. Pipeline Manager: Used to manage the state of the pipeline. This includes setting states, knowing what the current state of the pipeline is, and manipulating resources (i.e. Map/Unmap). This roughly follows the context interface for D3D11.
3. Parameter Manager: Used to provide a text based name to a particular resource type. This allows the program to attach constant buffers, shader resources, unordered access views, etc... to a text name which can then be used by the renderer to supply them to a shader with a corresponding name. This object is more or less 'glue' and doesn't follow any D3D objects.
After digging into the renderer, I was surprised to find out that my sub-conscious has been preparing this change for quite some time [grin]... All of the renderer methods that I took out and put into the resource manager were of the sort: Create*** and Get***. In contrast, all the methods that went to the pipeline manager used a Bind*** and Unbind*** naming convention. And finally, all the parameter manager methods used a Set*** Get*** paradigm. I guess its good to have someone working behind the scenes that knows what is going on [grin]!
Anyhow, this is by far the biggest change I've ever made to the renderer. Its always a little scary when I am making changes to the renderer that makes everything stop compiling... there's always an uncertainty that you are doing the wrong thing and you could be costing yourself a bunch of time. However, this doesn't appear to be one of those times - the surgery has been successfully completed, and the patient appears to be doing well.
All together, I have to say that this splitting of responsibilities has really been somewhat of an epiphany. By breaking up the renderer, I can now create pipeline manager objects with immediate or deferred contexts. I can also swap out my parameter manager for a new one to see if I can speed it up, and then if I want to go back I can just use the original one. If I want to log which parameters are being set for a given frame, I can just push a button and dynamically swap out the parameter system to a debug logging instance and record it all, then switch back to the regular one without even having to recompile... It really seems to me like a logical progression of the renderer, and I'm really glad that I'm going down this road. Once all the stitches are removed, I'll be making the jump to adding multithreading support as well - so it will be a busy few days ahead!
One final thought about this change: this will make it much easier to support multiple renderers in the future. By explicitly creating a parameter system that doesn't have direct ties to the objects within the renderer, it can very easily be reused with another API, a ray-tracer, or whatever. Also, the pipeline manager can easily wrap a different pipeline - its object oriented, so its easy to swap out... The general concept of my renderer doesn't depend on any particular feature of DX11, so I am happy to have a bit more clarity about having options going forward :)