Пользователь
0,0
рейтинг
16 июня 2014 в 21:56

Разработка → Apple Metal API: в чем же фишка? из песочницы

imageНа WWDC 2014 всех нас ждал сюрприз: анонс нового графического 3D API под названием Metal. Но на этот раз мы имеем дело не с новым высокоуровневым API поверх OpenGL ES (как было в случае с Scene Kit), а с новым низкоуровневым API для рендеринга и вычислений, которое может служить заменой OpenGL в играх. По словам Apple, Metal может быть до 10 раз быстрее, чем OpenGL ES (точнее говоря — может генерировать вызовы отрисовки [draw calls; передача данных на GPU] в 10 раз быстрее) и доступен только на устройствах с iOS и процессором последнего поколения A7.

Этот анонс спровоцировал новую волну обсуждения и споров насчет необходимости появления новых графических API, которые должны (или не должны — кто знает) заменить OpenGL. Предлагаемый вашему вниманию пост не намерен участвовать в этой дискуссии – его целью является разъяснение того, чем все-таки Metal отличается от OpenGL ES, чьей заменой он является. Чтобы понять, что такого особенного (или же наоборот, ничего особенного) есть в Metal API, нам придется немного заглянуть под «капот» графических API и GPU.

Как работают GPU и графические API

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

Для простого улучшения в работе GPU этот процесс стоит запустить асинхронно; тогда GPU не будет блокировать CPU и вызовы API будут возвращать результат почти мгновенно. В этом случае GPU возможно не будет использоваться на все 100%, поскольку ему возможно придется ждать от CPU новых вызовов рендеринга (= начала кадра), в то время как вызовы остальных команд будут ждать завершения предыдущих. Это становится причиной того, почему большинство графических драйверов собирают все вызовы отрисовки (и другие задачи, которые нужно будет выполнить на GPU — например, изменение состояний) для отрисовки всего кадра перед отправкой его на GPU. Эти буферизованные команды будут затем отосланы обратно после того, как будет получена команда для отрисовки следующего кадра, благодаря чему GPU будет использоваться настолько эффективно, насколько это возможно. Конечно, это добавит один кадр задержки: пока CPU будет создавать задание для текущего фрейма, прошлый фрейм будет рендериться на GPU. На самом деле, можно буферизовать больше одного кадра и таким образом добиваться большей частоты смены кадров — за счет еще большей задержки.

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

Итак, мы узнали как минимум две важные вещи о том, что происходит за сценой совместной работы OpenGL с современными GPU: изменение состояний может быть сложным, если требуется новая комбинация состояний и все операции на GPU будут задержаны на некоторое количество времени.

В приложении, один поток актуальных команд для одного кадра, которые надо выполнить на GPU, формируется и отправляется на GPU сразу весь за один раз (на самом деле все немного сложнее, но давайте не будет пока углубляться).

Подробнее прочитать о том, как работает современный пайплайн компьютерной графики вы можете в серии статей Fabian Giesens — “A trip down the Graphics Pipeline“.

Почему у другой программной модели могут быть преимущества

Как вы уже увидели, от программиста спрятано огромное количество сложностей и хитрых трюков (их наверняка еще больше, чем я упомянул), которые прячут то, что непосредственно происходит. Одни из них делают жизнь простого разработчика проще, другие — заставляют его искать способы обхитрить драйвер или «копать» в сторону побочных эффектов работы вызовов API.

Некоторые графические API сегодня пытаются убрать большую часть этих трюков, раскрывая скрываемую ими «запутанность» – и в некоторых случаях оставляя на волю программы решение всех связанных проблем. В этом направлении шли графические API PS3, в нем же идет AMD со своим Mantle, туда же собираются грядущие DirectX 12 и Apple Metal.

Что же изменилось?

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

Поскольку становится ясно, что эти буферы не будут выполняться прямо сразу (то есть во время создания) и что множественные буферы могут быть созданы и добавлены в очередь на выполнение в определенном порядке, приложение может позволить себе их построение в нескольких потоках в параллели. Также для программиста становится более очевидным, какие из результатов вычислений уже доступны, а какие — нет.

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

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

