A client requests a set of commands to be Presented as part of a future Scenic frame. A single Scenic frame can have multiple client “Presents”, where each Present represents a Session's update to the global scene graph. This doc describes the architecture internal to Scenic for how a request becomes pixels.
The diagram below shows the steps a client Present follows when it is requested. Everything between the Scenic FIDL Boundary and the Vulkan driver is currently single-threaded and executes sequentially.
Enqueue()
s a set of commands to change the contents of its part of the scene, and calls Present2()
to commit them.Present2()
request enters scenic_impl::Session
,. scenic_impl::Session
waits for any acquire fences to signal, as well as any previous Present2()
calls whose fences haven't been reached yet. scenic_impl::Session
then schedules an update for the targeted presentation_time
with the FrameScheduler
.FrameScheduler
starts sleeps until there's just enough time to prepare a frame in time for the targeted presentation time. At that point the FrameScheduler
wakes up and calls SessionUpdater::UpdateSessions()
on all SessionUpdaters
.GfxSystem
calls ApplyScheduledUpdates()
, which applies the commands to the scene graph which were enqueued in step 1. Note: GfxSystem
is a SessionUpdater
.SessionUpdaters
have successfully updated, the FrameScheduler
is notified that the scene graph is dirty, and triggers a RenderFrame()
call on the FrameRenderer
.gfx::Engine
's renderer traverses the scene graph and creates Escher::objects
for each element in the scene. The renderer then passes these objects to Escher
, and calls DrawFrame()
. Note: gfx::Engine
is a FrameRenderer
.Escher
interprets the scene graph objects as vk::commands
, and sends these commands to the GPU.