GPU加速器

224 阅读5分钟

什么是GPU

提到GPU加速器,我们会想起很多术语,比如 GPU Accelerated Compositing,再比如 hardware-accelerated Compositing,这些都是一个意思。为什么要做GPU加速呢,因为它在图像渲染方面的表现优于CPU,而且GPU可以和CPU共同工作,极大的提升渲染性能。 那么GPU(Graphic Processing Unit)是什么呢? GPU即图形处理器,又称显示核心、视觉处理器、显示芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上进行图像运算工作的微处理器。GPU最大的优势在于它高性能,低成本,可以短时间内完成大量的图像处理任务,远超CPU,而且不会影响CPU的性能。 那么GPU的工作内容都包含哪些呢?

  1. 顶点处理:根据顶点数据描绘3D图形骨架,这一步主要由Vertax Shader(定点着色器)完成
  2. 光栅化计算:显示器显示的图像是由像素组成的,将矢量图形(点和线)转化成像素的操作称为光栅化,比如一条斜线,被转化为阶梯状的连续像素,统一通过调用Skia图形库提供的绘图接口完成
  3. 纹理贴图:对应第一步的操作,第一步结束后,会对每一块多边形进行贴图(纹理映射 texture mapping),有TMU(Texture Mapping Unit)完成
  4. 像素处理:这个阶段发生于第二步之后,确认每个像素的最终属性,由Pixel Shader(像素着色器)完成
  5. 最终输出:由ROP(光栅化引擎)完成,一帧渲染完毕后,被送到显存帧缓冲区

浏览器渲染原理

RenderObject到 RenderLayer

在之前的文章中提到过,浏览器的加载渲染过程,但只提到了生成渲染树,在DOM中,每一个可视的Node都会对应一个RenderObject或者LayoutObject,组成RenderTree。每一个RenderObject都会对应一个RenderLayer或者PaintLayer,或者对应其祖先RenderObject的RenderLayer。 一般来说,有相同坐标空间的RenderObject,拥有相同的RenderLayer,RenderLayer最初是为了实现层叠上下文(stacking context),保证绘制的顺序和透明度,因此满足层叠上下文条件,就会生成一个新的RenderLayer。 总结生成RenderLayer的条件:

NormalPaintLayer

  1. 根节点
  2. 有明确的css位置属性,比如 relative absolute transform
  3. 透明的
  4. 有css filter属性
  5. 有css mask属性
  6. 有css reflection属性
  7. 有 CSS mix-blend-mode 属性(不为 normal)
  8. 有 CSS transform 属性(不为 none)
  9. backface-visibility 属性为 hidden
  10. 有 CSS column-count 属性(不为 auto)或者 有 CSS column-width 属性(不为 auto)
  11. 当前有对于 opacity、transform、fliter、backdrop-filter 应用动画

OverflowClipPaintLayer

  1. overflow不为visible

NoPaintLayer

  1. 不需要 paint 的 PaintLayer,比如一个没有视觉属性(背景、颜色、阴影等)的空 div。

满足上述条件的RenderObject有独立的RenderLayer,其余的和其第一个拥有RenderLayer的祖先RenderObject共享。

RenderLayers 也形成一个树层次结构。根节点是对应于页面中根元素的 RenderLayer,每个节点的后代都是视觉上包含在父层中的层。每个 RenderLayer 的子级都保存在两个按升序排序的列表中,negZOrderList 包含具有负 z 索引的子层(因此层低于当前层),posZOrderList 包含具有正 z 索引的子层(当前层之上的层)。

RenderLayer 到 GraphicsLayer

某些RenderLayer被认为是合成层(compositin layers, layers with their own backing surfaces),被认为是合成层的渲染层拥有独立的GraphicsLayer,其余的则和其第一个拥有 GraphicsLayer 父层共用一个,这类似于 RenderObject 与 RenderLayers 的关系。之所以不是每个渲染层都是合成层,主要还是为了性能。

那么渲染层在哪些情况会被认为是合成层呢?首先得是SelfPaintLayer(约等于NormalPaintLayer)

直接原因

  1. css backface-visibility: hidden

2. 对 opacity、transform、fliter、backdropfilter 应用了 animation 或者 transition(需要是 active 的 animation 或者 transition,当 animation 或者 transition 效果未开始或结束后,提升合成层也会失效)

3. video

4. 覆盖在video上的视频控制栏

5. 3D 或者 硬件加速的 2D Canvas 元素

6. 在 DPI 较高的屏幕上,fix 定位的元素会自动地被提升到合成层中

7. will-change 设置为 opacity、transform、top、left、bottom、right(其中 top、left 等需要设置明确的定位属性,如 relative 等

后代元素原因

  1. 有合成层后代同时本身有 transform、opactiy(小于 1)、mask、fliter、reflection 属性

3. 有合成层后代同时本身fixed定位

4. 有合成层后代同时本身overflow不为visible

5. 有 3D transfrom 的合成层后代同时本身有 preserves-3d、perspective 属性

overlap重叠

如果自身本来不具备成为合成层的条件,但却与合成层重叠,此时为了保证层叠顺序正确,某些情况下,该渲染层会被提升为合成层。举个简单的例子,但具体情况要复杂的多,这里不做详细的描述。用官方原话来说:

Layer has a sibling with a lower z-index which has a compositing layer (in other words the layer overlaps a composited layer and should be rendered on top of it) 即兄弟元素中存在叠放顺序较低的合成层

  <body>
    <div style="position: absolute; top: -100px; left: 100px; animation: fadeIn 100s;width: 400px; height:300px; background-color: pink;"></div>
    <div style="position: absolute; width: 400px; height:300px; background-color: aquamarine; z-index: 999;"></div>
  </body>

层压缩

Layer Squashing,为什么会有这一步,由于上面提到的各种各样的原因,生成合成层的原因有很多,尤其是层重叠,随随便便就能产生很多合成层,这非常耗费性能,有一种情况下是可以压缩合成层的,就是比如有多个兄弟渲染层因为层叠顺序较高被提升为合成层时,这几个兄弟层可以压缩为一个层。

GraphicsLayer 到 WebLayer