Улучшения времени сборки шейдеров и использования памяти в 2021 LTS

DAMIAN NACHMAN / UNITY TECHNOLOGIESSenior Technical Product Manager
Dec 28, 2022|13 Мин
Улучшения времени сборки шейдеров и использования памяти в 2021 LTS
Эта веб-страница была переведена с помощью машинного перевода для вашего удобства. Мы не можем гарантировать точность или надежность переведенного контента. Если у вас есть вопросы о точности переведенного контента, обращайтесь к официальной английской версии веб-страницы.

По мере того как набор возможностей конвейера рендеринга Unity Scriptable Render Pipeline (SRP) продолжает расти, увеличивается и количество вариантов шейдеров, обрабатываемых и компилируемых во время сборки. Наряду с постоянной поддержкой дополнительных графических API и постоянно растущим выбором целевых платформ, улучшения SRP продолжают расширяться.

Шейдеры компилируются и кэшируются после первоначальной ("чистой") сборки, что ускоряет последующие инкрементные ("теплые") сборки. Хотя чистые сборки обычно занимают больше всего времени, длительные теплые сборки могут быть распространенной больной точкой во время разработки и итераций проекта.

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

Чтобы решить эту проблему, команда Unity по управлению шейдерами усердно работает над созданием значимых и масштабируемых решений. Это позволило значительно сократить время сборки шейдеров и потребление памяти во время выполнения для проектов, созданных с помощью Unity 2021 LTS и более поздних версий.

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

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

Возможности условных шейдеров

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

Функция материала Clear Coat, включаемая художником во время создания, путем включения ключевого слова shader_feature

Функции условных шейдеров могут быть реализованы разными способами:

  • Статическое (во время компиляции) ветвление
  • Компиляция вариантов шейдеров
  • Динамическое (во время выполнения) ветвление

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

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

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

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

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

Снятие вариантов шейдеров

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

  • Включенные материалы и ключевые слова
  • Настройки проекта и конвейера рендеринга
  • Зачистка с помощью сценариев

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

Например, если свойство материала Clear Coat не включено ни для одного материала, использующего шейдер Complex Lit URP Shader, все варианты шейдеров, реализующие функцию Clear Coat, будут безопасно удалены во время сборки.

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

Scriptable stripping - это C# API, позволяющий исключать варианты шейдеров из компиляции во время сборки с помощью ключевых слов и комбинаций, не требующихся во время выполнения. Конвейеры рендеринга используют скриптовую зачистку для удаления ненужных вариантов в соответствии с настройками конвейера рендеринга проекта и качества активов, включенных в сборку.

Низкое качество Высокое качество Множитель вариантов Основной свет/Заливные тени: Выкл. Вкл. 2x Основное освещение/затенение: Вкл. Вкл. 1х Основной свет/затенение: Выключено Выключено 1x

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

Предварительная фильтрация вариантов шейдеров

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

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

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

Префильтрация вариантов шейдеров впервые появилась в версии 2023.1.0a14 и была перенесена в версии 2022.2.0b15 и 2021.3.15f1.

Сокращение времени обработки шейдеров при теплых сборках проектов в URP Boat Attack
Сокращение времени обработки шейдеров для теплых сборок проекта в URP Terrain Demo

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

Сокращение времени обработки шейдеров для чистых сборок проекта в URP Terrain Demo
Сокращение времени обработки шейдеров для теплых сборок проекта в URP Terrain Demo
Динамическая загрузка шейдеров

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

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

Новые настройки загрузки вариантов шейдеров теперь доступны из настроек игрока в редакторе . Используйте их, чтобы переопределить максимальное количество загружаемых шейдерных блоков и размер каждого шейдерного блока (МБ).

Редактор > Настройки проекта > Проигрыватель > Настройки загрузки вариантов шейдеров

С помощью следующего API C# вы можете переопределять параметры загрузки вариантов шейдеров с помощью скриптов редактора, например:

Вы также можете переопределить максимальное количество загружаемых шейдерных блоков во время выполнения, используя C# API через Shader.maximumChunksOverride. Это позволяет изменить бюджет шейдерной памяти, основываясь на таких факторах, как общий объем доступной системной и графической памяти, запрашиваемой во время выполнения.

Динамическая загрузка шейдеров появилась в версии 2023.1.0a11 и была перенесена в версии 2022.2.0b10, 2022.1.21f1 и 2021.3.12f. В случае Universal Render Pipeline (URP)'s Boat Attack мы наблюдали сокращение использования памяти шейдеров во время выполнения на 78,8%, с 315 Мбайт (по умолчанию) до 66,8 Мбайт (динамическая загрузка). Подробнее об этой оптимизации вы можете прочитать в официальном анонсе.

Динамическая загрузка шейдеров, используемая в URP Boat Attack, позволила сократить использование шейдерной памяти во время выполнения на 78,8%.
Что дальше?

Помимо вышеупомянутых важных изменений, мы работаем над улучшением генерации и удаления вариантов шейдеров в Universal Render Pipeline. Мы также изучаем дополнительные улучшения в управлении вариантами шейдеров в Unity в целом. Конечная цель - способствовать расширению набора функций движка, обеспечивая при этом минимальную нагрузку на сборку шейдеров и время выполнения.

Некоторые из наших текущих исследований связаны с дедупликацией шейдерных ресурсов для похожих вариантов, а также с общим улучшением ключевых слов шейдеров и API Shader Variant Collection. Цель - обеспечить большую гибкость и контроль над обработкой вариантов шейдеров и производительностью во время выполнения.

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

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

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