Data Oriented Design Changed How I Build Game Engines
Much of my free time goes into developing game dev tools. Recently, I've gotten serious about making my engine production-ready.
I initially used raylib to speed up my progress but as I increasingly want to add multithreading to my engine, raylib's higher level design left something to be desired. Thus I embarked into my vulkan journey.
Soon, I will do a write-up on the renderer's development but this blog post comes before all that. This blog post is about the incredible realization I had during this process.
The realization
The job of the tech in a game engine is to translate the intentions of the game designer into a game.
This is the greatest mindshift I had since I started working on games. This shift finally made Data Oriented Design click for me.
For example, if I want to support multiple renderers in my engine:
- Vulkan for windows and linux
- DX12 for windows and XBox
- Metal for Mac
- GNMX for PS4/5
I have two options, I could go with an object oriented approach or a data oriented one.
Object Oriented
In an Object Oriented manner I could have an IRenderer interface with pure virtual methods for each renderer to implement.
While this is simple, I have found it to be hard to implement cleanly due to the differences in capabilities between the graphics APIs we are abstracting over.
This can, for instance, lead to problems when attempting to write an optimized Vulkan renderer if your interface was originally designed for an OpenGL based renderer.
Data Oriented
In this approach we first define what the data our rendering engine consumes will look like. We define structs like:
- Vertex Array
- Index Array
- Mesh
- Texture
- Light
- Etc...
The multiple rendering engines will still implement an interface but this time it is much simplified compared to the Object Oriented interface, for example:
class IRenderer { public: virtual GLFWwindow* initWindow() = 0; virtual void init() = 0; virtual void update() = 0; virtual void cleanup() = 0; }
Each implementation of the renderer will, then, only need to concern itself with providing a consistent result given a set of data.
This effort can further be helped by using a shading language such as SLang that is capable to target multiple APIs with one language.
The Benefits of Data Oriented Design
Data oriented design and its benefits have been discussed ad nauseam but there are two I'd like to highlight:
- Decoupling the designer's intentions from the technology
- Allowing flexibility in the underlying engine
These two benefits are very much related to one another. Its because the designer's intentions are decoupled from the technology that we, as engine and tools devs, have the flexibility to update the engine without fear.
This is the approach I will take in writing my engine ence forward. Now, I'll need a while to refactor the entire engine.
Thanks for the read!