刷新率和帧率——60fps和60hz

  • 屏幕刷新率是一个硬件的概念,是说屏幕这个硬件刷新画面的频率。

  • 帧率FPS 是 Frame Per Second 的缩写,意思是每秒产生画面的个数,是一个软件的概念,与屏幕刷新率这个硬件概念要区分开,FPS 是由软件系统决定的。如果帧率为60fps,也就是1/60 ~= 16.67ms要更新一次屏幕。

    需要注意的是,显示器并不是一次性将画面显示到屏幕上,而是从左到右,从上到下逐行扫描,顺序显示整屏的像素点,不过这一过程快到人眼无法察觉到变化。

当帧率和刷新率不一致,会发生如下情况:

  1. 屏幕刷新速率比系统帧速率快

    此时,在前缓冲区内容全部映射到屏幕上之后,后缓冲区尚未准备好下一帧,屏幕将无法读取下一帧,所以只能继续显示当前一帧的图形,造成一帧显示多次,也就是卡顿(Jank)。

  2. 系统帧速率比屏幕刷新率快
    此时,屏幕未完全把缓冲区的一帧映射到屏幕,而系统已经在准备好了下一帧,并写入到缓冲区中,要求读取下一帧到屏幕,将会导致屏幕上半部分是上一帧的图形,而下半部分是下一帧的图形,造成屏幕上显示多帧,也就是屏幕撕裂(Tearing)。

Buffer

显示屏上的内容,是从硬件帧缓冲区读取的,大致读取过程为:从Buffer的起始地址开始,从上往下,从左往右扫描整个Buffer,将内容映射到显示屏上:

Vsync+Double Buffer

为了解决撕裂的问题,Android使用了Vsync+Double Buffer技术

Double Buffer

由于图像绘制和屏幕读取使用的同一个buffer,所以屏幕刷新的时候可能读取到的是不完整的一帧画面。因此我们使用双缓存技术,如上图所示,让图像绘制和屏幕拥有的各自的buffer,cpu/gpu始终将完成的一帧图像写入到Back Buffer,显示器读取使用Frame Buffer,当屏幕刷新时,Frame Buffer并不会发生变化,当Back Buffer准备就绪时才进行两个buffer交换。

问题来了,什么时候进行两个Buffer的交换呢?

Vsync

VSync 是垂直同期( Vertical Synchronization) 的简称。VSync 信号负责调度从 Back Buffer 到 Frame Buffer 的复制操作,可认为该复制操作在瞬间完成,因为实际上双缓冲的实现方式是交换 Back Buffer 和 Frame Buffer 的内存地址。

具体流程可以用下图来描述:

其中:

  • CPU和GPU代表上层的绘制执行者,各做一部分工作,本文章中对CPU和GPU的工作不进行介绍。
  • Composite代表的是Android系统服务对多个Surface的合成
  • Background Buffer和Front Buffer(Frame Buffer)分别代表的是硬件帧缓冲区中的前缓冲和后缓冲
  • 显示屏扫描完一帧之后,会发出VSync信号来切换并显示下一帧

上面的流程中,存在一个问题,屏幕的VSync信号只是用来控制帧缓冲区的切换,并未控制上层的绘制节奏,也就是说上层CPU/GPU的生产节奏和屏幕的显示节奏是脱离的:

上图中,横轴表示时间,纵轴表示Buffer的使用者,每个长方形表示Buffer的使用,长方形的宽度代表使用时长,VSync代表垂直同步信号,两个VSync信号之间间隔16.6ms。此图描述了Android在4.1系统版本之前,上层的绘图流程在没有VSync信号的时候,出现的绘制问题。

我们从时间为0开始看,当前屏幕显示第0帧,上层CPU开始计算第1帧的纹理,计算完成后,交由GPU进行栅格化。当下一个垂直同步信号到来,屏幕显示下一帧,这时候,上层CPU并未马上开始准备下一帧(不管出于什么原因,可能正在处理其他任务),而当CPU开始准备下一帧的时候已经太晚了,下一个VSync信号来临的时候,GPU未能绘制完第二帧的处理,导致屏幕再次显示上一帧,造成卡顿。

Drawing With VSync

因为上层不知道VSync信号已经发出,导致上层未能开始CPU的计算。google在Android 4.1系统中加入了上层接收垂直同步信号的逻辑,大致流程如下:


屏幕在显示完一帧后,发出的垂直同步除了通知帧缓冲区的切换之外,该消息还会发送到上层,通知上层开始绘制下一帧。

时间从屏幕显示第0帧开始,CPU开始准备第1帧图形的处理,好了之后交给GPU进行处理,在上层收到下一个VSync之后,CPU立马开始第2帧的处理,上层绘图的节奏就和VSync信号保持一致了,整个绘图非常流畅。

