How vsync work ? Why i not have a multiple of 16.6 ms between each eglSwapBuffers?

I do not understand, I took the source code of delphi to see how it is performed with OpenGL (under android). so on every paint delphi do :

eglSwapBuffers(TCustomAndroidContext.SharedDisplay, TCustomAndroidContext.SharedSurface)

so this make OpenGL swapping the back buffer with the display buffer (if i understand well), waiting for the vsync signal first (is this really true?). So as the vsync signal is fired every 16.6 ms I must have between every eglSwapBuffers a multiple of 16.6 (ex 16.6 or 33.2 or 49.8, etc).

To measure it I do like this :

I replace

procedure ContextFlip;
begin
if eglSwapBuffers(TCustomAndroidContext.SharedDisplay, TCustomAndroidContext.SharedSurface) = 0 then
glGetError;
end;

with

var vSyncStopWatch: TstopWatch;

procedure ContextFlip;
begin
if eglSwapBuffers(TCustomAndroidContext.SharedDisplay, TCustomAndroidContext.SharedSurface) = 0 then
glGetError;

vSyncStopWatch.Stop;
if vSyncStopWatch.Elapsed.TotalMilliseconds > 16.6 then allog('VSYNC deadline missed', floattostr(vSyncStopWatch.Elapsed.TotalMilliseconds), tallogType.WARN);
vSyncStopWatch := TstopWatch.StartNew;

end;

but what I don’t understand, is why I have value like 18ms, 22ms, 24ms, 28ms, 27ms, etc… instead of only 16.6 or 33.2 or 49.8, etc ? how is it possible ? does eglSwapBuffers really wait for the vsync signal ?

var vSyncStopWatch: TstopWatch;

eglSwapBuffers(…)

vSyncStopWatch.Stop;
if vSyncStopWatch.Elapsed.TotalMilliseconds > 16.6 then allog(‘VSYNC deadline missed’, … );
vSyncStopWatch := TstopWatch.StartNew;

…what I don’t understand, is why I have value like 18ms, 22ms, 24ms, 28ms, 27ms, etc… instead of only 16.6 or 33.2 or 49.8, etc ? how is it possible ?

There are several possibilities. But I’d first make sure your rendering load isn’t triggering frame overruns (i.e. your rendered frame rate < refresh rate). Try eliminating all of your draw work except the glClear() and eglSwapBuffers() and see what your CPU frame times are then.

Check this out:

search down for “Rendering Performance 101”, and start playing the videos there. Keep going at least through the one ones on VSync and Profiling GPU Performance. And check out the “Profile GPU Performance: M Update” video.

Keep in mind CPU != GPU. You’re timing on the CPU, but the commands you’re submitting on the CPU are executing later on the GPU. Also keep in mind that mobile GPUs have deep pipelines – often multiple VSync intervals deep. When you call eglSwapBuffers(), there’s a good chance the GPU hasn’t even rendered a single pixel for that frame you just submitted (by design!). Finally, keep in mind that you’re not rendering directly to the display. You’re rendering to an off-screen buffer and submitting your results to a compositor, which then later composites your rendered layer with other layers and displays it on-screen. So your CPU draw thread isn’t near as close to the VSync processing as you might otherwise think.

does eglSwapBuffers really wait for the vsync signal ?

In your CPU draw thread when it calls eglSwapBuffers(), no, not necessarily.

In the GPU/driver when it actually gets around to processing your eglSwapBuffers() call, yes (…if there’s no free buffer available).

That said, if your rendered frame rate is faster than your refresh rate, the whole pipeline fills up and often times you end up with your CPU draw thread synchronized to the VSync rate. Alternatively, if your rendered frame rate is slower than the refresh rate, then you’ll see all sorts of frame times measured on the CPU.

thanks Photon!

i try eliminating everything except glclear, now yes i have number more close to 16 but still i can see number like 15ms, 18ms or 20ms … this i don’t understand how i can have for exemple 15 ms :frowning:

[QUOTE=Dark Photon;1288379]
search down for “Rendering Performance 101”, and start playing the videos there. Keep going at least through the one ones on VSync and Profiling GPU Performance. And check out the “Profile GPU Performance: M Update” video.
.[/QUOTE]

yes i try to enable the android Profile GPU Performance tool, but unfortunatly, my app is not made with android studio, so this tool is not working :frowning:

