显示撕裂、掉帧的原因以及苹果的处理方案
本文阅读时间大约5分钟
前言
依旧还是老规矩,提出几个问题,希望看完本文后可以完美的回答:
- 屏幕撕裂罪魁祸首是谁?如何解决?
- 掉帧问题出现的原因,如何解决?
本文钟会出现很多专用的名词,不清楚可以去我另一篇文章中查看。
OpenGL (二)--OpenGL中那些晦涩难懂的名词、动词解析
屏幕扫描->显示
这是显示器的电子信号扫描图,会从左上到右下一个像素点一个像素点的扫描,于此同时也会从帧缓存区中一个像素一个像素的读取,最终完成显示。
屏幕撕裂
这个问题大家应该都遇到过,尤其喜欢玩游戏的同学更加常见,先上一张我的女神,无视上面的字是在找不到其他的了....
先说一些自己最直观的认知:这是两张图片拼接成的。可是在一个时刻为什么会出现两张图片呢?这就要从这张图片是如何渲染到屏幕上说起了。
计算机显示流程
- 理想状态:
显示器显示完一张位图后,cpu、gpu刚好把下一张位图处理好存放到帧缓存区中,这样显示器就可以展示新的内容。
- 现实状态
cpu、gpu的处理是根据位图的复杂程度决定的,导致这个处理时间或长或短。所以控制器读取的内容就会提前或者延后,而帧缓存区内容就会异常导致屏幕出现撕裂。对照屏幕扫描这个概念一起理解。
现在可以回答问题一:屏幕显示周期与cpu、gpu的处理周期不同步,加之显示的扫描原理,导致出现撕裂。
如何解决
为了解决撕裂,苹果大大引入了:垂直同步Vsync 双缓存区 DoubleBuffering
来彻底解决撕裂问题,如何理解呢?
- 垂直同步,既然之前会出现两者周期不同步的问题,那么对帧缓存区加入一个同步信号,保证:
- 当前位图已经完全扫描、显示完成,在帧缓存区中才会放入新的位图;
- 如果下一帧位图还没有渲染完成,那么原位图不会被销毁,继续进行下次扫描。
- 双缓存区,为GPU在增加一个缓存区域,当然显示控制器也会交叉读取两个帧缓存区内的内容。这是一种拿空间换时间的策略,当然这样做的好处:
- 不浪费cpu、gpu的资源,为提前渲染好的位图有一个区域保存,cpu、gpu就可以进行下一帧的处理。
- 减少
掉帧
的出现。
现在就可以彻底回答问题一了。
掉帧
可以说掉帧是为了解决撕裂问题而带来的副作用,但是在我看来掉帧还可以“眨眼补帧”,但是撕裂的体验就会非常差了。
Snip20200707_15.png
对图做一个简单解释:
- 每一个竖线分段代表16.67ms,因为大多数设备的刷新频率是60HZ,所以需要16.67ms之内就要处理好下一帧的位图数据。马上推出的120HZ-iPhone要真香了。
- 前两步出现了两次A,那第二次出现A就是掉帧,因为B没有处理好。后面2次B也是同理。
对于问题二,就很好解释了:cpu、gpu来不及处理下一帧数据,导致下个显示周期只能重复显示当前帧的位图。当然它也是为了解决屏幕撕裂带来的副作用。
如何优化
因为处理任务的不确定性,计算机永远都无法保证在一个周期内能完成所有任务,所以掉帧问题就目前技术是无法根本解决的,只能是优化。
目前苹果大大使用三缓存区的方案来进一步减少掉帧的出现,因为缓存区越多cpu、gpu的利用率就越高,出现卡顿的频率也会越少。
后序
相信在科学技术、硬件技术的发展下,这个问题可以得到完美的解决。