What is Vulkan and how does it differ from OpenGL?
Vulkan is the new generation, open standard API for high-efficiency access to graphics and compute on modern GPUs. This ground-up design, previously referred to as the Next Generation OpenGL Initiative, provides applications direct control over GPU acceleration for maximized performance and predictability.
Their page is quite marketese/jargon-heavy, as is the press release… In simple terms, what does Vulkan mean to game developers? (Gabe Newell is quoted as being strongly in favour, without further explanation.)
What exactly is Vulkan’s relationship to OpenGL? Its previous name «glNext» (short for «Next Generation OpenGL Initiative») makes it sound like a replacement.
Update: The Vulkan 1.0 spec was released on 16-02-2016.
3 Answers 3
Vulkan is a new API for hardware-accelerated graphics (and general computation) via traditional GPUs. OpenGL will continue to be developed, as it is a higher-level API than Vulkan is intended to be. Originally referred to «glNext,» one can infer that Vulkan was likely going to end up being «OpenGL 5,» but that the standards body eventually decided that a new name would better coincide with the relatively clean break the API purports to make from existing OpenGL paradigms.
Vulkan’s practical advantages to game developers are primarily about control (as in, allowing more of it, potentially allowing for better optimizations at the cost of significantly more up-front work on the developer’s part). Specifically:
- The API is oriented around asynchronous generation of command buffers across multiple threads and sequenced processing of those buffers to a command pipeline. This reflects the realities of modern hardware. Most high-profile and/or high-performance software built on OpenGL today implement this kind of behavior themselves; having the API support this itself means that developers need not implement and maintain that framework themselves, or that they can do so with less effort.
- Thread and memory management tasks are left to the application, not the driver, allowing game developers more control over those behaviors and thus potentially more accurate tailoring of those behaviors to their individual game’s needs.
- Validation and diagnostics layers can be independently enabled, allowing in theory for better tools integration with the API (something OpenGL itself has suffered from) and disabling of excessive validation, in theory allowing «the graphics on level three» to be that much more performant.
- There’s no hard API differential between mobile and desktop versions, which will in theory ease the porting of cross-platform games and if nothing else reduce version-checking headaches that everybody hates.
Vulkan’s very C-like / OpenGL-like in superficial structure (the look and feel of the API calls, et cetera. It is, however, better typed (in that not everything is a bare int ; there are relevant typedefs and so on).
It is much lower-level than OpenGL. One can expect a jump in operational setup and complexity between OpenGL and Vulkan as was seen in the D3D9 to D3D10 transition, which exposed a lot more of the under-the-cover details of GPU device operation to the API client. The transition is actually more akin to D3D11 to 12, since D3D12 is itself a very similar API to Vulkan, capability-wise.
Сравнительный тест DirectX 11, OpenGL и Vulkan
На минувшей неделе был представлен API Vulkan, о широкой поддержке которого заявили AMD и NVIDIA. Новый графический интерфейс разрабатывал Khronos Group, консорциум, основанный в 2000 году. Khronos Group отвечает за разработку и поддержку открытых стандартов в сфере мультимедийных приложений на разных платформах и устройствах. Консорциум поддерживают AMD и NVIDIA, а также многие другие компании.
На минувшей неделе была ратифицирована финальная версия 1.0 API Vulkan. AMD и NVIDIA представили соответствующие бета-драйверы. AMD заранее выпустила бета-версию Radeon Software еще 14 февраля. NVIDIA представила драйвер GeForce 356.39, который тоже ориентирован на поддержку API Vulkan.
Подход API Vulkan очень похож на API Mantle. Суть заключается в том, чтобы разработчики получили более глубокий доступ к «железу», чтобы выжать из него максимум. Такой подход позволяет максимально избежать существующих «узких мест». С другой стороны, разработчики должны точно знать, что они делают – например, при работе с памятью. Интерфейс OpenGL не так популярен, как DirectX, но позволяет выжать больше.
Интерфейс API Vulkan в версии 1.0 поддерживается под Windows 7, Windows 8.1, Windows 10, Android и Linux. Разработчики игр пока что не объявили о поддержки в конкретных играх, но здесь стоит дождаться Games Developer Conference, которая будет проводиться с 14 по 18 марта в Сан-Франциско. Из игровых движков пока есть информация о Source 2, который уже поддерживает API Vulkan. Процесс отладки облегчается поддержкой Valve, LunarG и Codeplay.
The Talos Principle
Хорошо, но какая игра или движок поддерживают API Vulkan? Игра The Talos Principle разрабатывалась компанией Croteam, которая и в прошлом была известна поддержкой многих графических API. И в последней итерации игра The Talos Principle не стала исключением – она поддерживает DirectX 9, DirectX 11, OpenGL и теперь Vulkan. Для студии разработчиков Vulkan является пробным шаром, хотя API Vulkan доступен в версии 1.0, поддержка пока находится в бета-стадии. На добавление поддержки разработчики Croteam затратили порядка трех месяцев. Но универсальный характер API позволяет вскоре представить вариант Linux.
API Vulkan теоретически совместим с несколькими платформами – но пока что тесты и сравнения можно провести только под Windows, причем здесь имеются свои ограничения. Реализация пока остается на очень раннем этапе. Путь рендеринга DirectX 11 совершенствовался многие годы, поэтому потенциала для оптимизации здесь уже нет. Здесь ситуация больше зависит от разработчиков драйверов, а именно AMD и NVIDIA. Игра The Talos Principle стала первой с поддержкой Vulkan. Поэтому пока нет возможности сделать сравнительный тест для оценки хорошей или плохой реализации поддержки.

Новые технологии первое время реализуются в примерах, подготовленных производителями. В случае DirectX 12 акцент был выставлен на Draw Calls, тот же тест 3DMark DirectX 12 опирается только на измерение производительности Draw Calls, игры DirectX 12, подобные Star Wars, тоже пытаются задействовать подобную нагрузку. Но The Talos Principle не так сильно зависит от высокой скорости Draw Call, чтобы низкоуровневый API дал большую разницу.
Поддержка API Vulkan версии 1.0 находится на ранней стадии, то же самое касается драйверов AMD и NVIDIA. Оба драйвера, по сути, относятся к бета-версиям, именно так их рассматривают производители GPU. Здесь обычно нет новых улучшений производительности или поддержки новых технологий, так что мы получаем шаг назад. Но как только определенный уровень разработки будет достигнут, драйверы обоих разработчиков GPU получат поддержку Vulkan в финальной версии. Когда это произойдет – не совсем понятно. Но пока ключевые приложения не используют Vulkan и игры с поддержкой API находятся в состоянии бета-версии, так что разработчики GPU могут спокойно дорабатывать свои драйверы.
Для тестов мы взяли нашу тестовую систему для видеокарт. Драйверы видеокарт AMD и NVIDIA мы уже описали выше. В настройках мы выставили максимальный уровень графики, но при этом протестировали и низкие разрешения вплоть до 1.280 x 720 пикселей, чтобы увеличить производительность Draw Call.
Тест The Talos Principle — 1.280 x 720 пикселей
Тест The Talos Principle — 2.560 x 1.440 пикселей
Тест The Talos Principle — 3.840 x 2.160 пикселей
Как можно видеть по результатам, API Vulkan дает существенный прирост по сравнению с OpenGL. Но до производительности DirectX 11 новый API не дотягивает. Тому есть несколько причин. С одной стороны, разработка под Vulkan находится в ранней стадии. Это касается и самого API, и драйвера, и игры The Talos Principle. По сравнению с OpenGL новый интерфейс позволяет освободить часть ресурсов и избежать «узких мест». Но DirectX много лет совершенствовался до текущего уровня. В любом случае, потенциал у API Vulkan очень хороший.
Если погрузиться в детали, то визуальных отличий между API Vulkan и DirectX 11 мы не обнаружили. Так что путь рендеринга очень хорошо адаптирован. У текущей реализации The Talos Principle видеокарты с 2 Гбайт памяти получают падение производительности, вероятно, из-за не самой эффективной работы с памятью. Как и Mantle и DirectX 12, API Vulkan может обращаться к ресурсам памяти на более глубоком уровне – сей факт можно рассматривать как преимущество, но он может стать и недостатком, если разработчики не смогут эффективно использовать память.
Несколько разочаровала ошибка в текущем драйвере NVIDIA, из-за которой после каждого теста приходилось перезагружать систему. Без перезагрузки игра «вылетала». Хотя с драйвером AMD мы не обнаруживали подобной ошибки.
Нынешняя реализация API Vulkan кажется обещающей. Пока что для игр на настольных ПК она будет не такой актуальной, поскольку рынок DirectX 11 и 12 очень велик, и по сравнению с тем же DirectX 12 затраты на реализацию могут быть слишком велики, а отдача слишком мала. Но если игры необходимо запускать на разных платформах с разными аппаратными требованиями, Vulkan может сыграть важную роль. В любом случае, следует дождаться реакции со стороны разработчиков игр, иначе мы получаем проблему курицы и яйца, из которой сложно выйти.
Unick-soft
Vulkan — это новое API для создания 3D приложений. Его разработало Khronos Group, которая занимается и развитием OpenGL. Большой вклад в создание API вложила компания AMD. Хотя и многие другие компании работали над ним, например Microsoft, Apple, Google, Sony. Это API поддерживают такие создатели «железа» как: NVidia, AMD, Intel, Qualcomm, Imagination Technologies, ARM.
Чем отличается Vulkan от OpenGL
Статья на Википедии выделяет 4 основных отличия:
- Никаких глобальных состояний, все состояния привязаны к объектам.
- Состояния привязываются к буферу команд, а не к контексту, как в OpenGL.
- В OpenGL работа с памятью и синхронизация происходит не явно, в Vulkan разработчик будет иметь возможность контролировать это.
- Отсутствие проверки на ошибки в драйвере, для ускорения работы.
Исходя из того, что новое API появилось в наши дни и на протяжении 18 месяцев Khronos Group его разрабатывала в тесном контакте с ведущими IT компаниями мира, можно делать вывод, что это API должно лучше подойти для современных 3D приложений.
Ниже вы можете увидеть схему работы Vulkan:
Будет ли Vulkan на Mac OS X?
После того как спецификация Vulkan была опубликована, найти драйвера для современных видеокарт не составляет труда. Но это только для Windows и Linux. Так как вулкан это только кроссплатформенный API, который не требует особой поддержки со стороны видеокарт, обновив драйвер, вы можете его начать использовать (если конечно ваша видеокарта в списке поддерживаемых).
Для Mac OS X всё намного сложнее. В El Capitan поддержки Vulkan нет, хотелось бы ждать в следующих версиях, однако есть одно «но». Apple в El Capitan добавила поддержку своего API — Metal. Раньше он использовался только для устройств на iOS. Исходя из этого, а также учитывая тот факт, что Apple привыкло контролировать всё, что касается их устройств, можно сделать вывод, что Vulkan может и не появиться на Mac OS X.
Что дальше?
По моему мнению, что ждёт Vulkan во многом зависит от того, насколько активно его начнут использовать разработчики и поддерживать производители видеокарт. Если развитие OpenGL на этом остановится, то для новых приложений выбора не будет и их придётся разрабатывать на Vulkan. Но существуют тысячи приложений на OpenGL, которые никто так сразу не ринется переписывать на Vulkan. Ещё и вопрос с Mac OS X не ясен, так как это очень распространённая система в США. Если для Mac OS X будет Metal, под Windows — DirectX, а под Linux Vulkan, то Vulkan никак не облегчит разработку кроссплатформенных приложений.
Декомпозируем игровую графику: технологии под капотом современных игр

С момента релиза War Robots прошло уже более 7 лет. В 2014 году мобильный игровой рынок был гораздо скромнее, чем сейчас, а девайсов, которые могли без проблем тянуть трехмерную игровую графику, — и того меньше. Несмотря на то, что уже случилась шейдерная «революция», и на замену графического конвейера с фиксированным функционалом (fixed-function pipeline) пришли вершинные и фрагментные шейдеры, возможностей для создания качественной картинки уровня настольного компьютера было явно недостаточно.
В основе же работы с любой графической системой лежит набор стандартизированных методов, маскирующих обращения к видеодрайверу для передачи команд графическому процессору — или, иными словами, контракт, в котором прописано, как с ней обращаться. Его называют графическим прикладным интерфейсом программирования — API (application programming interface). На старте разработки оригинальной игры фактически единственным среди графических API на мобильных платформах (Android, iOS) был OpenGL ES 2.0. Результат его эволюционного развития, OpenGL ES 3.0, был только-только утвержден, и на рынке даже не было устройств, которые бы его поддерживали. Таким образом, графика в Walking War Robots была основана на технологиях и возможностях, предоставляемых именно OpenGL ES 2.0.
У War Robots тех времен был вполне себе типичный графический стек, поддерживающий один направленный источник света и способный рассчитать от него затенение с учетом весьма простой системы материалов. Но в то же время игру отличали и довольно смелые решения: например, уже тогда применялась технология отрисовки террейна со сплатмапой, за счет плавного смешивания позволяющая рисовать протяженные комплексные поверхности без повторений однотипных мелких рисунков. Хотя и не все набирающие популярность методы нашли место в проекте — скажем, запеченное освещение (лайтмапы и лайтпробы) и система с множественными материалами тогда его обошли стороной.
Со временем графика в игре улучшалась и совершенствовалась, но довольно быстро ее развитие стало упираться ограничения OpenGL ES 2.0. Например, для полноценного использования получающих все большее распространение PBR-техник (physically-based rendering — PBR) нужна была возможность работы в линейном цветовом пространстве, что являлось неразрешимой проблемой для GLES 2.0. Наступил момент, когда потенциал эволюционного развития был достигнут, и без комплексного революционного подхода рывок в графике уже не представлялся возможным.

Первая итерация remastered-версии — прототип для Steam
К сожалению, несмотря на бытующее в некоторых кругах мнение, невозможно улучшить качество картинки в игре, просто «выкрутив настройки на максимум». А улучшить качество картинки в игре, которая находится в оперировании много лет, постоянно меняясь и развиваясь, — задача крайне нетривиальная. Как минимум, не выйдет сделать графику с нуля, без оглядки на ожидания игроков и на то, что уже прижилось в игре. Нужно очень бережно обращаться с существующим геймплеем и атмосферой, учесть огромное количество деталей, причем зачастую неочевидных. И, конечно, где долгая история активного оперирования, там накапливается внушительный объем кода (т.н. легаси). За годы существования War Robots, в игре накопилось множество крайне неочевидных решений: от уникальных и нужных, удивляющих своей изящностью, до поражающих воображение художественных костылей, когда-то решавших разнообразные технические проблемы, которые неизбежно приходили в проект с каждой новой версией Unity.
Все это не позволяло заранее определить с достаточной точностью объем и сложность работ, а отсутствие четкой картины финального результата только усугубляло проблему. Исходя из всего вышесказанного, очевидно, что сразу бросать сколь-либо значимые ресурсы на полноценный препродакшн с проработкой вижена, написанием документации, прототипированием и прочими редкими в нашем геймдеве животными вряд ли было бы хорошим решением, а учитывая плотный график фич и релизов — попросту нереальным: нельзя оставлять игроков без новых версий игры ради чего-то столь неопределенного.
К счастью, была возможность проверить идеи и уточнить многие детали с минимальным привлечением основной команды разработки: провести эксперимент на версии War Robots для Steam. Она хорошо подходила для этой цели по многим параметрам: практически полностью совпадающая кодовая база и арт, сравнительно небольшое количество игроков, при этом в среднем изрядно более мощное железо у этих самых игроков позволяло не так сильно заботиться об оптимизации на данном этапе, а сосредоточиться на красочной и насыщенной картинке.
В общих чертах идея эксперимента выглядела так:
определяемся с тем, как глубоко и какими средствами мы улучшаем картинку;
в рамках одной игровой карты перерабатываем графику (рендерер, модели, текстуры, шейдеры, свет, тени, обработку, эффекты, анимацию и т.д.) так, чтобы картинка ожила;
в процессе определяем объемы возможных работ по полной модернизации графики;
по результатам экспериментального релиза на Steam решаем, необходима ли такая модернизация вообще.
Как видно, на большинстве этапов задача вполне решаема силами одного технического художника, а небольшие изменения в пайплайне создания арта позволят в любом случае переиспользовать какую-то часть полученных результатов.
В качестве перерабатываемой карты была выбрана Canyon: на ней не так много геометрии, к новому игроку она попадает не первой, а потенциал к улучшению имеет значительный.

Первым делом, еще до каких-либо серьезных работ по графике, цветовое пространство проекта было переведено в линейное. Картинку, намекающую на реализм, можно получить и в цветовом пространстве sRGB, но это связано с таким количеством сложностей и неудобств на каждом этапе, что всерьез так делать имеет смысл только при необходимости поддерживать совсем устаревшие на сегодня устройства с версией OpenGL ES 2.0.
Чтобы получить первые быстрые результаты по сцене, часть геометрии окружения была заменена готовыми ассетами, а текстуры одного из роботов доработаны из исходников до технически корректного PBR. Немного доработок по свету, небольшая доработка пары шейдеров — и сцена начинает выглядеть чуточку современнее:

На получившейся картинке, помимо всего прочего, явно заметна нехватка динамического диапазона: освещение слишком однородное, будто в пасмурный день или в старой игре. В реальности освещенность ярких участков такой сцены может превосходить освещенность участков в тени в тысячи и десятки тысяч раз и доходить до сотни тысяч люкс. Невозможность работать с таким диапазоном (и значениями выше 1.0) при использовании буферов отрисовки форматов вроде R8G8B8A8_UNorm (8 бит беззнаковый целочисленный на канал) приводит к следующему почти обязательному требованию PBR — возможности отрисовки в широком динамическом диапазоне. Для этого используются буферы с плавающей запятой разной точности: от R32G32B32A32_FLOAT до формата R11G11B10_FLOAT.

Точность представления данных разных битовых форматов
Из таблицы видно, что, например, формат R32G32B32A32_FLOAT имеет точность 7.22 ненулевых знаков и огромное максимальное значение, однако требует значительно большего объема памяти для хранения — в 4 раза больше, чем R8G8B8A8_UNorm. На практике для хранения значений кадра в широком динамическом диапазоне нам достаточно максимального значения и точности R16G16B16A16_FLOAT — он и использовался в версии для Steam. Однако в большинстве случаев при должном обращении достаточно точности, обеспечиваемой форматом R11G11B10_FLOAT. Этот формат занимает в два раза меньше памяти, чем R16G16B16A16_FLOAT, и в точности вписывается в тот же «битовый бюджет», что и R8G8B8A8_UNorm. Отсутствие четвертого канала и вероятность возникновения небольшого цветового сдвига по причине меньшей точности синего канала не играют значительной роли, поэтому в мобильной версии мы по возможности используем его.
После получения кадра и постобработки получившегося HDR-изображения диапазон необходимо вернуть в рамки значений, доступных для вывода на экран, — для этого применяется процедура тонального отображения (tonemapping). Как в ремастере версии для Steam, так и в ремастере мобильном почти всегда мы используем алгоритм тонального отображения ACES: он позволяет получить «кинематографичную» картинку со слегка выжженными цветами в ярких областях.
На самой сцене больше всего изменений претерпел ландшафт. Логично было никак не затрагивать геймплей сцены — а значит, форма ландшафта в игровой зоне должна была остаться абсолютно такой же. Для этого с игровой зоны была снята карта высот (с точностью ±4 см), а на ее основе был процедурно сгенерирован новый ландшафт, изменения в форме которого касались только заднего плана. Текстуры ландшафта были, конечно же, перерисованы, маски сгенерированы, тесселяция добавлена, ручей налит, а после — подсушен. На небе появились динамические облака, в воздухе — пыль и дымка, а мост в центре карты — в очередной (но не в последний) раз переделан. Для понимания дальнейшего направления этого было достаточно.

Помимо сцены, улучшения получили и роботы. Под переработку попало более десятка роботов из числа популярных. Первым делом, если не нужны были существенные правки геометрии, от аниматора роботы получали новенький индивидуальный скелет на generic риге вместо общего на всех скелета на Humanoid, а также индивидуальный набор анимаций. Текстуры были либо доведены до адекватного PBR и доработаны в случае, если исходники текстур рисовались в Painter, либо перерисованы на базе имеющихся с нуля, либо использовали оригинальные маски (при наличии таковых).
Особую боль и недоумение вызывало отсутствие специальных клипов анимации прыжка и приземления прыгающих роботов. Для избавления от эффекта пенопластового клоуна роботы получали набор анимационных клипов для разных вариантов подготовки к прыжку, подготовки к приземлению и самого приземления, а также полноценную логику для их выбора и воспроизведения. Также прыгуны получили эффекты на включение двигателей и их последующее плавное остывание, а некоторые — изменяемое в соответствии с направлением прыжка направление сопел. Не то, чтобы это все было нужно в этой экспериментальной версии, но в проработке некоторых деталей стоит идти до конца.
В качестве развлечения в свободное время система инверсной кинематики для правильной постановки ног на наклонные поверхности, используемая ранее только на четырехногих роботах, была глубоко переработана и задействована на всех переработанных роботах двуногих.
Также были переработаны почти два десятка единиц вооружения: текстуры заменены на PBR, изменены некоторые анимации, слегка доработаны шейдеры эффектов, а для выстрелов и взрывов добавлены источники света.

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

Скриншоты в формате «было/стало»
Для оставшихся роботов и прочих ассетов был создан шейдер, в котором с помощью некоторых эвристик свойства из старого набора текстур (диффуз, спекуляр и карта нормалей) на лету преобразовывались в те, что были необходимы для полноценного расчета PBR.
Релиз экспериментальной версии для Steam случился в конце 2018 года. По его итогам были сделаны следующие выводы:
Не стоит недооценивать негативную реакцию пользователей на повысившиеся требования к железу;
Нужно аккуратно подходить к изменению привычных анимаций роботов: люди способны неплохо определять неврологические заболевания по походке. Особенно у Гриффина;
Motion blur в нашем жанре не нужен;
Физически корректное освещение — это хорошо, но к освещению сцен стоит подходить с учетом влияния контраста на геймплей;
Яркие вспышки от взрывов и выстрелов мешают стрелять и взрывать;
Ремастер для мобильных платформ — нужен.
Следующий этап — перенос ремастера на мобильные устройства
После того как все было готово с той самой первой версией ремастера, нам предстояла еще более амбициозная задача: перенести визуальную составляющую десктопного уровня из Steam на мобильные устройства.
Такие эффекты, как отрисовка динамической поверхности океана, зеркала воды с отражениями и преломлениями, блендинг нескольких слоев протяженного террейна, помимо возможностей графического API, требуют хорошего запаса вычислительной мощности. Вместе с этим, ремастер в обязательном порядке должен работать не хуже оригинала, обеспечивая комфортную игру на устройствах трехлетней и даже пятилетней давности. В итоге возникла дилемма: как реализовать графику десктопного уровня на мобильных устройствах и в то же время не снизить производительность графики в целом?
Компромисс нашелся в решении разделить устройства по уровню производительности и подготовить несколько пресетов качества. Каждый пресет отличается набором контента (количество и разрешение текстур, полигонаж объектов, наполнение игровых уровней) и стеком используемых графических решений (модель освещения, детализация отрисовки объектов, сложность эффектов постобработки). Таким образом, весь ассортимент мобильных устройств разделился на три категории — HD, LD и ULD.
Так выглядит игра в HD-пресете
Так — при LD-настройках
Так — в ULD
Современные топовые мобильные устройства без труда могут потянуть высоконагруженный графический стек — они и сформировали группу для HD-пресета качества. Самый массовый сегмент, включающий в себя устройства среднего уровня производительности, получил LD-пресет. А для совместимости с устройствами, которые из последних сил «вытягивали» оригинальную игру, сделан облегченный ULD-пресет. Таким образом, сформировались три группы девайсов, в каждой было выбрано свое референсное устройство (девайс или графический процессор), под которое готовился контент и настраивался графический стек.

Целевые устройства для разных пресетов качества
Но даже в пределах каждой из трех групп разброс производительности оказался в достаточно широких пределах и требовал более точной подстройки для комфортной игры. Поэтому для сглаживания изменений частоты кадров мы стали применять адаптивную подстройку разрешения отрисовки сцены. Изменение разрешения практически напрямую влияет на объем нагрузки на графический процессор и может варьироваться в реальном времени в зависимости от происходящего в игре, основываясь на истории нескольких последних кадров. Полноэкранное сглаживание (MSAA) эффективно маскирует моменты смены разрешения, снижая «ступенчатость» и «замыленность» картинки.

Таким образом, в ремастере имеет место «двухэтапная» схема масштабирования производительности:
на первом этапе для грубой настройки выбирается контент и графический стек разной степени сложности — один из трех пресетов качества;
на втором этапе для тонкой настройки подстраивается разрешение отрисовки, обеспечивая плавный и комфортный игровой процесс.
OpenGL ES vs. Metal & Vulkan — что выбрать?
Для работы с обновленным контентом от графического конвейера требовалась поддержка таких функций, как многопроходная отрисовка (multi-pass rendering), выборка из текстурных массивов (texture arrays), запись в буферы цвета вещественного формата (float-point color buffers). Используемый изначально в проекте OpenGL ES 2.0 все это поддерживать не мог. Отсюда — возникла необходимость перехода на более современный графический API, тем самым заодно повысив удобство работы и улучшив производительность.
На iOS очевидным выбором стал Metal API, который поддерживался на 99,2% устройств и полностью соответствовал нашим требованиям. Кроме того, замена OpenGL ES на Metal API рекомендуется самой компанией Apple. Он обладает гораздо более гибким функционалом и высокой производительностью, а также удобными средствами отладки и профилирования.
Android предлагает выбор между двумя графическими API: OpenGL ES 3.0+ и Vulkan. Первый существенно превосходит свою предыдущую редакцию 2.0 по функционалу, имеет прекрасно отлаженные драйверы и работает на 97,1% устройств пользователей, но при этом концептуально морально устарел и имеет весьма туманные перспективы. Альтернативой OpenGL ES является Vulkan — низкоуровневый графический API, идеологически близкий к Metal.
Результаты экспериментов с Vulkan на мобильных устройствах подтвердили более «ровную» производительность графического конвейера ремастера по сравнению с OpenGL ES. Вместе с этим доступность Vulkan API и его стабильное функционирование подтверждено лишь на 63% устройств, что делает его использование слишком рискованным. Так, например, в Unity в Scriptable Render Pipeline совсем недавно была добавлена модель RenderPass/SubPass, которая в полной мере позволяет раскрыть потенциал Vulkan API на мобильных платформах. К сожалению, на момент выпуска ремастера модель осталась незадействованной, вследствие чего результаты производительности при использовании Vulkan API по сравнению с OpenGL ES 3.0 оказались неоднозначными и отличались от устройства к устройству.
В результате в качестве графического API на Android мы остановились на OpenGL ES 3.0, а поддержка Vulkan пока остается в статусе экспериментальной.
Тени, освещение, постобработка — из каких этапов состоит отрисовка графики
«Двухэтапная» схема масштабирования производительности и переход на современные графические API позволили заложить основу для разработки гибкого и производительного графического конвейера. В результате для всех пресетов качеств — ULD, LD, HD — используется унифицированный многопроходный конвейер отрисовки, отличающийся набором входных данных и вариантами их обработки. Так, различаются разрешения текстур и детализация геометрии, сложность шейдеров и конфигурация проходов отрисовки.

Различия наборов текстур в пресетах
Технологически отрисовка каждого кадра состоит из трех основных этапов: проход отрисовки теней, проход наложения освещения и проход постобработки.

Различия проходов отрисовки в пресетах
Проход отрисовки теней использует две карты теней (shadow map). Первая из них представляет собой один каскад и обновляется каждый кадр, включая в себя объекты в области видимости камеры на близких расстояниях. Для объектов вдалеке от камеры используется глобальная предрассчитанная карта теней (shadow masks) с меньшей точностью границ тени (umbra) и полутени (penumbra). При расчете освещения выборки из обеих карт теней смешиваются друг с другом для незаметного и плавного перехода между ними и используются для затенения. Таким образом, в каждом кадре обрабатывается только небольшое подмножество объектов вблизи камеры, что позволяет существенно снизить нагрузку по обработке геометрии. В то же время использование прерассчитанной карты теней позволяет отображать тени от объектов по всей площади сцены.
При отрисовке геометрии в карту теней порядок следования индексов треугольников изменяется на обратный для более эффективного отсечения — это называется front-face culling. В результате этого значительно снижается нагрузка на растеризатор, ведь порядка 90% треугольников отбрасывается еще на раннем этапе. Карта теней при этом получается достаточно разреженной, что дополнительно повышает производительность при выборке и сравнении значений из нее. Ниже для сравнения приведены карты теней — с результатом классической отрисовки и инверсной.

Карты теней с обратным отсечением треугольников
Проход наложения освещения рассчитывает интенсивности освещенности объектов в сцене от одного основного источника света. Его вклад традиционно формируется из двух составляющих:
прямое освещение (direct), рассчитываемое в реальном времени;
непрямое освещение (indirect), выбираемое либо из предрассчитанных карт освещенности (lightmaps) для статических объектов, либо из ближайших зондов освещенности (lightprobes) для динамических объектов.
И для того, и для другого используется отрисовка в широком динамическом диапазоне (high dynamic range) c пофрагментным вычислением двухлучевой функции отражательной способности (bidirectional reflectance distribution function).
При расчете освещения на всех объектах в сцене используется одинаковая физически достоверная (physically based) модель. Благодаря этому мы можем применять для хранения параметров материала общие на все объекты в сцене текстурные массивы. Среди параметров материалов — альбедо (albedo), гладкость (smoothness), металличность (metallnes), нормали (normal) и значение окружающего затенения (ambient occlusion). В результате мы используем всего пять основных шейдеров для отрисовки всех объектов в сцене: mechs/drones/equip shader, terrain shader, decal shader, unique props shader, detail props shader.

В проходе постобработки производится сжатие широкого динамического диапазона в диапазон, подходящий для вывода на экран с помощью тонального отображения, а также цветокоррекция (color grading), виньетирование (vignette) и, при необходимости, конверсия цветового пространства из линейного в sRGB. Поверх получившегося изображения рисуются элементы графического интерфейса (UI) и после этого, наконец, следует вывод на экран.

Не только улучшенная картинка, но и производительность: снижаем время отрисовки кадра и разгружаем ЦП
Современные графические API — способ повысить не только качество картинки, но и производительность: с их помощью значительно снижается время отрисовки кадра, уменьшается нагрузка на центральный процессор и получается плавная и стабильная частота кадров.
Большое разнообразие материалов в сцене обычно сопровождается частой сменой ресурсов между вызовами отрисовки. Поскольку в процессе перепривязки ресурсов (resource binding) графический процессор не может заниматься отрисовкой, это приводит к вынужденным ожиданиям, а значит — к неполной загрузке ЦП. Для борьбы с этим происходит группировка вызовов отрисовки с одинаковыми материалами для последовательного исполнения (batching). Однако, если каждый материал в сцене уникален, традиционный подход группирования будет неэффективным и потребует перепривязки ресурсов практически при каждом вызове. Поэтому обычно количество уникальных материалов в сцене фиксировано, что накладывает ограничения на свободу действий при дизайне игровых уровней и подготовке контента.
Графический пайплайн ремастера не накладывает ограничения на количество уникальных материалов в сцене, поскольку не требует перепривязки ресурсов. Так, все текстуры из уникальных материалов собраны в текстурные массивы (texture array), а дополнительные параметры скомбинированы в единый константный буфер (uniform buffer).

Схема комбинирования материалов (констант и текстур)
Привязка таких «собранных» ресурсов происходит единожды вместе с соответствующим шейдером и не меняется на протяжении всех вызовов отрисовки, использующих этот шейдер. Нужный материал выбирается из коллекции непосредственно в шейдере за счет обращения к соответствующему слою текстурного массива по индексу и через рассчитываемый отступ до соответствующего элемента в константном буфере. Таким образом, число перепривязок ресурсов строго равно числу уникальных шейдеров, используемых в сцене. В ремастере в каждой сцене используется в среднем 12 вариантов шейдеров, получаемых из пяти основных за счет использования ключевых слов (keywords). В результате на 300-400 вызовов отрисовки в кадре приходится в среднем 20 перепривязок ресурсов, благодаря чему время подготовки кадра практически не зависит от количества уникальных материалов.
Техническая реализация такого решения требует поддержки со стороны графического API двух возможностей: выборки из текстурных массивов (texture array fetching) и использования динамических константных буферов (dynamic uniform buffer). Графический конвейер ремастера полностью поддерживает SRP batching на Metal и Vulkan и частично на OpenGL ES 3.0. Тут стоит напомнить, что использование текстурных массивов предполагает одинаковый формат, разрешение и количество mip-уровней в слоях. Динамические константные буферы, в свою очередь, требуют строгого соблюдения специфичного для каждого устройства шага выравнивания при установке отступов. Для большинства графических процессоров Mali это 16 байт, а для графических процессоров Adreno — 64 байта.
Для мобильных платформ, по сравнению с их стационарными аналогами, характерны небольшой объем видеопамяти и ограниченная емкость источника питания. Для решения этих двух проблем практически все современные мобильные графические процессоры построены на тайловой архитектуре. Среди ее ключевых особенностей можно выделить следующие отличия:
для минимизации перерисовки пикселей (pixel overdraw) геометрия предварительно распределяется по небольшим участкам в экранном пространстве — тайлам;
каждый тайл обрабатывается независимо, локализуя отрисовку небольшой областью экрана;
при обработке тайла его геометрия сначала сортируется, а потом уже отрисовывается, что позволяет достичь того же эффекта, как и при предварительной отрисовке в буфер глубины (z-prepass) на стационарных платформах.
Следует отметить, что использование особенностей тайловой архитектуры не требует каких-либо действий или установок со стороны графического API и неявно выполняется видеодрайвером.
Другим важным преимуществом тайловых архитектур является наличие тайловой памяти. Она расположена непосредственно на GPU и позволяет избегать довольно энергозатратного экспорта/импорта промежуточных данных в видеопамять. Типичными сценариями использования тайловой памяти являются разрешение сэмплов полноэкранного сглаживания (multi-sample anti-aliasing resolving) без дополнительного прохода, создание «виртуальных» буферов без выделения памяти (memoryless attachments), использование временных буферов (transient attachments) между проходами отрисовки. Для работы с тайловой памятью на современных API (Metal/Vulkan) предусмотрены явные методы, в то время как OpenGL ES 3.0 позволяет только задать определенные подсказки видеодрайверу. В ремастере для всех поддерживаемых графических API применяется полноэкранное сглаживание (MSAA) без отдельного прохода разрешения (resolve) и без использования промежуточной видеопамяти (memoryless) под семплы.
Отладка и диагностика: как отследить, что с новыми технологиями все в порядке
Любой проект с высокой нагрузкой будет требовать постоянного контроля производительности. Профилирование графики правильнее всего планировать на самом начальном этапе, как только более или менее сформирован графический стек. Так, при работе над ремастером мы обновили автоматические бенчмарки, измеряющие производительность при отрисовке сцен, мехов/экипировки и эффектов. Так мы смогли оперативно выявлять и реагировать на регрессии, а при необходимости — глубже изучали причины просадок. Для этого у нас в ходу такие инструменты, как Qualcomm Snapdragon Profiler, ARM Graphics Analyzer и Xcode Frame Debugger — именно с их помощью происходит диагностика проблем, специфичных для отдельных графических процессоров, и довольно заметно влияющих на производительность:
«проливание» регистров графического процессора (GPU register spilling), характерное для сложных вычислений;
излишний импорт/экспорт данных из тайловой памяти в глобальную при работе с полноэкранным сглаживанием и составляющими буфера кадра (framebuffer attachments);
наличие в сцене недружественной для тайловых архитектур геометрии, состоящей из длинных вытянутых треугольников;
чрезмерное использование прозрачных и полупрозрачных материалов, существенно увеличивающее перерисовку пикселей (pixel overdraw);
оптимальное соотношение между арифметическими операциями и операциями чтения/записи, приводящее к неполной загрузке графического процессора;
эффективность использования кэша 1-го и 2-го уровня для предвыборки из текстур и снижения задержек доступа к данным.
Это основные показатели производительности различных блоков GPU, наиболее полезные для контроля эффективного распределения нагрузки. Практика регулярного профилирования позволила нам с самого начала работы над ремастером выявлять узкие места и не допускать просадок производительности.
Пример окна ARM Graphics Analyzer
Пример окна Qualcomm Snapdragon Profiler
Помимо мониторинга эффективной работы «железа» конкретных мобильных систем, при работе с Unity не менее важно уделять внимание корректности вызовов графических API. Для проверки GLES 3.0 и Vulkan мы использовали RenderDoc, а для Metal — Xcode Frame Debugger. С их помощью можно детально проверить:
структуру кадра отрисовки (установка шейдеров и привязка ресурсов);
промежуточные состояния графического конвейера (настройка теста глубины, параметров альфа-смешивания, переключения буферов кадра);
консистентность ресурсов (формат, разрешение, компрессия).
Такое инспектирование вызовов графического API оказалось просто незаменимым для отладки различного рода падений и зависаний на широком ассортименте мобильных устройств, встречающихся на ремастере.
Пример окна Xcode GPU Frame Debug
Пример окна RenderDoc
Пример окна RenderDoc
Подводя итоги: об опыте работы над новым графическим пайплайном
Сейчас, когда релиз ремастера состоялся, можно смело сказать, что работа над обновлением графической составляющей была действительно захватывающей и интересной. Эксперименты с возможностями мобильных графических процессоров позволили подобрать решения, которые отлично масштабируются на широкий ассортимент устройств:
Использование текстурных массивов и скомбинированных константных буферов позволило значительно сократить число вызовов отрисовки и снять ограничение на максимальное количество уникальных материалов в сцене;
Переход на буферы цвета в вещественном формате открыл нам новые возможности для вычисления физически достоверного освещения в широком динамическом диапазоне и применения эффектов постобработки;
Применение пресетов качества и динамическая подстройка разрешения перевела визуальную часть проекта на современных устройствах на качественно новый уровень, при этом обеспечив хорошую производительность и на девайсах 4-5 летней давности, как это и подобает ремастеру.
Работа над проектом подарила команде бесценный и уникальный опыт не только по подготовке контента и переделке графического конвейера, но и по наработке методик тестирования, отладки и улучшения производительности.