- 02.View如何显示在屏幕
- 03.绕不开的VSYNC
- 04.生产者和消费者模型
- 05.渲染上机制有哪些保护
- 一个 view 究竟是如何显示在屏幕上的?
- 一般都比较了解 view 渲染的三大流程,但是 view 的渲染远不止于此:此处以一个通用的硬件加速流程来表征
- image
- 关于整个View显示在屏幕上的流程如下
- Vsync 调度:很多同学的一个认知误区在于认为 vsync 是每 16ms 都会有的,但是其实 vsync 是需要调度的,没有调度就不会有回调;
- 消息调度:主要是 doframe 的消息调度,如果消息被阻塞,会直接造成卡顿;
- input 处理:触摸事件的处理;
- 动画处理:animator 动画执行和渲染;
- view 处理:主要是 view 相关的遍历和三大流程;
- measure、layout、draw:view 三大流程的执行;
- DisplayList 更新:view 硬件加速后的 draw op;
- OpenGL 指令转换:绘制指令转换为 OpenGL 指令;
- 指令 buffer 交换:OpenGL 的指令交换到 GPU 内部执行;
- GPU 处理:GPU 对数据的处理过程;
- layer 合成:surface buffer 合成屏幕显示 buffer 的流程;
- 光栅化:将矢量图转换为位图;
- Display:显示控制;
- buffer 切换:切换屏幕显示的帧 buffer;
- 通常会说,屏幕的刷新率是 60 帧,需要在 16ms 内做完所有的操作才不会造成卡顿。但是这里需要明确几个基本问题:
- 第一个问题:为什么是 16ms?16ms 内都需要完成什么?
- 第二个问题:系统如何尽力保证任务在 16ms 内完成?16ms 内没有完成,一定会造成卡顿吗?
- 第一个问题:为什么是 16ms?16ms 内都需要完成什么?
- 一般的屏幕刷新率是 60fps,所以每个 vsync 信号的间隔也是 16ms。
- 16ms内要做的:VSync 延迟、input输入处理、动画、测量/布局、绘制、同步和上传、命令问题、交换缓冲区。也就是我们常用的 GPU 严格模式。
- 回到 Vsync 的话题,消费 Vsync 的双方分别是 App 和 s
- 其中 App 代表的是生产者,sf 代表的是消费者,两者交付的中间产物则是 surface buffer。
- image
- 再具体一点,生产者大致可以分为两类
- 一类是以 window 为代表的页面,也就是我们平时所看到的 view 树这一套;
- 另一类是以视频流为代表的可以直接和 surface 完成数据交换的来源,比如相机预览等。
- 一般的生产者和消费者模式,会存在相互阻塞的问题
- 比如生产者速度快但是消费者速度慢,亦或是生产者速度慢消费者速度快,都会导致整体速度慢且造成资源浪费。
- 所以 Vsync 的协同以及双缓冲甚至三缓冲的作用就体现出来了。
- 思考一个问题:是否缓冲的个数越多越好?过多的缓冲会造成什么问题?
- 这里结合 view 的一生,我们可以把两个流程合在一起,让我们的视角再高一层:
- image
- 系统如何尽力保证任务在 16ms 内完成?从系统的渲染架构上来说,机制上的保护主要有几方面:
- Vsync机制的协同;
- 多缓冲设计;
- surface 的提供;
- 同步屏障的保护;
- 硬件绘制的支持;
- 渲染线程的支持;
- GPU 合成加速;
- 这些机制上的保护在系统层面最大程度地保障了 App 体验的流畅性,但是并不能帮我们彻底解决卡顿。
- 为了提供更加流畅的体验,一方面,我们可以加强系统的机制保护,比如 FWatchDog;另一方面,需要我们从 App 的角度入手,治理应用内的卡顿问题。