[Перевод] Оптимизация Android-игры mTricks Looting Crown для платформы Intel Atom

Самая популярная категория мобильных приложений — игры. В былые времена возможности процессоров и графических ускорителей портативных устройств были весьма ограничены, что сказывалось на их производительности. В итоге большинство игр приходилось делать достаточно простыми. Сегодня вычислительные мощности смартфонов и планшетов значительно выросли, а значит, появилась возможность создавать высококачественные, ресурсоёмкие игры. Однако мобильные CPU и GPU всё еще уступают тем, которые устанавливают в персональные компьютеры.

Рост рынка мобильных приложений привёл к тому, что многие производители игр для PC теперь создают игры для мобильных платформ. Однако традиционные подходы к проектированию игр не очень хорошо работают в мобильной среде. То же самое касается и графических ресурсов PC-игр, которые слишком «тяжелы» для мобильного аппаратного обеспечения.

363a75cd06c04121816a05e27cb69cf4.jpg

Из этой статьи вы узнаете о том, как можно проанализировать и улучшить производительность мобильной игры и о том, как оптимизировать графические ресурсы для мобильных платформ.
Всё это мы рассмотрим на примере игры mTricks Looting Crown. IA-версия игры уже опубликована, вот ссылка на неё.

574da7115a4426b1a526261ea2feec96.jpg
Игра mTricks Looting Crown.

1. Предварительные сведения


У компании mTricks есть огромный опыт в разработке компьютерных игр с использованием различных коммерческих движков. Планируя следующий проект, эксперты компании, учитывая рост производительности мобильных устройств, спрогнозировали готовность мобильного рынка к сложным MMORPG. В итоге свой новый проект компания нацелила на мобильные платформы, а не на обычные компьютеры.

Для начала, mTricks перенесла свои PC-наработки на Android. Однако производительность решения оставляла желать лучшего. В частности, одной из аппаратных платформ, на которую ориентировались при разработке, были устройства, основанные на процессорах Intel Atom (Bay Trail).

Компания mTricks столкнулась с двумя проблемами, которые обычно встают перед PC-разработчиками, переходящими к созданию мобильных приложений.

  1. Традиционные для PC графические ресурсы и подходы к проектированию не годятся для мобильных приложений. Всё дело в том, что мобильные процессоры и видеокарты пока отстают от аналогичных компонентов персональных компьютеров.
  2. Мобильные устройства создают на основе широкого спектра компонентов, которые имеют различные характеристики. Это и вычислительные возможности CPU и GPU, и количество оперативной памяти, и размер экрана. Как результат, на различных целевых платформах в распоряжении игры оказываются различные ресурсы, что влияет на внешний вид и производительность приложения.


2. Основные положения


Looting Crown — это так называемая SNRPG (Social Network + RPG), то есть — ролевая игра с функциями социальной сети. Она поддерживает трёхмерную графику и различные режимы многопользовательской игры (PvP, PvE, Clan vs Clan). В ходе разработки и оптимизации игры mTricks использовала референсное устройство, построенное на платформе Bay Trail. Ниже приведены технические характеристики этого устройства.

Характеристики устройства и результаты тестирования

Показатель Характеристика устройства (диагональ экрана — 10 дюймов)
CPU Intel Atom Quad Core 1.46 Ghz
RAM 2Gb
Разрешение экрана 2560×1440
Очки в тесте 3DMark ICE Storm Unlimited 15094
Тест графики 13928
Тест физических эффектов 21348


Компания mTricks при разработке игры использовала Intel Graphics Performance Analyzers (Intel GPA) для поиска узких мест в работе CPU и GPU. Результаты анализа применялись для решения проблем с графическими ресурсами и производительностью.

Эталонная точка, с которой начинали оптимизацию и анализ производительности, составила 23 кадра в секунду (FPS, Frame per Second). Ниже показаны характеристики загрузки графического ядра (GPU Busy) и статистика нагрузки на процессор, которую генерирует приложение (Target App CPU Load). Данные получены за 2 минуты работы приложения. Средняя загрузка графического ядра составила 91%. Нагрузка на процессор составила порядка 27%.

17eecfe2876799eab65be54cea766fb9.png
Эталонная точка измерений загруженности процессора и графического ядра. Данные получены с помощью Intel GPA System Analyzer.

