Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Getting current graphics mode's refresh rate

This thread is locked; no one can reply to it. rss feed Print
Getting current graphics mode's refresh rate
cinolt
Member #15,261
August 2013

TL;DR: Is there any way to get the current graphics mode's refresh rate?

I'm using Allegro 5.1 pulled on August 13, 2013, on a Windows 7 x86_64 laptop.

I'm currently looking to make a game loop that ideally runs each loop iteration on each monitor frame iteration (probably not correct wording there).

So in initialization I create the window specifying ALLEGRO_VSYNC then enter the loop, draw graphics then al_flip_display. The problem with this is that it is dependent on the refresh rate of the graphics mode. So if an object moves 1 pixel every frame on a display with a refresh rate of 60Hz, it will move twice as fast on a display with 120Hz. So, I need to know the refresh rate beforehand to accomodate for this in the game logic (distance = velocity / refresh rate).

al_get_new_display_refresh_rate apparently only returns what was previously set with al_set_new_display_refresh_rate (it should probably be said more explicitly in the docs).
al_get_num_display_modes/al_get_display_mode can enumerate all display modes, but does not tell you which is the current.

So the only option I have left is for the user to manually check the refresh rate of his graphics mode then enter it in the options, which we all know is backwards at its core.

(As an aside, I realize that graphics configurations can override the application's request for VSYNC, but I can't find any justification ever to disable VSYNC. Why the hell would anyone want tearing? It seems natural to align the CPU framerate with the GPU framerate. Nobody would even think of overwriting an audio buffer that's currently playing in the APU.)

Arthur Kalliokoski
Second in Command
February 2005
avatar

I've had a bit of code for many years that simply counts how many screen refreshes occur for, say, 3 seconds. You could be displaying a splash screen during this wait.

They all watch too much MSNBC... they get ideas.

cinolt
Member #15,261
August 2013

@Arthur:

TBH I've always hated code of that nature. It's so work-aroundy. Sure it might work well-enough every single time it's run, but conceptually it's garbage. I'd prefer the manual configuration over that.

Elias
Member #358
May 2000

Just use al_get_time inside your game loop. So something like:

t = t2 = al_get_time();
while (1) {
    dt = t2 - t;
    do_logic(dt);
    do_rendering(dt);
    t = t2;
    t2 = al_get_time();
    al_flip_display();
}

Now your logic and your rendering will get passed 0.16666 with 60Hz and 0.00833 with 120 Hz and you can use that to adjust for it in whatever way you think is best.

--
"Either help out or stop whining" - Evert

cinolt
Member #15,261
August 2013

@Elias:

That's what I've done before, but getting the refresh rate seems much more simpler.

SiegeLord
Member #7,827
October 2006
avatar

cinolt said:

I'm currently looking to make a game loop that ideally runs each loop iteration on each monitor frame iteration (probably not correct wording there).

This is a bad idea. It over-complicates network programming, precludes replaying demos, invites the possibility of differing gameplay depending on which monitor you use, and doesn't play well with disabled vsync. Decoupling the game logic from the frame rate while maintaining smooth, tear-free rendering isn't particularly hard, and should be the preferred method.

Quote:

It seems natural to align the CPU framerate with the GPU framerate.

No, it is very unnatural. It's just happens particularly simple to code so people erroneously reach out for it first.

Anyway, I think you enumerate the display modes (`al_get_display_mode`) and then force one of them via al_set_new_display_refresh_rate. I'm not sure how this works for non-true-fullscreen displays.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

torhu
Member #2,727
September 2002
avatar

Famous example of why this is a bad idea: In Quake III certain frame rates would make you jump a little longer, because the floating point rounding errors would turn out differently depending on the frame rate.

cinolt
Member #15,261
August 2013

SiegeLord said:

It over-complicates network programming, precludes replaying demos

I have no idea how you can conclude this from just the game loop model.

Quote:

invites the possibility of differing gameplay depending on which monitor you use

Actually know about what the thread is about please, I'm asking how to get the current refresh rate specifically to prevent this.

Quote:

and doesn't play well with disabled vsync

I can't deny this, but it's going to be a requirement for this model. Not that it's an unreasonable one.

Quote:

Anyway, I think you enumerate the display modes (`al_get_display_mode`) and then force one of them via al_set_new_display_refresh_rate. I'm not sure how this works for non-true-fullscreen displays.

So tell me how this works for getting the refresh rate of the current graphics mode configuration?

torhu said:

Famous example of why this is a bad idea: In Quake III certain frame rates would make you jump a little longer, because the floating point rounding errors would turn out differently depending on the frame rate.

Floating point errors happen not only because of frame rate -- the problem lies within floating point itself. That's why I'm using rational numbers instead.

I've hacked Allegro to support what I want, I'll probably post a feature request on the mailing list for a more complete implementation.

torhu
Member #2,727
September 2002
avatar

You know it all, but you still ask. Interesting ;D

SiegeLord
Member #7,827
October 2006
avatar

cinolt said:

I have no idea how you can conclude this from just the game loop model.

Person A and person B have different monitors. Person A records a demo and sends it to person B. A simple implementation of demo replay functionality will produce erroneous replay on B's computer because the simulation runs at a different rate. Similar issue with the networking.

Quote:

Actually know about what the thread is about please, I'm asking how to get the current refresh rate specifically to prevent this.

It does very little to prevent it. Consider the following game world: player falling in a gravitational field (acceleration = 100) with initial velocity (1, 0). The initial position is (0, 1). When the player hits the ground (Y = 0), he stops falling... however if he goes past (0.15, 0) he will die, as there is lava there. Examine how the coordinates evolve for two different values of FPS:

FPS = 50

t       vy      x       y
0        0      0       1
0.02    -2      0.02    1
0.04    -4      0.04    0.96
0.06    -6      0.06    0.88
0.08    -8      0.08    0.76
0.1     -10     0.1     0.6
0.12    -12     0.12    0.4
0.14    -14     0.14    0.16
0.16     0      0.16    0

Result: Death

FPS = 100

t        vy     x       y
0        0      0       1
0.01    -1      0.01    1
0.02    -2      0.02    0.99
0.03    -3      0.03    0.97
0.04    -4      0.04    0.94
0.05    -5      0.05    0.9
0.06    -6      0.06    0.85
0.07    -7      0.07    0.79
0.08    -8      0.08    0.72
0.09    -9      0.09    0.64
0.10    -10     0.1     0.55
0.11    -11     0.11    0.45
0.12    -12     0.12    0.34
0.13    -13     0.13    0.22
0.14    -14     0.14    0.09
0.15    -15     0.15    0

Result: Barely made it

That sounds like a gameplay difference to me.

Quote:

So tell me how this works for getting the refresh rate of the current graphics mode configuration?

For each refresh rate you obtain by enumerating the graphics modes, you try to create a display. Assuming I understand how its supposed to work, it'll fail if you chose a refresh rate incompatible with what is currently set.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

cinolt
Member #15,261
August 2013

SiegeLord said:

Person A and person B have different monitors. Person A records a demo and sends it to person B. A simple implementation of demo replay functionality will produce erroneous replay on B's computer because the simulation runs at a different rate. Similar issue with the networking.

You're assuming a certain model that wouldn't work with different refresh rates. However there are models that can support replays/networking with different refresh rates.

Quote:

It does very little to prevent it. Consider the following game world: player falling in a gravitational field (acceleration = 100) with initial velocity (1, 0). The initial position is (0, 1). When the player hits the ground (Y = 0), he stops falling... however if he goes past (0.15, 0) he will die, as there is lava there. Examine how the coordinates evolve for two different values of FPS:

Again, you're assuming a certain model of collision detection. My collision detection will support different refresh rates. By the way it looks like you got your two examples mixed up there, how does 0.16 -> 0 mean death and 0.09 -> 0 mean not death? 0.09 is past 0.15 and not 0.

SiegeLord
Member #7,827
October 2006
avatar

cinolt said:

You're assuming a certain model that wouldn't work with different refresh rates. However there are models that can support replays/networking with different refresh rates.

Yes, they exist, but they are more complicated than they would have had been they not been dependent on the refresh rate (which is exactly what I said originally).

Quote:

Again, you're assuming a certain model of collision detection.

This has relatively little to do with collision detection, it has to do with how the position is calculated over time. It is impossible in the general case to make this independent of the integration timestep (for some restricted systems it is possible, but again... the restriction is unnecessary if the timestep was independent of the refresh rate).

Quote:

By the way it looks like you got your two examples mixed up there, how does 0.16 -> 0 mean death and 0.09 -> 0 mean not death? 0.09 is past 0.15 and not 0.

Those are Y coordinates. Them changing to 0 means that the player has landed on the ground. In the first case, the X axis at the time of landing is 0.16, which means the player is in the lava. In the second case the X axis at the time of landing is 0.15 which means that the player is not in the lava just yet.

"For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

cinolt
Member #15,261
August 2013

My bad, I overlooked the example.

SiegeLord said:

Yes, they exist, but they are more complicated than they would have had been they not been dependent on the refresh rate (which is exactly what I said originally).

pre·clude (pr-kld)
tr.v. pre·clud·ed, pre·clud·ing, pre·cludes
1. To make impossible, as by action taken in advance; prevent.

Quote:

This has relatively little to do with collision detection, it has to do with how the position is calculated over time. It is impossible in the general case to make this independent of the integration timestep (for some restricted systems it is possible, but again... the restriction is unnecessary if the timestep was independent of the refresh rate).

The reason that your example demonstrates a discrepancy is because position over time is calculated with constant velocity over each interval, but with the velocities being changed at different times (higher FPS means more frequent updates to the velocity).

Position over time in my engine calculated through "events", I don't want to get into it but I don't think it's as restricted as you're making it to be.

Put it this way, it seems to me that you're advocating that the frames always involve the same "delta t", aka framerate. How can you be sure that you're al_flip_display'ing at anything near the desired framerate? Sure you can al_sleep, but you still have no idea how long it takes for game logic computation etc. Think about CPU's with differing clock rates, your program will be al_flip_display'ing at different frequencies over different CPU clock rates.

Tear-free rendering must involve waiting for v-sync anyway.

Elias
Member #358
May 2000

This has nothing to do with tearing, you only get tearing when disabling vsync (which nobody would ever recommend I hope). What SiegeLord is saying is that there's no point synchronizing the amount of game state updates with the amount of screen refreshes - because it will cause the gameplay to depend on the used monitor (unless you do something very complex).

Instead, make it so you always have the exact same gameplay and try to adjust the rendering to account for the different refresh rates. (There's many different ways to do the latter.)

--
"Either help out or stop whining" - Evert

cinolt
Member #15,261
August 2013

Elias said:

This has nothing to do with tearing, you only get tearing when disabling vsync (which nobody would ever recommend I hope).

When you enable v-sync, at least in Allegro, al_flip_display waits for the next refresh cycle. So the game loop would have to run with a rate that is at most the refresh rate.

http://alleg.sourceforge.net/a5docs/refman/display.html#al_flip_display

"If ALLEGRO_VSYNC is 1, this function will force waiting for vsync."

SiegeLord obviously advocates handling the possibility of disabled v-sync:

SiegeLord said:

... and doesn't play well with disabled vsync.

It was my presupposition that enabling v-sync means that the game loop would be synchronized with the refresh rate. Am I wrong?

Sirocco
Member #88
April 2000
avatar

cinolt said:

It was my presupposition that enabling v-sync means that the game loop would be synchronized with the refresh rate. Am I wrong?

Depends on how you coded your "game loop." If you only update your game state between drawing frames, then yes. If your updates are independent of your drawing loop (which is the preferred approach these days) then no.

-->
Graphic file formats used to fascinate me, but now I find them rather satanic.

Arthur Kalliokoski
Second in Command
February 2005
avatar

Sirocco said:

If you only update your game state between drawing frames, then yes. If your updates are independent of your drawing loop (which is the preferred approach these days) then no.

Let's say you were coding the next Mortal Kombat. If you update the state between frames, it'd be like taking pictures for a karate tutorial, with a picture taken at each step of a karate move, and the players halt obligingly until the cameraman says it's OK to proceed to the next step. If the updates are independent of a loop, it'd be more like taking pictures of a for-real tournament match, and the fighters have no knowledge of any pictures they're captured in.

In the second instance in the game, the action would still have to wait, but it'd wait on the timer instead of a video frame, just like the real tournament fighters would have to "wait" on the limits of inertia, momentum and muscle strength which prevents them from being infinitely fast.

They all watch too much MSNBC... they get ideas.

Go to: