问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Android Systrace 基础知识 - Vsync 解读

创作时间:
作者:
@小白创作中心

Android Systrace 基础知识 - Vsync 解读

引用
1
来源
1.
https://www.cnblogs.com/linhaostudy/p/18474449

Vsync机制是Android系统中确保画面流畅渲染的关键技术。本文从Systrace的角度,深入解析了Vsync信号在App渲染和SurfaceFlinger合成过程中的作用,帮助开发者理解Android图形渲染的底层原理。

本文是Systrace系列文章的第七篇,主要介绍Android中的Vsync机制。文章会从Systrace的角度来看Android系统如何基于Vsync每一帧的展示。Vsync是Systrace中一个非常关键的机制,虽然我们在操作手机的时候看不见,摸不着,但是在Systrace中我们可以看到,Android系统在Vsync信号的指引下,有条不紊地进行着每一帧的渲染、合成操作,使我们可以享受稳定帧率的画面。

Vsync信号的产生与传递

Vsync信号可以由硬件产生,也可以用软件模拟,不过现在基本上都是硬件产生。负责产生硬件Vsync的是HWC(Hardware Composer),HWC可生成VSYNC事件并通过回调将事件发送到SurfaceFlinger。DispSync将Vsync生成由Choreographer和SurfaceFlinger使用的VSYNC_APP和VSYNC_SF信号。

在Android基于Choreographer的渲染机制中,Choreographer的引入主要是配合Vsync,给上层App的渲染提供一个稳定的Message处理时机,也就是Vsync到来的时候。系统通过对Vsync信号周期的调整,来控制每一帧绘制操作的时机。目前大部分手机都是60Hz的刷新率,也就是16.6ms刷新一次,系统为了配合屏幕的刷新频率,将Vsync的周期也设置为16.6ms,每个16.6ms,Vsync信号唤醒Choreographer来做App的绘制操作,这就是引入Choreographer的主要作用。

渲染层(App)与Vsync打交道的是Choreographer,而合成层与Vsync打交道的,则是SurfaceFlinger。SurfaceFlinger也会在Vsync到来的时候,将所有已经准备好的Surface进行合成操作。

Android图形数据流向

首先我们要大概了解Android中的图形数据流的方向,从下面这张图,结合Android的图像流,我们大概把从App绘制到屏幕显示,分为下面几个阶段:

  1. 第一阶段:App在收到Vsync-App的时候,在主线程进行measure、layout、draw(构建DisplayList,里面包含OpenGL渲染需要的命令及数据)。这里对应的Systrace中的主线程doFrame操作
  2. 第二阶段:CPU将数据上传(共享或者拷贝)给GPU,这里ARM设备内存一般是GPU和CPU共享内存。这里对应的Systrace中的渲染线程的flush drawing commands操作
  3. 第三阶段:通知GPU渲染,真机一般不会阻塞等待GPU渲染结束,CPU通知结束后就返回继续执行其他任务,使用Fence机制辅助GPU CPU进行同步操作
  4. 第四阶段:swapBuffers,并通知SurfaceFlinger图层合成。这里对应的Systrace中的渲染线程的eglSwapBuffersWithDamageKHR操作
  5. 第五阶段:SurfaceFlinger开始合成图层,如果之前提交的GPU渲染任务没结束,则等待GPU渲染完成,再合成(Fence机制),合成依然是依赖GPU,不过这就是下一个任务了。这里对应的Systrace中的SurfaceFlinger主线程的onMessageReceived操作(包括handleTransaction、handleMessageInvalidate、handleMessageRefresh)
  6. 第六阶段:最终合成好的数据放到屏幕对应的Frame Buffer中,固定刷新的时候就可以看到了

下面这张图也是官方的一张图,结合上面的阶段,从左到右看,可以看到一帧的数据是如何在各个进程之间流动的

Systrace中的图像数据流

了解了Android中的图形数据流的方向,我们就可以把上面这个比较抽象的数据流图,在Systrace上进行映射展示

上图中主要包含SurfaceFlinger、App和hwc三个进程,下面就来结合图中的标号,来进一步说明数据的流向

Vsync-sf(SurfaceFlinger的VSync信号)主要用于控制SurfaceFlinger的绘制节奏,SurfaceFlinger是Android系统中负责合成图形缓冲区并将其显示在屏幕上的系统服务。它确保了图形的流畅显示和合成过程的同步性。

Vsync-app(应用程序的VSync信号)是发送给应用程序的垂直同步信号,应用程序可以根据这个信号来进行绘制操作,以确保绘制的内容在合适的时间被提交给SurfaceFlinger进行合成显示。

不是同一个信号,但它们都源自同一个硬件Vsync信号

  1. 第一个Vsync信号到来, SurfaceFlinger和App同时收到Vsync信号
  2. SurfaceFlinger收到Vsync-sf信号,开始进行App上一帧的Buffer的合成
  3. App收到Vsycn-app信号,开始进行这一帧的Buffer的渲染(对应上面的第一、二、三、四阶段)
  4. 第二个Vsync信号到来,SurfaceFlinger和App同时收到Vsync信号,SurfaceFlinger获取App在第二步里面渲染的Buffer,开始合成(对应上面的第五阶段),App收到Vsycn-app信号,开始新一帧的Buffer的渲染(对应上面的第一、二、三、四阶段)

