前言
    帧率 vs 屏幕刷新频率
        帧率
        屏幕刷新频率
    VSync 是啥
    VSync 有啥作用
        单缓存
        双重缓存Double Buffer
        三重缓存Triple Buffer
    更多文章

前言

本文讲解 VSync 产生的原因及其作用。内容涉及如下方面:

帧率 vs 屏幕刷新频率;
    单缓存,双重缓冲,三重缓存及各自的优缺点;
    VSync 的工作过程;

帧率 vs 屏幕刷新频率
帧率

即 Frame Rate,单位 fps,是指 gpu 生成帧的速率,如 33 fps,60fps,越高越好。
屏幕刷新频率

即 Refresh Rate 或 Scanning Frequency,单位赫兹/Hz,是指设备刷新屏幕的频率,该值对于特定的设备来说是个常量,如 60hz。

如下图,屏幕的刷新过程是每一行从左到右(行刷新,水平刷新,Horizontal Scanning),从上到下(屏幕刷新,垂直刷新,Vertical Scanning)。当整个屏幕刷新完毕,即一个垂直刷新周期完成,会有短暂的空白期,此时发出 VSync 信号。所以,VSync 中的 V 指的是垂直刷新中的垂直/Vertical。

对于一个特定的设备,帧率和刷新频率没有必然的大小关系。
VSync 是啥

安卓系统中有 2 种 VSync 信号:屏幕产生的硬件 VSync 和由 SurfaceFlinger 将其转成的软件 Vsync 信号。后者经由 Binder 传递给 Choreographer。
硬件 VSync 是一个脉冲信号,起到开关或触发某种操作的作用。
更多信息请自行复习《计算机组成原理》或《数字电路与逻辑设计》等大学教材(就像考研备考的时候研友感慨的:出来混,迟早要还的,当时没学好,现在还得接着学)。

VSync 有啥作用
单缓存

在第一章我们讲到,帧率和刷新频率没有必然的大小关系。先记住这一点。
首先,我们来看下,没有引入 VSync 时,屏幕显示图像的工作流程。

如上图,CPU/GPU 向 Buffer 中生成图像,屏幕从 Buffer 中取图像、刷新后显示。这是一个典型的生产者——消费者模型。
理想的情况是帧率和刷新频率相等,每绘制一帧,屏幕显示一帧。而实际情况是,二者之间没有必然的大小关系,如果没有锁来控制同步,很容易出现问题。例如,当帧率大于刷新频率,当屏幕还没有刷新第 n-1 帧的时候,GPU 已经在生成第 n 帧了,从上往下开始覆盖第 n-1 帧的数据,当屏幕开始刷新第 n-1 帧的时候,Buffer 中的数据上半部分是第 n 帧数据,而下半部分是第 n-1 帧的数据,显示出来的图像就会出现上半部分和下半部分明显偏差的现象,我们称之为 “tearing”,如下图:

双重缓存(Double Buffer)

注意,此处的“双缓冲”和计算机组成原理中的“二级缓存”是两回事。三重缓存也是如此。
为了解决单缓存的“tearing”问题,双重缓存和 VSync 应运而生。双重缓存模型如下图:

两个缓存区分别为 Back Buffer 和 Frame Buffer。GPU 向 Back Buffer 中写数据,屏幕从 Frame Buffer 中读数据。VSync 信号负责调度从 Back Buffer 到 Frame Buffer 的复制操作,可认为该复制操作在瞬间完成。其实,该复制操作是等价后的效果,实际上双缓冲的实现方式是交换 Back Buffer 和 Frame Buffer 的名字,更具体的说是交换内存地址(有没有联想到那道经典的笔试题目:“有两个整型数,如何用最优的方法交换二者的值?”),通过二位运算“与”即可完成,所以可认为是瞬间完成。

双缓冲的模型下,工作流程这样的:
在某个时间点,一个屏幕刷新周期完成,进入短暂的刷新空白期。此时,VSync 信号产生,先完成复制操作,然后通知 CPU/GPU 绘制下一帧图像。复制操作完成后屏幕开始下一个刷新周期,即将刚复制到 Frame Buffer 的数据显示到屏幕上。

在这种模型下,只有当 VSync 信号产生时,CPU/GPU 才会开始绘制。这样,当帧率大于刷新频率时,帧率就会被迫跟刷新频率保持同步,从而避免“tearing”现象。

注意,当 VSync 信号发出时,如果 GPU/CPU 正在生产帧数据,此时不会发生复制操作。屏幕进入下一个刷新周期时,从 Frame Buffer 中取出的是“老”数据,而非正在产生的帧数据,即两个刷新周期显示的是同一帧数据。这是我们称发生了“掉帧”(Dropped Frame,Skipped Frame,Jank)现象。
三重缓存(Triple Buffer)

双重缓存的缺陷在于:当 CPU/GPU 绘制一帧的时间超过 16 ms 时,会产生 Jank。更要命的是,产生 Jank 的那一帧的显示期间,GPU/CPU 都是在闲置的。
如下图,A、B 和 C 都是 Buffer。蓝色代表 CPU 生成 Display List,绿色代表 GPU 执行 Display List 中的命令从而生成帧,黄色代表生成帧完成。

如果有第三个 Buffer 能让 CPU/GPU 在这个时候继续工作,那就完全可以避免第二个 Jank 的发生了!

于是就有了三缓存:

工作原理同双缓冲类似,只是多了一个 Back Buffer。

需要注意的是,第三个缓存并不是总是存在的,只要当需要的时候才会创建。之所以这样,是因为三缓存会显著增加用户输入到显示的延迟时间。如上图,帧 C 是在第 2 个刷新周期产生的,但却是在第 4 个周期显示的。最坏的情况下,你会同时遇到输入延迟和卡顿现象。
更多文章

