专栏首页码上积木又卡了~从王者荣耀看Android屏幕刷新机制

又卡了~从王者荣耀看Android屏幕刷新机制

前言

正在带妹子上分的我,团战又卡了,我该怎么向妹子解释?在线等。

“卡”的意思

不管是端游还是手游,我们都会时不时遇到“卡”的时候,一般这个卡有两种含义:

  • 掉帧
  • 画面撕裂

那么问题来了,这些情况到底是什么原因导致的?又该怎么解决?

掉帧

首先,要知道是什么,帧率又是什么。

帧,就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一格镜头。一帧就是一幅静止的画面,连续的帧就形成动画,如电视图象等。

帧率(每秒帧数),简单地说,就是在1秒钟时间里传输的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次,通常用fps(Frames Per Second)表示

这下大家应该知道了,帧就是一个静止画面,很多个帧一起就组成了视频、电影、游戏画面。

而帧率就是我们游戏常见到的fps,指一秒钟绘制出现的帧数,单位为“赫兹”(Hz)

这里简单科普下,一般要求连贯性的话,帧数至少要高于每秒约10至12帧的时候,人眼才会认为是连贯的,此现象叫做“视觉暂留现象”,是由人眼的生物构造决定的。通过这个现象,早期的无声电影通过手摇驱动,将画面快速播放,就能让人感觉在播放完整连续的视频。

按照我们的认知,这个帧率一般是越大越连贯,就越不卡。但同时,带来的消耗也就越多,比如电影需要更多的胶卷,电脑需要更好的硬件支持。所以电影一般通用的帧率为24Hz,而电脑、手机一般帧率为60Hz,这样就能保证正常条件下能让人舒服得观看和使用。

掉帧的意思就很明显了,本来游戏的fps为60,突然降到了20,也就是一秒只有20帧了,那能不卡吗?

那么,掉帧原因到底是啥呢?

其实原因大家都知道,不信你继续看...

硬件原因

“我这个手机玩游戏卡死了”

“你那啥破手机啊,赶快换一个~”

这个对话应该时常发生,所以大家也都清楚,硬件的好坏一定程度上决定了玩游戏“卡不卡”,配置高的硬件玩游戏就能保证游戏的流畅。

软件原因

“你这啥App啊,做的啥游戏啊,这么卡,我这手机配置这么高,就玩你这个卡”

“额,可能是游戏优化没做好,”

第二个原因,就是因为游戏/软件自身的优化就没做好,图片弄的很大,布局嵌套太深,那么帧 的计算和渲染就更耗时间,就会有可能导致掉帧。

网络原因

“不行了,太卡了,我这ping都快1000了,怎么玩啊”

“快换流量啊,团战要输了,少个人怎么打”

对了,第三个原因就是网络原因,这也是最常发生的原因了,网络的波动会影响 画面 的传输,所以就会掉帧。

屏幕刷新机制

上述三个原因,其实都涉及到屏幕刷新的基本机制。

在典型的显示系统中,不管是手机还是电脑,一般都涉及到三个部分:

  • CPU,中央处理器。用于计算数据,信息处理。
  • GPU,图形处理器。用于处理图像图形,也就是俗称的显卡。
  • display,显示屏幕。用于展示画面,也就是我们的手机屏幕、电脑显示器。

整个显示过程就是:

  • CPU计算屏幕需要的数据,然后交给GPU。
  • GPU对图像进行处理绘制,然后存到缓存区。
  • display再从这个缓存区读取数据,显示出来。

每一帧都是重复这个工作,也就是1秒中需要60次这样循环操作,每次操作需要的时间就约等于16.6ms。也就是我们常说的Android系统中,会每隔16.6ms刷新一次屏幕。

关于屏幕刷新机制,有一张很经典的图片:

可以看到,16.6ms一到,系统就发送了VSync信号,然后屏幕会从缓存区获取了新的一帧图像并显示出来,与此同时,CPU也开始了下一帧数据的计算,然后计算好交给GPU,最后放到缓存区,等待下一次VSync信号。

