Finally let’s talk a little about this engine that we created so far. The main advantage is that we have a modular architecture and is very easy for us to add a new modules into our scene. It’s like plug and play. I think that this architecture is super easy to follow and should give you a good start. Unfortunately the engine is not finished and we will continue to add new features in chapters to come. We can’t stay in NDC space forever :).
Problems with this architecture:
1. The Rendering Loop
A big problem with this architecture is the drawing loop. We are using a “naive approach” to render our models. Changing the shader program is a super expensive task and we should sort our models in some way to minimize OpenGL calls. For example we have a quad and a triangle and they use the same shader program. It’s much better if we call this program once and then draw all models (which are tied to this program). Imagine that you have 1000 different models tied to one shader. Changing the shader after each model will bend you GPU in half even the high-end ones. 🙂
Every OpenGL API call has a cost due to validation and hazard checks and some CPU cycles required to call the driver. To reduce this driver overhead it’s better to have less API calls.
To address the less driver overhead a few initiatives were taken by various companies. Apple started the “Metal API”. AMD started the “Mantle API”. Microsoft with the latest DX12. When Valve ported L4D1 from DX to OpenGL they worked with AMD, Intel and nVidia. These OpenGL hardware implementers pioneered and championed a movement called AZDO (Approaching Zero Driver Overhead.)
The Khronos group noticed there was a mass consensus from all sorts of companies in various industries. AMD donated the work they had done with Mantle; the Khronos group at this years GDC (2015) adopted it and is finalizing the specifications for Vulkan where the desktop version of OpenGL 4.x and the embedded version of OpenGL ES are unified and simplified !
Here is a partial list of who’s on board with Vulkan — never before have so many companies from across a wide discipline of the various industries been so unified towards a graphics API.
It’s probably a good thing in C++ land that the 2D graphics “Cairo” API proposal for standard C++ was rejected in 2014.
- Vulkan: https://www.khronos.org/vulkan
- Vulkan: https://www.youtube.com/watch?v=qKbtrVEhaw8
- Cool presentation about Vulkan: https://www.khronos.org/assets/uploads/developers/library/2015-gdc/Valve-Vulkan-Session-GDC_Mar15.pdf
2. STL library
In this architecture we abused of STL map. I already told you in the previous article why STL can be bad in game development. Big companies avoid STL for AAA games or even smaller games and implement their own libraries. In this architecture it doesn’t matter that much. This architecture will be used to present some graphics techniques and STL can help us save some time. Of course it doesn’t mean that you can’t modify and replace STL for your needs.
- Ubisoft Montreal doesn’t use STL, Exceptions, or RTTI. https://www.youtube.com/watch?
3. Object Oriented Programming (OOP) vs Data Oriented Design (DOD)
If you are an experienced game programmer who has worked in the industry for some time and accidentally see this architecture, you’ll call Mike Acton; show him this engine and he will probably attempt to point out all of its design decisions that kill performance! :).
We treated all models as individual entities because we love OOP. This is great for now and for further chapter where we focus on rendering techniques even for small games, I don’t think that there are any issues with this.
However problems will appear later on, where you have tons and tons of objects with different behaviors, different memory sizes, lots of if-else statements, huge hierarchy tree, etc. If you know how CPU and memory are working behind you’ll know that lots of branch mispredictions and cache misses will appear. And OOP does not scale up in perfromance. Also it’s a little bit hard to parallelize the architecture. So instead of OOP we can use DOD.
So Data-Orientated Design is a design and architecture methodology where you:
- Favor composition over inheritance
- Flatten your hierarchy
- Know your Data
- Profile first, THEN chose your algorithm.
There are tons of posts on this subject on the Internet which explains better than me what’s with the DOD pattern:
- Great exmaples here: http://gamedevelopment.tutsplus.com/articles/what-is-data-oriented-game-engine-design–cms-21052
- Another great examples: http://gamesfromwithin.com/data-oriented-design
- This guy is amazing : https://molecularmusings.wordpress.com/2013/05/02/adventures-in-data-oriented-design-part-3a-ownership/
Reddit’s game wiki has a section on DOD if you want to read more.
Mike Acton is the master of DOD and has a fantastic C++ talk.
The classical introduction to DOD is Tony Albrecht’s “Pitfalls of Object Oriented Programming”: www.slideshare.net/roycelu/
pitfalls-of- objectorientedprogramminggcap0 9
Of course this doesn’t mean that game developers don’t use OOP anymore or games don’t use OOP. OOP is used but with extra care especially where speed is required. For example the layers where I prepared initialization for OpenGL and the layers for Managers are fine.
In the end I’m not saying that we should throw this engine on the window because it’s not perfect. This architecture is a start and I’ll use it for next tutorials and of course we will try to improve it and make it better. Any feedback on this little rendering/game engine would be wonderful so feel free to drop us your thoughts in the comment section below. See ya in chapter 2 🙂
You can also find the code on GitHub: https://github.com/SergiuCraitoiu1/Basic_Game_Engine