Оптимизация Godot Engine Vulkan для Android

Изображение талисмана Godot Engine

Обзор

Godot Engine — популярный мультиплатформенный игровой движок с открытым исходным кодом и надежной поддержкой Android. Godot можно использовать для создания игр практически любого жанра, и он поддерживает как 2D, так и 3D-графику. В версии Godot 4 представлена ​​новая система рендеринга с расширенными функциями для высококачественной графики. Средство рендеринга Godot 4 разработано для современных графических API, таких как Vulkan.

Фонд Godot Foundation привлек экспертов по оптимизации графики из The Forge Interactive и сотрудничал с Google для анализа и дальнейшего улучшения средства рендеринга Godot 4 Vulkan и объединения этих оптимизаций обратно в репозиторий проекта. Оптимизации помогают разработчикам улучшать собственные средства визуализации Vulkan на Android.

Методика и результаты оптимизации

В процессе оптимизации в качестве целей для тестирования использовались две разные 3D-сцены в Godot. Время рендеринга сцен измерялось на нескольких устройствах во время каждой итерации оптимизации. Чтобы претендовать на включение, изменения в средстве рендеринга должны были показать улучшение производительности хотя бы на некоторых протестированных устройствах и не могли привести к снижению производительности ни на одном устройстве.

При тестировании использовались несколько популярных архитектур графических процессоров Android. Хотя многие оптимизации принесли общие улучшения, некоторые оптимизации оказали большее влияние на конкретные архитектуры графических процессоров. Сумма всех работ по оптимизации привела к общему сокращению времени обработки кадров графического процессора на 10–20%.

Общая оптимизация Vulkan

Компания Forge выполнила общий архитектурный рефакторинг серверной части рендеринга Godot Vulkan, чтобы повысить производительность и помочь серверной части масштабироваться в соответствии с возросшими требованиями к рендерингу контента. Оптимизации не относятся только к мобильному оборудованию, но приносят пользу всем платформам Godot Vulkan.

Поддержка динамического смещения UBO

При привязке набора дескрипторов, содержащего объект динамического универсального буфера (UBO), Vulkan позволяет указывать динамические смещения в UBO в параметрах привязки. Эту функцию можно использовать для упаковки данных для нескольких операций рендеринга в один UBO, перепривязывая набор дескрипторов с другим динамическим смещением для выбора подходящих данных для шейдера. Средство рендеринга Godot Vulkan было обновлено, чтобы иметь возможность использовать динамические смещения вместо того, чтобы всегда инициализировать смещение равным нулю. Это улучшение позволяет оптимизировать эффективность в будущем.

Пулы наборов линейных дескрипторов

Раньше поведением по умолчанию в средстве визуализации Godot Vulkan было создание всех пулов наборов дескрипторов с использованием флага VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT , что означало, что выделения наборов дескрипторов могли быть освобождены обратно в пул, и из пула можно было выполнить перераспределение. Этот режим требует дополнительных затрат по сравнению с пулами наборов дескрипторов, которые допускают только линейное распределение с последующим полным сбросом пула.

Там, где это возможно, пулы наборов дескрипторов теперь создаются как линейные пулы без установки VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT . При необходимости линейные пулы затем сбрасываются целиком. Эта работа также включает дополнительную оптимизацию пакетной привязки набора дескрипторов, когда это возможно, сокращая количество дискретных вызовов vkCmdBindDescriptorSets() .

Поддержка неизменяемого сэмплера

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

Неизменяемые сэмплеры жертвуют гибкостью, поскольку больше не нужно управлять дискретными объектами сэмплера и привязывать их к ним. Средство рендеринга Godot Vulkan было обновлено для поддержки использования неизменяемых сэмплеров; Использование сэмплера было изменено, чтобы использовать неизменяемые семплеры, где это возможно.

Оптимизация, ориентированная на мобильные устройства

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

Оптимизации включают в себя:

  • Заменить использование больших push-констант
  • Ленивое выделение буфера
  • Поддержка постоянного буфера
  • Изменение режима декодирования ASTC
  • Предварительный поворот экрана

Заменить использование больших push-констант

Push-константы — это функция, которая позволяет вводить значения констант для активной программы шейдера в буфер команд. Push-константы удобны тем, что не требуют создания и заполнения буфера и не привязаны к дескрипторам. Однако константы push имеют ограниченный максимальный размер и могут отрицательно повлиять на производительность мобильного оборудования.

Во время тестирования на устройствах Android производительность была улучшена за счет замены использования push-константы размером более 16 байт на унифицированные буферы. Шейдеры, которые использовали 16 байт или меньше константных данных, были более производительными с push-константами. Помимо соображений производительности, некоторое графическое оборудование имеет минимум 64-байтового выравнивания для унифицированных буферов, что снижает эффективность памяти из-за неиспользуемого заполнения по сравнению с использованием push-констант.

