Искать

Одна сцена, 10 графических оптимизаций для разработчиков контента для консолей

Last updated: January 2019

What you will get from this page: Console graphics optimization tips, courtesy of Unity’s Rob Thompson, a console graphics developer (who представил их на конференции Unite), and our demo team. These optimizations were made to an especially difficult scene to ensure smooth 30fps performance.

Качество уровня AAA благодаря программируемым процессам рендеринга Unity

«Книга мертвых» (in this article we refer to it as BOTD) was produced by Unity's demo team. It’s a real-time rendered animated short, essentially created to test-drive and show off the capabilities of the new (and still experimental) Scriptable Render Pipelines (SRP). The SRPs allow you to code the core of your render loop in C#, thereby giving you much more flexibility for customizing how your scene is drawn to make it specific to your content.

console scriptable rendering pipeline

There are two SRPs available: the High-Definition Render Pipeline (HDRP) which offers all of the features that you'd expect from a modern, AAA quality, high fidelity renderer, while the Lightweight Render Pipeline (LWRP) maintains responsive performance when scaling for mobile. BOTD uses the HDRP, and you can find advanced learning resources for the SRPs at the end of this article.

All of the assets and all of the script code for BOTD are доступны in the Asset Store.

Глобальная оптимизация для достижения 30 кадров в секунду (или лучше) на консолях при разрешении в 1080p

Цель данной демонстрации состояла в том, чтобы предложить интерактивный опыт, в рамках которого люди могли бы гулять по окружающей среде и иметь все то, что им было знакомо по традиционным играм уровня AAA. В особенности, мы хотели показать, как КМ работает на Xbox One и PS4. Мы хотели добиться не менее 30 кадров в секунду в разрешении 1080p.

Поскольку это демонстрация, а не полная игра, основной упор оптимизаций был сделан на рендеринг.

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

Для начала Роб и демо-группа нашли сцену, в которой был самый медленный рендеринг; вот экранный снимок этой сцены:

console scriptable rendering pipeline

Эта сцена в большой степени неизменна, меняется лишь то, что попадает в обзор камеры. ЕСли бы они смогли оптимизировать эту сцену, они в конечном счете повысили бы производительность по всей КМ.

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

Вкратце, вот как прорисовывалась эта сцена:

  • С помощью HDRP
  • Большинство художественных текстур представляли собой карты размером от 1K до 2K, некоторые имели размер 4K.
  • Для отраженного освещения используется Baked Occlusion и Baked GI, а для прямого солнечного освещения - Single Dynamic Shadow Casting Light.
  • В любой точке происходило несколько тысяч вызовов отрисовки (вкупе с расчетами шейдеров)
  • До начала оптимизации на рендеринг сцены на PS4 Pro уходило около 45 мсек.
Что было с кадром до оптимизации

Перед тем, как начать оптимизацию, Роб с командой взглянули, что происходит с кадром шаг за шагом, и увидели следующее:

  • The Gbuffer was at 11ms (you can find a description of the Gbuffer layouts for HDRP in этой публикации by Unity lead graphics developer Sebastien Lagarde)
  • Motion Vectors и Screen Space Ambient Occlusion шли достаточно быстро, занимая 0,25 и 0,6 мсек, соответственно
  • Для карт теней из процедуры построения теней от динамических источников света требовалось аж 13,9 мсек
  • Отложенный рендеринг освещения занимал 4,9 мсек
  • На обработку атмосферного рассеяния уходило 6,6 мсек

И вот как выглядел кадр графического процессора, с начала до конца:

console GPU frame

Как вы видите, на обработку кадра уходило 45 мсек, а две оранжевые линии показывают, где должен заканчиваться кадр, чтобы добиться скорости 30 и 60 кадров в секунду, соответственно.

10 способов оптимизации «Книги мертвых»

Контролируйте число пакетов

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

However keeping the batch count low is still a valuable tip for any platform. The team did this by using Технология Occlusion Culling, and, primarily, дублирование в графическом процессоре. Avoid using Dynamic batching on consoles unless you are sure it’s providing a performance win.

В данном случае дублирование в графическом процессоре оказалось самым полезным способом. Без него было бы 4500 пакетов для этой сцены. Благодаря его использованию число пакетов сократилось до 1832.

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