VSync信号是啥呢?我们暂且按下不表,待会再说,可以先理解它为一种同步刷新信号,同步CPU和屏幕。当信号来的时候,屏幕开始切换画面,CPU开始下一帧计算。

为了方便理解,我做了个小动画:

通过上面的解释,我们知道了一帧显示的时间是16.6ms,在这个时间内,CPU和GPU必须把数据处理好并放到缓存区(buffer)中。

如果在某次的16.6ms中,CPU和GPU没有绘制好下一帧数据,那么display就无法更新下一帧数据了,这就是掉帧

所以才有了以上三个原因会导致掉帧,再来回顾下:

  • 1、硬件原因。硬件比较差也就是CPU和GPU计算不给力,导致一帧的数据没准备好,所以掉帧。
  • 2、软件原因。在硬件够用的情况下,App或者游戏的一帧数据计算繁杂,嵌套太多或者图太大,也会导致下一帧数据不能在16.6ms中被准备好,导致掉帧。
  • 3、网络原因。在硬件软件都正常情况下,由于网络波动,CPU的计算数据都没有从网络上获取到,那么肯定会导致CPU数据的准备延迟,最终导致掉帧。

那么掉帧之后,屏幕刷新机制会怎么处理后续的帧呢?

  • 如果是游戏的话,因为即时性比较重要,所以丢失的帧就不会再去管了,而是直接准备当前时间应该显示的内容,最终显示到屏幕。所以这种情况掉的帧就真的掉了。
  • 如果是应用的话,可能对数据的完整性比较重要,所以如果第2帧掉了,那么屏幕就继续显示第1帧,而CPU和GPU继续准备第2帧的数据,如果能在下一个16.6ms内完成第2帧数据,那么屏幕就会接着显示第二帧了。比如有时候手机卡的时候,我们去操作App,操作会延迟,就是掉帧了。这种情况帧并不是真的掉了,而是延迟了。

画面撕裂

接下来就看看画面撕裂,为什么一帧中会出现两帧的画面呢?

首先理解一个概念:「逐行扫描」

「逐行扫描」就是说,显示器显示画面并不是“蹭”一下就打出一张画面来,而是从上到下一行一行显示出来的,只不过是显示得比较快所以肉眼看不出来而已。

之前说了屏幕的数据是从缓存区Buffer中取的,如果在屏幕取数据并逐行扫描显示画面的过程中,Buffer中的数据变了,那么就有可能导致画面撕裂。

最明显的例子就是:显卡的fps是180,而显示器的fps是60。也就是显卡一秒钟能产生180张画面,而显示器一秒钟只能读取60张画面。

那么显示器从Buffer中读取数据逐行扫描的过程中,本来需要1/60 秒显示完一张画面,但是在1/180的时间点,显卡就把下一张画面的数据存到Buffer了,结果显示器的下半截就显示的是第二张画面的内容了。也就造成了画面撕裂。

再来个动画解释下:

所以为了防止这种状况,一般显示系统会加入一个双缓存+垂直同步的概念:

  • 首先,开启垂直同步,就会将GPU的fps限制为和显示器的fps一样。

系统会在显示器绘制完一帧之后发送一个垂直同步信号,然后CPU和GPU就准备下一帧的内容,等待显示器下一帧绘制完,又会发送一个垂直同步信号。如此反复,就限制了显卡的fps,按照显示器的标准来绘制图像。

这个垂直同步信号就叫做 VSync信号

玩游戏的朋友应该都知道,很多游戏内设置页都有 垂直同步 的开启选项,为的就是将显卡的fps和显示器的fps适配,防止画面撕裂。

  • 其次,通过双缓存保证一帧数据的连贯性。

1、缓存区backBuffer用于CPU/GPU图形处理

2、缓存区frameBuffer用于显示器显示

这样分工明确之后,屏幕只会读取framebuffer的内容,是一帧完整的画面。而CPU/GPU计算的新一帧内容会放到backbuffer中,不会影响到framebuffer的内容。

只有当屏幕绘制完一帧内容之后,才会将CPU/GPU计算好的新一帧内容也就是backbuffer内容和framebuffer进行交换。

这样就保证了一帧数据的完整连贯。

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

  • 1、交换两个缓存区(framebuffer、backbuffer)内容。
  • 2、显示器开始显示第2帧内容,也就是交换后的framebuffer内容。
  • 3、CPU/GPU开始计算处理第三帧的内容,并在处理好内容后放到backbuffer中。

再来个动画:

Android Project Butter(黄油计划)

问题都解决了吗?并没有。

加入VSync信号之后,掉帧问题变得更严重了:

可以发现,加入了VSync信号后,虽然统一了CPU处理的时间点,但是掉帧问题可能会被再一次放大,从掉一帧直接变成后续一直掉帧。因为第二个的16.6ms被浪费了,CPU必须等到第三个16.6ms才能开始新一帧的数据处理,直接影响后续的所有帧进度。

怎么办呢?在保留VSync信号的同时有可能最大利用上CPU/GPU吗?

三缓存来了:

1、缓存区backBuffer用于CPU/GPU图形处理

2、缓存区TripleBuffer用于CPU/GPU图形处理

3、缓存区frameBuffer用于显示器显示

刚才说的情况导致的原因就是因为在第二个VSync信号来的时候,因为backBuffer被GPU占用,所以CPU无法去开始新一帧的计算。

加入了第三个缓存区,那么在第二个VSync信号来的时候,CPU就可以利用TripleBuffer开始新一帧的计算,而无视正在被GPU占用的backBuffer

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

三缓存和上面说到的Vsync同步信号都是 Android 4.1 发布的一个Project Butter(黄油计划)中提出的,为的是就是让Android能让黄油/奶油般顺滑。

最后贴个三缓存机制下的刷新机制图:

小结

今天了解了Android系统的刷新机制,虽然没有代码,但是面试中也是常常被问到的,再次总结下:

1、为了解决画面撕裂问题,引入了垂直同步信号VSync信号双缓存

  • 每次VSync信号到达的时候,屏幕进行画面切换,CPU/GPU开始准备下一帧内容。
  • CPU/GPU每次准备好数据后,放到一个单独的缓存区backBuffer,当屏幕准备好之后,将backBuffer数据和frameBuffer数据交换,屏幕只读取frameBuffer缓存区的数据,保证了数据的完整连续性。

2、为了解决VSync信号下CPU/GPU无法最大化利用的问题,引入了三缓存。

VSync信号来的时候,即使GPU还没处理好上一帧数据,backBuffer还不空闲,但是CPU也可以利用第三个缓存区正常开始处理下一帧的数据,最大化利用CPU/GPU,保证垂直同步机制的同时不浪费资源。

3、掉帧的根本原因是因为在一帧时间内(一般为16.6ms),CPU/GPU无法把下一帧的数据准备好。

即使引用了三缓存和垂直同步,但是掉帧的情况该发生还是会发生,我们作为App软件开发者,能做的就是尽可能优化布局,减少嵌套,减少CPU/GPU计算画面数据的时间,让每一帧时间内正常准备好下一帧图像数据。

至于刷新机制在Android源码中到底是怎么实现的呢?下期会带来Choreographer的解析。

参考

https://www.jianshu.com/p/0d00cb85fdf3 https://www.zhihu.com/question/49764664/answer/469342536 https://blog.csdn.net/yangwen123/article/details/16344375

感谢大家的阅读,有一起学习的小伙伴可以关注下公众号—码上积木❤️ 每日一个知识点,建立完整体系架构。

