This contains a lot of technical programmer nonsense. TL;DR? For some reason I had 4 game executables and 2 sets of data. After some refactoring I now have 1 of each.
A while back I did some testing on DirectX 11 vs Directx 9. The takeaway there was that DirectX 11 performed much better on newer systems and it was worth having two versions of the game – though at this point I’m curious how many DirectX 9 only users are out there…
The bad part of this, is that the way I originally wrote the code was to have a fully different version of the game. I treated it as a separate platform – as if I was implementing a port to another OS. This made sense when I did it. It got the code ready for supporting multiple platforms, but for a distribution across windows PCs, it’s not ideal.
There was a DirectX 9 executable, and a DirectX 11 executable. Both versions have their own copies of all the game data as well. All the data is precompiled for fast loading, and DirectX 9 uses some repeated data and index buffer tricks to implement fast instancing. DirectX 11 doesn’t need this. The vertex and pixel shaders are also different between shader model 2 and shader model 4.
To compound the multiple exe problem, throughout development I’ve also compiled 32-bit and 64-bit versions of the game. I think this promotes good programming practices, sets up for easier porting to other platforms, and makes my game engine easily reusable in the situation where it actually uses more than 2G or 3G of RAM.
So that’s 4 exes total:
While a lot of people that play this game would be tech savvy enough to click on the best choice for their system, I felt like there are a lot of users that just want to click on the game icon and get the best experience automatically for their system. The solution? I can think of two. One is to have a simple 32-bit ‘launcher’ program that determines what the system can handle, and start the right version of the game. The other is to put the rendering interface into DLLs and load the best one.
I didn’t really like the first solution, because while it would be fast to implement, I’d still have two copies of the game data. But I was dreading doing the second. Dreading it like I know it’s going to waste two weeks of time, and introduce 50 annoying bugs. It’s something that needs to be done though, so I started some experiments to see how bad it would be to implement. (I had scheduled 1 week to deal with this issue….)
Luckily it wasn’t so bad and I finished it over a weekend.
Already having separated the rendering code to support DirectX 9 and DirectX 11, it was just a matter of code reorganization – taking the respective functionality out of the engine code, putting them in two different DLLs, and dealing with converting a few static libraries into shared DLLs. Then I wrote an common interface that calls the right functions depending on which renderer is active. At video initialization time, the engine can see which DLLs it can load – if DirectX 11 can’t load then only DirectX 9 is supported. If both can load, then the user can pick which rendering interface to use, but it defaults to DirectX 11.
Sharing the data was also easyish. Most all the game data is the identical, and what’s different just stores both copies of the data in the different formats. The renderer determines which set of data to load. I could have just stored the raw data and converted on load, but I hate to increase loading time.
And since I really just moved code around, there won’t be many bugs. None reported yet, anyway.
On a happy note, since I had already implemented a way to restart the graphics system at runtime, I could use that same code to switch rendering APIs during the game. Anyone that encounters bad stalls and hardware issues with the DirectX 11 renderer can at anytime switch to DirectX 9. You don’t even have to restart the game to switch – just head to the options menu, pick DirectX 9, wait 2 seconds, and the game continues. This is very non-useful for most people, but it made me smile that it worked without too much effort – and it gives me a really easy way to test performance between different graphics rendering interfaces.
Because the rendering calls are really separated now, it should now be easy to implement an OpenGL renderer and test performance of it versus DirectX 9 and DirectX 11. And with the newly announced AMD Mantle, I have a perfect test bed for trying it out and seeing what performance gains it could give. Wait – no no no, I’m done with feature creep at the moment. Maybe later.
So back to my original intention – this work brought me back to two executables:
The obvious choice here is to just ship Banished-x32.exe. The worst I’ve seen the game take memorywise is 320M of ram using DirectX 9. DirectX 11 takes significantly less. Clearly I’m not even close to the limit of a 32-bit memory space. And while sometimes it appears that the 64-bit version runs at something like 0.25% faster than the 32-bit version, I can’t really validate it since it’s not always true.
So in the end, one executable to deal ship with instead of 4.
Now back to working on the in-game tutorial!