Epic Games, авторы движка Unreal Engine, потенциально нашли способ решения основной беды UE 5 — “подвисания” и статтеринга. Во вторник, 4 февраля, они объяснили в своём блоге разработки, как устроена компиляция шейдеров, как они оптимизируют её в версии движка 5.2, и пообещали поделиться техническими подробностями на Unreal Lifestream в этот четверг, 6 февраля, в 22:00 по мск на Twitch и YouTube.
Unreal Engine у многих ассоциируется не только со впечатляющей картинкой, но и с “тормозами”, от которых не застрахована даже самая современная и производительная система. Среди известных разработчиков активным противником Unreal Engine является Даниэль Вавра, который создавал Kingdom Come: Deliverance на движке CryEngine и осудил CD Project Red за переход на UE5 именно за неспособность среды быстро обрабатывать крупные сцены в открытом игровом мире.
Как устроена компиляция шейдеров и откуда берутся “провисы”
Простыми словами, шейдеры — это фрагменты кода, описывающие конкретные визуальные эффекты для графического рендеринга. Это может быть как анимацией перемещения из точки в точку, так и динамическим расчётом цвета пикселя на основе разных источников освещения и материалов. Раньше они были простыми, но в современных играх они стали большими и комплексными, описывают реалистичные изображения и анимации, а их количество идёт на десятки тысяч.
Шейдеры в Unreal Engine пишутся на C++, с использованием стандартизированных форматов и API, таких как Direct3D и Vulkan, для упрощения работы. Но графические процессоры не понимают этот формат, и драйвера преобразуют код игры во что-то “удобоваримое” для конкретной видеокарты — этот процесс и называется компиляцией шейдеров.



Когда игре нужно отрендерить что-то, а шейдеры ещё не скомпилированы, она буквально “замораживается”, пока не завершится этот процесс. Вот, как объясняют это сами Epic Games:
В рендеринге объекта обычно принимают участие несколько шейдеров (например, шейдеры вершин и пикселей, работающие вместе), а так же ряд других настроек для графического процессора: режимы отбраковки, наложения, сравнения глубины и трафарета и так далее. Вместе они описывают конфигурацию, или состояние графического конвеера.
Epic Games
Некоторые настройки влияют на исполняемый код шейдера, в этих случаях драйвера начинают компилировать шейдеры, только получив команду на отрисовку. Это может занять десятки миллисекунд или даже больше для одной команды, что приводит к очень длинным кадрам, когда шейдер используется в первый раз — феномен, известный большинству геймеров как тормоза и статтеринг
В современных API все шейдеры и настройки для отрисовки объекта упаковываются в единый пакет, называемый Pipeline State Object (PSO), и в теории, движки могут подготовить всё необходимое заранее, чтобы компиляция шейдеров завершилась до рендеринга. Unreal Engine, по словам Epic Games, создаёт и объединяет необходимые PSO в кэш на моменте загрузки сейва или нового игрового уровня, что очень ресурсоёмко, особенно в динамичных играх, в которых этот кэш нужно постоянно обновлять.
Решение проблемы
В Unreal Engine 5.2 Epic Games вводят систему предварительного кэширования PSO. Загруженный объект проверяется на используемые для его рендеринга материалы, информацию о модели (статическая она или анимированная). Также учитываются глобальные настройки системы, и всё это вместе используется, чтобы заранее вычислить, какие именно PSO могут пригодиться для визуализации объекта. Это приводит к снижению вероятности “заиканий” и “подвисов”.
Объекты, которые создаются уже в процессе игры, ждут подготовки своего PSO, прежде чем появиться, или используют уже скомпилированные материалы по умолчанию, и это приводит к проседанию FPS всего на несколько кадров.
Таким образом, на примере Fortnite — для матча игра компилирует 30 тыс. PSO, а использует из них 10 тыс. Хотя это всё ещё довольно большое число, это лишь малая часть из миллионов отсечённых на стадии предварительного кэширования возможных комбинаций.

Epic Games признают, что решение не идеальное, и больше подходит для материалов, чем для глобальных шейдеров (как например, эффекты пост-обработки вроде размытия в движении), и они так же продолжат “подвисать”. Студия продолжит работать над уменьшением требовательности движка к графической памяти, автоматизировав процесс решения, какие PSO следует хранить в кэше.
Разработчикам же они рекомендуют воздержаться от возвращения к и использованию DirectX 11 и устаревших API, так как уже готовят в ближайшем будущем некоторые решения по оптимизации.