Есть нюанс и в заточке под A7 — благодаря ему Metal заточен под работу на системах с общей памятью, т.е. CPU и GPU могут получать прямой доступ к одним данным без необходимости перебрасывать их по шине PCI. Metal дает прямой доступ для программы к буферам из CPU, и ответственность за то, что эти данные не используются одновременно и GPU, ложится на плечи программиста. Эта полезная функция позволяет смешивать произведение вычислений на GPU и CPU.

И как это в 10 раз быстрее?

Каждый вызов отрисовки стоит сколько-то времени на CPU и сколько-то времени на GPU. Metal API уменьшает время, затрачиваемое CPU, благодаря упрощению контроля за состояниями и благодаря этому уменьшению числу проверок на ошибки от драйвера на правильность комбинаций состояний. Еще помогает предварительное вычисление состояний: можно не просто выполнять проверку на ошибки во время билда, но и само изменения состояния потребует меньшее количество вызовов API. Возможность параллельного построения буферов команд еще больше увеличивает число вызовов отрисовки в том случае, если приложение привязано к CPU.

А вот рендеринг на GPU с другой стороны быстрее не становится, приложение которое делает совсем немного вызовов отрисовки для больших мешей (меш — часть модели, состоящая из вершин объекта] не получит никакого преимущества от перехода на Metal.

Может ли то же самое быть сделано на OpenGL?

На GDC 14 была отличная презентация “Approaching Zero Driver Overhead” за авторством Cass Everitt, John McDonald, Graham Sellers и Tim Foley. Основной ее идеей было уменьшение работы драйвера в OpenGL при помощи увеличения количества работы, производимым вызовов отрисовки, и использованием новых объектов GL и меньшего количества числа вызовов GL для повышения эффективности.

Эта и другие идеи потребуют дальнейшего расширения OpenGL и появления новых версий этого API, но многое из этого можно будет перенести в OpenGL ES. Что мы потеряем — так это возможность прямого управления командными буферами, со всеми своими «за» и «против».

Какова вероятность увидеть это в будущем? Из-за поддержки обратной совместимости, остается надеяться только на появление некоего набора функций, который можно будет назвать «современное ядро», но и его скорее всего придется сделать совместимым со всем вплоть до оригинальной функции glBegin(). Это ограничение будет действовать на протяжении всего потенциального будущего OpenGL и станет пределом его эволюции, делая альтернативы вроде Metal API все более предпочитаемыми…