本文分享自微信公众号 - 码上积木(Lzjimu),作者:积木zz

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-04-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深入浅出,Andorid 端屏幕采集技术实践

    随着全球产业链线上化和数字化的加速,移动端实时屏幕共享在各行各业场景下都有了广泛的应用,比如在线教育、视频会议、远程业务咨询、手游直播。而屏幕采集则是实现实时屏...

    glumes
  • Pico Goblin VR测评:价格公道实惠,但仍有一定上升空间

    VRPinea
  • 风靡全国,日活8000万,《王者荣耀》后台技术架构演进!

    这个曾经在端游时代主导搭建 RTS 游戏《霸三国》框架的技术团队,在转型做 MOBA 手游《王者荣耀》后为游戏提供了巨大的支持,但这个过程也并非一帆风顺。

    51CTO技术栈
  • 你已经是台成熟的vivo手机了,要自己学会打王者

    刚刚,他们披露了AI研究方面的最新进展,和此前的潮头公司一样,vivo也把目光投向游戏领域,而且一出手就是《王者荣耀》。

    量子位
  • 华为用“荣耀3C“猎杀红米,智能手机呈鼎立之势

    “荣耀”独立发展是华为从企业服务到个人消费,从传统渠道到电商渠道,从通信设备服务商到互联网科技集团转型的重要里程碑。在其宣布此项决定之后,其动作自然十分...

    罗超频道
  • 极客资讯丨2017年的中国互联网“十大事件”!

    一川水巷
  • 进击的 Vulkan 移动开发(一)之今生前世

    文章开始之前先来讲一讲《王者荣耀》,作为曾经珠海市香洲区第五十号鲁班七号,可是有着辉煌的战绩。

    glumes
  • 跌了2个京东,又跌了2个小米,苹果手机终于卖不动了

    2019年1月3日,新年工作日的第一天,同时也是乔布斯注册成立苹果公司的42周年纪念日。

    量子位
  • 《王者荣耀》2亿用户量的背后:产品定位、技术架构、网络方案等

    用户1263954
  • 智能手机回归商业本质:与其奇技淫巧不如好好做产品

    “只有潮退了,才知道谁在裸泳。”中国智能手机市场进入了存量市场,天花板到了,生意没那么好做了。 中国手机行业正在上演第二次洗牌 IDC数据显示,2016年小米的...

    罗超频道
  • 王者荣耀爆款H5有何过人之处?

    敦煌壁画是我们民族引以为傲的瑰宝 但是它的绚丽正在一点点消失... 腾讯联合王者荣耀和敦煌研究院 最近发起了一个数字供养人计划 希望有更多人了解和热爱敦煌 为...

    腾讯大讲堂
  • 管窥华为东莞工厂:荣耀3C3X、P6、P7都在这里诞生

    华为向来低调不喜曝光,尤其是作为重中之重的手机生产线,更加隐秘。 在华为荣耀3C第400万台下线庆典暨荣耀3C 4G首发品鉴会后,华为荣耀公开了其位于东莞南方工...

    机器人网
  • VR时代降临,你真的不考虑换一款VR-ready手机吗?

    VRPinea
  • 用自己训练的AI玩王者荣耀是什么体验?

    简单地说,就是可以让你在电脑上控制手机!它支持鼠标控制、键盘输入、电脑剪切板复制粘贴、拖放文件传输到手机、以及拖放 APK 文件进行安装。

    Jack_Cui
  • 专项测试实战 | 如何测试 App 流畅度(基于 FPS 和丢帧率)

    FPS 和丢帧率可以在一定程度上作为 APP 流畅度的一项衡量标准,本文介绍利用 adb shell dumpsys gfxinfo 命令获取软件渲染加载过程的...

    霍格沃兹测试开发
  • Winter漫聊手机——开篇

    所谓漫聊,即无忧虑地聊,且不局限。因而,虽说是聊手机,但Winter也会附带性地聊点电脑、相机、VR及厂商等。时间顺序总是最适合懒人的,那就从2011年聊起吧。

    冰之角
  • ElasticSearch实战:IK中文分词插件

    https://github.com/medcl/elasticsearch-analysis-ik

    BH8ANK
  • 传余承东或将“撒手”Mate与P系列?荣耀、OPPO、小米的渠道战已经打响

    遭遇“黑天鹅”,华为于去年拆分出售荣耀。1月25日,有媒体报道称,华为正就出售高端智能手机品牌P和Mate事项,与上海政府支持企业牵头的财团进行了数月的谈判,且...

    用户2908108
  • 小学生学编程!30行Python代码刷王者荣耀金币!通过荣耀学Python

    哈哈 ,我相信如果有小学生,初中生之类的很希望自己也能做出这样一个脚本的!因为农药里面的英雄还真的贵,小编也和朋友玩过,什么1w8得8千的。这个确实很难打金币!...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券