Наступают чудесные времена для графики на iOS 8!
На недавней WWDC компанией Apple был представлен новый графический API под названием Metal, отличительной особенностью которого стала высокая эффективность, низкий уровень издержек и оптимизация под чип A7. Это предоставляет разработчикам возможность воспользоваться всеми аппаратными преимуществами устройств на iOS и добиться намного большего уровня реалистичности, детализации и интерактивности в играх, чем когда бы то ни было.
В данный момент процесс реализации поддержки Metal уже запущен, а пока мы бы хотели рассказать вам кое-что об этой технологии и объяснить, почему же это так круто.
Глянцевый Метал
В Metal заложено несколько ключевых моментов, позволяющих снизить загрузку CPU, просчитать его производительность в определенных условиях и оптимизировать все процессы:
• Cоздание и проверка предварительных компонентов отрисовки. Шейдеры могут компилироваться и частично оптимизироваться в автономном режиме. Все, что связано с рендеринговым пайплайном: шейдеры, вертекстные компоновки, режимы блендинга, форматы рендер таргетов и т.д. могут быть созданы и подтверждены еще даже до того, как начнется, собственно, сам рендеринг. То есть не надо проверять каждую составляющую отрисовки и мощность CPU высвобождается для других целей.
• Обсепечение на порядок более гибкой многопоточности. Ресурсы могут создаваться из любого потока, и доступен ряд возможных способов подготовить заявку на отрисовку из нескольких параллельных потоков.
• У всех устройств на базе iOS единая память для CPU и GPU. Нет необходимости представлять, что данные из CPU должны быть ‘‘скопированы’’ в некую видеопамять. Когда вы создаете буфер обмена, то надо всего лишь указать, что в нем находятся данные, и это ровно та же память, которую будет использовать и GPU.
• Дайте юзеру (движку) осуществлять синхронизацию. OpenGL ES прыгал через множество костылей и о многих моментах ‘’догадывался’’, для того, чтобы можно было реализовывать все возможные сценарии. В Metal синхронизация данных между CPU и GPU является прерогативой юзера. Движок ведь и на самом деле лучше знает, что ему надо делать!
• Все GPU в iOS-устройствах используют архитектуру отложенного рендеринга на основе тайлов. Это в ясном виде используется в Metal API, особенно когда речь идет о целях рендеринга. API теперь не пытается ничего предугадать — все действия с буфером кадров, типа загрузок и сохранений тайлов, и реализации сглаживания, происходят в явном виде.
• Все пункты, перечисленные выше, необходимы для того, чтобы можно было значительно снизить нагрузку на процессор и гораздо более четко прогнозировать степень его производительности и загрузки.
• Новый язык на базе C/C++11 предназначен как для графических, так и для вычислительных шейдеров. А это значит, что iOS будет уметь работать с вычислительными шейдерами, атомарностью, произвольной записью в буфер и прочими фишками с прикольными названиями, которые сейчас доступны на GPU.
• Никакой дурной наследственности, новый API очень прост и отлично оптимизирован. А, и еще у него есть супер-полезный опциональный ‘‘слой отладки’’, который дополнительно все проверяет и уведомляет о любой ошибке или заблуждении, которые вы сделали.
А теперь давайте углубимся в детали еще поглубже!
Вопрос заявок на отрисовку
Если вы занимаетесь созданием игр, особенно для мобильных устройств, то наверняка знаете, что большое количество заявок на отрисовку сильно нагружает процессор. Каждый и любой объект рендеринга требует для себя некоторое количество процессорной мощности, и в реальности на мобильных устройствах вы не сможете единовременно реализовать отрисовку больше нескольких сотен видимых объектов за один раз. В реальности же вы наверняка очень захотите использовать ресурсы CPU и для других нужд — геймплейная логика, физика, AI, анимирование персонажей и все остальное. В Unity есть некие оценочные параметры для минимизации количества сделанных заявок на отрисовку — статический и динамический батчинг (или смешной русскоязычный термин — ‘‘дозирование’’ — прим. перев.), occlusion culling (еще один смешной термин ‘‘окклюзивное обрезание’’ — прим. перев.), LOD (уровни детализации) и distance-based layer culling (удаление слоев в зависимости от их удаленности); кроме того, можно объединять близкие объекты, которые стоят друг рядом с другом, и помещать текстуры в атласы для уменьшения количества материалов.
Хороший вопрос заключается в том, почему должен использоваться ресурс CPU, чтобы что-то отрисовывать? В конце концов, это же то, чем реально должен заниматься GPU.
Некоторые издержки происходят на стороне ‘‘движка’’ — процессору необходимо управлять видимыми объектами, выяснять, какой шейдер сейчас надо рендерить, с каким из объектов какому источнику света необходимо взаимодействовать, какой параметр материала сейчас надо применить и все такое. Что-то из этого закэшировано, что-то выполняется в нескольких потоках; и в целом, это независимый от платформы код. В каждом релизе Unity мы стараемся оптимизировать эту часть, и Metal, в общем, на это никак не влияет.
Однако, в остальной части процессорных издержек можно уличить именно ‘‘графический API и драйвер’’. В зависимости от игры, эта часть может быть очень важной. Metal — это попытка решить вопрос с этой частью, будучи гораздо более подходящей для современного железа, на несколько более низком уровне, и выполняя чудовищно меньшее количество догадок, чем обычно делал OpenGL ES. Упреждающий рендеринг, его создание и валидация; явная загрузка и сохранение рендер-таргетов; отсутствие тацев с бубнами для синхронизации на стороне API — все эти вещи способствуют снижению нагрузки на процессор.
Насколько мы уже успели протестировать, новые API+драйвер загружают CPU всего лишь на несколько процентов. Это существенное снижение, особенно по сравнению с тем, что раньше этот показатель был на уровне 15-40% от полной загрузки CPU! Это значит, что остальное скрывается где-то в нашем коде. И мне кажется, что нам надо продолжать его оптимизацию (смайл).
Ну и не терпится познакомиться с возможностями Metal по объединению рендеринга из нескольких потоков; это также открывает для нас очень интересные возможности для оптимизации.
Возможности вычислений
Благодаря Metal можно будет использовать GPU для вычислений за пределами типовых сценариев: не только для вершинных + фрагментарных шейдеров — но и для шейдеров, известных под названием “вычислительные”. В принципе, это дает возможность запускать любой тип ‘‘параллельных вычислений’’ на множестве маленьких процессоров внутри GPU. Вычислительные шейдеры так же используют концепт ‘‘локального хранилища’’ — очень быстрой выделенной части памяти-на-GPU, которая может быть использована для обмена данными между параллельными рабочими элементами. Такой участок памяти позволяет использовать GPU для вещей, которые очень не просто было бы реализовать с помощью старых добрых вершинных и фрагментарных шейдеров.
Есть куча интереснейших областей, для которых можно будет использовать вычислительные шейдеры — оптимизация пост-процессинговых эффектов, системы частиц, работа с выборками и отрезанием света и тени, и все в этом духе.
В то же время, в Unity пока еще не используются вычислительные шейдеры, мы все с нетерпением ждем, что их можно будет употребить для множества, огромного множества классных штук. Захватывающие времена грядут!
FAQ
Когда я смогу этим воспользоваться?
Нам не терпится начать отгрузки, но назвать конкретных дат мы пока не можем. Мы уже сделали многое, но нужно еще работать и работать до того, как все будет готово. Наш текущий план — интегрировать все части Metal, что обеспечит мощный прирост производительности процессора. Надеемся, что это произойдет в Unity 5.0. А немного позже мы хотим добавить поддержку вычислительных шейдеров (этот момент немного сложнее и тредует большего внимания с нашей стороны).
Каковы будут системные требования?
Metal будет работать на iOS 8 и устройстве с процессором не слабее A7 (iPhone 5S, iPad Air, iPad Mini Retina).
Что мне нужно будет сделать, чтобы получить преимущества от оптимизации загрузки CPU с помощью Metal?
В общем, ничего. Как только мы добавим поддержку Metal в Unity, все заработает само. Все ваши существующие проекты, все ваши шейдеры и графические эффекты будут просто работать. Просто наслаждайтесь низким уровнем загрузки процессора!
Но что по поводу шейдеров, ведь в Metal для них используется другой язык?
Мы позаботимся и об этом. Сейчас вы, скорее всего, пишете шейдеры на Cg/HLSL, а мы конвертируем это в GLSL для OpenGL ES за кулисами. Для Metal мы будем конвертировать все это примерно таким же образом.
Еще разок, что же мне можно будет сделать благодаря тому, что загрузка CPU будет оптимизирована, и у меня появятся свободные ресурсы?
Улучшить физику, AI или сделать еще сложнее и комплекснее логику и геймплей. Разместить и отрисовать больше объектов на экране. Или просто наслаждаться экономией аккумулятора устройства. Все зависит от вас!
Автор: goroshkin