客户端请求一组命令,以便作为未来 Scenic 帧的一部分呈现。单个 Scenic 帧可以有多个客户端“呈现”,其中每个呈现都表示会话对全局场景图的更新。本文档介绍了 Scenic 内部的架构,用于说明请求如何变成像素。
下图显示了客户端呈现被请求时所遵循的步骤。Scenic FIDL 边界和 Vulkan 驱动程序之间的所有内容目前都是单线程的,并且按顺序执行。
- 客户端
Enqueue()一组命令来更改其场景部分的内容,并调用Present2()来提交这些命令。 Present2()请求进入scenic_impl::Session。scenic_impl::Session会等待任何获取栅栏发出信号,以及任何先前Present2()调用(其栅栏尚未到达)。然后,scenic_impl::Session会使用FrameScheduler为目标presentation_time安排更新。FrameScheduler开始休眠,直到有足够的时间来准备一个帧,以便及时在目标呈现时间呈现。此时,FrameScheduler会唤醒并对所有SessionUpdaters调用SessionUpdater::UpdateSessions()。- 对于每个客户端会话,
GfxSystem都会调用ApplyScheduledUpdates(),该调用会将第 1 步中排队的命令应用于场景图。 注意:GfxSystem是SessionUpdater。 - 会话中的命令会应用于全局场景图。此时,场景图处于不一致的状态(“脏”),在对场景图进行后处理之前,不应由其他系统(即输入)读取。
- 当所有
SessionUpdaters都成功更新后,系统会通知FrameScheduler场景图是脏的,并对FrameRenderer触发RenderFrame()调用。 - 如需绘制帧,
gfx::Engine的渲染器会遍历场景图,并为场景中的每个元素创建Escher::objects。然后,渲染器会将这些对象传递给Escher,并调用DrawFrame()。 注意:gfx::Engine是FrameRenderer。 Escher将场景图对象解释为vk::commands,并将这些命令发送到 GPU。- GPU 处理这些命令,并将结果发送到显示驱动程序。
- 显示驱动程序将像素推送到屏幕。