hmm, so how can i efficiently detect a frame drop ?

In OpenGl (under android if it’s matter) does vsync signal absolutely fixed at every 16.6 ms interval and can not fluctuate or could it be a little “moveable” in some circumstance ?

I mean it’s must it be absolutely like this:

16.6ms — 16.6ms — 16.6ms — etc

or could it be like this?:

16.6ms – 18ms — 16.6ms — 15ms — etc …

I ask this because between each eglswapBuffers I have strange value like 12ms, 15ms, 18ms, 22ms, etc… and I don’t understand why.

I think you’re just going to have to dig in and figure out how to profile rendering performance on Android.

Here’s a tree of Android Graphics documents that looks worth a read:

It could very well be that your app is just not getting full use of the CPU and GPU for some reason, and/or your timing method is insufficient.

Note that when you start rendering, the buffer chain is empty (meaning there are 2-3 free buffers), so when you call swap your app may very well return quickly or even near immediately, yielding CPU draw thread frame times < the VSync time. The same scenario will likely occur if your app pauses rendering for some reason and then restarts rendering again (on mobile, most apps aren’t just blasting frames to the display non-stop; particularly if nothing changed; that’s just a waste of CPU/GPU/power/battery).

yes i try to enable the android Profile GPU Performance tool, but unfortunatly, my app is not made with android studio, so this tool is not working :frowning:

I’m no Android guru, but I don’t think that’s a prerequisite. It’s built into Android, and as far as I recall worked with all apps that I tested. See this for details:

So if you haven’t already, just give it a shot! It’s under Settings -> Developer Options.

hmm, so how can i efficiently detect a frame drop ?

I’d recommend doing some more reading on how to do this properly on Android.

Here’s one search link I hit that looks promising. I’m sure there are many more:

yes but how to find it :frowning:

yes, so it’s mean that eglswapbuffers can return immediatly if buffer chain is empty ? anyway this not explain the exotic number (14 - 18 - 19 - 22 - etc…) i have between each eglswapbuffers :’ only maybe like you say, app is just not getting full use of the CPU and GPU for some reason but how to get it out … :frowning:

i already try, on android 6.0, 5, etc, on several phone, didn’t work :frowning: on other app yes it’s work!

Personally i start to think that the vsync is not really “fixed”, it’s around 16.6 ms but could be sometime less or higher. i have some anim that are not fluid like 60fps but that also are not slow like 30 fps so i can’t explain it in different way

That seems pretty unlikely. For instance, here’s what Android requires of folks implementing an Android graphics stack (the system layers on which your application is built):

https://source.android.com/devices/graphics/implement-vsync

Implementing VSYNC

                       To implement the Android graphics HAL ... You must implement VSYNC with a maximum 1 ms lag (0.5 ms or less is recommended); timestamps returned must be extremely accurate."

So no, that doesn’t explain your results.

It’s more likely that there is a performance problem with your app or a problem (possibly a mistaken assumption) with the way your app is using the system. Like I said, under Android, your app’s draw thread isn’t really tied that closely to VSync.

thanks photon, but i not understand, what the purpose of a function waitForVsync if in some way eglSwapBuffers already look like to wait it. what is very strange is to not have multiple of 16.6 ms between eglSwapBuffers and this why i start to think that vsync is not really fixed

Good luck with your research in trying to nail this down. You’ve reached the limit of my knowledge.

In a few websearches, I did see references in the android source code to where it is setting up for primary, external, and virtual displays. In one example driver it indicated that VSync was driven by the hardware for the primary display but emulated for external and virtual displays (link – see “fake_vsync” refs at the bottom; also mentioned in the following presentation on slide 25). Also here’s a potentially useful presentation on the Android graphics pipeline (link – search for vsync references; slide 26 enumerates those display types I mentioned). And on another Android link, I saw a mention that apps always start drawing at a VSync event. So you might try changing your timing from end-of-frame -to- end-of-frame (after Swap) to beginning-of-frame -to- beginning-of-frame. However, it’s unclear whether they were talking about app drawing in terms of CPU draw thread queueing up commands or drawing in terms of actual rasterization (fragment work), so they may be referring to a point deeper down in the pipeline.

thanks photon! I will read your link carefully. I start to think now that my delay problem could be cause by some background task rumning time to time like garbage collector or something like this.