Who the fuck uses OpenGL in 2021?
Many devs do (e.g. i do use it all the time). The issue isn't OpenGL, which can certainly do way more advanced graphics than the mix between Doom and Quake graphics this game has.
As you can see in this grab from running the game with MSI Afterburner it barely uses the CPU (7%) or GPU (10%):
I decided to check out the game under a profiler i wrote recently (meant for profiling Free Pascal programs but it can be used with any executable - you just wont get any symbols, etc, just summaries from in which DLL or EXE time was spent on) and i noticed something:
Most of the time is spent in AMD's OpenGL driver and MSVBVM60.DLL, which is the Visual Basic 6 runtime. Also some decent time is spent in the game's own executable.
So i decided to check out why is so much time spent there. I mean, ok, i had a hunch - too much time in the runtime itself (meaning not much time spent in the game's own executable)
and too much time in the OpenGL driver sounds like the game is making a lot of calls. I loaded the Math001.dll (which is basically the engine) in Ghidra and i found some questionable calls (pretty much everything seems to go through a couple "draw primitive" calls), but to be sure that is the issue i also ran the game using APITrace and...
First of all,
61833 calls! That is a lot of calls (to give you an idea, one of the higher calls for Hedon is around 5500 and even Ion Fury does around 22000 or so calls - but Ion Fury also draws a crapton of stuff). More importantly many of these calls are redundant, e.g. it disables vertex attrib arrays right before enabling them again and resends data without need (e.g. that matrix uniform 5 is set to the same identity matrix over and over every few triangles it draws). Also all geometry drawn is sent anew instead of being stored (at least the static bits) to the GPU memory (Ion Fury for example does a lot of draw calls but level geometry is already stored on the GPU as a buffer) and A TON of these draw calls do not actually contribute to the final frame at all.
So basically that is the issue: the engine is making a ton of unnecessary draw calls, it doesn't reuse existing state and it always sends all geometry anew every time it needs to draw something. Writing a state manager and batching calls whose output wouldn't affect the final frame if they are reordered (e.g. all opaque zbuffered geometry can be easily reordered) should improve performance dramatically.
When i wrote
Post Apocalyptic Petra's initial OpenGL backend i did it in the simplest way possible (which basically meant a crapton of calls
per triangle - i didn't think much about since the game was originally software rendered anyway) and got around 100fps on my PC, though i didn't notice it initially. Once i noticed it, i thought to try and optimize it a bit (i had a brand new 165Hz monitor) since 100fps on a modern PC for barely PS1 graphics is eh, so i wrote a state tracker and batcher and even with AMD's suboptimal OpenGL Windows driver the performance jumped to ~2000 FPS. This took me an afternoon or so, though obviously the engine is very simple and i don't know what sort of functionality that 001 engine's renderer has. But regardless, this sort of functionality should improve performance a lot even for 2D games.