Двойная буферизация замедляет рендеринг кадров | анализ systrace
Я работаю над простой 2D-игрой с пользовательским видом холста (postInvalidate()) и HardwareAcceleration. После нескольких недель анализа производительности я решил синхронизировать свои операции обновления и рисования с импульсом VSYNC через интерфейс Choreographer.FrameCallback. Я думаю, это правильный способ получить плавные движения.
Однако я все еще испытываю неустойчивые движения. Я проанализировал это с помощью systrace и заметил, что это как-то связано с моим BufferQueue. Как только начинается двойная буферизация, время кадра превышает 16 мс. Я сделал скриншот моего следа с некоторыми объяснениями:
Вся операция рисования ожидает освобождения буфера SurfaceFlinger (потребителя) для удаления своего нового пустого буфера.
Можете ли вы сказать мне, если это обычное поведение или что может быть причиной этого?
1 ответ
На графике у вас есть примечание "SurfaceFlinger пропускает VSYNC".
Однако, если вы посмотрите на строку BufferQueue, вы увидите, что буфер прибыл после крайнего срока VSYNC. SurfaceFlinger проснулся, но делать было нечего.
Затем ваше приложение предоставило дополнительный буфер, что означало, что у вас есть два ожидающих буфера. Поскольку вы продолжали предоставлять буфер на каждом VSYNC, очередь никогда не возвращалась к нулевым буферам. При заполненной очереди каждая попытка добавления дополнительных буферов приводит к блокировке.
FWIW, ваш BufferQueue имеет тройную буферизацию: два находятся в очереди, один на дисплее.
Есть несколько вещей, которые вы можете сделать:
- Приложение пропустит фреймы, если вы пропустили крайний срок.
- Укажите время представления для кадров, чтобы SurfaceFlinger удалял их, если время прошло.
- Умышленно отбрасывайте кадр время от времени, чтобы освободить очередь. (Не предпочтительный подход.)
# 2 работает только с GLES для SurfaceView, поэтому мы можем его игнорировать.
# 1 может работать на вас; Вы можете увидеть пример в Графика. По сути, это говорит: "Если следующий VSYNC запускается менее чем за 2 мс или уже выстрелил, не беспокойтесь о рендеринге текущего кадра". Подход View/invalidate не дает такого же детального контроля, как GLES, поэтому я не уверен, насколько хорошо это будет работать.
Ключ к плавной анимации на занятом устройстве - это не каждый кадр со скоростью 60 кадров в секунду. Главное, чтобы ваши обновления основывались на дельта-времени, чтобы все выглядело гладко, даже если вы пропустите кадр или два.
Дополнительные сведения о графической архитектуре см. В этом документе.