Вот сцена без дублирования.

console scriptable rendering pipeline

И вот та же сцена с дублированием.

console scriptable rendering pipeline

Используйте несколько ядер, доступных на консолях

Обе консоли Xbox One и PS4 являются многоядерными устройствами, так что чтобы добиться наилучшей производительности ЦП, нам нужно стараться постоянно загружать эти ядра.

If you follow Unity news, you’ll know that Unity is currently developing высокопроизводительную многопоточную систему, that will make it possible for your game to fully utilise the multicore processors available today and in the future. (Very) briefly, this system comprises three sub-systems: the Entity Component System, the систему задач C# and the Burst Compiler.

Новая многопоточная система все еще находится в раннем экспериментальном режиме. В графической системе Unity вы можете опробовать ее посредством режима Graphics Jobs (опять же, в экспериментальном режиме). До режима Graphics Jobs можно добраться, перейдя Player Settings -> Other Settings.

console Graphics Jobs

Режим Graphics Jobs дает оптимизацию производительности на консолях почти во всех обстоятельствах, только если вы не вызываете буквально горстку пакетов. Этот режим доступен в двух вариантах:

  • Вариант Legacy Jobs доступен на PS4 и в DirectX 11 для Xbox One
    • Снимает нагрузку с главного потока, распределяя работу по другим ядрам. Учтите, что в очень больших сценах это может приводить к появлению узкого места в “потоке рендеринга” - потоке, который Unity использует для сообщения графическим API владельцев платформы.
  • Вариант Native Jobs доступен на PS4 и в DirectX 12 для Xbox One (вскоре появится)
    • Распределяет большинство нагрузки по доступным ядрам; этот вариант лучше всего подходит для больших сцен.
    • Должен стать наилучшим вариантом с версии 2018.2 (в версии 2018.1 и более ранних версиях он мог больше нагружать основной поток, приводя к регрессу производительности).

Используйте инструменты анализа производительности от владельца платформы

Microsoft and Sony provide отличные инструменты for analyzing your project’s performance both on the CPU and on the GPU. These tools are available to you for free if you're working on console. Learn them early on and keep using them throughout your development cycle. Pix for Xbox One is Microsoft's offering and the Razor Suite is Sony's; as Rob says, they are your main tools in your arsenal when it comes to optimization on these platforms.

Профилируйте эффекты постобработки

Роб говорит, что он профилировал игры Unity на PS4, где, неведомо для разработчиков, до ⅔ времени рендеринга кадра уход на постобработку. Такое часто происходит из-за загрузки из Asset Store ассетов постобработки, рассчитанных главным образом на ПК. Выглядит так, что они прекрасно идут на консолях, но их характеристики производительности в действительности плохие.

So, when применяете такие эффекты, profile how long they take on the GPU, and iterate until you find a happy balance between visual quality and performance. And then, leave them alone, because they comprise a static cost in every scene, meaning you know how much GPU bandwidth is left over to work with.

Избегайте тесселяции (если на то нет серьезной причины)

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

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

console tesselation

Тесселированное замещение позволило добавить углубления и сучковатые детали в геометрию, которая правильно затеняет себя таким образом, которого невозможно достичь при обычном мэппинге.

Поскольку деревья являются по большей части “героями” в КМ, это было оправдано. Это было проделано путем использования одной и той же меши на деревьях на уровнях детализации LOD 0 и LOD 1. Разница между ними состоит в том, что теселлированное замещение сокращается, так что оно больше не действует ко времени достижения LOD 1.

Стремитесь к достойному заполнению волновых фронтов все время на графическом процессоре

Ok, это громкая фраза, так что сначала следует разобраться, что такое "заполнение волновых фронтов".

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

console wave front occupancy

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

Инструменты Pix и Razor могут детально показывать заполнение волновых фронтов. Показанные выше графики взяты из Pix for Xbox One. Слева мы видим пример хорошего заполнения волновых фронтов. Зеленая полоса у нижнего края графика свидетельствует о выполнении волновых фронтов вертексных шейдеров, а над ней синим цветом отображается выполнение волновых фронтов пиксельных шейдеров.

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

Как так вышло? Этот сценарий типичен для случаев, когда выполняются задачи вертексных шейдеров, не приводящие к пиксельным.