3. Кто виноват, процессор или видеоядро?


Есть два способа узнать о том, что именно является узким местом системы: CPU или GPU. Один из них заключается в использовании обходных режимов (override modes). Второй подразумевает изменение тактовой частоты CPU.

Одним из обходных режимов, предусмотренных в Intel GPA System Analyzer, является режим Disable Draw Calls (отключить функции рисования). Он помогает понять, процессор или видеоядро являются узким местом системы. После проведения испытаний в этом режиме нужно сравнить полученные результаты с теми, которые были получены в стандартном состоянии системы. Интерпретировать эти результаты поможет следующая таблица.

Как анализировать игры с помощью обходного режима Disable Draw Calls

Изменение производительности в режиме Disable Draw Call Интерпретация
FPS меняется незначительно Скорость работы игры привязана к производительности CPU. Воспользуйтесь инструментами Intel GPA Platform Analyzer или Intel VTune Amplifier для того, чтобы выяснить, какие именно функции наиболее сильно нагружают систему.
FPS заметно улучшается Скорость работы игры привязана к производительности GPU. Воспользуйтесь средством Intel GPA Frame Analyzer для того, чтобы выяснить, обработка каких именно запросов на вывод изображений занимает больше всего времени.


Intel GPA System Analyzer позволяет исследовать производительность приложения с различными настройками CPU. Это очень полезно в деле поиска узких мест. Для того чтобы определить, привязана ли производительность игры к CPU, нужно сделать следующее:

  1. Удостоверьтесь в том, что частота кадров вашего приложения не привязана к вертикальной синхронизации (Vertical Sync, Vsync). Для этого взгляните на панель уведомлений Intel GPA System Analyzer. Если этот режим включен, вы увидите слово Vsync, выделенное серым цветом: e8421601940b7ee9e08a033a77c9c595.jpg
  2. Попробуйте выставлять различные частоты CPU, пользуясь ползунками на панели Platform Settings в окне Intel GPA System Analyzer. Если FPS меняется при изменении частоты процессора, очень похоже, что производительность приложения привязана к CPU


a35931389e437d97750096d823cd248d.png
Модификация частоты процессора на панели Platform Settings.

В следующей таблице приведены результаты экспериментов с Looting Crown. В режиме Disable Draw Calls частота кадров не меняется. Это позволяет сделать вывод о том, что производительность игры привязана к CPU. Однако, при установке максимально возможной частоты процессора (режим Highest CPU Frequency), FPS так же не меняется. Это, в свою очередь, говорит о том, что производительность Looting Crown привязана к видеоядру. Для того чтобы разрешить это противоречие, надо вернуться к эталонной точке измерений, к данным по нагрузке на процессор и видеоядро, которые мы приводили выше. А именно, мы видим, что на референсном устройстве, построенном на платформе Bay Trail, видеоядро загружено на 91%, а процессор — на 27%. Как результат, процессор не может раскрыть весь свой потенциал до тех пор, пока видеочип работает на пределе. GPU, в нашем случае, и является узким местом системы. Поэтому мы, для начала, займёмся оптимизацией использования видеоядра, после чего повторим тестирование.

Результаты измерения FPS в различных режимах

Режим FPS
Обычный 23
Disable Draw Calls 23
Highest CPU Frequency 23


4. Поиск узких мест GPU


Как уже было сказано, мы выяснили, что узкое место игры — в GPU. Проанализируем ситуацию с помощью Intel GPA Frame Analyzer. Вот как выглядит информация о кадрах для эталонной точки измерений.

14ab2f65d41fe2263bc2d39915461e0d.png
Просмотр данных с помощью Intel GPA Frame Analyzer.

4.1. Уменьшение количества вызовов функции рисования


Мы уменьшили количество обращений к функции рисования благодаря объединению сотен статических сеток в одну и применив текстуры большего размера.

Рассмотрим показатели до оптимизации и после. При измерениях мы пользуемся единицей измерения, называемой «эрг» («erg»). Эрг — это команда, выполняющая какую-либо работу на графическом ядре при выводе кадра. Например, эрги — это функции рисования, очистки, другие обращения к графическим API.

Показатели эталонной точки измерений

Показатель Значение
Общее число эргов 1726
Общее число примитивов 122204
Длительность работы GPU, мс 23
Время, нужное для показа кадра, мс 48


Оценка затрат на вывод изображения для эталонной точки измерений

Тип операции Количество эргов Время, мс %
Очистка 0 0.2 0.5
Океан 1 6 13.7
Местность
2~977
20
41.9
Трава
19~977
18
39.0
Персонаж, здания, эффекты
978~1676
19
40.6
Пользовательский интерфейс
1677~1725
1
3.4


Общее время вывода «Местности» составляет 20 мс, в то время как на «Траву», которой эта «Местность» заросла, — 18 мс. Это — около 90% времени от того, которое требуется для обработки «Земли». Поэтому продолжаем анализ для того, чтобы понять, почему вывод «Травы» требует столь серьезных затрат времени.

fa5458bec8ae7a369a2305b8ca800e75.png
Процесс построения «местности».

4e8d772e5665cbd4663c80822e28a7b3.png
Текстура «Травы».

Looting Crown заполняет большую часть «земли» маленькими квадратиками «травы». В итоге, количество обращений к функции рисования в графе «Местность» (в таблице ниже) составляет 960. Время рисования одного такого фрагмента очень мало. Однако вывод всех фрагментов перегружает систему. Сравнительно простая операция потребляет неоправданно большое количество ресурсов. Поэтому мы остановились на том, что нужно уменьшить количество вызовов функции рисования за счёт объединения нескольких сотен статических сеток в одну. Кроме того, мы решили использовать текстуру большего размера. Вот, что получилось после этой оптимизации:

Сравнение затрат на вывод изображения при использовании маленьких и больших текстур

Показатель Значение
Маленькая текстура, мс. 18
Количество эргов 960
Большая текстура, мс. 6
Количество эргов 1


06be6618cfe012db7b6127bf8c199052.png
Измененная «Местность».

Вывод «местности», состоящей из текстур маленького размера, требует большого количества вызовов функции рисования. Поэтому мы уменьшили количество таких вызовов и сэкономили 12 миллисекунд на выводе «травы».

4.2. Оптимизация графических ресурсов


Вот какие результаты получены при применении текстуры большого размера для «Травы».

Данные о производительности, полученные после первой оптимизации

Показатель Значение
Общее число эргов 179
Общее число примитивов 27537
Длительность работы GPU, мс. 24
Время, нужное для показа кадра, мс. 27


Оценка затрат на вывод изображения после первой оптимизации

Тип операции Количество эргов Время, мс %
Очистка 0 2 10.4
Океан
18
6
23.6
Местность
1~17, 19, 23~96
14
53.4
Трава
19
6
23.2
Персонаж, здания, эффекты
20~22, 97~131
1
5.9
Пользовательский интерфейс
132~178
1
5.7


После первого прохода оптимизации мы снова проверили, привязана ли производительность игры к GPU. Были выполнены те же самые измерения, что и ранее — в режимах отключения функций рисования (Disable Draw Calls) и наивысшей частоты процессора (Highest CPU Frequency).

Результаты измерения FPS после первой оптимизации

Режим
FPS
Обычный
40
Disable Draw Calls
60
Highest CPU Frequency
40


Из таблицы видно, что при отключении функций рисования FPS растёт, а при выставлении максимальной частоты процессора — не меняется. Это говорит о том, что производительность Looting Crown всё еще привязана к графическому ядру. Кроме того, мы снова проверили нагрузку, которую игра создаёт на CPU и GPU.

932de868bf1239e6dad661d20acf8d8c.png
Загруженность процессора и графического ядра после первой оптимизации. Данные получены с помощью Intel GPA System Analyzer.

Здесь видно, что на референсной системе, построенной на платформе Bay Trail, загрузка процессора составляет порядка 13%, а вот графическое ядро загружено на 99%. Таким образом, оптимизации, касающиеся использования центрального процессора, не дадут роста производительности игры до тех пор, пока мы не разберемся с перегрузкой видеоядра.

Игра Looting Crown была изначально создана для PC. Её графические ресурсы не подходят для мобильных устройств, которые имеют менее мощные CPU и GPU, нежели устройства настольные. Поэтому мы подвергли графические ресурсы серии оптимизаций.

