RenderingNG 架构

Chris Harrelson
Chris Harrelson

在本部分中,您将了解如何设置 RenderingNG 的组件部分,以及渲染流水线如何在这些部分中流动。

从最高级别开始,渲染任务如下:

  1. 将内容渲染到屏幕上的像素。
  2. 为内容从一种状态转换为另一种状态添加视觉效果动画
  3. 响应输入进行滚动
  4. 高效地将输入转送到正确的位置,以便开发者脚本和其他子系统做出响应。

要渲染的内容是每个浏览器标签页的帧树,以及浏览器界面。以及来自触摸屏、鼠标、键盘和其他硬件设备的一连串原始输入事件。

每个帧包含:

  • DOM 状态
  • CSS
  • 画布
  • 外部资源,例如图片、视频、字体和 SVG

框架是指 HTML 文档及其网址。 在浏览器标签页中加载的网页包含一个顶级框架、顶级文档中包含的每个 iFrame 的子框架,以及它们的递归 iFrame 后代。

视觉效果是指应用于位图的图形操作,例如滚动、转换、剪裁、滤镜、不透明度或混合。

架构组件

在 RenderingNG 中,这些任务会在逻辑上分布在多个阶段和代码组件中。这些组件最终会位于各种 CPU 进程、线程以及这些线程中的子组件中。每种方法都对实现所有 Web 内容的可靠性可伸缩性能可扩展性起着重要作用。

渲染管线结构

渲染流水线示意图。
箭头表示每个阶段的输入和输出。阶段用颜色标记,以表明它们执行哪个线程或进程。在某些情况下,阶段可以在多个位置执行,具体取决于具体情况,因此有些阶段会显示两种颜色。绿色阶段是渲染进程主线程;黄色是渲染进程合成器;橙色阶段是可视化进程。

渲染会在流水线中进行,并在此过程中创建多个阶段和工件。每个阶段都代表在渲染过程中执行一项明确定义的任务的代码。工件是阶段的输入或输出数据结构

各阶段如下:

  1. 动画:根据声明式时间轴,更改计算样式并随时间更改属性树
  2. 样式:将 CSS 应用于 DOM,并创建计算样式
  3. 布局:确定屏幕上 DOM 元素的大小和位置,并创建不可变 fragment 树
  4. 预绘制:根据需要计算属性树,并使所有现有的显示列表和 GPU 纹理图块失效。
  5. 滚动:通过更改属性树来更新文档和可滚动 DOM 元素的滚动偏移量。
  6. 绘制:计算一个显示列表,用于描述如何从 DOM 光栅化 GPU 纹理图块。
  7. 提交:将属性树和显示列表复制到 compositor 线程。
  8. 分层:将显示列表拆分为复合层列表,以便独立进行光栅化和动画处理。
  9. 光栅化、解码和绘制工作流:分别将显示列表、编码图片和绘制工作流代码转换为 GPU 纹理图块
  10. 激活:创建一个合成器帧,表示如何在屏幕上绘制和放置 GPU 图块以及任何视觉效果。
  11. 汇总:将所有可见合成器帧中的合成器帧合并到单个全局合成器帧中。
  12. 绘制:在 GPU 上执行汇总的 compositor 帧,以在屏幕上创建像素。

如果不需要,可以跳过渲染流水线的阶段。例如,视觉效果和滚动动画可以跳过布局、预绘制和绘制。 因此,动画和滚动在图表中分别用黄色和绿色圆点标记。如果可以为视觉效果跳过布局、预绘制和绘制,则可以完全在 compositor 线程上运行这些操作,并跳过主线程。

此处未直接描述浏览器界面渲染,但可以将其视为此流水线的简化版本(事实上,其实现会共用大量代码)。视频(也未直接描绘)通常使用独立代码进行渲染,该代码会将帧解码为 GPU 纹理图块,然后将这些图块插入合成器帧和绘制步骤。

进程和线程结构

CPU 进程

使用多个 CPU 进程可实现网站之间的性能和安全隔离,以及与浏览器状态的隔离,还可实现与 GPU 硬件的稳定性和安全隔离。