前段时间我写了一篇文章浏览器渲染流水线解析与网页动画性能优化,对目前 60 左右版本的 Chrome 的渲染流水线进行解析,文末也讨论了当前渲染流水线的一些不足和未来演化的方向。
当前的渲染流水线过于复杂和冗长,特别是对于非合成器动画来说,过多的线程/进程间交互增加了不少额外开销,异步光栅化的机制也是有利于合成器动画而不利于非合成器动画。而未来的演化理应需要简化渲染流水线,减少线程/进程间交互,避免非必要的额外开销,光栅化和合成不再像现在一样泾渭分明,渲染流水线可以支持更灵活和动态自适应的图层化和光栅化策略,根据硬件的能力和性能,还有页面的绘制特征采取不同的图层化和光栅化方式,从而最大化页面的动画性能。
最近通过阅读 Chrome 官方的一些文档,对 Chrome 渲染流水线未来演化的一些细节也有了更多认识。本文主要针对最近一次 Blinkon 上的演讲 What is Viz: The Future of Chrome Compositing 进行解读(如果该网址无法访问,可以从作者的 Github 上下载完整的 Slides),回馈对此感兴趣的读者。
FBI WARNING
个人解读不保证绝对正确
1 Servicification
Chrome 渲染流水线的演化是在 Chrome 整个系统架构演化的大背景下发生的,官方称这个过程为 Servicification,释义来自于维基百科:
Servicification is “the migration from monolithic legacy applications into service-based components”
对 Chrome 来说,就是:
Splitting a monolithic Chrome browser up into components.
也就是说 Chrome 整体架构会朝向现代 OS 所采用的 SOA (Services Oriented Architecture) 方向发展,原来的各种模块会被重构成独立的 Services,每个 Service 都可以运行在独立进程,访问 Services 必须通过定义好的接口,通过 IPC 进行通讯,从而构建一个更内聚,松耦合,易于维护和扩展的系统,更好实现 Chrome 的目标:
- Speed
- Simplicity
- Security
- Stability
Chrome 的渲染相关模块最终会重构成两个 Services,一个负责非网页部分绘制的 UI Service,包括浏览器的 UI 界面,Chrome OS 的 GUI 界面等;一个负责网页部分绘制的 Service,也就是本文主要讨论的 Viz。
Chrome 整个系统架构演化这个题目太过庞大,本文不再过多讨论,感兴趣的读者可以阅读官方的这篇文档 —— Chrome Service Model。
2 Viz
Viz 是 Visuals 的简写,按照规划:
- GPU 进程被改造成 Viz 进程,用于运行 Viz Service;
- 分布在其它进程的跟渲染有关的光栅化,多级合成器等,最终都会被整合到 Viz Service,统一运行在 Viz 进程;
最终要达成的目标:
- 实现 Chrome Servicification 的架构目标,Service 内部更内聚,跟外部的关系更松耦合;
- 光栅化,合成,GPU 调用等全部汇集在同一个 Service 内部,统一在同一个进程,使得 Chrome 可以对渲染流水线进行重组和简化,减少不必要的开销,提高整体效率;
上图显示了 Chrome 当前的渲染流水线:
- GPU 进程的用途是实现对 GPU 的虚拟化封装,其它进程可以通过 Command Buffer(可以看做是 Chrome 提供的一个 Virtual GL Context)跨进程地访问 GPU,Command Buffer 通过支持跨进程,带来了更好的安全性和健壮性,但是也引入了一定的额外开销;
- 光栅化和 Layer Compositor 运行在 Renderer 进程,光栅化器(GPU 光栅化)通过 Command Buffer 跨进程访问 GPU;
- Display Compositor 运行在 Browser 进程,同样通过 Command Buffer 跨进程访问 GPU;
Viz 改造是逐步进行的,每一阶段会实现一些新特性,本文后续的部分会对这些新特性的内容进行介绍。
2.1 Tadpole - Direct Compositing
Direct Compositing 实际包含前后两个步骤:
- 首先是 Display Compositor 要从 Browser 进程迁移到 Viz 进程(原 GPU 进程);
- 然后 Display Compositor 原来使用的 GLRenderer 会替换成新的 SkiaRenderer,SkiaRenderer 直接使用 Native GL 而不是通过 Command Buffer 封装的 Virtual GL;
Direct Compositing 预计能带来 10% - 15% 左右的性能提升,减少了进程间交互和 Command Buffer 带来的额外开销。在这个过程中 Renderer 进程保持不变。
2.2 OOP Rasterization
OOP 是 Out of Process 的缩写,所谓 OOP Rasterization 就是将光栅化从 Renderer 进程迁移到 Viz 进程。
原来的光栅化器(GPU 光栅化)运行在 Renderer 进程,它将 2D 绘图指令转换成 GL 绘图指令通过 Command Buffer 交给 GPU 进程运行。OOP Rasterization 后,位于 Renderer 进程的 Layer Compositor 需要支持 2D 绘图指令的序列化和反序列化,将 2D 绘图指令传递到 Viz 进程执行。
OOP Rasterization 处于跟 Direct Compositing 并行开发的阶段,并最终会进行融合。融合后的结果如上图,光栅化器(GPU 光栅化)和 Display Compositor 同样使用 SkiaRenderer,直接调用 Native GL 而不是通过 Command Buffer 封装的 Virtual GL。
2.3 Vulkan
Command Buffer 基本上是以 GL 为模板设计出来的,API 跟 GLES 也保持一一对应,这也意味着很难让 Command Buffer 同时也支持 Vulkan。Chrome 引入对 Vulkan 的支持主要是通过 Skia,SkiaRenderer 或者 Skia Ganesh Compositor(抱歉我也搞不清到底哪个会是最后官方的称谓)会同时支持使用 GL 或者 Vulkan 作为 Backend,根据设备的硬件能力进行选择。
预计使用 Vulkan 比起使用 GL 会带来 10 - 15% 的性能提升。
2.3.1 WebGL
对于 WebGL 来说,为了保证在 Renderer 进程使用 GPU 的安全性和健壮性,WebGL 对 GL 的调用还是一样要通过 Command Buffer。后端的实现可能有两种方式,一种是后端仍然在一个独立的 GL Context 上使用 GL,然后 WebGL 绘制的 FrameBuffer 通过平台相关的 API share 到 Vulkan Context;另外一种是通过 Angle for Vulkan (aka Vangle) 将 GL 指令转换成 Vulkan 指令在 Vulkan Context 上运行,个人猜测移动平台上多半是前者。
2.4 Salamander - Central Layerization
Salamander 是目前规划的 Viz 改造的最后阶段:
- Layer Compositor 从 Renderer 进程迁移到 Viz 进程,并和 Display Compositor 融合成 Unified Compositor;
- Renderer 发送给 Viz 的数据只包括每一个排版对象的绘图指令,和携带图层数据的 Property Trees,Unified Compositor 根据这些数据和其它信息来决定最终的图层化策略;
- OOPIF 的绘制得到更好的支持,避免不必要的光栅化和合成;
虽然官方的文档没有说明,但是个人觉得在这里 Unified Compositor 可以根据需要选择不同的光栅化策略,比如为个别图层分配 Offscreen Buffer,采用 ASync 或者 On Demand Rasterization 的光栅化策略;而另外一些图层则不分配 Buffer,采用 Direct Rasterization 的光栅化策略;
3 Summary
3.1 Viz Status
正在进行中
- Tadpole: relocate the DisplayCompositor to Viz in 66
- OOP Rasterization in Viz Q2 2018
- SkiaRenderer in 67
2018 Q3 之后开始
- Vulkan graphics
- Salamander: central layerization
整个过程还是相当漫长,目前有明确的版本规划的只是 67 的 Direct Composting,其它只有大概的时间规划,还没有明确会在哪个版本 Landing。
3.2 Viz Take-aways
从两个角度思考 Viz:
- Chrome 图形子系统的 Servicification 过程;
- 更好的 GPU 进程;
Viz 从下面三个方面带来渲染性能的提升:
- 10 - 15% 的性能提升来自于移除不必要的 Command Buffer 的使用;
- 10 - 15% 的性能提升来自于对 Vulkan 的支持;
- 对 OOPIF 绘制的更好支持,避免不必要的光栅化和合成;