1. Минимизация вызовов функции рисования (Draw Calls)

▪ С 10 до 2 уменьшено количество материалов объектов.
▪ Уменьшено количество слоёв частиц.

2. Уменьшено количество полигонов

▪ С помощью средства Simplygon уменьшен уровень детализации (LOD, Level Of Details) персонажей.

017efb423dbd43b86a47713e589c1b43.png
Персонаж на разных стадиях уменьшения уровня детализации.

▪ Уменьшено число полигонов, используемых для вывода «местности». Для начала мы уменьшили детализацию гор, которые расположены далеко и не требуют высокой детализации. Затем уменьшили число полигонов для плоской «земли», для моделирования которой достаточно пары треугольников.

3. Использованы оптимизированные карты освещения.

▪ Отключено динамическое освещение для «Времени суток».
▪ Сведен к минимуму размер карты освещения для каждой из сеток, в частности — для фона.

4. Сведено к минимуму изменение состояний элементов рендеринга.

▪ Уменьшено количество материалов, что снизило количество изменений состояний элементов рендеринга и изменений текстур.

5. Отделены анимированные части статических сеток.

▪ Движок Havoc, который использовался при создании игры, не поддерживает обновление только той области объекта, которая подвергается анимации. Если у объекта подвижна лишь небольшая часть, то он, всё равно, обновляется целиком. Для того чтобы справиться с этим, мы отделили подвижные части (дым, выделен красным кружком на следующем рисунке) от неподвижной части объектов. В итоге получилось две раздельных модели игровых объектов.

cd39831a15f8c51dbf63767a96919fd2.jpg
Отделение анимированного дыма от статической сетки.

4.3. Эффективное применение Z-отсечения


Когда 3D-видеокарта выводит объекты, трехмерная сцена (точки в которой имеют координаты x, y, z) проецируется на плоскость (переход к модели координат x, y). Для того чтобы сохранить информацию о глубине каждого пикселя (то есть — данные координаты z) используется так называемый Z-буфер или буфер глубины. Если в одной и той же точке плоскости нужно вывести два трехмерных объекта, GPU сравнивает данные по глубинам этих объектов. Видеоядро перезапишет текущий пиксель, если новый объект находится ближе к наблюдателю, чем прежний. Таким образом, использование Z-буфера позволяет правильно воспроизвести привычную глубину пространства. Техника Z-отсечения (Z-culling) заключается в том, что сначала рисуются те объекты, которые расположены ближе, они перекрывают удалённые объекты, которые не приходится рисовать только затем, чтобы позже «закрасить». Z-отсечение позволяет улучшить производительность при рендеринге скрытых поверхностей.

В Looting Crown часть местности покрыта океаном, часть — травой. Большая часть океана находится позади травы, то есть — эти области скрыты. Однако океан выводится раньше, чем трава, что не даёт эффективно применить Z-отсечение. Ниже показаны данные анализа времени работы GPU при выводе океана и травы. На рисование океана требуется 18 эргов, на траву — 19. Если бы трава выводилась раньше океана, то, так как расположена она ближе к зрителю, большую часть пикселей океана просто не нужно было бы выводить. Это привело бы к уменьшению времени, которое GPU требуется для прорисовки объектов. После второй оптимизации, как показано на соответствующем рисунке, время работы GPU при выводе океана снизилось с 6 мс. до 0.3 мс.

a31062477e73a48d19dd301250da9442.png
Затраты на рисование океана после первой оптимизации.

1cedc782216cc38de5b11056941c048a.png
Затраты на рисование травы после первой оптимизации.

ca4b2b45c26ce7ff3e40c3aacf5e7465.png
Затраты на рисование океана после второй оптимизации.

Результаты


Предприняв вышеописанные шаги, mTricks оптимизировала все графические ресурсы в расчете на мобильные устройства. При этом удалось сохранить высокий уровень качества. Количество эргов удалось сократить с 1726 до 124. Число примитивов снизилось со 122204 до 9525.

f60b4e5d70f31570cd3e0263440d93c9.jpg
Изменения графических ресурсов.

Ниже показаны результаты оптимизации. Так, после всех улучшений, показатель FPS изменился с 23 до 60 кадров в секунду на устройстве, построенном на платформе Bay Trail.

