Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » anticipating the display refresh for minimal lag

This thread is locked; no one can reply to it. rss feed Print
anticipating the display refresh for minimal lag
Mark Oates
Member #1,146
March 2001
avatar

Per usual, I have a timer set at 60 fps (I'm assuming the monitor refresh is 60fps) and when the timer event is fired it 1) updates the game info 2) draws everything to the backbuffer, and 3) waits for the vsync to flip.

I thought about coming up with a way that anticipates the refresh and render time so there is the least amount of delay waiting for the vsync... basically "right-align" the game refresh to the anticipated vsync time.

My first theory is to measure how long the update takes and modify the timer al_set_timer_speed accordingly. Maybe the whole thing is futile because a un-anticipated longer update would lose a whole frame, making the entire thing worse.

Has anybody tried something like this with any success? ???

Edgar Reynaldo
Member #8,592
May 2007
avatar

I think you'd be better off trying to 'left-align' your timer to the vsync interval. So that your timer ticks just after vysnc completes. That would give you the most time for logic and drawing that is available to you for each frame.

I would enable vysnc, call al_flip_display(), and then immediately start the timer that runs at the refresh rate. That way everything lines up nicely.

Mark Oates
Member #1,146
March 2001
avatar

I think you'd be better off trying to 'left-align' your timer to the vsync interval. So that your timer ticks just after vysnc completes. That would give you the most time for logic and drawing that is available to you for each frame.I would enable vysnc, call al_flip_display(), and then immediately start the timer that runs at the refresh rate. That way everything lines up nicely.

Interesting, I hadn't thought of that.

Unfortunately that maximizes the problem I'm trying to solve. (Note that I'm just doing this as an experiment more than anything.)

In a real-case scenario, say you want to minimize the record latency on a keyboard. The above technique puts in a lot of dead time waiting for the sync. That specific problem might best be solved by threads, so it's a bad example.

On another note, is it possible to get the available refresh rates on a display? I think I may have asked a long time ago, can't remember (?)

Edgar Reynaldo
Member #8,592
May 2007
avatar

al_get_display_refresh_rate

Are you talking about the latency when recording keystrokes? al_get_time combined with full event monitoring should get you pretty precise times. Just because it may take a whole 1/60th of a second to display something doesn't mean you can't precisely record when it occurred.

Mark Oates
Member #1,146
March 2001
avatar

I'm thinking more playback, but yea.

The real purpose I'm interested in minimizing the delay is because I noticed an interesting phenomenon on my phone. When dragging a fullscreen list with my finger, the display "follows" my finger with the lag. Even though it's microscopic and measured in millimeters, it's enough that it feels reactionary and computor. I want to get as close to the same feeling I have putting my finger on a piece of paper and sliding it across a desk - the feeling that the list is attached to my finger and not by a rubber band.

doesn't that just return the last requested refresh rate? Wait, there it is! al_get_num_display_modes

Elias
Member #358
May 2000

Are you sure this effect is caused by the 16.7 ms delay? If you are using a finger and not a stylus, the hardware has to somehow average the center of your finger while you move it and it will change (at least with my fat fingers it does - I can actually scroll around a bit without moving the finger by just applying pressure in different directions :P).

Also if you didn't write the scrolling yourself, it may use a calculation which makes it not follow exactly on purpose. Something like: new_x = (old_x + touch_x) / 2; Or it may use momentum. Both would cause smoother movement, but add a delay.

It may as well be the delay of course, just throwing out ideas. Would be interesting having a simple Allegro example just scrolling something around.

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

Oscar Giner
Member #2,207
April 2002
avatar

I don't think you can do anything about that, since the lag is introduced by the vsync itself (even more if it¡s using triple buffering). This happens even on commercial games. Just try any game that uses a hardware mouse cursor (most of them) and a GUI with some kind of mouse hover effect, and you'll see the mouse over effect seems to follow the mouse pointer with a certain lag. Games that don't use a hardware cursor are even worse, since then the cursor itself is lagged.

Elias
Member #358
May 2000

Ah, true, I actually see this effect here in Windows 7. If I click the scrollbar to the right in the middle of the three notches then scroll up and down the mouse cursor goes past all the notches and doesn't stay pinned to the middle one as I would have expected.

Still, that's obviously fixable by simply redrawing the scrollbar at the same time as the mouse cursor and not at some later time.

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

Mark Oates
Member #1,146
March 2001
avatar

Elias said:

Are you sure this effect is caused by the 16.7 ms delay?

It's so fast and brief (single frame speed), that I believe it is.

Quote:

Also if you didn't write the scrolling yourself, it may use a calculation which makes it not follow exactly on purpose. Something like: new_x = (old_x + touch_x) / 2; Or it may use momentum. Both would cause smoother movement, but add a delay.

That was my thought, too, but I think that's not the case.

Games that don't use a hardware cursor are even worse, since then the cursor itself is lagged.

Elias said:

Ah, true, I actually see this effect here in Windows 7.

Yea, that's the one. You can isolate the effect when storing mouse_x, mouse_y on the ALLEGRO_EVENT_MOUSE_AXES, then using them to draw something (which is shown beneath hardware cursor, usually delayed by ~1 frame). Moving the mouse slowly shows the drag most clearly.

Quote:

Still, that's obviously fixable by simply redrawing the scrollbar at the same time as the mouse cursor and not at some later time.

You'd still have the vsync reaction problem, though. And/or you'd have to change the mouse cursor to include the component you're dragging.

[......]

After a few tests, a minimal lag still persists. Each solution I try (which only marginally reduced the drag) introduces potential new problems that only seems to worsen the overall situation. It seems that the minimal lag comes with no sync at all, which introduces tearing, while moving the update closer to the time of sync Destabilizes the 60fps cycle.

weapon_S
Member #7,859
October 2006
avatar

Two questions out of curiosity (a.k.a. being useless-ness): how do you measure the lag? (Probably by using your eyes... to look at the difference between hardware and software cursor?) How do you move "the update closer to the time of sync"? (By a rest...?)

Mark Oates
Member #1,146
March 2001
avatar

Really I measured with my eyes, but also with al_get_time(). The time numbers are so low it's hard to quantify them without puttin' in some of that fancy math and making graphs. I also set up a little strobe to easily spot a unevenness in frames, and also a vertical line sweeping across the screen to easily spot tearing.

weapon_S said:

Probably by using your eyes... to look at the difference between hardware and software cursor?

Exactly.

Quote:

How do you move "the update closer to the time of sync"? (By a rest...?)

This part I didn't do, as I found that the delay would increase slowly when the sync was on before popping back, so I just rolled with that. Otherwise I would use al_set_timer_speed once offset the timer, and then reset it right after that first tick.

Go to: