В этом документе показано, как оптимизировать производительность игр с помощью инструментов для выявления и устранения узких мест, связанных с процессором и видеокартой.
Оптимизация ЦП
Если анализ покажет, что игра сильно нагружает процессор, необходимо провести дальнейшее расследование. Для этого нужно определить конкретные потоки или API, которые вызывают узкие места и снижают частоту кадров.
Для оптимизации работы процессора универсальное решение, как правило, неэффективно. Вместо этого необходимо определить наиболее ресурсоемкую задачу в зависимости от игры или сценария, а затем оптимизировать соответствующую логику и функции.
инструменты трассировки времени игрового движка
В проведении этого анализа могут помочь следующие инструменты:
Невероятные открытия
В проектах Unreal Engine инструмент Unreal Insight Tool упрощает анализ информации о временных параметрах отдельных потоков, составляющих кадр.
В качестве примера, поток GameThread обычно использует наибольшую долю процессорного времени, в основном за счет времени тактов (Tick Time). Кроме того, значительная часть времени тактов расходуется на задачи, связанные с FActorComponentTickFunction .
Для оптимизации FActorComponentTick крайне важно исключить вычисления и реализовать отсечение для персонажей и объектов, расположенных вне поля зрения камеры. Кроме того, использование анимации на основе LOD (уровня детализации) может дополнительно повысить производительность.

Профайлер Unity (Unity)
Анализ с помощью Unity Profiler показывает, что основной поток потребляет более 45 мс, при этом PostLateUpdate.FinishFrameRendering занимает 16,23 мс, что делает его наиболее ресурсоемкой операцией. При этом наблюдается множество вызовов Inl_RenderCameraStack. Рекомендуется определить необходимость включения камер и оптимизировать их соответствующим образом.

Инструменты профилирования на системном уровне
Используйте следующие инструменты профилирования:
Перфетто
С помощью Perfetto Trace можно определить назначение ядер ЦП и подробные сведения о выполнении каждого потока на устройстве под управлением Android. Это позволяет выявлять узкие места в производительности путем анализа данных о выполнении потоков.
корпус для размещения процессора
Трассировка показывает, что нагрузка на потоки GameThread и RenderThread вызывает задержки в отображении QueuePresent потока RHI, что приводит к ситуации, когда производительность процессора ограничена из-за VSync.

Корпус для графического процессора
Трассировка показывает, что само завершение работы графического процессора занимает более 25 мс, что свидетельствует о ситуации, когда производительность графического процессора ограничена.

Simpleperf
Для выявления функций с наибольшей загрузкой ЦП можно использовать simpleperf. Для достижения оптимальных результатов рекомендуется отсортировать эти функции, чтобы в первую очередь обрабатывать те, которые используют больше всего ресурсов.

Simpleperf помогает анализировать данные о функциях, которые используют больше всего процессорного времени. Для оптимизации использования ЦП начните с функций, которые используют больше всего ресурсов ЦП. В этом примере функция USkeletalMeshComponent , связанная с анимацией в ActorComponentTickFunctions , использует больше всего ресурсов ЦП.
Оптимизация графического процессора
Если анализ покажет, что игра сильно зависит от графического процессора, необходимо провести дальнейшее исследование. Для этого потребуется использовать различные инструменты и методы для оптимизации и анализа работы GPU.
Для оптимизации работы графического процессора используйте отладчик кадров, чтобы проанализировать конвейер рендеринга и вызовы отрисовки для каждой сцены. Кроме того, необходимо досконально понимать архитектуру графического процессора и поведение конвейера, чтобы выявлять ненужные операции или области, требующие оптимизации.
В следующих разделах описаны методы и инструменты для оптимизации работы графического процессора.
Удалите ненужные RenderPasses
Для повышения производительности рендеринга и снижения нагрузки на графический процессор необходимо исключить ненужные проходы рендеринга. К ним относятся любые проходы, в которых отсутствуют вызовы отрисовки или выходные данные которых не используются в итоговом кадре.
Используйте отладчик для графического процессора, например RenderDoc , чтобы проанализировать конвейер рендеринга и выявить возможности для оптимизации.
Отсутствие вызовов отрисовки: Проверьте, содержит ли проход рендеринга какие-либо вызовы отрисовки. Если вызовов отрисовки нет, удалите проход.
Неиспользуемый выходной сигнал: проверьте, обращаются ли последующие проходы к выходным данным прохода рендеринга или отображают их, например, цвет или глубину. Если нет, удалите проход.
Объединяемые проходы: Определите проходы, которые можно объединить:
- Тот же буфер кадров или вложения
- Совместимые операции по погрузке или хранению.
- Отсутствие барьеров зависимости между ними

Минимизируйте операции по загрузке или хранению.
Операции загрузки или сохранения данных требуют значительных ресурсов, поскольку используют большой объем памяти. Сведите к минимуму ненужные операции загрузки и сохранения. Выполняйте эти действия только тогда, когда требуются вложения внутри RenderPass . В противном случае замените их операциями Clear или Don't care чтобы уменьшить накладные расходы.
Как оптимизировать
Используйте отладчик для графического процессора, например RenderDoc , чтобы проанализировать конвейер рендеринга и выявить следующие возможности оптимизации:
Загрузка: Если вложенный проход рендеринга не использует данные из предыдущего прохода или вложения, операция загрузки не требуется. В таких случаях использование параметров
Don't careилиClearможет уменьшить накладные расходы.Сохранение: Если после текущего прохода рендеринга не используется привязка прохода рендеринга, операция сохранения не требуется. В таких случаях используйте либо
Don't care, либоClear.Заменить: Определите, можно ли заменить текущие настройки загрузки или сохранения на
ClearилиDon't Careбез влияния на итоговый кадр.

Избегайте отбрасывания, чтобы включить Early-Z.
Технология Early-Z повышает производительность на мобильных платформах. Однако инструкция discard внутри шейдера автоматически отключает Early-Z. Если инструкция discard не является необходимой, удалите её.
Раннее Z-ускорение
Эта оптимизация значительно сокращает количество операций фрагментного шейдера и повышает производительность графического процессора.
Раннее тестирование глубины Z и трафарета

Как оптимизировать
Используйте отладчик для графического процессора, например RenderDoc , чтобы проанализировать конвейер рендеринга и выявить следующие возможности оптимизации:
Использование ключевого слова
discardво фрагментных шейдерах: ключевое словоdiscardпредотвращает выполнение графическим процессором предварительных проверок глубины, поскольку видимость фрагмента заранее неизвестна.Изменение параметра
gl_FragDepth: Динамическое изменениеgl_FragDepthизменяет глубину фрагмента, что отключает оптимизацию Early-Z, поскольку конечная глубина неизвестна до обработки фрагмента.Включение альфа-канала для покрытия фрагментов: Когда включен альфа-канал для покрытия фрагментов (часто используется в рендеринге MSAA), покрытие фрагментов зависит от значений альфа-канала. Это может замедлить проверку глубины и отключить функцию Early-Z.

Оптимизировать формат текстур
Оптимальный выбор формата текстур снижает потребление памяти, повышает эффективность использования полосы пропускания и улучшает производительность рендеринга. Использование форматов с чрезмерно высокой точностью может привести к растрате ресурсов графического процессора без каких-либо визуальных преимуществ.
Как оптимизировать
Используйте отладчик для графического процессора, например RenderDoc , чтобы проанализировать конвейер рендеринга и выявить следующие возможности оптимизации:
- Используйте
D24S8вместоD32S8для буферов глубины и трафарета: использованиеD24S8для буферов глубины и трафарета снижает потребление памяти на 20% по сравнению сD32S8, при этом практически не наблюдается заметной разницы в качестве изображения в большинстве приложений. - Используйте сжатие
ASTCдля цветных текстур: сжатиеASTCзначительно сокращает объем памяти, используемой для текстур, — до 8 раз по сравнению с несжатыми форматами — при сохранении высокого визуального качества. - Используйте форматы с половинной плавающей запятой вместо форматов с полной плавающей запятой: используйте
R16FилиRG16Fдля уменьшения пропускной способности памяти и потребления памяти. Эти форматы хорошо подходят для буферов постобработки.
Оптимизация сложности геометрии
Минимизация геометрической сложности повышает производительность рендеринга, особенно на мобильных устройствах с ограниченными возможностями графического процессора. Это включает в себя использование меньшего количества вершин и треугольников, объединение объектов для уменьшения количества вызовов отрисовки и удаление нерендеренной или ненужной геометрии. Такие методы, как упрощение сетки, уровень детализации (LOD) и отсечение по пирамиде видимости или окклюзии, могут значительно снизить нагрузку на графический процессор и увеличить частоту кадров.
Как оптимизировать
Используйте инструменты профилирования и отладчики графического процессора, такие как RenderDoc , Android GPU Inspector или другие анализаторы производительности, чтобы выявить узкие места в производительности, связанные с геометрией.
Уменьшите количество треугольников: сведите к минимуму использование полигонов, особенно для небольших или удаленных объектов.
Используйте уровень детализации (LOD): в зависимости от расстояния до камеры автоматически используются более простые сетки.
Объединение небольших сеток: консолидация статических объектов для уменьшения количества вызовов отрисовки и нагрузки на процессор.
Отсечение по пирамиде видимости и окклюзии: Избегайте отрисовки объектов, находящихся за пределами поля зрения или заслоненных другими элементами.
Удалите ненужные вложения
Дополнительные параметры рендеринга (например, цвет, глубина, трафарет) потребляют пропускную способность памяти и ресурсы графического процессора, даже если они не используются. Удаление ненужных или избыточных параметров повышает производительность и снижает энергопотребление, особенно на мобильных платформах.
Как оптимизировать
Используйте инструменты профилирования и отладчики графического процессора, такие как RenderDoc , Android GPU Inspector или другие анализаторы производительности, чтобы выявить узкие места в производительности, связанные с геометрией.
- Проверьте фактическое использование: есть ли какие-либо вызовы отрисовки или шейдеры, которые записывают или считывают данные из прикрепленного файла?
- Проанализируйте выходные данные кадра: используйте
RenderDocили аналогичные утилиты, чтобы определить, вносит ли прикрепленный файл вклад в итоговое изображение. - Рассмотрите возможность использования временных или фиктивных подключений: для временных данных, не требующих постоянного хранения, следует использовать временные подключения или операцию сохранения "Don't Care".
Оптимизация точности шейдеров
Использование чрезмерно высокой точности (например, highp вместо mediump или lowp ) в шейдерах увеличивает нагрузку на графический процессор, энергопотребление и нагрузку на регистры, особенно на мобильных графических процессорах. Использование минимально необходимой точности для переменных (например, позиций, цветов, UV-координат) позволяет повысить производительность без заметного визуального эффекта.

Как оптимизировать
Используйте инструменты профилирования и отладчики графического процессора, такие как RenderDoc, Android GPU Inspector или другие анализаторы производительности, чтобы выявить узкие места в производительности, связанные с геометрией.
Проверьте код шейдера: оцените переменные шейдера и убедитесь, что высокая точность используется только при необходимости, например, для вычислений глубины или экранного пространства. Используйте среднюю или низкую точность для цветов, UV-координат или значений, не требующих высокой точности.
Используйте отладчики графического процессора: диагностические утилиты, такие как RenderDoc или мобильные профилировщики графических процессоров (например, AGI, Mali/GPU Inspector), выявляют повышенное использование регистров или задержки шейдеров, связанные с проблемами точности.

Включить отсечение задних граней
Для твердых объектов часто нет необходимости отображать треугольники, обращенные от камеры (задние грани).
Как оптимизировать
Использование VK_CULL_MODE_NONE может негативно повлиять на производительность, поскольку оно заставляет графический процессор отрисовывать как лицевую, так и обратную сторону граней, что увеличивает нагрузку на рендеринг.

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