Isolate Rendering Modules
Example: slice_ui_gl1.1.dll slice_ui_gl3.1.dll slice_ui_vk1.1.dll slice_ui_cpu.dll
When initializing, a function bool Usable ()
within each module can check whether the system's graphics drivers provide adequate support. If this is false, then simply unload the module and fall back to another one, or if there are no other modules to fall back to then show an error message telling the user it's impossible to continue (if a CPU renderer is implemented, maybe this could still fail if a window can't be created to put the output into, etc.).
When building the modules, they can be provided with only the headers for the API level they are targeting (for example GL 3.1 UI renderer would have GLAD for GL 3.1 core, and GL 1.1 UI renderer would have GLAD for GL 1.1 core, so accidentally using unavailable functions will quickly and reliably result in a compiler error).
It should be possible to pass arguments to the engine to force a specific renderer to be used, for example if a user has issues with the game on their graphics drivers, or during development to test that the CPU renderer works even though GL 1.1 is very widely supported.