e5fec4dfb038c6d5675be8b132c6bda8.png
Увеличение FPS в ходе оптимизации.

Изменение FPS, нагрузки на GPU и CPU

Показатель
Эталонная точка
Первая оптимизация
Вторая оптимизация
FPS
23
45
60
Загрузка GPU, %
91
99
71
Нагрузка на CPU, %
27
13
22


После первой оптимизации анализ игры на Bay Trail-устройстве показал, что её производительность всё еще привязана к GPU. Целью второй оптимизации было снижение нагрузки на графическое ядро за счёт оптимизации графических ресурсов и более рационального использования Z-буфера. В итоге нам удалось добиться 60 кадров в секунду. Так как Android использует Vsync, 60 FPS — это максимум, достижимый на данной платформе.

Начало работы с Intel Graphics Frame Analyzer для OpenGL


Если вы хотите проанализировать собственное Android-приложение с помощью инструментов Intel, вам понадобится соответствующий инструментарий. В частности, полноценную рабочую среду для создания и анализа Android-приложений можно организовать, воспользовавшись Intel INDE и Intel GPA. Intel GPA можно установить как самостоятельно, так и вместе с установкой INDE.

При загрузке Intel GPA нужно выбрать файл, соответствующей вашей рабочей среде и той платформе, на которой планируется заниматься исследованиями графики. В нашем случае, при условии, что в качестве ОС компьютера, на котором производится разработка, используется Windows, выбран пакет Windows 7/8.1 (x64) Graphics Frame Analyzer for OpenGL.

Посмотрим, как приступить к анализу приложений с помощью Intel Graphics Frame Analyzer для OpenGL. Перед проведением анализа нужно соответствующим образом подготовить приложение. А именно, в файл AndroidManifest.xml нужно внести следующее разрешение:



Так же, в разделе этого файла, нужно включить возможность отладки приложения:

   


Без такой подготовки, даже если вы установите на устройство debug-версию приложения, Graphics Frame Analyzer не сможет с ним работать. Кроме того, важно, чтобы устройство определялось ADB.

После того, как приложение установлено на Android-устройство, можно запускать Graphics Frame Analyzer для OpenGL. Если в заголовке окна приложения вы увидите подключённое к компьютеру мобильное устройство, значит до этого момента всё было сделано правильно. Теперь можно воспользоваться кнопкой Add (Добавить), которая расположена в рабочей области окна.

Graphics Frame Analyzer выполнит анализ устройства и, в разделе Analyzable applications (Приложения, подходящие для анализа), покажет список приложений, которые можно проанализировать.

fa7f09672fbb84a30ff316798ba278bb.png
Список приложений, полученный с устройства.

В нашем случае используется планшет Asus Fonepad 8 с CPU Intel Atom Z3530. На устройстве установлена Android 5.0.

В списке находится приложение-пример работы с OpenGL, которое подготовлено так, как было указано выше. Оригинал приложения можно найти здесь. Кроме того, вы можете загрузить проект, в котором выполнены все необходимые настройки.

После двойного щелчка по значку приложения в левой части окна программы появится кнопка Capture (Захват). После нажатия на эту кнопку будет проведен захват данных приложения и в правой части окна появится миниатюра, соответствующая экрану приложения. Щелчок по этой миниатюре приводит к открытию страницы со списком результатов ранее проведенных испытаний. На этой странице надо щёлкнуть по нужному значку — и мы попадаем в окно, где представлены результаты анализа.

1b512e7bdbfb1e08da2dd8c062f5fe06.png
Окно результатов анализа.

Выводы


Приступая к оптимизации игры, сначала определите узкие места. Intel GPA способен помочь в этом деле. Он даёт разработчику мощные аналитические инструменты. Если производительность игры привязана к CPU, ценную информацию можно получить с помощью Intel VTune Amplifier. Если же производительность игры «упирается» в возможности GPU, поискать узкие места можно с помощью Intel GPA.

Для того чтобы исправить проблемы игры, завязанные на GPU, стоит заняться поиском эффективных способов уменьшения вызовов функции рисования, числа полигонов, изменений состояний элементов рендеринга. Кроме того, можно проверить размеры текстур местности, анимацию объектов, карты освещенности, выяснить, правильно ли организована работа с Z-буфером.

© Habrahabr.ru