I spent the last three weeks or so bringing VideoVenture into the 21st century, upgrading from old-style OpenGL 1.1 to a more modern architecture. My self-imposed goal is to make the engine compatible with Core Profile or OpenGL ES 2.0 by avoiding deprecated features. I'm still a long way off from that goal but I'm closer than before and made practical gains along the way.
The first step along the road was OpenGL 1.5, replacing all immediate-mode draw calls (glBegin, glEnd, glVertex, glNormal, glColor, glTexCoord, and friends) with buffer objects and array-draw calls (glDrawArrays, glDrawElements, and so forth). I focused my initial efforts on DrawList world-entity rendering, which ended in disappointment. The new style imposed a noticeable performance drag, losing to immediate mode by 10-40% depending on how I did it. I also found it all too easy to crash the graphics system, often ending up a dozen levels deep in a call stacks in another thread. The
Windows 7 WOW64 AVX exception bug certainly didn't help.
Draw calls seemed to be stalling while waiting for geometry to upload so I added a render queue to defer them to the end of the frame. That definitely helped, cutting the penalty to less than 10%. I figured I would just have to live with it. The big breakthrough came this past weekend after switching everything else to the new style. After weeks of being measurably slower I finally managed to beat OpenGL 1.1 by 5-10% on my desktop machine--no small feat with Nvidia's OpenGL driver. Then I ran it on my laptop and got a 3x speedup with the integrated GPU (600+ FPS vs. ~200 FPS). Apparently, the reputation of Intel's graphics driver is well-deserved...
Last night, I discovered that these gains are very fragile. Attempting to "cutting out the middle man" by submitting geometry directly to the vertex and index buffers incurred a 30-40% performance penalty so I abandoned that approach immediately. I had a similar issue with Battlezone 1.5, where lock and unlock consumed 40% of the total execution time until I stored geometry in a buffer and copied it all at once.
I need to prune the variant code paths since they all have worse performance or simply don't work. Then I need to clean up the public interface since the current version makes babies cry, dogs howl, and paint peel.
The next step will be OpenGL 2.0, adding support for shaders. My early attempts suffered even worse performance penalties than switching to buffers, cutting frame rate by a third. Unfortunately, I managed to break shader support while rewriting the rendering system. The game currently crashes if I try to enable them.