Main compositor written using Vulkan implementation.
- Author
- Jakob Bornecrantz jakob.nosp@m.@col.nosp@m.labor.nosp@m.a.co.nosp@m.m
-
Lubosz Sarnecki lubos.nosp@m.z.sa.nosp@m.rneck.nosp@m.i@co.nosp@m.llabo.nosp@m.ra.c.nosp@m.om
-
Ryan Pavlik ryan..nosp@m.pavl.nosp@m.ik@co.nosp@m.llab.nosp@m.ora.c.nosp@m.om
begin_frame and end_frame delimit the application's work on graphics for a single frame. end_frame updates our estimate of the current estimated app graphics duration, as well as the "swap interval" for scheduling the application.
We have some known overhead work required to composite a frame: eventually this may be measured as well. Overhead plus the estimated app render duration is compared to the frame duration: if it's longer, then we go to a "swap
interval" of 2.
wait_frame must be the one to produce the next predicted display time, because we cannot distinguish two sequential wait_frame calls (an app skipping a frame) from an OS scheduling blip causing the second wait_frame to happen before the first begin_frame actually gets executed. It cannot use the last display time in this computation for this reason. (Except perhaps to align the period at a sub-frame level? e.g. should be a multiple of the frame duration after the last displayed time).
wait_frame should not actually produce the predicted display time until it's done waiting: it should wake up once a frame and see what the current swap interval suggests: this handles the case where end_frame changes the swap interval from 2 to 1 during a wait_frame call. (That is, we should wait until whichever is closer of the next vsync or the time we currently predict we should release the app.)
Sleeping can be a bit hairy: in general right now we'll use a combination of operating system sleeps and busy-waits (for fine-grained waiting). Some platforms provide vsync-related sync primitives that may get us closer to our desired time. This is also convenient for the "wait until next frame" behavior.