Pixel 的生命周期

客户端请求一组命令,以便作为未来 Scenic 帧的一部分呈现。单个 Scenic 帧可以有多个客户端“呈现”,其中每个呈现都表示会话对全局场景图的更新。本文档介绍了 Scenic 内部的架构,用于说明请求如何变成像素。

下图显示了客户端呈现被请求时所遵循的步骤。Scenic FIDL 边界和 Vulkan 驱动程序之间的所有内容目前都是单线程的,并且按顺序执行。

  1. 客户端 Enqueue() 一组命令来更改其场景部分的内容,并调用 Present2() 来提交这些命令。
  2. Present2() 请求进入 scenic_impl::Sessionscenic_impl::Session 会等待任何获取栅栏发出信号,以及任何先前 Present2() 调用(其栅栏尚未到达)。然后,scenic_impl::Session 会使用 FrameScheduler 为目标 presentation_time 安排更新。
  3. FrameScheduler 开始休眠,直到有足够的时间来准备一个帧,以便及时在目标呈现时间呈现。此时,FrameScheduler 会唤醒并对所有 SessionUpdaters 调用 SessionUpdater::UpdateSessions()
  4. 对于每个客户端会话,GfxSystem 都会调用 ApplyScheduledUpdates(),该调用会将第 1 步中排队的命令应用于场景图。 注意:GfxSystemSessionUpdater
  5. 会话中的命令会应用于全局场景图。此时,场景图处于不一致的状态(“脏”),在对场景图进行后处理之前,不应由其他系统(即输入)读取。
  6. 当所有 SessionUpdaters 都成功更新后,系统会通知 FrameScheduler 场景图是脏的,并对 FrameRenderer 触发 RenderFrame() 调用。
  7. 如需绘制帧,gfx::Engine 的渲染器会遍历场景图,并为场景中的每个元素创建 Escher::objects。然后,渲染器会将这些对象传递给 Escher,并调用 DrawFrame()。 注意:gfx::EngineFrameRenderer
  8. Escher 将场景图对象解释为 vk::commands,并将这些命令发送到 GPU。
  9. GPU 处理这些命令,并将结果发送到显示驱动程序。
  10. 显示驱动程序将像素推送到屏幕。

客户端从提交显示请求到成为屏幕上的像素的类和调用关系的可视化表示。