pioneerspacesim/pioneer — pull request #2572 by robn (2013-12-11 05:58:57+00:00)
Title: OpenGL matrix state optimisation

From @fluffyfreak in #2541.

>...having [implemented the profiler] I plowed head first into optimising what I found and that was that the old GUI, a and a few other places, were still calling the `glGet*` functions all over the place. This causes a sync event with the GPU and drivers and generally stalls things - this varies massively between systems and GPU manufacturers drivers so your mileage may vary drastically.
>
> It meant for example that `Gui::Screen::EnterOrtho` was taking 88% of our CPU time on my nVidia 650M... alone.
>
> Dealing with these means tracking all of our `glPushMatri`x, `glPopMatrix`, `glTranslate`, `glRotate` (none), `glScale`, `glMatrixMode`, `glLoadIdentity`, `glLoadMatrix` calls. I think that's all of them!
>
> I've created an interface for all of these in the Renderer class and implemented it within the RendererLegacy class. Then I changed everything over to calling the Renderer implementations rather than OpenGLs.
>
> I'm still getting some minor hiccups but they're on the order of ~0.5 seconds rather than the ~15 seconds I was having. If you'd like to test the before and after then hyperspace to Canti (3, 5, -1) and head for Ibarrez which should be about 1014 AU distant. You'll have to watch it for quite a while but I got the enormous stutters (~15 secs) with alarming regularity.

My initial reaction upon seeing this the first time was to reject immediately because it adds all this GL-specific state control to the renderer. The intent is to eventually have a state-free renderer, with each draw call providing a complete GPU state which can then be sorted and batched appropriately. So clearly adding more state is a backward step.

I had to change my tune a little on that after trying it. The improvements are significant. I think for such obvious benefits a relatively contained set of state functions is acceptable.

I've done a bunch of tidying up to get it compiling cleanly and to make it match our conventions. The only substantial change is to remove the hand-rolled stack and just use `std::stack` instead.

I think this is safe to merge. There are no obvious regressions that I can see from some light testing, and I'm satisfied the code isn't more intrusive that it needs to be.