iOS Rendering 四:Core Animation

2022-05-25  本文已影响0人  iOS_修心
Core Animation Pipeline 渲染流水线
  1. Handle Events: 处理触摸事件,这个过程中有可能会需要改变页面的布局和界面层次。

  2. Commit Transaction:此时 app 会通过 CPU 处理显示内容的前置计算,比如布局计算、图片解码等任务,接下来会进行详细的讲解。之后将计算好的图层进行打包发给 Render Server。

  3. Decode:打包好的图层被传输到 Render Server 之后,首先会进行解码。注意完成解码之后需要等待下一个 RunLoop 才会执行下一步 Draw Calls。

  4. Draw Calls:解码完成后,Core Animation 会调用下层渲染框架(比如 OpenGL 或者 Metal)的方法进行绘制,进而调用到 GPU。

  5. Render:这一阶段主要由 GPU 进行渲染。

  6. Display:显示阶段,需要等 render 结束的下一个 RunLoop 触发显示。

Commit Transaction 发生了什么

一般开发当中能影响到的就是 Handle Events 和 Commit Transaction 这两个阶段,这也是开发者接触最多的部分。

  1. Layout:构建视图

这个阶段主要处理视图的构建和布局,遍历的操作[UIView layerSubview][CALayer layoutSubLayers]

由于这个阶段是在 CPU中进行,通常是 CPU 限制或者 IO 限制,所以我们应该尽量高效轻量地操作,减少这部分的时间,比如减少非必要的视图创建、简化布局计算、减少视图层级等。代码的主要调用结构如下:

Layout调用伪代码
  1. Display:绘制视图

这个阶段主要是交给 Core Graphics 进行视图的绘制,注意不是真正的显示,而是得到前文所说的图元 primitives 数据:

根据UIView和CALayer的关系,我们知道,主要是CALayer来负责一个view的展示,并最终将得到的bitmap赋值给contents属性,保存在backing store中供后续使用。

我们知道view的绘制会在drawRect:方法中,我们在其中打断点,可得到一下堆栈信息

drawRect:绘制堆栈

通过调用堆栈,可以得到此过程主要如下:

  1. 根据Layout获得的数据,进行展示
  2. 通过CALayer和UIView之间的代理来进行展示,主要实现在的display方法中
  1. 以上是默认的流程,如果自己重写实现了drawRect:,这个方法会直接调用 Core Graphics绘制方法得到bitmap数据,同时系统会额外申请一块内存,用于暂存绘制好的bitmap。这样绘制过程从 GPU转移到了CPU,这就导致了一定的效率损失。与此同时,这个过程会额外使用 CPU 和内存,因此需要高效绘制,否则容易造成 CPU 卡顿或者内存爆炸
Display伪代码
  1. Prepare:Core Animation 额外的工作
  1. Commit:打包并发送

注意: commit 操作是依赖图层树递归执行的,所以如果图层树过于复杂,commit 的开销就会很大。这也是我们希望减少视图层级,从而降低图层树复杂度的原因。

Rendering Pass: Render Server 的具体操作

Render Server 通常是OpenGL 或者是Metal。以 OpenGL 为例,那么上图主要是 GPU 中执行的操作,具体主要包括:

  1. GPU 收到 Command Buffer,包含图元 primitives 信息

  2. Tiler 开始工作:先通过顶点着色器 Vertex Shader 对顶点进行处理,更新图元信息

  3. 平铺过程:平铺生成 tile bucket 的几何图形,这一步会将图元信息转化为像素,之后将结果写入 Parameter Buffer 中

  4. Tiler 更新完所有的图元信息,或者 Parameter Buffer 已满,则会开始下一步

  5. Renderer 工作:将像素信息进行处理得到 bitmap,之后存入 Render Buffer

  6. Render Buffer 中存储有渲染好的 bitmap,供之后的 Display 操作使用

使用 Instrument 的 OpenGL ES,可以对过程进行监控。OpenGL ES tiler utilization 和 OpenGL ES renderer utilization 可以分别监控 Tiler 和 Renderer 的工作情况

动画渲染原理

OS 动画的渲染也是基于上述 Core Animation 流水线完成的。这里我们重点关注 app 与 Render Server的执行流程。

日常开发中,如果不是特别复杂的动画,一般使用 UIView Animation 实现,iOS 将其处理过程分为如下三部阶段:

Step 1:调用 animationWithDuration:animations: 方法
Step 2:在 Animation Block 中进行 Layout,Display,Prepare,Commit 等步骤。
Step 3:Render Server 根据 Animation 逐帧进行渲染。

上一篇 下一篇

猜你喜欢

热点阅读