说到界⾯卡顿,基本上就是两个原因:CPU耗时任务、GPU渲染耗时。
优化⽅案基本也是从这两个⽅向⼊⼿。但是为什么耗时的操作会导致丢帧?以及撕裂是怎么出现的?单缓冲、⼆级缓冲、三缓冲⼜是什么?我们知道在整个显⽰过程中,需要 CPU、GPU、显⽰屏 三个模块协调⼯作,⼤致流程如下:1. CPU 负责计算数据,把计算好数据交给 GPU
2. GPU 会对图形数据进⾏渲染,渲染好后放到缓冲区 buffer ⾥存起来3. 显⽰屏 以特定的把 buffer ⾥的数据呈现到屏幕上
屏幕发光原理
我们先了解⼀下,⼏种屏幕的发光原理,⽅⾯后⾯理解屏幕刷新流程:
CRT 显⽰器由很多荧光点组成,发光管是⼀个射线管,靠电⼦束⾼速击打荧光粉发光(据说离的太近,会有辐射)LED 显⽰器是靠⼆极管发光,⼀直常亮的,⾃⾝有固定的刷新率(⼀般是 60HZ)
屏幕刷新过程
从发光原理来看,我们知道有⼀个电⼦束(类似扫描抢)的东西存在,屏幕的刷新就从这开始了:
从初始位置(第⼀⾏左上⾓)开始扫描,从左到右,进⾏⽔平扫描(Horizontal Scanning)
每⼀⾏扫描完成,扫描线会切换到下⼀⾏起点,这个切换过程叫做⽔平消隐,简称 hblank(horizontal blank interval),并发送⽔平同步信号(horizontal synchronization,⼜称⾏同步)
依次类推,整个屏幕(⼀个垂直周期)扫描完成后,显⽰器就可以呈现⼀帧的画⾯
屏幕最后⼀⾏(⼀个垂直周期)扫描完成后,需要重返左上⾓初始位置,这个过程叫垂直消隐,简称 vblank(vertical blank interval)扫描线回到初始位置之后,准备扫描下⼀帧,同时发出垂直同步信号(vertical synchronization,⼜称场同步)。这⾥解释⼀下⼏个名词:
# 垂直消隐
完成⼀帧的扫描后,扫描点会回到初始点,准备扫描下⼀帧,这个过程会花⼀点时间,会有短暂的空⽩期。为了避免看到⼀个斜线显⽰在屏幕上,需要把扫描点变blank,这个过程就是垂直消隐,也叫场消隐。
# 垂直同步信号
当扫描点回到初始点,在准备扫描下⼀帧的时候,同时发出垂直同步信号,告诉显卡可以渲染下⼀帧了。这种情况下,显卡的渲染能⼒会受到的制约。如果显⽰器刷新频率是60Hz,显卡帧率最多只会达到60。对于⾼帧率的显卡,开启垂直同步⾃然会制约其性能发挥。
# 屏幕刷新频率
即 Refresh Rate 或 Scanning Frequency ,是指屏幕刷新的频率,单位赫兹/Hz,⼀般是 60hz。也就是以这个频率发出 垂直同步信号,告诉 GPU可以往 buffer ⾥写数据了,即渲染下⼀帧。
CPU GPU⼯作流程
我们再回来看第⼀部分 CPU 和 GPU,他们是如何⼯作的呢?
1. CPU 绘制 View 树,计算好图形数据,提交到系统内存中
2. CPU提交完成以后,通知 GPU 计算完成,系统总线会把数据拷贝到 GPU 的显存⾥3. GPU 开始处理数据,以特定的把数据写到显卡的缓冲区⾥4. 视频控制器收到,逐⾏读取帧缓冲区的数据,交给显⽰器
CPU、GPU 的计算和交互还是挺复杂的,涉及到虚拟内存地址映射,我们暂且不深⼊研究了,这⾥我们主要看第三步:
GPU 以特定的帧率把处理结果写到显卡的缓冲区⾥
这⾥我们就需要了解单缓冲、双缓冲、垂直同步信号的概念了,我们⼀个⼀个来看:
#显卡帧率
即 Frame Rate,单位 fps,是指 gpu ⽣成帧的速率,如 33 fps,60fps,越⾼越好。
#单缓冲
单缓冲,也就是只有⼀个缓冲区(buffer),GPU 向 buffer 中写⼊数据,屏幕从 buffer 中取图像数据、刷新后显⽰,理想的情况是和相等,每绘制⼀帧,屏幕显⽰⼀帧。⽽实际情况是,⼆者之间没有必然的⼤⼩关系,如果没有同步机制,很容易出现问题。
1. 例如,当显卡帧率⼤于屏幕刷新频率,屏幕准备刷新第2帧的时候,GPU 已经在⽣成第3帧了,就会覆盖第2帧的部分数据。
2. 当屏幕开始刷新第2帧的时候,缓冲区中的数据⼀部分是第3帧数据,⼀部分是第2帧的数据,显⽰出来的图像就会出现明显的偏差,也就是撕裂(tearing)。
#双缓冲
为了单缓冲的撕裂和效率问题,双缓冲诞⽣了。
双缓冲有两个缓冲区:frame buffer、back buffer,GPU 向 back buffer 中写数据,屏幕从 frame buffer 中读数据。这样不仅可以提升效率,⽽且可以避免因为帧率和刷新率不⼀致,导致图像数据错乱。但是这两个 buffer怎么去同步呢?这⾥就需要了当开启垂直同步后,就会变成这样:
1. GPU 会等待发出后,复制 back buffer 的数据到 frame buffer⾥(交换两个缓冲区的内存地址)2. 渲染下⼀帧数据,写到缓冲区⾥
这样看来,帧率⼤于刷新频率时,帧率就会被迫跟刷新频率保持同步,从⽽避免撕裂现象。需要注意的是,双缓冲 + 垂直同步信号仍然不能完全保证正常显⽰,⽐如说:
1. 收到垂直同步信号时,如果 GPU 正在往缓冲区⾥写数据,CPU、GPU 绘制⼀帧的时间超过16ms,也就是⼀个还没有准备完,这时候两个缓冲区不会发⽣复制。
2. 当屏幕进⼊下⼀个刷新周期时,从 frame buffer 中取出的是上⼀帧数据,即两个刷新周期显⽰的是同⼀帧数据,也就是掉帧(Jank)。为此,引⼊了 三缓冲,但是仍然避免不了卡顿和延迟的现象,这⾥就不详细介绍了,可以⾃⾏查阅相关资料。
参考链接
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务