理解Android VSYNC信号的必要性

17

我想更好地了解安卓显示子系统,但仍有一个让我困惑的问题是如何处理VSYNC信号,以及为什么首先存在这么多信号。

安卓设计在其核心使用VSYNC,但有多个VSYNC信号可供选择。通过https://source.android.com/devices/graphics/implement.html中的“VSYNC Offset”部分,有一个流程图,其中说明了三个VSYNC信号:HW_VSYNC_0、VSYNC和SF-VSYNC。我知道HW_VSYNC用于更新DispSync中的时序,而VSYNC和SF-VSYNC由应用程序和surfaceflinger使用,但为什么需要这些单独的信号呢?此外,这些信号的偏移量如何影响它们?是否有可用的时间图能够更好地解释这一点呢?

感谢您提供的任何帮助。

1个回答

30
为了理解这些内容,最好从系统级图形架构文档开始,特别注意三倍缓冲的需求部分和相关的图表(最好是动态GIF)。句子开头的“如果应用程序在VSYNC信号中间开始渲染”是特指DispSync。一旦你读过那个,希望设备图形文档中的DispSync部分就更有意义了。
大多数设备没有配置DispSync偏移量,因此只有一个VSYNC信号。以下内容假定已启用DispSync。
硬件仅提供一个VSYNC信号,对应于主显示器刷新。其他信号由SurfaceFlinger DispSync代码在固定偏移处生成。一些巧妙的软件用于保持时间不会失调。
这些信号用于触发SurfaceFlinger合成和应用程序渲染。如果您遵循架构文档中的部分,您会发现这在应用程序呈现其内容和内容出现在屏幕上之间建立了两个延迟帧。可以这样想:给定三个VSYNC发生时,应用程序在V0处绘制,系统在V1处进行合成,然后将合成帧发送到显示器在V2处。
如果您正在尝试跟踪触摸输入,例如在用户手指下移动地图,则任何延迟都将被用户视为反应迟钝的触摸响应。目标是最小化延迟以提高用户体验。假设我们稍微延迟事件,使应用程序在V0.5处绘制,我们在V1.2处合成,然后在V2处切换到显示器。通过偏移应用程序和SF活动,我们将总延迟从2帧减少到1.5帧,如下所示。

enter image description here

这就是DispSync的作用。在您链接的页面上的反馈图中,HW_VSYNC_0是物理显示器的硬件刷新,VSYNC导致应用程序进行渲染,而SF_VSYNC导致SurfaceFlinger执行组合。将它们称为“VSYNC”有点不准确,但在LCD面板上,将任何东西称为“VSYNC”可能都是不准确的。
反馈循环图中提到的“退休栅栏时间戳”是一种巧妙的优化。由于我们在实际的硬件VSYNC上没有做任何工作,如果关闭刷新信号,我们可以稍微更有效率一些。DispSync代码将使用退休栅栏的时间戳(这是一个完全不同的讨论)来查看是否失去同步,并且会暂时重新启用硬件信号,直到再次保持同步。
编辑:您可以在Nexus 5 boardconfig中查看值的配置方式。请注意VSYNC_EVENT_PHASE_OFFSET_NSSF_VSYNC_EVENT_PHASE_OFFSET_NS的设置。

1
fadden,再次感谢您的帮助。只有两个问题:1)我制作的定时图表有意义吗?原始图表(2帧延迟):i.imgur.com/4E2cD9l.png DispSync图表:i.imgur.com/p7LdmXF.png 2)如果您减小偏移量,是否可能在单个帧中进行绘制和合成(冒着降低渲染时间的风险)? - Shookit
这些图看起来不错。在一个VSYNC间隔(通常为16.7毫秒)内绘制和组合是可能的,但实际上很难经常达到这些期限,因此经常尝试这样做会产生不稳定的结果。请注意,如果所有内容都适合叠加层,则SurfaceFlinger组合非常快,但如果它回退到GLES组合,则需要更长时间,特别是如果SF和应用程序最终竞争GPU资源。 DispSync的最准确的可视化是启用了它的设备(例如Nexus 5)的systrace输出。 - fadden
1
硬件上有没有不支持DispSync的原因?还是制造商需要进行更多测试才能实现?我正在N4上进行测试,我注意到N4没有定义任何VSYNC_EVENT_PHASE_OFFSET_NS标志(也没有RUNNING_WITHOUT_SYNC_FRAMEWORK)。在这种情况下,这些标志默认为0,禁用了DispSync? - Shookit
我们曾希望OEM能够提供反相VSYNC信号,但这并没有实现,因此使用了软件解决方案。据我上次检查,很少有设备启用了DispSync。RUNNING_WITHOUT_SYNC_FRAMEWORK是单独但相关的——它指的是图形文档中“显式同步”部分所描述的栅栏系统。例如,Nvidia tegra3板设置了这个参数,如https://android.googlesource.com/device/asus/grouper/+/lollipop-release/BoardConfigCommon.mk。他们使用了较旧的“隐式同步”方法,不过现在可能已经修复了。 - fadden
1
明白了,非常感谢您的时间。我会在有空的时候整理成您的答案。一个快速核实:如果没有使用DispSync,那么HW_VSYNC_0是否会立即触发VSYNC-app和VSYNC-sf,还是这些仍然会被软件计时器触发?或者最终是什么导致这些信号触发? - Shookit
如果未启用DispSync,则硬件VSYNC会触发SF和应用程序。需要注意的是,并非所有应用程序都是基于VSYNC驱动的。框架UI运行在Choreographer回调上,因此动画发生在VSYNC上,但许多应用程序(特别是游戏)只是尽可能快地将帧抛出到SurfaceView。它们仍然受VSYNC限制,因为它们会阻塞等待BufferQueue清空,但它们不会明确地在VSYNC上休眠。(老实说,图形架构文档的大小可以增加10倍,仍然无法涵盖所有细节。) - fadden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接