Author Topic: [C++][OpenGL]VSync & framerate  (Read 13076 times)

0 Members and 1 Guest are viewing this topic.

Offline lucastar

  • C= 64
  • **
  • Posts: 50
  • Karma: 5
    • View Profile
[C++][OpenGL]VSync & framerate
« on: April 12, 2013 »
Hi again, i found a function on the internet that allows enabling or disabling VSync in OpenGL. The downside it's that it only works in Windows (because of the wgl stuff).
Here is the code:
Code: [Select]
void setVSync(bool sync)
{
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALPROC)( int );
PFNWGLSWAPINTERVALPROC wglSwapIntervalEXT = 0;

const char *extensions = (char*)glGetString( GL_EXTENSIONS );

if( strstr( extensions, "WGL_EXT_swap_control" ) == 0 )
{
return;
}
else
{
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALPROC)wglGetProcAddress( "wglSwapIntervalEXT" );

if( wglSwapIntervalEXT )
wglSwapIntervalEXT(sync);
}
}

If i enable VSync, framerate stays stable at 59.874...
I i dont, it goes to 6K.

My question is, which is the ideal framerate? It has to be enough to let us see everything without delay, but it has to synchronize the drawing too.

And why with VSync framerate goes down to 59.9 and not to 60 - 63?

Offline Knurz

  • Atari ST
  • ***
  • Posts: 121
  • Karma: 25
    • View Profile
    • GitHub Repository
Re: [C++][OpenGL]VSync & framerate
« Reply #1 on: April 12, 2013 »
Hi.

If you want to enable VSync with Linux/GLX you can try this:
Code: [Select]
In Linux / GLX
Use the GLX_EXT_swap_control extension to control swap interval. Check the GLX-specific extensions string via glXQueryExtensionsString() to verify that the extension is actually present.
The extension provides glXSwapIntervalEXT(), which also directly specifies the swap interval. glXSwapIntervalEXT(1) is used to enable vsync; glXSwapIntervalEXT(0) to disable vsync.

But this works only if you disabled the option that the driver should take care of vsync (or you have statically enabled it).
So you can't override the settings in the driver with wglSwapIntervalEXT.

I've found another solution for me which is independent of the settings of the driver but it's not that accurate (in fact you cannot query the driver if the screen is fully drawn). I'm using a high-precision timer (win32) and I'm only drawing something if a 1/60 sec. time passed (~0.0167 ms). The advantage of this is if someone has statically disabled the vsync in his driver your program isn't going crazy because he has no real timer anymore.

There are several well documentated code-snippets around here so have a look at them.

Maybe there are newer, better solutions to this problem, but I didn't find anything which provides a more stable framerate on different (driver) settings with OGL.

Brgds.
Remember what the dormouse said: Feed your head

Offline lucastar

  • C= 64
  • **
  • Posts: 50
  • Karma: 5
    • View Profile
Re: [C++][OpenGL]VSync & framerate
« Reply #2 on: April 12, 2013 »
But this works only if you disabled the option that the driver should take care of vsync (or you have statically enabled it).
So you can't override the settings in the driver with wglSwapIntervalEXT.

Are you sure?
If i execute code in my pc(without calling the function), it enables VSync automatically (as if the driver had taken care of it by default). But if then i turn it off with the function the VSync disables.

(I hope you understand what i'm trying to say,  :P)

Saludos

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: [C++][OpenGL]VSync & framerate
« Reply #3 on: April 12, 2013 »
Technically, modern flat-screens don't have an actual vertical-refresh anymore but still provide a (more or less random) refresh rate.
Most screens work at 60hz because it displays most common framerates (24, 25, 30fps) at not too fractional steps.
Some others do 100hz, 3d-displays generally have doubled refresh and some displays do 59.94hz instead of 60.0 because it's twice the speed of ntsc.

Enabling the vertical sync makes the call to "swapBuffers" wait for the next vertical-refresh to happen.
This means if your rendering took 10ms since the last frame, it will wait another 6ms to display the image (because at 60hz each frame is ~16ms).
If your rendering took 20ms, it will wait another 12ms and the previous image will stay for two frames.
Such "frame drops" generally happen from time to time because your PC just had something else to do for a moment.
That's why the driver has a triple-buffer feature, so it can use the waiting time to already start with the next frame.

With wglSwapIntervalEXT you can't only wait for the next frame but also for the second or third one (so your framerate drops to 30hz or 20hz).
Most people perceive 60hz quite a bit smoother than 30hz, so I'd always go for 60.
Rendering more frames doesn't make much sense in production because your display can't show them anyway - it's only useful for performance measurements.
Challenge Trophies Won:

Offline Knurz

  • Atari ST
  • ***
  • Posts: 121
  • Karma: 25
    • View Profile
    • GitHub Repository
Re: [C++][OpenGL]VSync & framerate
« Reply #4 on: April 12, 2013 »
But this works only if you disabled the option that the driver should take care of vsync (or you have statically enabled it).
So you can't override the settings in the driver with wglSwapIntervalEXT.

Are you sure?
If i execute code in my pc(without calling the function), it enables VSync automatically (as if the driver had taken care of it by default). But if then i turn it off with the function the VSync disables.

(I hope you understand what i'm trying to say,  :P)

Saludos

I don't know the exact behaviour of an AMD card (I'm NVIDIA user)... On NVIDIA you have a combo-box with 3 Options avail:
- Force VSync ON
- Force VSync OFF
- Let Application decide

Let's say that User 1 has Option 3 enabled. So your program is doing well because your application is telling the driver "Use Vsync".
User 2 has Option 1 where your wglSwapIntervalEXT has no effect (it's already enabled and the statement does nothing).
Assuming User 3 has Option 2 enabled, your wglSwapIntervalEXT has also no effect (it's not enabled and your app cannot enable it).

Many users have the option 3 enabled (AFAIK it's the setting by default) and your app will do fine on most PCs, but if someone has Option 2 enabled, your program is going nuts because it has no blocking when calling glFinish() or similar.

This are the behaviours my tests and experience gave me while testing my "framework" on different cards/settings/PCs.
I'm initalizing OGL with wglSwapIntervalEXT(1) but I don't count on it in my rendering loop.

Brgds,
Berny/Knurz
Remember what the dormouse said: Feed your head

Offline lucastar

  • C= 64
  • **
  • Posts: 50
  • Karma: 5
    • View Profile
Re: [C++][OpenGL]VSync & framerate
« Reply #5 on: April 12, 2013 »
I don't know the exact behaviour of an AMD card (I'm NVIDIA user)... On NVIDIA you have a combo-box with 3 Options avail:
- Force VSync ON
- Force VSync OFF
- Let Application decide

I am an NVIDIA user too, but i can't tell which option was selected because I'm not at home right now.
AMD shows this (I'm translating from my laptop, it may sound strange  ;D):
-Always disbled
-Disabled, except when application tells the opposite
-Enabled, except when application tells the opposite
-Always Enabled

So, how to call the graphics driver?? I think I'm getting on too difficult things here...

By the way, very good answer hellfire, very well explained, thanks.

Offline Canopy

  • Atari ST
  • ***
  • Posts: 208
  • Karma: 20
    • View Profile
Re: [C++][OpenGL]VSync & framerate
« Reply #6 on: April 12, 2013 »
the answer.. thats not been mentioned fully (knurz hinted at it) is to use delta timing to hit 60 fps, and forget about the VBL entirely.

then it doesn't matter what the users card is set to and your program will run the same in every environment.
« Last Edit: April 12, 2013 by Canopy »