Библиотека Android Frame Pacing, также известная как Swappy, входит в состав Android Game SDK. Она помогает играм, использующим OpenGL и Vulkan, обеспечивать плавную отрисовку и правильную смену кадров на устройствах Android.
Синхронизация кадров – это синхронизация логики игры и цикла отрисовки с подсистемой дисплея ОС и базовым оборудованием дисплея. Подсистема отображения Android была разработана таким образом, чтобы избежать определенных визуальных артефактов, таких как разрывы. Подсистема отображения предотвращает разрывы, выполняя следующие действия:
- Внутреннее буферирование предыдущих кадров
- Обнаружение задержек при отправке кадров
- Продолжать показывать текущий кадр при обнаружении запоздавшего кадра.
Несоответствие времени показа кадров возникает, когда цикл отрисовки игры выполняется с частотой, отличной от частоты, поддерживаемой встроенным оборудованием дисплея. Проблемы возникают, когда цикл отрисовки игры выполняется слишком медленно для оборудования дисплея, что приводит к непостоянному времени отображения. Например, если игра с частотой 30 кадров/с запускается на устройстве, которое поддерживает 60 кадров/с, то из-за цикла рендеринга повторяющийся кадр остается на экране ещё на 16 мс. Это приводит к существенным несоответствиям во времени формирования кадра, например 33 мс, 16 мс и 49 мс. Слишком сложные сцены усугубляют проблему, поскольку приводят к пропуску кадров.
Библиотека синхронизации кадров выполняет следующие задачи:
- Компенсирует заикание из-за коротких игровых кадров.
- Добавляет временные метки, чтобы кадры показывались вовремя, а не раньше.
- Использует расширения временных меток презентации
EGL_ANDROID_presentation_timeиVK_GOOGLE_display_timing.
- Использует барьеры синхронизации для длинных кадров, которые приводят к задержкам и заиканию.
- Внедряет в приложение задержки. Это позволяет конвейеру отображения догнать, а не позволяет наращивать противодавление.
- Используются барьеры синхронизации (
EGL_KHR_fence_syncиVkFence).
- Выбирает частоту обновления, чтобы обеспечить гибкость и плавное воспроизведение, если устройство поддерживает несколько частот обновления.
- Предоставляет статистику для отладки и профилирования с помощью статистики кадров.
Чтобы узнать, как настроить библиотеку для работы в разных режимах, ознакомьтесь со статьей Поддерживаемые режимы работы.
Чтобы реализовать рендеринг с помощью OpenGL или Vulkan, ознакомьтесь со следующими статьями:
- Как интегрировать Android Frame Pacing в рендерер OpenGL
- Как интегрировать Android Frame Pacing в рендерер Vulkan
Подробнее о библиотеке Frame Pacing…
Ограничение количества кадров в секунду
Ограничение количества кадров в секунду (FPS) позволяет играм работать с подходящим количеством кадров в секунду, используя только изменения на стороне платформы и не требуя никаких действий со стороны разработчиков.
При реализации ограничения частоты кадров используются следующие компоненты.
GameManagerService
Компонент
GameManagerService хранит всю информацию о режиме и вмешательстве для каждого пользователя и каждой игры. Информация о частоте кадров в секунду хранится в GameManagerService вместе с другими данными о вмешательстве, например коэффициентом уменьшения разрешения, в сопоставлении <PACKAGE_NAME, Interventions> для каждого профиля пользователя.
Информация о частоте кадров в секунду становится доступна при изменении игрового режима или обновлении вмешательства. UID уникален для каждого PACKAGE_NAME и пользователя и может быть преобразован в пару <UID, Frame Rate> для отправки в SurfaceFlinger.
SurfaceFlinger
Компонент SurfaceFlinger уже поддерживает ограничение частоты кадров приложения, если она является делителем частоты обновления экрана. При получении сигнала VSync SurfaceFlinger проверяет его действительность для приложения с ограничением частоты кадров. Для этого он сравнивает временную метку VSync с частотой кадров приложения. Если частота кадров не совпадает с VSync, SurfaceFlinger удерживает кадр, пока они не совпадут.
На рисунке ниже показано взаимодействие между GameManagerService и SurfaceFlinger:
Рисунок 1. Взаимодействие между GameServiceManager и SurfaceFlinger.
SurfaceFlinger поддерживает пару <UID, Frame Rate>, чтобы задать новый приоритет ограничения частоты кадров. Значение UID уникально для каждого пользователя и игры, поэтому у разных пользователей одного устройства могут быть разные настройки частоты кадров в одной и той же игре. Чтобы ограничить частоту кадров в игре, GameManagerService вызывает SurfaceFlinger для переопределения частоты кадров для UID. С помощью этого механизма SurfaceFlinger обновляет сопоставление при каждом изменении игрового режима или вмешательства. SurfaceFlinger обрабатывает изменение частоты кадров, соответствующим образом фиксируя буферы.
Подробнее об ограничении частоты кадров…