写博客的初衷不是分享,而是帮助自己总结整理、深化记忆。
也许本文不值一看,但是下面这些文章则不然:

Android Performance Patterns: Understanding VSYNC
    Google I/O 2012 - For Butter or Worse: Smoothing Out Performance in Android UIs
    Getting To Know Android 4.1, Part 3: Project Butter - How It Works And What It Added
    Google I/O 2011: Accelerated Android Rendering
    Triple Buffering: Why We Love It
    Android图形显示系统(一)
---------------------  
作者:zhaizu  
来源:CSDN  
原文:https://blog.csdn.net/zhaizu/article/details/51882768  
版权声明:本文为博主原创文章,转载请附上博文链接!

快速理解 VSync相关推荐

  1. Flutter 对 iOS、Android(双端开发者)的快速理解(一)

    原文链接 更多教程 如果你有移动端开发经验,无论你是iOS还是Android开发者,你都可以利用现有的知识快速理解Flutter开发. 本文会通过对比双端开发和Flutter中的差异来说明. Flut ...

  2. Java快速创建大量对象_3分钟 快速理解JVM创建对象的步骤!

    原标题:3分钟 快速理解JVM创建对象的步骤! 我们平时创建一个对象只需要new.然而我们知道对象的创建到底经历了哪些呢?实际上只不过仅仅的3步就完成了.先来看看完整的创建过程,再来一步一步的分析. ...

  3. python爬虫入门教程--快速理解HTTP协议(一)

    http协议是互联网里面最重要,最基础的协议之一,我们的爬虫需要经常和http协议打交道.下面这篇文章主要给大家介绍了关于python爬虫入门之快速理解HTTP协议的相关资料,文中介绍的非常详细,需要 ...

  4. 通俗易懂:快速理解ipv4的NAT穿透原理

    NAT基础   IPv4由于最初的设计原因,长度只有32位,所以只提供了大约40亿个地址.这造成了地址耗尽危机.   NAT(Network Address Translation,网络地址转换),也 ...

  5. 学一点 mysql 双机异地热备份----快速理解mysql主从,主主备份原理及实践

    学一点 mysql 双机异地热备份----快速理解mysql主从,主主备份原理及实践 原文 学一点 mysql 双机异地热备份----快速理解mysql主从,主主备份原理及实践 感谢大家在上一篇 学一 ...

  6. TensorFlow学习笔记(二):快速理解Tutorial第一个例子-MNIST机器学习入门 标签: 机器学习SoftmaxTensorFlow教程 2016-08-02 22:12 3729人阅

    TensorFlow学习笔记(二):快速理解Tutorial第一个例子-MNIST机器学习入门 标签: 机器学习SoftmaxTensorFlow教程 2016-08-02 22:12 3729人阅读 ...

  7. 一篇文章带你快速理解JVM运行时数据区 、程序计数器详解 (手画详图)值得收藏!!!

    受多种情况的影响,又开始看JVM 方面的知识. 1.Java 实在过于内卷,没法不往深了学. 2.面试题问的多,被迫学习. 3.纯粹的好奇. 很喜欢一句话:"八小时内谋生活,八小时外谋发展. ...

  8. IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议

    1.前言 IM应用从服务端数据的角度来看,它是一种很特殊的应用场景,抛开基础数据.增值业务和附属功能不谈,单从IM聊天工具的立身之本--聊天数据来说,理论上是不需要在服务端存储的(或者说只需要短暂存储 ...

  9. 网络编程懒人入门(三):快速理解TCP协议一篇就够

    1.前言 本系列文章的前两篇<网络编程懒人入门(一):快速理解网络通信协议(上篇)>.<网络编程懒人入门(二):快速理解网络通信协议(下篇)>快速介绍了网络基本通信协议及理论基 ...

最新文章

  1. python os.path模块学习(转)
  2. Linux中的echo简介(自我总结)(44)
  3. 3、Swing布局管理器
  4. python爬虫的scrapy安装+pymongo的安装
  5. com.android.dazhihui,大智慧(com.android.dazhihui) - 9.36 - 应用 - 酷安
  6. Snort日志输出插件详解
  7. oracle unused 语法_oracle--set unused
  8. 哪吒汽车在售车型涨价3000-5000元
  9. Python+matplotlib响应鼠标滚轮事件调整图形大小
  10. syn-proxy源码分析(1)
  11. jdk优先级队列是如何实现的
  12. Ubuntu 14.04 安装xvid编码器
  13. Java 每半年就会更新一次新特性,再不掌握就要落伍了:Java14 的新特性
  14. android studio 讯飞语音,讯飞语音 使用步骤(针对androidStudio):语音转文字:(示例代码)...
  15. SkyWalking分布式系统应用程序性能监控工具-中
  16. 两年数据对比柱形图_2018年、2019年的数据对比图!想学习这种对比图的做法!安排...
  17. 嘉鱼县开展寒冬送暖志愿服务活动
  18. 游戏外挂防封心得防检测防封技术
  19. matlab分析gnss数据,Matlab读取GNSS 观测值o文件代码示例
  20. 使用高通Vuforia开发AR增强现实游戏(开篇)

热门文章

  1. Java 17 版本的新特性
  2. 方案解读:为什么要选择LPC55系列做电竞鼠标键盘
  3. Discuz二次开发基本知识总结
  4. Android滑动解锁功能实现,Android_滑动解锁
  5. 栅格法建立环境地图及MATLAB实现
  6. 供配电系统之功率的运算
  7. window部署redis集群
  8. 酒店小秘:酒店行业应用再添新兵
  9. 在 linux 上使用 sendmail 发送邮件
  10. ArcGIS在城乡规划中的应用【4】——通过【连接字段】工具实现国空用地编码转换为用地名称