Present and missed pageflips

davyaxel at free.fr davyaxel at free.fr
Sat Nov 19 10:56:02 UTC 2016


Hi,

I begun the discussion on irc, but thought it deserved to be on the mailing list.
The discussion is also related to the FIFO extension that some are interested to add (for Vulkan for example).

First to show the problem, lets describe a scenario with a problem currently:
App rendering at 90 fps, screen refresh being 60 fps.
To have triple buffering behaviour, the app is using 4 backbuffers, and presents them with target_msc=0, and without the options copy and async.

The following queue is expected:
1 buffer on screen
1 buffer scheduled for next pageflip
1 buffer waiting X Present side with vblank->sync_flip=TRUE that it can be scheduled for pageflip

1 buffer application side

When sending the application remaining buffer, two cases:
1) if msc hasn't increased since last Present call, it is supposed to release the buffer with vblank->sync_flip=TRUE
2) if msc has increased since last Present call, it is supposed to not release the buffer with vblank->sync_flip=TRUE, but the buffer who was on screen
is supposed to have been released.

Thus the application is supposed to have always a buffer to render to, and not have to wait.

However now imagine that rendering one the buffer scheduled for next pageflip was not finished. In that case to my understanding, the kernel
reschedules the buffer for the next available pageflip.
If that happens, when doing 2), the application gets no new buffer, and is blocked.

Now imagine that the second pageflip succeeds. We have now the following situation:
1 buffer was on screen and was released
1 buffer was scheduled for next pageflip and is now on screen
1 buffer was waiting with sync_flip=TRUE at current_msc-2 is now scheduled for next pageflip
1 buffer was waiting with sync_flip=TRUE at current_msc-1 and is still waiting.

When we render the released buffer, and send it again, since it is presented at current_msc it doesn't
release any of the previous buffers. The situation is blocked again.

Thus because of just one missed pageflip, the application is now forced to render at 60 fps.
I was experimented with triple buffering, and I observed the 60 fps behaviour, what I described is
what I think happens, but please correct me if you think it is another scenario.

The trivial way to unblock the application is to use 5 buffers (and it indeed works on the application
I was testing on).
Should it be the solution ? Or should the Xserver behaviour be adapted to prevent the blocking ?

There are some interests to have a FIFO mechanism for Present, and I believe the question is also the same:
the FIFO queue could not release buffers because pageflips are late in exactly the same way. We need either
to make it official that we should adapt on the fly the number of backbuffers to prevent blockings, or
we need to change what the Xserver is doing.

Any thoughts ?

Yours,

Axel Davy


More information about the xorg-devel mailing list