- PVSM.RU - https://www.pvsm.ru -
Всем привет!
В мире существует огромное количество приложений на OpenGL, и, кажется, Apple c этим не вполне согласна. Начиная с iOS 12 и MacOS Mojave, OpenGL переведен в статус устаревшего. Мы интегрировали Apple Metal в MAPS.ME и готовы поделиться своим опытом и результатами. Расскажем, как рефакторили наш графический движок, с какими трудностями пришлось столкнуться и, самое главное, сколько у нас теперь FPS.
Всех, кто заинтересовался или раздумывает над добавлением поддержки Apple Metal в графический движок, приглашаем под кат.
Наш графический движок проектировался как кроссплатформенный, и так как OpenGL является, по сути, единственным кроссплатформенным графическим API для интересующего нас набора платформ (iOS, Android, MacOS и Linux), то выбрали его в качестве основы. Мы не сделали дополнительный уровень абстракции, который скрывал бы характерные для OpenGL особенности, но, к счастью, оставили потенциальную возможность его внедрения.
С появлением графических API нового поколения Apple Metal и Vulkan, мы, разумеется, рассматривали возможность их появления в нашем приложении, однако, нас останавливало следующее:
Когда весной 2018 года Apple объявила о переводе OpenGL в статус deprecated, стало понятно, что откладывать больше нельзя, и вышеописанные проблемы необходимо тем или иным способом решить. Кроме того, мы давно уже работали над оптимизацией как скорости работы приложения, так и энергопотребления, и Apple Metal, казалось, мог в этом помочь.
Почти сразу мы обратили внимание на MoltenVK [2]. Этот фреймворк эмулирует Vulkan API при помощи Apple Metal, к тому же его исходный код был не так давно открыт. Использование MoltenVK, казалось, позволило бы заменить OpenGL на Vulkan, и вообще не заниматься отдельной интеграцией Apple Metal. Кроме того, разработчики Qt отказались от отдельной поддержки рендеринга на Apple Metal [3] в пользу MoltenVK. Однако, нас остановили:
Получалось, что OpenGL нам необходимо сохранить, а значит не обойтись без абстрагирования движка от графического API. Apple Metal, OpenGL ES, а в будущем и Vulkan, будут использованы при создании независимых внутренних компонентов графического движка, которые смогут быть полностью взаимозаменяемыми. OpenGL будет играть роль fallback-варианта в тех случаях, когда Metal или Vulkan по той или иной причине недоступны.
План реализации был такой:
Чтобы понять, как именно абстрагировать графический API, давайте сначала определим, какие ключевые концептуальные различия есть между OpenGL и Metal.
Процесс рефакторинга графического движка, в основном, заключался в поиске лучшего решения для избавления от особенностей OpenGL, которыми активно пользовался наш движок. Встраивание Metal, начиная с какого-то из этапов, шло параллельно.
Наш абстрактный объект мы назвали графическим контекстом, и в случае OpenGL он просто декорирует вызовы OpenGL-команд, а в случае Metal — содержит корневой интерфейс MTLDevice, через который вызываются команды Metal.
Разумеется, пришлось распространить этот объект (а так как рендеринг у нас многопоточный, то даже несколько таких объектов) по всех подсистемам.
Создание очередей команд, кодировщиков (encoders) и управление ими мы скрыли внутри графического контекста, чтобы не распространять по движку сущности, которых просто не существует в OpenGL.
В итоге, примерно через 5 месяцев работ мы смогли в первый раз запустить MAPS.ME с полноценным рендерингом на Apple Metal. Пора было узнать, что же у нас получилось.
Мы использовали в эксперименте устройства Apple разных поколений. Все они были обновлены до iOS 12. На всех исполнялся одинаковый пользовательский сценарий — навигация по карте (перемещение и масштабирование). Сценарий был заскриптован, чтобы гарантировать почти полную идентичность процессов внутри приложения при каждом запуске на каждом из устройств. В качестве тестовой локации выбрали район Лос-Анджелеса — одна из самых высоконагруженных областей в MAPS.ME.
Сначала сценарий исполнялся с рендерингом на OpenGL ES 3.0, затем на том же устройстве с рендерингом на Apple Metal. Между запусками приложение полностью выгружалось из памяти.
Измерялись следующие показатели:
При измерении FPS исключалось рисование непосредственно на экране устройства, так как вертикальная синхронизация с частотой обновления экрана не позволяет получить достоверные результаты. Поэтому кадр рисовался в текстуру в памяти. Для синхронизации CPU и GPU в OpenGL использовался дополнительный вызов команды glFinish
, в Apple Metal — waitUntilCompleted
для MTLFrameCommandBuffer
.
iPhone 6s | iPhone 7+ | iPhone 8 | ||||
---|---|---|---|---|---|---|
OpenGL | Metal | OpenGL | Metal | OpenGL | Metal | |
FPS | 106 | 160 | 159 | 221 | 196 | 298 |
FPS (только рендеринг) | 157 | 596 | 247 | 597 | 271 | 833 |
Доля медленных кадров (< 30 fps) | 4,13 % | 1,25 % | 5,45 % | 0,76 % | 1,5 % | 0,29 % |
iPhone X | iPad Pro 12.9' | |||
---|---|---|---|---|
OpenGL | Metal | OpenGL | Metal | |
FPS | 145 | 210 | 104 | 137 |
FPS (только рендеринг) | 248 | 705 | 147 | 463 |
Доля медленных кадров (< 30 fps) | 0,15 % | 0,15 % | 17,52 % | 4,46 % |
iPhone 6s | iPhone 7+ | iPhone 8 | iPhone X | iPad Pro 12.9' | |
---|---|---|---|---|---|
Ускорение кадра на Metal (в N раз) | 1,5 | 1,39 | 1,52 | 1,45 | 1,32 |
Ускорение рендеринга на Metal (в N раз) | 3,78 | 2,41 | 3,07 | 2,84 | 3,15 |
Улучшение по медленным кадрам (в N раз) | 3,3 | 7,17 | 5,17 | 1 | 3,93 |
В среднем, прирост производительности кадра при использовании Apple Metal составил 43 %. Минимальное значение зафиксировано на iPad Pro 12.9’ — 32 %, максимальное — 52 % на iPhone 8. Просматривается зависимость: чем меньше разрешение экрана, тем больше Apple Metal превосходит OpenGL ES 3.0.
Если оценивать часть кадра, ответственную непосредственно за рендеринг, то в среднем скорость рендеринга на Apple Metal выросла в 3 раза. Это говорит о существенно лучшей организации, и, как следствие, эффективности Apple Metal API по сравнению с OpenGL ES 3.0.
Количество медленных кадров (меньше 30 мс), на Apple Metal сократилось примерно в 4 раза. Это означает, что восприятие анимаций и перемещения по карте стало более плавным. Наихудший результат зафиксирован на iPad Pro 12.9’ с разрешением 2732 x 2048 пикселей: OpenGL ES 3.0 дает примерно 17,5 % медленных кадров, тогда как Apple Metal — только 4,5 %.
Энергопотребление тестировалось на iPhone 8 на iOS 12. Исполнялся одинаковый пользовательский сценарий — навигация по карте (перемещение и масштабирование) в течение 1 часа. Сценарий был заскриптован, чтобы гарантировать почти полную идентичность процессов внутри приложения на каждом запуске. В качестве тестовой локации был также выбран район Лос-Анджелеса.
Мы использовали следующий подход к измерению энергопотребления. Устройство не подключено к зарядке. В настройках разработчика включено логирование энергопотребления. Перед началом эксперимента устройство полностью заряжено. Конец эксперимента наступает по завершению сценария. В конце эксперимента фиксировалось состояние заряда батареи, а логи энергопотребления импортировались в утилиту для профилирования батареи в XCode. Мы регистрировали, какая часть заряда была потрачена на работу GPU. Кроме того, здесь мы дополнительно утяжелили рендеринг, включив отображение схемы метро и полноэкранный антиалиасинг.
Яркость экрана не менялась во всех случаях. Никаких других процессов, кроме системных и MAPS.ME, не исполнялось. Был включен авиарежим, выключены Wi-Fi и GPS. Дополнительно проводилось несколько контрольных измерений.
В итоге, для каждого из показателей формировалось сравнение Metal с OpenGL, а затем коэффициенты отношения усреднялись, чтобы получить одну агрегированную оценку.
OpenGL | Metal | Прирост | |
---|---|---|---|
Потраченный заряд батареи | 32 % | 28 % | 12,5 % |
Профилирование Battery Usage в XCode | 1,95 % | 1,83 % | 6,16 % |
В среднем, энергопотребление версии с рендерингом на Apple Metal незначительно улучшилось. На энергопотребление нашего приложения GPU оказывает не слишком большое влияние, порядка 2%, потому что MAPS.ME нельзя назвать высоконагруженным с точки зрения использования GPU. Небольшой выигрыш достигается, вероятно, за счет уменьшения вычислительных затрат при подготовке команд для GPU на CPU, что, к сожалению, нельзя выделить при помощи инструментов профилирования.
Встраивание Metal обошлось нам в 5 месяцев разработки. Этим занимались два разработчика, правда, почти всегда по очереди. Мы, очевидно, значительно выиграли по производительности рендеринга, немного выиграли по энергопотреблению. Кроме того, мы получили возможность встраивать новые графические API, в частности, Vulkan, куда меньшими усилиями. Почти целиком «перебрали» графический движок, в результате нашли и исправили несколько старых багов и проблем с производительностью.
На вопрос, действительно ли нашему проекту нужен рендеринг на Apple Metal, мы готовы ответить утвердительно. Дело не столько в том, что мы любим инновации, или в том, что Apple может окончательно отказаться от OpenGL. Просто на дворе 2018 год, а OpenGL появился в далеком 1997-м, давно пора сделать следующий шаг.
P.S. Пока мы не запустили фичу на всех iOS-устройствах. Для ручного включения напишите в строке поиска команду ?metal
и перезапустите приложение. Чтобы вернуть рендеринг на OpenGL, введите команду ?gl
и перезапустите приложение.
P.P.S. MAPS.ME — это open-source проект. С исходными кодами вы можете ознакомиться на github [4].
Автор: rokuz
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/opengl/302054
Ссылки в тексте:
[1] сейчас поддерживается Vulkan: http://blog.qt.io/blog/2017/06/06/vulkan-support-qt-5-10-part-1/
[2] MoltenVK: https://github.com/KhronosGroup/MoltenVK
[3] отказались от отдельной поддержки рендеринга на Apple Metal: http://blog.qt.io/blog/2018/05/30/vulkan-for-qt-on-macos/
[4] github: https://github.com/mapsme/omim
[5] Источник: https://habr.com/post/430850/?utm_campaign=430850
Нажмите здесь для печати.