一文摸透 垂直同步、双缓冲、三缓冲

显示绘制--垂直同步、双缓冲、三缓冲

网上这类的文章挺多,我看的时候也晕乎,有点是爬虫趴下来的格式图片都挂了,有的参入和很多代码方面的讲解,一些概念性的平台无关的机制如果能不涉及代码细节,可能会更好。

我尝试用这篇文章,把尝试把这三个东西讲清楚。(前置知识:需要先了解什么是掉帧,16ms这个数字怎么来的)

屏幕显示图像的原理

拿过去的CRT显示器原理来说,CRT的电子枪按照上面的方式,从上到下逐行扫描,扫描完成以后显示器就呈现一帧的画面,然后电子枪就回到初始位置继续下一次扫描。

为了把显示器的显示和系统视频控制器同步,显示器会用硬件时钟产生一系列定时信号。
当电子枪换下一行准备扫描的时候,显示器会发出一个水平同步信号HSync。
当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个垂直同步信号VSync。
显示器通常以VSync信号的频率来刷新。

计算机系统中的CPU、GPU、显示器的大致协同工作如下:


image.jpeg

CPU计算好现实内容提交到GPU,GPU渲染完成后将渲染结果放入帧缓冲区,随后视频控制器就会按照VSync信号逐行读取帧缓冲区的数据,然后在显示器上显示。

即,电脑显示一张画面是分成两个步骤完成的。

  • 第一步是CPU和显卡把所要显示的画面数据计算出来。
  • 第二步是显示器把这些数据写到屏幕上。

这两步工作都需要时间,并且可以并行执行,因为具体执行这两个过程的硬件是相互独立的(是cpu/显卡 和 视频控制器)。但是呢,这两个工作的耗时是不同的。
cpu以及显卡每秒能计算出的画面数量是根据硬件性能决定的。 但是显示器每秒刷新频率是固定的(一般是60hz,所以每隔16.667ms就会刷新一次)。

这种两边速率不统一的问题(先不说谁快谁慢),引入了帧缓冲(FrameBuffer)的概念。

帧缓冲能在一定程度上提升效率,但还是有几个问题:

  • 画面闪烁
  • 画面撕裂
  • 跳帧
  • 卡顿

接下来聊聊显示上会遇到的几个问题以及方案的演进:

画面撕裂、跳帧、闪烁

image.jpeg

如上面说过的,显示器刷新的时候是从最上面的一行像素开始逐行向下刷新,所以从顶端到底部的刷新是有时间差的。如果显卡的性能很强,也就是显卡帧率大于屏幕刷新率的时候,就会出现屏幕上半部分还停留在上一帧的画面,新的一帧的数据已经拷贝上来了,那么屏幕的下半部分渲染出来的就是下一帧的画面-----这种情况被称为画面撕裂(问题-1)。
如果显卡再快一点,那么下一帧的图像还没来得及显示,下下一帧的数据就覆盖上来了,中间这帧就跳过了-----这种情况被称为跳帧(问题-2)。
反过来,如果显卡帧率小于显示器刷新率,那每次在屏幕上看到的可能不是完整的图形,每次看到的图形比上次更完整一些。于是在用户看起来,画面是卡顿掉帧不顺滑(问题-3)。
在单缓冲的场景下,渲染下一帧的时候先清除画布的当前视图,这样就会导致画面看起来闪烁,比如大学时候在win32的GDI+写过小游戏的朋友一定有印象,不使用额外手段的情况下,画面动起来的时候是会一闪一闪的。(问题-4)。

方案:针对这问题-1和-2,引入了垂直同步的技术

垂直同步(V-Sync),开启后GPU会等待显示器的VSync信号发出后再进行新的一帧渲染和缓冲区更新。即,把显卡帧率锁定为显示器的刷新率,

由上述结论我们只能得到,垂直同步可以在显卡帧率比显示器刷新率高的时候解决撕裂和跳帧的问题。但是,显卡帧率小于显示器刷新率的时候,也就是问题-3和问题-4,引入了双缓冲技术

双缓冲技术,GPU会预先渲染好一帧放入一个缓冲区内,让视频控制器读取,当下一帧渲染好后,GPU会直接把视频控制器的指针指向第二个缓冲区。也就是说,在一帧被渲染完以后才会交给屏幕显示,不会看到“半成品画面”。并且有两个缓冲区互换,不需要在显示前台清理画布,所以不会闪烁。

安卓在4.1引入了是三缓存+垂直同步的机制。

下面再来说一下Android的三重缓冲:先对比总结一下上面说的几种情况

image.jpeg
image.jpeg

GPU帧率小于显示器刷新率的时候还是会出现下面的情况(掉帧):


image.jpeg

这样当掉帧的时候,第二个16ms时间段内,显示控制器占用一个Buffer,GPU暂用一个Buffer。两个Buffer都被占用,导致CPU空闲下来浪费了资源,因为垂直同步的原因只有V-SYNC时间点CPU才能触发绘制工作。

这时候引入第三个Buffer。这个Tripple Buffer机制利用CPU/GPU的空闲等待时间提前准备好数据,但是不一定会使用。


image.jpeg

如上图所示,一开始会掉帧一次后面就不会掉帧了。这个所谓的引入Buffer的机制,就和App和SurfaceFlinger通信的时使用的匿名共享内存Ashmem里的数据结构SharedClient里的SSHaredBufferStack关联上了,这个stack有16个位置,在4.1以后这个启用了3个缓冲位。这块SurfaceFlinger的文章我会进行专门的整理。

参考文献:
https://source.android.com/devices/graphics/index.html
https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/
https://developer.android.google.cn/topic/performance/vitals/render#java

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343