Ленивое выделение буфера

Большинство мобильных графических устройств используют архитектуру отложенного рендеринга на основе тайлов (TBDR). Графические процессоры, использующие TBDR, разбивают большую область экрана на сетку из более мелких фрагментов и выполняют рендеринг для каждого фрагмента. Каждый тайл поддерживается небольшим объемом высокоскоростной оперативной памяти, которая используется графическим процессором для хранения данных при рендеринге тайла. С помощью TBDR цели рендеринга, которые никогда не выбираются другой целью за пределами их прохода рендеринга, могут эффективно оставаться полностью в тайловой оперативной памяти и не требовать буфера для резервного хранилища основной памяти.

VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT был добавлен во время создания соответствующих целей рендеринга, таких как основные цели цвета и глубины, чтобы избежать выделения буферной памяти, которая никогда не будет использоваться. Экономия памяти при ленивом выделении в примерах сцен составила примерно 50 мегабайт ОЗУ.

Поддержка постоянного буфера

Мобильное оборудование использует унифицированную архитектуру памяти (UMA) вместо аппаратного различия между основной и графической оперативной памятью. Когда основная и графическая ОЗУ разделены, данные должны быть перенесены из основной ОЗУ в графическую ОЗУ для использования графическим процессором. Godot уже реализует этот процесс передачи в своем рендеринге Vulkan посредством использования промежуточных буферов. На оборудовании UMA промежуточный буфер не требуется для многих типов данных; Память может использоваться как процессором, так и графическим процессором. В Forge реализована поддержка постоянных общих буферов на поддерживаемом оборудовании, чтобы по возможности исключить промежуточное хранение.

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

Изменение режима декодирования ASTC

Адаптивное масштабируемое сжатие текстур (ASTC) — предпочтительный современный формат сжатия текстур на мобильном оборудовании. Во время распаковки графический процессор по умолчанию может декодировать текселы в промежуточное значение с большей точностью, чем требуется для визуальной точности, что приводит к потере эффективности текстурирования. Если поддерживается целевым оборудованием, расширение VK_EXT_astc_decode_mode используется для указания 8-битных ненормализованных значений для каждого компонента при декодировании вместо 16-битных значений с плавающей запятой.

Предварительный поворот экрана

Для оптимальной производительности при использовании Vulkan на Android игры должны согласовывать ориентацию экрана устройства с ориентацией поверхности рендеринга. Этот процесс называется предварительным вращением . Невыполнение предварительного поворота может привести к снижению производительности из-за того, что ОС Android необходимо добавить проход компоновщика для поворота изображений вручную. В рендерер Godot была добавлена ​​поддержка предварительного поворота на Android.

Отладка улучшений

Помимо оптимизации производительности, The Forge улучшила возможности отладки проблем с графикой в ​​рендерере Godot благодаря следующим дополнениям:

  • Расширение неисправности устройства
  • Панировочные сухари
  • Маркеры отладки

Расширение неисправности устройства

Когда графический процессор сталкивается с проблемой во время операций рендеринга, драйвер Vulkan может вернуть результат VK_ERROR_DEVICE_LOST из вызова API Vulkan. По умолчанию дополнительная контекстная информация о том, почему драйвер вернул VK_ERROR_DEVICE_LOST не предоставляется. Расширение VK_EXT_device_fault предоставляет драйверу механизм предоставления дополнительной информации о характере неисправности. Godot добавил поддержку включения расширения неисправности устройства (если доступно) и сообщения информации, возвращаемой драйвером.

Сбой графического процессора или остановка выполнения могут оказаться сложной задачей для отладки. Чтобы помочь определить, какое графическое содержимое могло быть отображено во время ошибки, в средство рендеринга Godot была добавлена ​​поддержка навигационной цепочки . Хлебные крошки — это определяемые пользователем значения, которые можно прикрепить к содержимому в списках отрисовки на графе рендеринга. Данные навигационной цепочки записываются перед началом нового прохода рендеринга. В случае сбоя или остановки выполнения текущее значение навигационной цепочки можно использовать для определения того, какие данные могли вызвать проблему.

Маркеры отладки

Маркеры отладки, если они поддерживаются драйвером, используются для именования ресурсов. Это позволяет связать читаемые пользователем строки с такими операциями, как проходы рендеринга, и такими ресурсами, как буферы и текстуры, при использовании графического инструмента, такого как RenderDoc. В средство рендеринга Godot Vulkan была добавлена ​​поддержка аннотаций маркеров отладки.

Блог Godot Engine — новости о сотрудничестве с Google и The Forge

Запрос на совместную работу Godot Engine Vulkan