Используйте Depth Prepass

Более детальный анализ с помощью Pix и Razor показал, что получалось много перерисовки на проходе Gbuffer. Это особенно плохо на консоли при взгляде на альфа-тестируемые объекты.

Если на консоли вы отдаете команды discard для пикселей или записываете прямо в глубину пиксельного шейдера, вы не можете воспользоваться преимуществами раннего отклонения глубины. Волновые фронты пиксельных шейдеров все равно будут запущены, даже если работа будет выброшена в конце.

Решение состояло в том, чтобы добавить Depth Prepass. Depth Prepass включает в себя рендеринг сцены заранее только в глубину, используя очень легкие шейдеры, чем те, что могут служить базисом более интеллектуального отклонения глубины, где и содержатся самые глубокие шейдерные связи Gbuffer.

The HDRP now includes a Depth Prepass for all alpha tested objects, but you can also switch on a full Depth Prepass if you want. The settings for controlling HDRP, what render passes are used, and features enabled, are all made available via the .

Если вы поищите в проекте HDRP ассет HD Render Pipeline, вы найдете массу флажков, контролирующих всё, что HDRP делает.

Что касается КМ, использование Depth Prepass было большим плюсом для графического процессора, но учтите, что при этом добавляется нагрузка на ЦП в виде дополнительных пакетов.

Уменьшите размер карт теней

Как уже было упомянуто ранее, карты теней в этой сцене генерируются по схеме отбрасывания тени от единственного источника направленного света. Было использовано разделение карты теней на 4 части, и изначально они рендерились как 4K-карта теней с глубиной 32 бит, поскольку эти величины выбираются по умолчанию для HDRP-проектов. Разрешение карты теней почти всегда является ограничивающим фактором при рендеринге карты теней; это было подтверждено анализом с помощью Pix и Razor.

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

The shadow map resolution was dropped to 3k, which provided a perfectly acceptable trade-off against performance. The demo team also added an option specifically to allow developers to render to 16-bit depth Shadow maps. If you want to give that a go for yourself загрузить the project assets.

Наконец, при изменении разрешения карты теней им также потребовалось изменить некоторые настройки света.

Reduce size of shadow

К этому моменту команда внесла изменения в карты теней и перепозиционировала камеру карты теней, чтобы добиться наилучшего использования уменьшенного разрешения. Что они стали делать дальше?

Прорисовывайте только последний (мелкомасштабный) кусок карты теней один раз при загрузке уровня

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

Они не увидели ощутимого падения в качестве. Эта оптимизация оказалась очень удачной, поскольку она не только экономила время рендеринга кадра, но и сокращала количество пакетов на ЦП.

После этой серии оптимизаций их фаза создания карты теней сократилась с 13 мсек до менее 8 мсек; фаза освещения уменьшилась с 4,9 мсек до 4,4 мсек, а на обработку атмосферного рассеяния стало уходить 4,2 мсек вместо прежних 6,6 мсек.

Вот к чему команда пришла в конце оптимизации карты теней. Теперь они могли обеспечить 30 кадров в секунду на PS4 Pro.

console GPU frame

Используйте асинхронные вычисления

Async Compute is a method available for minimizing periods of underutilization on the GPU with useful compute shader work. It’s currently only supported on PS4, but coming to DX12 for Xbox One very soon. It's accessible through Unity's Command Buffer interface. It's not just exclusively for the SRP but is primarily aimed at it. Code examples are available in the BOTD assets, or look at the HDR PSOS.

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

КМ использует асинхронные вычисления для сбора списка тайлового освещения, что составляет часть отложенного освещения, и это всё выполняется по большей части с compute shaders на консоли в HDRP. Это также используется для вычислений SSAO. Оба процесса перекрываются с рендерингом карты теней, чтобы заполнять пробелы в использовании волновых фронтов.

For a run-through of some conceptual code where Async Compute is employed, tune into выступление Роба на Unite at 35:30.

Дополнительные ресурсы

Мы очень хотим знать, нравится ли вам наш контент.

Да, хочу больше Нет, могло быть и лучше
Согласен

Мы используем cookie-файлы, чтобы вам было удобнее работать с нашим веб-сайтом. Подробные сведения смотрите на странице политики обработки cookie-файлов.