ios 图像显示原理及掉帧卡顿、离屏渲染的原因分析与优化

如题所述

第1个回答  2022-06-07
1.CPU和GPU通过总线连接起来,工作流程如上图示:

在CPU中的工作完成会生成一个位图(bitmap),位图再经由总线在合适的时机上传给GPU处理,GPU拿到位图之后会进行相应位图的图层渲染(顶点变换、纹理混合等操作),之后会把结果放到帧缓冲区(Frame Buffer)中,由视屏控制器根据Vsync信号,在指定时间前提取对应帧缓冲区中的屏幕显示内容,最终显示到手机屏幕上。

2.UI视图显示到屏幕上的大概流程如上图示:创建一个UIView,它的显示部分是由CALayer负责的,CALayer有一个contents属性(即最终要绘制到屏幕上的位图),比如说创建的是一个显示“Hello world”的UILable,那么contents中放置的结果就是一个关于"Hello world"的文字位图。另外系统会在合适的时机回调一个drawRect:方法,在此基础上我们就可以绘制一些想要自定义的内容,绘制好的位图,会经由CoreAnimation框架,提交给GPU部分的OpenGL渲染管线进行位图的渲染,最终显示到屏幕上。

3.CPU工作:负责UI布局、文本计算,绘制,图片解码,绘制纹理交给GPU

4.GPU工作:纹理混合,顶点变换,渲染到帧缓冲区

1.通常来说页面滑动的流畅性是60fps(指每一秒会有60帧画面更新),人眼看到的是流畅的效果。也因此每隔 s(即16.7ms)就要产生一帧画面,也就是说在这16.7ms时间内GUP和CPU要协同完成产生一帧的数据,比如CPU花了一定的时间做UI布局、文本计算、视图的绘制和图片解码,并把产生的位图提交给GPU,GPU又要花一定的时间进行纹理混合渲染,然后在下一帧的VSync垂直信号到来之前显示这一帧画面。

在上图中,如果CPU和GPU协同工作的时间在16.7ms内,那么图像的显示是流畅的;如果CPU花费了大量时间来做frame的布局、视图绘制和图片解码,那么留给GPU的时间就不多了,GPU要想把图层合成、纹理渲染全部完成就要超过16.7ms,那么在下一帧的垂直信号VSync到来之前,还没有准备好当前的一帧画面,这就产生了掉帧,体现在滑动上的就是上下滑动卡顿的效果。

总而言之,在规定的16.7ms内,CPU和GPU并没有在下一帧的Vsync信号到来之前把当前的一帧画面生产完成,由此产生了掉帧卡顿。

2.滑动优化方案

CPU资源消耗分析

GPU资源消耗分析

基于上述的分析保持界面流畅,优化的时候就要从CPU和GPU两方面考虑。

优化参考 iOS如何优化项目

参考文章 Texture的异步渲染和布局引擎

1.有关概念:

CPU渲染及非GPU缓冲区的渲染统称为离屏渲染

2.离屏渲染消耗性能的原因

3.何时会触发?

4.检测离屏渲染

5.光栅化

光栅化简介:隐式创建一个位图,各种阴影遮罩等效果也会保存到位图中缓存起来,从而减少渲染的频度,把GPU的操作转到CPU上,生成位图缓存,直接读取调用。(注:对于经常变动的内容,不要开启光栅化,防止性能浪费,如Cell的复用)

任何时候优先考虑避免触发离屏渲染,无法避免时优化方案有两种:

•Rasterization:适用于静态内容的视图,也就是内部结构和内容不发生变化的视图,对上面的所有效果而言,在实现成本以及性能上最均衡的。即使是动态变化的视图,开启 Rasterization 后能够有效降低 GPU 的负荷,不过在动态视图里是否启用还是看 Instruments 的数据。

•规避离屏渲染,用其他手法来模拟效果,混合图层是个性能最好、耗能最少的通用优化方案,尤其对于 rounded corer 和 mask

关于离屏渲染触发及优化可以看下面的文章:

离屏渲染优化详解:实例示范+性能测试

图像撕裂原因:当视频控制器还未读取完成时,GPU将新的一帧内容提交到帧缓冲区并把两个帧缓冲区进行更新后,视频控制器就会把新的一帧数据的下半段显示到屏幕上,造成画面撕裂的现象。

•解决方案:垂直同步机制

•弊端:GPU会等待显示的V-Sync信号发出后,才进行新的一帧渲染和缓存区更新。能解决画面撕裂现象,也增加了画面流畅度,但需要消耗更多的计算资源,由此可能导致卡顿。

参考文章 ios图像显示原理

Texture相关参考资料

官方文档: http://texturegroup.org/docs/getting-started.html

官方文档部分译文一: https://juejin.im/post/5a16acf56fb9a04509092ce5

官方文档部分译文二(布局系统): https://juejin.im/post/5a1be41351882561a20a32e9#heading-17

即刻技术团队关于ASDK:

一、 https://zhuanlan.zhihu.com/p/25371361

二、 https://zhuanlan.zhihu.com/p/26283742

三、 https://zhuanlan.zhihu.com/p/29537687

iOS 保持界面流畅的技巧: https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/

ASDK源码剖析: http://beelearning.cn/2017/11/ASDK/

从 Auto Layout 的布局算法谈性能 : https://draveness.me/layout-performance