OpenGL分析UI卡顿掉帧的原因

2,923 阅读3分钟

1. 计算机图像渲染原理

理想情况是在一定的频率下,人眼中看到流畅的画面(一般60fps),扫描完一张图,屏幕刷新一帧图像,当每一秒有60帧的画面更新,相当于每隔16.7ms就有1帧画面更新,如果CPU和GPU能在16.7ms内处理完1帧画面那么就是流畅的,反之就会出现卡顿

图像的显示流程是:扫描图像--->帧缓存区--->视频控制器发出指令读取帧缓存区位图信息--->数模转换(数字信号转换为模拟信号)---> 显示 显示器的刷新是逐⾏进⾏的,因此为了防显示的时候屏幕缓冲区的数据分属于两个不同的帧,且两帧图像有一定的位移,我们就会看到撕裂图像的现象,如下图

撕裂发生的前提:CPU以及GPU的计算能力跟不上现在的帧率(60fps),此时才会有可能发生撕裂

一般出现在低端设备,加载一个高fps的视频/游戏场景。在iOS设备上并不常见,在非常低端的iOS设备上,加载一个APP界面上出现非常高频的动效以及图层复杂度高且涵盖动画效果时,可能出现撕裂----> 苹果采用双缓存+垂直同步信号

撕裂的根本原因是:CPU以及GPU的计算能力跟不上现在的帧率,双缓存+垂直同步只能让我们感觉不到撕裂,显示上一帧的内容,这样就会引发新的问题掉帧

2. 垂直同步和双缓冲--->解决撕裂--->引发新问题掉帧

常规的GPU⾄少都会有两个帧缓冲区。显示在屏幕上的称为屏幕缓冲区,没有显示的称为离屏缓冲区。在一个缓冲区渲染完成之后,通过将屏幕缓冲区和离屏缓冲区交换,实现图像在屏幕上的显示。

显示器的刷新时,为了防止缓冲区的数据分属于两个不同的帧,给帧缓冲区加锁,因此交换一般会等待显示器刷新完成的信号,在显示器两次刷新的间隔中进行交换,这个信号就被称为垂直同步信号,这个技术被称为垂直同步

双缓冲区要等待缓冲区交换之后再进行显示,如果未交换,仍显示上一帧的数据,使得帧率无法完全达到硬件允许的最⾼水平-->引入三缓冲区技术.

三缓冲区技术 :有1个屏幕缓冲区和两个离屏缓冲区,在等待垂直同步时,来回交替渲染两个离屏的缓冲区,而垂直同步发生时,屏幕缓冲区和最近渲染完成的离屏缓冲区交换,充分利用硬件性能

3. 掉帧

接收到垂直信号时,CPU和CPU处理图片数据未完成,拿不到缓冲区的数据,重复渲染同一帧数据(上一次缓存中的数据)到屏幕,称为掉帧。

4. 卡顿和掉帧的原因:

CPU/GPU 渲染流水线耗时过长-->掉帧

使用垂直同步信号+双缓存区以掉帧为代价解决撕裂问题

使用三缓冲也有可能掉帧,但可以减少掉帧次数