Vsync Offset

文章最开始有提到,Vsync信号可以由硬件产生,也可以用软件模拟,不过现在基本上都是硬件产生,负责产生硬件Vsync的是HWC,HWC可生成VSYNC事件并通过回调将事件发送到SurfaceFlinger,DispSync将Vsync生成由Choreographer和SurfaceFlinger使用的VSYNC_APP和VSYNC_SF信号。

其中app和sf相对于hw_vsync_0都有一个偏移,即phase-app和phase-sf,如下图

Vsync Offset我们指的是VSYNC_APP和VSYNC_SF之间有一个Offset,即上图中phase-sf - phase-app的值,这个Offset是厂商可以配置的。如果Offset不为0,那么意味着App和SurfaceFlinger主进程不是同时收到Vsync信号,而是间隔Offset(通常在0-16.6ms之间)

目前大部分厂商都没有配置这个Offset,所以App和SurfaceFlinger是同时收到Vsync信号的。可以通过Dumpsys SurfaceFlinger来查看对应的值

Offset为0:(sf phase - app phase = 0)

Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]
DispSync configuration: 
          app phase 1000000 ns,              sf phase 1000000 ns 
    early app phase 1000000 ns,        early sf phase 1000000 ns 
 early app gl phase 1000000 ns,     early sf gl phase 1000000 ns 
     present offset 0 ns                      refresh 16666666 ns

Offset不为0 (SF phase - app phase = 4 ms)

Sync configuration: [using: EGL_ANDROID_native_fence_sync EGL_KHR_wait_sync]
VSYNC configuration:
         app phase:   2000000 ns             SF phase:   6000000 ns
   early app phase:   2000000 ns       early SF phase:   6000000 ns
GL early app phase:   2000000 ns    GL early SF phase:   6000000 ns
    present offset:         0 ns         VSYNC period:  16666666 ns

Offset为0

首先说Offset为0的情况,此时App和SurfaceFlinger是同时收到Vsync信号,其对应的Systrace图如下:

这个图上面也有讲解,这里就不再详细说明,大家只需要看到,App渲染好的Buffer,要等到下一个Vsync-SF来的时候才会被SurfaceFlinger拿去做合成,这个时间大概在16.6ms。这时候大家可能会想,如果App的Buffer渲染结束,Swap到BufferQueue中,就触发SurfaceFlinger去做合成,那岂不是省了一些时间(0-16.6ms)

答案是可行的,这也就引入了Offset机制,在这种情况下,App先收到Vsync信号,进行一帧的渲染工作,然后过了Offset时间后,SurfaceFlinger才收到Vsync信号开始合成,这时候如果App的Buffer已经Ready了,那么SurfaceFlinger这一次合成就可以包含App这一帧,用户也会早一点看到。

Offset不为0

下图中,就是一个Offset为4ms的案例,App收到Vsync4ms之后,SurfaceFlinger才收到Vsync信号

Offset的优缺点

Offset的一个比较难以确定的点就在于Offset的时间该如何设置,这也是众多厂商默认都不进行配置Offset的一个原因,其优缺点是动态的,与机型的性能和使用场景有很大的关系

  1. 如果Offset配置过短,那么可能App收到Vsync-App后还没有渲染完成,SurfaceFlinger就收到Vsync-SF开始合成,那么此时如果App的BufferQueue中没有之前累积的Buffer,那么SurfaceFlinger这次合成就不会有App的东西在里面,需要等到下一个Vsync-SF才能合成这次App的内容,时间相当于变成了Vsync周期+Offset,而不是我们期待的Offset
  2. 如果Offset配置过长,就起不到作用了

HW_Vsync

这里需要说明的是,不是每次申请Vsync都会由硬件产生Vsync,只有此次请求vsync的时间距离上次合成时间大于500ms,才会通知hwc,请求HW_VSYNC

以桌面滑动为例,看SurfaceFlinger的进程Trace可以看到HW_VSYNC的状态

后续App申请Vsync时候,会有两种情况,一种是有HW_VSYNC的情况,一种是没有有HW_VSYNC的情况

不使用HW_VSYNC

使用HW_VSYNC

HW_VSYNC主要是利用最近的硬件VSYNC来做预测,最少要3个,最多是32个,实际上要用几个则不一定, DispSync拿到6个VSYNC后就会计算出SW_VSYNC,只要收到的Present Fence没有超过误差,硬件VSYNC就会关掉,不然会继续接收硬件VSYNC计算SW_VSYNC的值,直到误差小于threshold.关于这一块的计算具体过程,可以参考这篇文章:SW-VSYNC的生成与传递,关于这一块的流程大家也可以参考这篇文章,里面有更细节的内容,这里摘录了他的结论

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号