3

我正在尝试在尽可能多的 Android 设备上以 60 fps 的速度运行具有挑战性且对延迟敏感的应用程序。它涉及处理来自相机的实时帧(理想情况下也是 60 fps)以及使用 OpenGL ES 2/3 在顶部渲染额外的图形。

我首先只是尝试识别和最小化活动的任何系统级开销,使用带有最小测试应用程序的 systrace,该应用程序在 SurfaceTexture 中获取相机帧并使用 OpenGL ES 2 将它们渲染到 GLSurfaceView。

我一直在研究带有 Android 8.0 的三星 Galaxy S8(具有 Mali GPU 和 4 大 4 小 CPU 设置的 Exynos 版本)。

当接收到相机帧但不渲染它们时(例如,通过将 GLSurfaceView 切换到 RENDERMODE_WHEN_DIRTY 而不是 RENDERMODE_CONTINUOUSLY),CPU 使用率在整个板上显得相当低,每帧的 CPU 使用量很少,这看起来与 SurfaceTexture 的队列和出队缓冲区有关。正如预期的那样,当没有更新任何表面时,SurfaceFlinger 似乎什么都不做。

一旦我开始渲染新帧,事情就会变得更加有趣。我的应用程序中的 GLThread 只需要大约 1.5 毫秒的 CPU 时间,这与我的预期大致相同。出乎意料的是 SurfaceFlinger 所需的 CPU 时间。

这是 systrace 的一些输出,对于大多数帧来说都是典型的:

SurfaceFlinger 系统跟踪

呈现的每一帧都经过 2 个 SurfaceFlinger 操作 - 有一个handleMessageInvalidate调用 an updateTexImage,然后是一个handleMessageRefresh主要用于 的doComposition,其中大部分用于postFramebuffer.

请注意,此时的大部分时间,线程在 CPU 上处于活动状态,而不是处于休眠状态。这大约是 SurfaceFlinger 中一个核心花费的帧时间的三分之一——如果调度程序决定为我的一个重要线程使用同一个核心,这将非常重要。

我已经阅读了很多关于 SurfaceFlinger 内部的内部文档,包括讨论硬件 Composer 的页面:https ://source.android.com/devices/graphics/arch-sf-hwc 。

我对 HWC 的理解是所有的合成都是在显示硬件中完成的——我希望 CPU 端的工作尽可能少;只是锁定最新的缓冲区并将它们传递给 HWC。

dumpsys SurfaceFlinger确实表明 HWC 正在用于所有层:

|    type   |  handle    | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name 
|-----------+------------+------+------+----+------+-------------+--------------------------------+------------------------+------
|       HWC | 75cee57f40 | 0000 | 0020 | 00 | 0100 | RGBx_8888   |    0.0,    0.0, 1152.0, 2960.0 |    0,    0, 1152, 2960 | SurfaceView - com.example.tangobravo.camera1test/com.example.tangobravo.camera1test.MainActivity@e16091d@3#0
|       HWC | 75cee59b40 | 0000 | 0000 | 00 | 0105 | RGBA_8888   | 1104.0,    0.0, 1440.0, 2960.0 | 1104,    0, 1440, 2960 | com.example.tangobravo.camera1test/com.example.tangobravo.camera1test.MainActivity#0
|       HWC | 75cee58100 | 0000 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0,   96.0, 2960.0 | 1344,    0, 1440, 2960 | StatusBar#0
| FB TARGET | 75cee55b60 | 0000 | 0000 | 00 | 0105 | RGBA_8888   |    0.0,    0.0, 1440.0, 2960.0 |    0,    0, 1440, 2960 | HWC_FRAMEBUFFER_TARGET

发生什么了?为什么这里的 HWC 这么贵?我应该为应用程序使用更好的(更低的开销)模式吗?

我希望 NEON CPU 合成器能够在 5 毫秒左右的时间内通过这些层,因此 HWC 在 CPU 使用率方面并没有带来多大的优势。

4

0 回答 0