Главная » Программирование игр под Android » Почему OpenGL ES-рендеринг такой медленный? – РАЗРАБОТКА ИГР ДЛЯ ОС ANDROID

0

То, что НТС Него медленнее, чем устройства второго поколения, не секрет. Тем не менее чип PowerVR в Droid чуть-чуть быстрее, чем чип Adreno в Nexus One, так что предыдущие результаты на первый взгляд достаточно странные. При дальнейшем исследовании мы можем, наверное, объяснить разницу не различной мощностью графического процессора, а тем, что вызываем множество методов OpenGL ES в каждом фрейме и эти методы занимают очень много памяти. Это значит, что они фактически вызывают С-код, который требует больше памяти, чем вызов метода Java на Dalvik. У Nexus One есть динамический компилятор, так что он имеет некоторое пространство для оптимизации. Поэтому давайте будем считать, что разница обусловлена динамическим компилятором, (что, возможно, не совсем правильно).

А теперь посмотрим, что в OpenGL ES оставляет желать лучшего: множество изменений состояний в каждом кадре (например, смешивание, включение/выключение нанесения текстуры и т. д.); большое количество изменений матриц в каждом кадре; множество операций привязывания текстур в каждом кадре; многократные изменения вершин, цвета и координат текстуры в каждом кадре.

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

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

Ключевой момент состоит в том, что вызов glDrawElements или glDrawArraysO не выполняется сразу. Вместо этого команда помещается в буфер, который асинхронно обрабатывается графическим процессором. Это значит, что вызов методов рисования не блокируется. Поэтому вряд ли стоит измерять, сколько времени займет вызов gl DrawEl ements , поскольку сама работа может быть проделана в будущем.

Именно поэтому мы все измеряем в кадрах в секунду. Когда фреймбуферы меняются местами (да, и в OpenGL ES применяется двойная буферизация), OpenGL ES выполняет все отложенные операции.

Вновь сравним OpenGL ES с автомобилестроительным заводом. В то время как новые треугольники поступают в командный буфер с помощью вызова gl DrawEl ements  или glDrawArrayst), конвейер графического процессора должен закончить визуализацию текущих треугольников из предыдущих вызовов (например, треугольник может находиться на стадии растеризации). Этим обусловлены следующие особенности.

На замену актуальной привязанной текстуры уходит много памяти. Любые еще не обработанные, но использующие текстуру треугольники в командном буфере должны сначала быть визуализированы.

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

Изменение состояния смешивания требует много памяти. Любые еще не визуализированные, но требующие/не требующие смешивания треугольники в командном буфере, к которым должны быть применены старые матрицы, должны сначала быть визуализированы. О Наконец, много памяти требуется на изменение модели-вида или проекционной матрицы. Любые находящиеся в командном буфере треугольники, которые пока не были обработаны и к которым должны применяться старые матрицы, придется отображать в первую очередь. Конвейер застынет.

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

Источник: Mario Zechner / Марио Цехнер, «Программирование игр под Android», пер. Егор Сидорович, Евгений Зазноба, Издательство «Питер»

По теме:

  • Комментарии