Почему SurfaceFlinger все еще использует 5 мс процессорного времени на кадр с Hardware Composer?

Я пытаюсь запустить сложное и чувствительное к задержкам приложение со скоростью 60 кадров в секунду на как можно большем количестве устройств Android. Он включает в себя обработку живых кадров с камеры (в идеале также со скоростью 60 кадров в секунду) наряду с рендерингом дополнительной графики поверх OpenGL ES 2/3.

Во-первых, я просто пытаюсь определить и минимизировать любые накладные расходы на уровне системы, используя systrace с минимальным тестовым приложением, которое получает кадры камеры в SurfaceTexture и отображает их с помощью OpenGL ES 2 в GLSurfaceView.

Я исследовал Samsung Galaxy S8 (версия Exynos с графическим процессором Mali и 4-мя маленькими настройками процессора) с Android 8.0.

При получении кадров камеры, но не при их рендеринге (например, путем переключения GLSurfaceView на RENDERMODE_WHEN_DIRTY, а не на RENDERMODE_CONTINUOUSLY), загрузка ЦП оказывается довольно низкой по всей плате с небольшим объемом использования ЦП на кадр, который выглядит связанным с очередями и выгрузкой буферов для SurfaceTexture. SurfaceFlinger, кажется, ничего не делает, когда ни одна из поверхностей не обновляется, как ожидалось.

Как только я начинаю рендерить новые кадры, все становится интереснее. GLThread в моем приложении занимает всего ~1,5 мс процессорного времени, примерно то, что я ожидал. Что является неожиданным, так это время процессора, требуемое в SurfaceFlinger.

Вот немного вывода systrace, типичного для большинства кадров:

SurfaceFlinger systrace

Каждый представленный кадр проходит 2 операции SurfaceFlinger - есть handleMessageInvalidate это вызывает updateTexImageи затем handleMessageRefresh что в основном тратится на doComposition, причем большая часть этого потрачена на postFramebuffer,

Обратите внимание, что большую часть этого времени поток активен на процессоре, а не спит. Это примерно треть времени кадра для одного ядра, потраченного в SurfaceFlinger - это очень важно, если планировщик решит использовать то же ядро ​​для одного из моих важных потоков.

Я прочитал довольно много внутренних документов, посвященных внутренним компонентам SurfaceFlinger, включая эту страницу, посвященную Композитору аппаратного обеспечения: https://source.android.com/devices/graphics/arch-sf-hwc.

Мое понимание HWC заключалось в том, что вся композиция была выполнена на оборудовании дисплея - я ожидал, что работа на стороне процессора будет минимальной; просто фиксируя последние буферы и передавая их в 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 обеспечивает большую выгоду с точки зрения использования процессора.

0 ответов

Другие вопросы по тегам