小米电池休眠自动解除 手机充不进电7个小妙招( 三 )


Instruments 中 Display 工具所显示的 Surface/VSync 信号时间戳 。如下图所示:

Display:指对应显示器的单个 Surface 上屏持续的时间 , 对应 CPU-GPU 管线的渲染频率VSync:指垂直同步信号时间戳,对应屏幕硬件的刷新频率在 60Hz 屏幕上,iOS 设备默认采用双缓冲刷新机制,也就是前帧缓存和后帧缓存 。GPU 总是在后帧缓存上进行当前帧的绘制 。当 VSync 信号到来时 , 交换前后帧缓存的指针(Swap FrameBuffer),屏幕刷新显示新的内容 。
而当屏幕以 120Hz 显示内容时,iOS 会切换成三缓冲刷新机制(见上图中三种颜色的 Surface) , 这减少渲染管线的压力,但同时会增加一定的渲染上屏延迟 。
Metal 应用可以通过设置 -[CAMetalLayer setMaximumDrawableCount:] 为 2 来在 120Hz 屏幕上强制启用双缓冲机制,避免这种延迟 。
如果屏幕显示内容未发生变化 , Surface 则不会发生交换,一个 Surface 的 Display 可能持续数个 VSync 间隔,但多余的 VSync 信号依然代表着硬件层额外的屏幕刷新 , 造成额外的电量消耗 。
非 ProMotion 设备首先让我们看看传统的固定刷新率的设备的情况 。
VSync 信号间隔固定为 16.67msXR 的屏幕刷新率为固定的 60Hz,这一点对应的具体指标是 VSync 信号的间隔,而在任何场景下,XR 的 VSync 信号的间隔均为固定的 16.67ms 。
此外 , 在显示静态内容时 , 由于视图 Layer Tree 无变化,Core Animation 不会有提交新的事务提交,backboardd 不会进行刷新 , 所以对应这一帧的 Surface 也长时间(数十秒)未被交换下去,Core Animation FPS 的值显示为 0 。
但由于 VSync 信号仍然以 60Hz 的频率持续触发,屏幕此时正在不停重复展示同样的 Frame Buffer,消耗了额外的电量 。
CADisplayLink 基本完全跟随 VSync 信号根据过去对 iOS 系统的认知 , 我们知道 CADisplayLink 是由 VSync 信号驱动的:

默认配置的 CADisplayLink 的回调应该与 VSync 信号基本同时 。
这一点在 XR 上得到了验证,用 Instruments 记录一次主线程发生的卡顿,得到:

其中:
第一行 runloop 记录每次 RunLoop AfterWaiting -> BeforeWaiting 的间隔第二行 tick 记录默认配置的 CADisplayLink 回调间的间隔最下面则是硬件 Display/VSync 事件时序图可以观察到下述现象,符合我们之前的对 DisplayLink 的认识:
没有卡顿的情况下,VSync 信号和 RunLoop 的唤醒 & CADisplayLink 回调的触发严格一一对应 。RunLoop 卡顿,无法处理 Source 1 信号,DisplayLink 回调被延迟到卡顿结束时 。在此过程中 VSync 信号间隔始终保持不变 。ProMotion 设备下面看看 ProMotion 设备的测试结果 。
VSync 信号间隔可变在 ProMotion 屏幕上 VSync 信号间隔是可变的,具体而言:
显示静态内容时,屏幕降频 , 最低以 10Hz 的频率进行刷新显示 Core Animation 动画时,系统会适配动画的帧率设置改变刷新率*通过 preferredFrameRateRange 可以设置 hint 请求高刷,但并不一定生效,详见下文“动态帧率的应用场景”部分 。
显示滑动中内容时 , 刷新率在 80Hz 左右波动,并且跟随滑动速度变化而变化 。快滑时刷新率升高 , 慢滑时降低 。显示视频时,刷新率和视频帧率维持一致可以看到 VSync 信号间隔能主动跟随显示内容的渲染帧率的改变而改变 。

推荐阅读