Оригинал статьи:
http://renderingpipeline.com/2014/06/whats-the-big-deal-with-apples-metal-api/
Сергей Попов @SergDrakon
карма
6,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (14)

  • 0
    Блин. Нет графиков. Не одного… :(
    • +92
      Держите.
      Скрытый текст

      Простите, не могла удержаться. уж очень «подробный» запрос :)
      • +2
        Графиков возрастания скорости, я думаю =)
        • +8
          Я вижу большинству, и этот понравился :-)
  • 0
    Интересная штучка. Большие игроки типа Unity3D или Unreal Engine и так поддерживают 3-5 разных графических API, добавить еще один им не сложно.

    А так жалко конечно что опять все разное на всех платформах. С другой стороны, простые кроссплатформенные 2д движки могут ограничиться OpenGL и не париться особо. Сменить OpenGL на metal полностью еще не скоро станет возможным (на рынке полно старых девайсов), а поддерживать оба АПИ сложно и не факт что вообще что-то даст в плане производительности.
    • +5
      Вот я не могу понять таких комментаторов (без обид). Кто принуждает вас использовать Metal? Пишите с OpenGL.
      А про загадочных людей, поддерживающих оба апи — уже вопросы к ним. Видимо и деньги есть, и время есть.
    • +1
      Эпики со своим Unreal Engine 4 уже. Точнее даже, к самому WWDC представили.
    • +3
      Большие игроки типа Unity3D или Unreal Engine и так поддерживают 3-5 разных графических API, добавить еще один им не сложно

      А производители движков от этих Metal/Mantle и иже с ним и есть главные победители. Если сейчас ещё и Qualcomm, ARM, NVIDIA и Intel (а ведь на Android ещё есть экзотичные Vivante и Broadcom) придумают по своему API, то будут два варианта:
      а). Чтобы добиться высокой производительности свой движок под каждый из 5-7 «мобильных» API обычным разработчикам будет дорого поддерживать, поэтому проще лицензировать сторонние. Как следствие, Epic, Unity и прочие в большом профите, ибо без них будет вообще никуда, особенно для студий без поддержки зажиточных издателей.
      б). Для консистенции пользовательского впечатления все продолжат использовать OpenGL ES. А то будет непорядок, если какой-нибудь Asphalt 10 от Gameloft на Samsung Galaxy S7 с Mali будет работать в 10 раз медленнее, чем на Galaxy S7 с Adreno, или наоборот, из-за того, что не осилили допилить движок под какой-нибудь специфический собственнический API.

      Вообще интересно, как Google на это дело с Metal API отреагирует. Изобретёт свой велосипед по традиции с Renderscript Compute, или понесёт бабло в Khronos для ускорения проектирования и стандартизации OpenGL ES Next.
  • +5
    Забавно, что на первых массовых ускорителях 3dfx тоже был минималистичный API Glide, с полным доступом к памяти ускорителя и командами, предельно близкими к железу. Потом всё пошло по пути усложнения API, и где-то на DirectX 7 с его T&L сложность API достигла пика и повернула обратно, сначала к шейдерам, потом к вычислениям на GPU, а теперь, сделав полный круг, вернулись к минимальному API. Прошло каких-то 18 лет.
    • +4
      Просто время программистов подешевело и железо опять стало узким местом. Вот и заставляют людей писать более низкоуровневый код.
  • +8
    В OpenGL ES 2.0+ и OpenGL Core Profile (3.0+) вообще нет вызовов glBegin(), так что вы уж учень утрируете либо сознательно привираете — уже никто не тащит обратную совместимость такого уровня. Fixed pipe остался в прошлом. В числе возможных кандидатов на включение в OpenGL 5 и ES 4 очень много расширений, уменьшаяющих количество вызовов API и нагрузку на CPU в целом. Так что OpenGL еще повоюет на этом поле.
    Его проблема в другом, учитывая заточенность на конкретную архитектуру SoC, можно одновременно и сильно оптимизировать API и дать доступ к уникальным фишкам, вроде того же прямого доступа к памяти GPU, хотя AMD может быть тоже что-то подобное сделает для своих APU. Но скорее это будет для OpenCL или вычислительных шейдеров OpenGL, чем для задач GPU.
  • +1
    :)
    Название как-то связано со старым добрым S3 MetaL или просто совпадение?
  • +3
    Есть нюанс и в заточке под A7 — благодаря ему Metal заточен под работу на системах с общей памятью, т.е. CPU и GPU могут получать прямой доступ к одним данным без необходимости перебрасывать их по шине PCI. Metal дает прямой доступ для программы к буферам из CPU, и ответственность за то, что эти данные не используются одновременно и GPU, ложится на плечи программиста. Эта полезная функция позволяет смешивать произведение вычислений на GPU и CPU.
    Я думаю вам стоит поправить этот абзац. Иначе можно подумать, что если у нас какой-нибудь Core i7 с GPU на борту, то для старых API данные все равно идут по шине PCI (которого может даже не быть). Насколько я понял вся соль — в отсутсвии синхронизации доступа CPU/GPU, а не в «прямом» доступе. Ну и стало быть не важно лежит между GPU и системной памятью PCI или нет.
  • +1
    Эх, помню я время, когда каждую неделю с новым детонатором приходило по 5 новых NV_, а с каждым новым каталистом — пара, тройка ATI_ или EXT_
    А еше через полгода мы все стирали и заменяли на ARB_…
    Не надо мне такого счастья больше…

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.