小结一下Vsync的作用:当屏幕扫描完第1帧画面之后,系统发送VSync信号,这时会发生三件事:

  1. 交换两个缓存区(framebuffer、backbuffer)内容。

  2. 显示器开始显示第2帧内容,也就是交换后的framebuffer内容。

  3. CPU/GPU开始计算处理第三帧的内容,并在处理好内容后放到backbuffer中。

提到垂直同步这里就多提一句,其实我认为对于PC上的大型游戏来说,只有配置足够高,高到显卡输出帧率可以稳定的高于显示器的刷新频率,才有开启垂直同步的必要。因为只有这个时候,画面撕裂才会真正成为一个问题。而对于很多情况下主机性能不足导致游戏输出帧率低于显示器的刷新频率的情况下,尤其是帧率稳定在40~60之间时,开启垂直同步可能会导致帧率倍数级的下降(具体原因我们在Graphic架构一文中提到过,当帧生成速度不及VSync速度时,帧率的下降不是平缓的,而且很可能是倍数级的。当然这在android系统上并非严重问题,因为android上很少有高速的复杂场景的频繁切换。事实上,在Android的普通应用场景下,VSync的使用不仅不会降低帧率,还可以有效解决卡顿问题)。[8]

Android Project Butter(黄油计划)

问题解决了吗?没有,因为试想一下,如果CPU和GPU没能在下一个VSync信号到来之前完成下一帧的绘制工作,又会是怎么样的呢?

还是从屏幕显示第A帧开始,时间进入第一个16.6ms,CPU和GPU合成第B帧,当下一个VSync信号到来的时候,GPU未能及时完成第B帧的绘制,此时,屏幕显示又持有一个Buffer用于显示,这样的话,就导致两个缓冲区都被占用了,屏幕只能继续显示上一帧,GPU继续在另一个缓冲区中合成第B帧,此时CPU无法开始下一帧的合成,因为缓冲区用完了,CPU只有在VSync信号来的时候才开始绘制下一帧,也是就是说在第二个16.6ms时间内,CPU一直处于空闲状态,未进行下一帧的计算。只有等到第二个VSync信号来了之后,CPU才开始在绘制下一帧。

如果CPU和GPU需要合成的图形太多,将会导致连续性的卡顿,如果CPU和GPU大部分时候都无法在16.6ms完成一帧的绘制,将会导致连续的卡顿现象。于是Android推出了黄油计划,目的就是让Android能让黄油般顺滑,引入了Triple Buffer技术,在双缓存的基础上多加了一个buffer。

  • 缓存区backBuffer用于CPU/GPU图形处理
  • 缓存区TripleBuffer用于CPU/GPU图形处理
  • 缓存区frameBuffer用于显示器显示

从上图可以看出,在第一个VSync到来时,尽管显示器占了一个Buffer,GPU占了一个Buffer,CPU仍然可以在第三个Buffer中开始下一帧的计算,整个显示过程就开始时卡顿了一帧,之后都是流畅的。

可以理解为 CPU、GPU、Display每个人都有一个缓存区,这样三个就能同时做自己的事而互不影响,最大化利用每个模块。

总结:

  1. fps帧率是软件的概念,可以理解为gpu每秒生产帧的个数,refresh rate刷新率是硬件的概念,为显示器每秒刷新的次数。

  2. 单缓冲区时,当帧率和刷新率不匹配会出现卡顿和撕裂现象,后面引入了Double Buffer、Vsync和Triple Buffer等概念来解决卡顿和撕裂问题。

  3. Android4.1之前,VSync信号并未传递给上层,导致Buffer的生产与消费节奏不统一,Android4.1之后,上层开始绘制时机都放到了VSync信号的到来时候。

  4. 除了在上层引入VSync机制,Android在4.1还加入了三缓冲,目的是当GPU和Display都占用buffer的时候,cpu可以在下一个Vsync到来时获取Buffer从而正常的工作,减少卡顿的产生。

参考

  1. Vsync
  2. 理解 VSync
  3. Android Performance Patterns: Understanding VSYNC Youtube视频
  4. Android图形显示系统(一)
  5. 聊聊Android屏幕刷新机制
  6. Android 屏幕刷新机制
  7. Android Project Butter分析
  8. Android 4.4 Graphic系统详解(2) VSYNC的生成
  9. Android性能优化之渲染篇

