Game Development Community

Get better framerates with this quick fix to glfinish()

by Stephen Lujan · in Torque Game Engine · 04/06/2007 (1:15 am) · 12 replies

Note I'm using the standard TGE 1.5 not the cvs version. I'm not sure if this matters.

Anyways, for some reason the profiler told me that glFinish was eating up 25% of my time while using opengl. It turns out that glFinish seems completely unnecessary in opengl. Its needed in direct 3d still for accurate gui rendering, but according to my computer glFinish consumed only a tiny bit of time using direct 3d. So i did the obvious thing here and got noticeable improvement in my framerates.

in engine/gui/core/guiCanvas.cc do a search for glfinish()
this is the only call to the function that's not commented out
#if defined(TORQUE_OS_WIN32)
   PROFILE_START(glFinish);
   glFinish(); // This was changed to work with the D3D layer -pw 
   PROFILE_END();
#endif

to fix things i replaced the above code with this...

#if defined(TORQUE_OS_WIN32)
   PROFILE_START(glFinish);
   //stephen new: this slows down but maintains gui in d3d so...
   if (dStrcmp(Con::getVariable( "$pref::Video::displayDevice" ), "D3D") == 0)
   {
		glFinish(); // This was changed to work with the D3D layer -pw 
		// Con::printf("glFinish!");//debugging check
	}
   PROFILE_END();
#endif

It seems almost too easy, if I've done anything wrong let me know, but the only difference I see is about a 30% increase in frame rate on my computer!

EDIT: Sorry about the extra thread. My computer spazzed a bit. Hopefully it will get deleted in a shortly.

#1
04/06/2007 (2:01 am)
I wonder if this would have any sense on the Mac OpenGL code - supposing it does exists.
#2
04/06/2007 (2:10 am)
Just tested this on my build.
running a fairly modded engine myself, including stencil buffered outlines on all items and players.
getting 25 at the lowest, after this change getting 26 at the lowest.
so not much change on my system, but for others it might work better, would like to find out though.
#3
04/06/2007 (2:26 am)
@jake
You were testing using opengl right? I forgot to mention in the thread heading that this is only a fix for opengl. Also my platform is really old which could explain why it was spending a quarter of its time on glfinish(). Plus I think it has a lot to do with gui rendering and i noticed that when i had a lot of complex guis open in during a mission glfinish() consumed an even greater chunk of my frame times. If you have a computer that's way faster than mine and used very few gui's you shouldn't see a difference anywhere near as big as mine.

try using the profiler with and without the change and look at what percentage glFinish is using up.
just enter in the console
profilerEnable(true);
then
profilerDump();

On my computer it went from about 25% to 0.026% or something like that.

@Stephan
I have no idea if this will effect anything other than opengl as I don't know much about the renderer really. I actually found a mention about disabling glfinish in someone's plan file as an optimization and I unfortunately forgot who. Anyways I did some investigation and confirmed what a time killer it was in opengl and that opengl worked fine without it and direct 3d didn't. I also tried glflush instead but this also produced a few gui rendering errors in D3D. The only usage of glfinish in the entire engine was preceded by by "#if defined(TORQUE_OS_WIN32)" so its a safe bet this only effects windows platforms.
#4
04/06/2007 (3:13 am)
I tried this on two different builds that I have.

The first being a stock TGE 1.5 and the second being a modified version of TGE 1.5 (being used in a game that is on schedule to be released at the end of the month -- a little shameless self promotion doesn't hurt).

The stock version saw a boost of 10 to 20 frames at times.

The modified version saw a boost of only 3 - 6 frames at best, but the loading time was reduced a little further then what I already have it down to. The loading probably went from 7 seconds to about 3.

I also remember the optimization about removing the glFinish calls, but when I tried it I had mixed results. This seems to work better in my opinion.

Nice work.

Has anyone tried this on TGE 1.5.1?? I'm tempted to try it out and see what happens.
#5
04/06/2007 (4:45 am)
1.5.1 - is would improve.
I have similar "fix" in my custom build (TGE1.5+AFX+TGB all-in-one), and there are improvements. Actually, it seen to improve most when you have lots of gui elements.
Before fix, "glFinish" was about 19%, after - 0.04% in profiler (and about +5FPS - from 45 to 50FPS when most "complicated" GUI is opened - inventory with lots of items).
#6
04/06/2007 (5:39 am)
Just a note incase someone would want to use the D3D wrapper in Torque with this change. glFinish is required for it, or else your GUI's will sort incorrectly.
#7
04/06/2007 (5:46 am)
Interesting find Stephen..

@Stephan: on TGE 1.3 I would think this will help the Mac too, since the conditional compilation for Win32 wasn't there, i.e. the Mac as well as Win32 was doing glFinish().
#8
04/06/2007 (8:17 am)
Makes sense -- glFinish blocks until the current drawing state catches up.

glFinish man page

Thanks for catching this!
#9
04/06/2007 (9:20 am)
@stefan

I thought the D3D wrapper was pretty much covered by the line I added?

if (dStrcmp(Con::getVariable( "$pref::Video::displayDevice" ), "D3D") == 0)
#10
05/20/2007 (12:11 pm)
FYI, I added a commented-out solution for this in TGE 1.5.2 so you can just uncomment the if statement if you want this behaviour.
#11
05/20/2007 (2:17 pm)
@Stephen Lujan:

It's possible, I didn't check your code.. but simply removing glFinish () will break the D3D wrapper. Sorting will be incorrect, I think. If your code works around it then all well :)

Edit: Doh I see it now. Sorry.
#12
05/30/2007 (5:59 am)
Nice catch Stephen!

We've got a good 20%+ improvement on our frame rates after implementing the change :)