Separating OpenGL rendering away from win32_handmade.cpp

HMH currently calls OpenGL functions in the platform code. I want these decoupled to ease porting, and benefit from hot code reloading. Basically, I want the platform to dictate as little of the actual rendering process as possible. This attitude is in alignment with the software renderer. Casey eventually moves the renderer between the game and platform, but that isn't actually related to the OpenGL rendering at all, unless I'm missing something important.

As an exercise I began to move these to the game code's translation unit. Obviously I cannot LoadLibrary() or GetProcAddress() without having access to those functions provided by the platform. I tried sending them as function pointers to Game.UpdateAndRender() but there's a linker problem being unable to resolve their symbols.

Because Casey hasn't already done this, I'm going to presume there's a good explanation why. Anyone know? Am I being silly here?

Which episodes does Casey elaborate on the whole compiling process / translation units business? I've seen them before but I think they're largely in the Q&A sections and so I can't hunt for them by searching titles.

Edited by Jesse on Reason: clarity
Well, to begin with, while you could pass LoadLibrary et al to the game as function pointers (not sure why you were getting a linker error, it was probably something else going on), I would point out that that would immediately make all the game code not be cross-platform because now it relies on passing a pointer to a Windows internal function. So if you were somehow going to go that route, you'd want to pass a generic library loading routine and a generic function loading routine that you implement with a known signature that then calls LoadLibrary on Windows, but other things on other platforms.

However, that too is a little risky, because what name do you pass to LoadLibrary? The dynamic libraries for the graphics layer will be different on different platforms, etc.

This is generally why rendering (and other hardware-dependent things) want to live in a middle layer between the platform code and the game code, because they typically do depend on something, even if that something is not the OS but rather the particular API (OpenGL or Vulkan, whatever).

If you want to allow these things to be hotloaded, I would recommend treating them as a separate translation unit, just like the game, and pass all the functions they need to them, etc.

- Casey
Hey Casey!

I was planning on eventually treating LoadLibrary and GetProcAddress more consciously platform agnostic. As you kind of said, the whole ordeal is awkward enough, so I thought I'd post to learn about alternatives. Heading towards the separate translation unit route was certainty part of the master plan. It was just that I thought integrating into the game would be easier to get right first, then pull into its own TU. I just don't see how making it its own TU simplifies the separating process. I'll keep trying though!

Thanks for responding! Love the series!

Edited by Jesse on