Android帧的产生(2)——FPS、Vsync和Triple Buffer相关推荐

  1. Android SurfaceFlinger 学习之路(五)----VSync 工作原理

    原址 VSync信号的科普我们上一篇已经介绍过了,这篇我们要分析在SurfaceFlinger中的作用.(愈发觉得做笔记对自己记忆模块巩固有很多帮助,整理文章不一定是用来给别人看的,但一定是为加强自己 ...

  2. Android帧缓冲区(Frame Buffer)硬件抽象层(HAL)模块Gralloc的实现原理分析

    前面在介绍Android系统的开机画面时提到,Android设备的显示屏被抽象为一个帧缓冲区,而Android系统中的SurfaceFlinger服务就是通过向这个帧缓冲区写入内容来绘制应用程序的用户 ...

  3. FPS, VSync, Triple Buffering

    FPS       FPS代表frames per second,中文意思是每秒显示帧数,它描绘了当前系统的绘制更新频率,它是一个运行时特征. 它的值受到多个因素的影响:画面的变化速度,画面的复杂程度 ...

  4. Android帧布局(Frame Layout)

    Android帧布局(Frame Layout) FrameLayout是最简单的一个布局管理器.FrameLayout为每个加入其中的组件创建一个空白区域(一帧),这些组件根据layout_grav ...

  5. Android 帧动画何时停止播放

    为什么80%的码农都做不了架构师?>>>    关于android帧动画没有提供结束播放的接口回调表示不理解,也许是基于播放动画的时候,系统在干其他事情,无法确切地保证动画在tota ...

  6. android 帧动画的使用

    今天,简单讲讲android里如何使用帧动画. 其实也很简单,不过之前自己需要写一个帧动画时,忘记了具体怎么写,在网上查找资料后,解决了这个问题.所以这里记录一下. 一.概述 帧动画,顾名思义就是这个 ...

  7. Android帧动画特点,Android帧动画和补间动画看这篇足够了

    原标题:Android帧动画和补间动画看这篇足够了 距离活动开始还有两天,重庆的开发者们赶快报名行动起来吧! 写在前面 为了使用户的交互更加流畅自然,动画也就成为了一个应用中必不可少的元素之一.在 A ...

  8. android 帧动画张数限制,Android帧动画和补间动画看这篇足够了

    原标题:Android帧动画和补间动画看这篇足够了 写在前面 为了使用户的交互更加流畅自然,动画也就成为了一个应用中必不可少的元素之一.在 Android 中常用的动画分类无外乎三种,最早的帧动画.补 ...

  9. Android帧动画

    对于 Android 帧动画 大体上可以理解成 一张张图片 按一定顺序切换, 这样当连续几张图是一组动画时,就可以连起来了看成是一个小电影,你懂得 好得,比就装到这里,下面开始进入正题,由于产品需求 ...

最新文章

  1. 聊聊抖音、奈飞、Twitch、大疆、快手、B站的多媒体关键技术
  2. 【拓扑排序】【bitset】Gym - 101128A - Promotions
  3. 如何使用PHP获取当前年份?
  4. linuxsvn源代码版本库建立
  5. css 添加 referer,http中Referer和Referrer Policy
  6. python类介绍_面向对象 Python的类 介绍
  7. 手机电脑的芯片主要是由_全体起立!苹果自研电脑芯片登场,iOS迎大更新…WWDC20精彩远不止这些...
  8. 信息学奥赛C++语言: 趣味整数1(自守数)
  9. Linux系统使用GPT分区表方案推荐
  10. linux sh-3.2 怎么开机,linux 开机执行脚本文件
  11. C#类、接口、虚方法和抽象方法
  12. dojo + jersey 上传图片到数据库
  13. AOJ0121 Seven Puzzle【BFS】
  14. [NOIP2011]聪明的质检员
  15. Keras学习---MLP和CNN模型建立篇
  16. 内存共享【Delphi版】
  17. ds哈希查找—二次探测再散列_哈希算法高大上?也不过如此
  18. win10系统打开tftp服务器,win10系统开启TFTp的操作方法
  19. ACI注册国际项目考试地点汇总
  20. java坦克大战登录界面设计_JAVA课程设计——坦克大战

热门文章

  1. 鸿蒙os价格表,搭载鸿蒙 OS!华为智慧屏新品来袭:价格 3000+
  2. 2017 年实验班选拔试题
  3. Java编程开发好学吗 怎样才能学好Java编程
  4. 实现C# 与ABB机器人建立通讯,并对机器人进行实时的控制
  5. Ubuntu下通过sftp远程登录linux系统,并实现上传、下载文件
  6. 达梦数据库关键字与字段名冲突
  7. google谷歌云盘_Google 12岁生日快乐
  8. 超分辨率重建测试(ESRGAN)
  9. 解决nginx文件服务器访问403
  10. yolov5小目标检测-提高检测小目标的检测精度