Что такое Metal iOS

Обновлено: 06.12.2022

Metal — это стандартный графический API для устройств Apple. Unity поддерживает Metal в мобильной операционной системе Apple iOS. Подробнее
см. в глоссарии , tvOS и macOS (автономная версия и редактор).

Metal имеет более широкий набор функций на платформах Apple, чем OpenGL ES. Ознакомьтесь с преимуществами и недостатками использования Metal ниже.

Преимущества использования металла

  • Снижение нагрузки на ЦП при вызовах графического API
  • Уровень проверки уровня API
  • Улучшенное управление графическим процессором в системах с несколькими графическими процессорами.
  • Поддерживает цели рендеринга без памяти (в iOS/tvOS)
  • Новый стандарт Apple для Apple
  • Компьютерные шейдеры
  • Шейдеры тесселяции

Недостатки использования металла

  • Нет поддержки недорогих устройств.
  • Нет поддержки геометрических шейдеров

Ограничения и требования

iOS и tvOS поддерживают Metal для Apple A7 или более новых SoC.

В macOS Metal поддерживается Intel HD и Iris Graphics из серии HD 4000 или новее, графические процессоры на базе AMD GCN и графические процессоры на базе Nvidia Kepler или новее.

Metal не поддерживает геометрические шейдеры. Программа, работающая на графическом процессоре. Подробнее
см. в глоссарии.

Включение металла

Чтобы редактор Unity и автономный проигрыватель использовали Metal в качестве графического API по умолчанию, выполните одно из следующих действий:

В редакторе перейдите в меню: «Правка» > «Настройки проекта». Широкий набор настроек, которые позволяют настроить поведение физики, аудио, сети, графики, ввода и многих других областей вашего проекта. Дополнительные сведения
см. в глоссарии , затем выберите категорию «Проигрыватель» и включите поддержку Metal Editor.

Или, если вы используете MacOS, откройте Терминал и используйте аргумент командной строки -force-metal.

Metal включен по умолчанию на автономных проигрывателях iOS, tvOS и macOS.

Проверка Metal API

Xcode предлагает проверку Metal API, которую можно использовать для отслеживания неясных проблем. Чтобы включить проверку Metal API в Xcode:

В Unity создайте свой проект для iOS. Это создает проект Xcode.

Откройте сгенерированный проект Xcode в Xcode и выберите "Редактировать схему".

Открытие окна редактирования схемы

Изменение уровня проверки Metal API

Ошибки проверки прерывают выполнение кода в редакторе XCode и появляются в журналах устройств.

Примечание. Включение проверки увеличивает нагрузку на ЦП, поэтому включайте ее только для отладки.

Выбор устройства GPU

Metal позволяет выбрать устройство GPU при запуске приложения. Это позволяет вам тестировать проект с различными настройками графического процессора или экономить электроэнергию за счет использования маломощного графического процессора.

Чтобы изменить целевое устройство графического процессора в редакторе Unity, выберите меню: Unity > Настройки… > Общие и установите Устройство для использования:

Изменение целевого графического процессора в редакторе
< /p>

Изменение целевого графического процессора в редакторе

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

Изменение целевого графического процессора в автономном проигрывателе
< /p>

Изменение целевого графического процессора в автономном проигрывателе

Использование целей рендеринга без памяти

Metal позволяет использовать цели рендеринга без памяти для оптимизации памяти на мобильных устройствах, представленных в iOS и tvOS 10.0. Это позволяет выполнять рендеринг в RenderTexture без резервного копирования в системной памяти, поэтому содержимое только временно сохраняется во внутренней памяти во время рендеринга. Процесс вывода графики на экран (или в текстуру рендеринга). По умолчанию основная камера в Unity отображает изображение на экране. Подробнее
см. в глоссарии.

Среда Metal поддерживает расширенный рендеринг 3D-графики с ускорением на GPU и рабочие нагрузки параллельных вычислений. Metal предоставляет современный и оптимизированный API для мелкозернистого низкоуровневого управления организацией, обработкой и представлением графических и вычислительных команд, а также управлением соответствующими данными и ресурсами для этих команд. Основная цель Metal — минимизировать нагрузку на ЦП, необходимую для выполнения этих рабочих нагрузок графического процессора.

Metal – это высокооптимизированная платформа для программирования графических процессоров iPhone и iPad. Название происходит от того факта, что Metal является графическим фреймворком самого низкого уровня на платформе iOS (то есть он «наиболее близок к металлу»).

Среда предназначена для достижения двух разных целей: рендеринга 3D-графики и параллельных вычислений. У этих двух вещей много общего.Обе задачи запускают специальный код на огромном количестве данных параллельно и могут выполняться на графическом процессоре.

Кому следует использовать металл?

Прежде чем говорить об API и самом языке затенения, мы должны обсудить, какие разработчики выиграют от использования Metal. Как упоминалось ранее, Metal предлагает две функции: рендеринг графики и параллельные вычисления.

Для тех, кто ищет игровой движок, Metal не лучший выбор. В этом случае Apple Scene Kit (3D) и Sprite Kit (2D) являются лучшими вариантами. Эти API предлагают высокоуровневый игровой движок, включая моделирование физики. Другой альтернативой может быть полнофункциональный 3D-движок, такой как Unreal Engine от Epic или Unity, оба из которых не ограничены платформой Apple. В каждом из этих случаев вы получаете (или будете получать прибыль) от возможностей Metal без прямого использования API.

При написании механизма рендеринга на основе низкоуровневого графического API альтернативой Metal являются OpenGL и OpenGL ES. Мало того, что OpenGL доступен почти для каждой платформы, включая OS X, Windows, Linux и Android, по OpenGL также написано огромное количество руководств, книг и практических руководств. Прямо сейчас ресурсы Metal очень ограничены, и вы ограничены iPhone и iPad с 64-разрядным процессором. С другой стороны, из-за ограничений OpenGL его производительность не всегда оптимальна по сравнению с Metal, который был написан специально для решения таких проблем.

При поиске высокопроизводительной библиотеки параллельных вычислений для iOS ответ на вопрос, какую из них использовать, очень прост. Металл - единственный вариант. OpenCL — это частный фреймворк для iOS, а Core Image (который использует OpenCL) недостаточно мощен и гибок для этой задачи.

Преимущества использования металла

Самым большим преимуществом Metal является значительное снижение накладных расходов по сравнению с OpenGL ES. Всякий раз, когда вы создаете буфер или текстуру в OpenGL, они копируются, чтобы исключить возможность случайного доступа к данным во время их использования графическим процессором. Копирование больших ресурсов, таких как текстуры и буферы, является дорогостоящей операцией, выполняемой в целях безопасности. Металл, с другой стороны, не копирует ресурсы. Разработчик отвечает за синхронизацию доступа между CPU и GPU. К счастью, Apple предоставляет еще один отличный API, который значительно упрощает синхронизацию ресурсов: Grand Central Dispatch. Тем не менее, использование Metal требует некоторого понимания этой темы, но современный движок, который загружает и выгружает ресурсы, в то же время отрисовывая много прибыли, когда эта дополнительная копия избегается.

Еще одним преимуществом Metal является использование предварительно оцененного состояния графического процессора, чтобы избежать избыточной проверки и компиляции. Традиционно в OpenGL вы устанавливаете состояния графического процессора одно за другим, и новый набор состояний необходимо проверять при вызове отрисовки. В худшем случае OpenGL потребуется снова перекомпилировать шейдеры, чтобы отразить новые состояния. Конечно, эта оценка необходима, но Metal предпочитает использовать здесь другой подход. Во время инициализации механизма рендеринга набор состояний запекается в предварительно оцененном проходе рендеринга. Этот объект прохода рендеринга можно использовать с разными ресурсами, но остальные состояния будут постоянными. Проход рендеринга в Metal можно использовать без дополнительной проверки, что сводит к минимуму накладные расходы API и позволяет значительно увеличить количество вызовов отрисовки на кадр.

API Metal

Хотя многие API на платформе предоставляют конкретные классы, Metal предлагает многие из своих типов в виде протоколов. Причина этого в том, что конкретные типы объектов Metal зависят от устройства, на котором работает Metal. Это также поощряет программирование интерфейса, а не реализацию. Однако это также означает, что вы не сможете создавать подклассы классов Metal или добавлять категории, не активно и опасно используя среду выполнения Objective-C.

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

Интересно отметить, что Apple еще не реализовала программный рендеринг для Metal, который можно было бы использовать в симуляторе iOS. При подключении фреймворка Metal приложение должно выполняться на физическом устройстве.

Программа Basic Metal

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

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

Создание устройства и взаимодействие с UIKit

В Metal устройство — это абстракция графического процессора. Он используется для создания многих других типов объектов, таких как буферы, текстуры и библиотеки функций. Чтобы получить устройство по умолчанию, используйте функцию MTLCreateSystemDefaultDevice:

Обратите внимание, что устройство не относится к конкретному классу, а соответствует протоколу MTLDevice, как указано выше.

В следующем фрагменте показано, как создать слой Metal и добавить его в качестве подслоя к фоновому слою UIView:

Библиотеки и функции

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

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

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

Очередь команд

Команды отправляются на устройство Metal через связанную с ним очередь команд. Очередь команд получает команды потокобезопасным способом и сериализует их выполнение на устройстве. Создать очередь команд очень просто:

Построение конвейера

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

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

Для получения функций запрашиваем их по имени из библиотеки:

Затем мы создаем дескриптор конвейера, настроенный с функциями и форматом пикселей:

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

Загрузка данных в буферы

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

Первые четыре числа каждой строки представляют компоненты x, y, z и w каждой вершины. Вторые четыре числа представляют красный, зеленый, синий и альфа-компоненты цвета вершины.

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

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

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

Анимация

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

Структура Uniforms состоит из одного члена, представляющего собой матрицу 4x4, содержащую матрицу поворота. Тип матрицы matrix_float4x4 берется из библиотеки Apple SIMD, набора типов, использующих преимущества параллельных операций с данными там, где они доступны:

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

Подготовка к рисованию

Чтобы рисовать на слое Metal, нам сначала нужно получить «рисуемый» слой.Рисуемый объект управляет набором текстур, подходящих для рендеринга в:

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

Вызовы отрисовки

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

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

Непосредственно перед вызовом отрисовки мы настраиваем кодировщик команды рендеринга с нашим предварительно скомпилированным состоянием конвейера и настраиваем буферы, которые станут аргументами для нашего вершинного шейдера:

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

Наконец, чтобы сообщить кодировщику, что мы закончили выдачу вызовов отрисовки, мы вызываем endEncoding :

Представление фреймбуфера

Теперь, когда наши вызовы отрисовки закодированы и готовы к выполнению, нам нужно сообщить буферу команд, что он должен отображать результаты на экране. Для этого мы вызываем PresentDrawable с текущим объектом рисования, полученным из слоя Metal:

Чтобы сообщить буферу, что он готов к планированию и выполнению, мы вызываем commit :

Язык затенения металла

Несмотря на то, что Metal был анонсирован на той же конференции WWDC, что и язык программирования Swift, язык затенения основан на C++11 с некоторыми ограниченными функциями и некоторыми добавленными ключевыми словами.

Язык шейдинга Metal на практике

Чтобы использовать данные вершин из наших шейдеров, мы определяем тип структуры, соответствующий расположению данных вершин в программе Objective-C:

Нам также нужен очень похожий тип для описания типа вершины, который будет передаваться от нашего вершинного шейдера к фрагментному шейдеру. Однако в этом случае мы должны определить (с помощью атрибута [[position]]), какой элемент структуры следует рассматривать как позицию вершины:

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

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

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

Функция фрагмента выполняется один раз для каждого пикселя. Аргумент создается Metal в процессе растеризации путем интерполяции между параметрами положения и цвета, указанными в каждой вершине. В этой простой функции фрагмента мы просто передаем интерполированный цвет, уже созданный Metal. Затем он становится цветом пикселя на экране:

Почему бы просто не расширить OpenGL?

Компания Apple входит в состав Совета по обзору архитектуры OpenGL, а также исторически предоставляла собственные расширения GL для iOS. Но изменить OpenGL изнутри кажется трудной задачей, потому что у него другие цели разработки. В частности, он должен работать на самых разных устройствах с огромным набором аппаратных возможностей. Хотя OpenGL продолжает улучшаться, этот процесс становится медленнее и сложнее.

Металл, с другой стороны, был создан исключительно для платформ Apple. Даже если на первый взгляд API на основе протокола выглядит необычно, он очень хорошо сочетается с остальными фреймворками. Metal написан на Objective-C, основан на Foundation и использует Grand Central Dispatch для синхронизации между CPU и GPU. Это гораздо более современная абстракция конвейера графического процессора, чем может быть OpenGL без полной перезаписи.

Металл на Mac?

Выпуск Metal для OS X будет лишь вопросом времени. Сам API не ограничивается процессорами ARM, на которых работают iPhone и iPad.Большинство преимуществ Metal можно перенести на современные графические процессоры. Кроме того, iPhone и iPad делят оперативную память между процессором и графическим процессором, что позволяет обмениваться данными без фактического копирования каких-либо данных. Текущие поколения компьютеров Mac не предлагают унифицированную память, но это тоже будет лишь вопросом времени. Возможно, API будет адаптирован для поддержки архитектур с выделенной оперативной памятью, или Metal будет работать только на компьютерах Mac следующего поколения.

Обзор

В этой статье мы попытались предоставить полезное и непредвзятое введение в структуру Metal.

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

В этом учебном пособии по Metal вы узнаете, как перенести свой проект с OpenGL на API 3D-графики Apple: Metal.

Версия


Metal был представлен в 2014 году как API общего назначения для вычислений на базе графического процессора. В 2018 году Apple отказалась от поддержки OpenGL в iOS 12 как для iOS, так и для macOS.

В этом руководстве вы узнаете, как преобразовать приложение, использующее OpenGL, в приложение Metal. Для выполнения этого руководства вам понадобится работающее приложение OpenGL. Стартовый проект для этого руководства — это готовый проект из руководства по OpenGL. Вы можете загрузить то, что вам нужно, с помощью кнопки Загрузить материалы вверху или внизу этого руководства.

Прежде чем начать, вы можете ознакомиться с этими замечательными ресурсами по Metal и OpenGL.

Если у вас нет опыта работы с 3D-графикой, не волнуйтесь! Вы все еще сможете следовать за ним. Если у вас есть некоторый опыт 3D-программирования или OpenGL, этот учебник может показаться вам проще. Многие из тех же концепций применимы и к металлу.

Примечание. Приложения Metal не запускаются в симуляторе iOS. Для них требуется устройство с чипом Apple A7 или более поздней версии. Для выполнения этого руководства вам понадобится устройство A7 или новее.

OpenGL ES и металл

OpenGL ES разработан как кроссплатформенная среда. Это означает, что с небольшими изменениями вы можете запускать код C++ OpenGL ES на других платформах, таких как Android.

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

Результатом стал Metal, который может обеспечить до 10✕ количества вызовов отрисовки для вашего приложения по сравнению с OpenGL ES. Эффекты потрясающие — вы, возможно, помните их из примера Zen Garden в программном докладе WWDC 2014.

Понимание концептуальных различий

С точки зрения разработки OpenGL и Metal похожи. В обоих случаях вы настраиваете буферы с данными для передачи на графический процессор и указываете вершинные и фрагментные шейдеры. В проектах OpenGL есть GLKBaseEffect, который является абстракцией поверх шейдеров. Для Metal такого API нет, поэтому шейдеры нужно писать самому. Но не волнуйтесь — это не так уж сложно!

Самая большая разница между OpenGL и Metal заключается в том, что в Metal вы обычно работаете с двумя типами объектов:

  1. Объекты-дескрипторы.
  2. Объекты в скомпилированном состоянии.

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

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

Пришло время изучить различия самостоятельно!

Начало работы

Напоминаем, что загрузите нужные файлы с помощью кнопки Загрузить материалы в верхней или нижней части этого руководства. Затем откройте OpenGLKit.xcodeproj в папке Starter. Вы увидите проект, в котором используется OpenGL.

Metal Square

Вы должны увидеть вращающийся красочный квадрат. Этот квадрат визуализируется с помощью OpenGL. Однако, поскольку целью развертывания для этого проекта является iOS 12, существует несколько предупреждений об устаревании OpenGL.Вы можете увидеть их в Xcode в навигаторе задач.

Теперь вы нарисуете тот же квадрат, но с помощью Металла. И избавьтесь от всех этих надоедливых предупреждений!

Интеграция металла

Откройте ViewController.swift и измените ViewController так, чтобы он был подклассом UIViewController вместо GLKViewController . В Metal нет такой вещи, как MetalViewController. Вместо этого вы должны использовать MTKView внутри UIViewController.

MTKView является частью платформы MetalKit. Чтобы получить доступ к этому API,
добавьте в начало файла следующее:

Переход с OpenGL

Пришло время немного почистить OpenGL. Выполните следующие действия:

<р>1. Переименуйте оба экземпляра setupGL() в setupMetal().
2. Удалите методы tearDownGL() и deinit(). С Metal нет необходимости в такой явной очистке.
3. Найдите и удалите все расширение GLKViewControllerDelegate, так как этот контроллер представления больше не является GLKViewController. Обратите внимание, что glkViewControllerUpdate содержит логику вращения. Это полезно, но пока удалите его.
4. Удалите следующий код из верхней части setupMetal():

<р>5. Удалите следующие свойства из верхней части ViewController:

Наконец, в верхней части объявления класса ViewController добавьте выход в MTKView:

Настройка раскадровки

ViewController больше не является GLKViewController , поэтому вам необходимо внести некоторые изменения в раскадровку.

Откройте Main.storyboard. В этом примере раскадровка содержит две сцены с именами Сцена контроллера просмотра. В одном есть GLKView, а в другом — MTKView и подключение к выходу, который вы только что добавили в исходный код.

Все, что вам нужно сделать, это установить сцену с MTKView в качестве начального контроллера представления. Найдите сцену, на которую в данный момент не указывает стрелка. Нажмите на панель вверху, чтобы выбрать контроллер представления. Кроме того, вы можете выбрать его на панели структуры документа. Затем откройте инспектор атрибутов и установите флажок Является ли контроллер начального представления.


< /p>

После этого вы можете удалить первую сцену. Хорошая работа!

Настройка металла

Вы готовы? Пришло время использовать металл!

В Metal основным объектом, который вы будете использовать для доступа к графическому процессору, является MTLDevice . Следующий по важности объект — MTLCommandQueue. Этот объект представляет собой очередь, в которую вы будете передавать закодированные кадры.

Откройте ViewController.swift и добавьте следующие свойства:

Теперь перейдите к setupMetal() . Замените его содержимое следующим:

Это намного короче, чем то, что было раньше!

Это захватит устройство Metal по умолчанию в системе, а затем создаст очередь команд с устройства. Затем он назначает устройство представлению Metal. Наконец, он устанавливает контроллер представления в качестве делегата представления для получения обратных вызовов при рисовании и изменении размера.

Теперь вам нужно реализовать протокол MTKViewDelegate.

Внизу ViewController.swift добавьте это расширение:

Это расширение реализует два метода.

  1. Этот метод вызывается при изменении размера изображения, например при повороте экрана.
  2. Этот метод вызывается для фактического рисования.

Базовый рисунок

Все готово для рисования! Для простоты сначала нарисуйте серый фон.

Для каждого кадра, который вы хотите нарисовать в Metal, вы должны создать командный буфер, в котором вы указываете, что и как вы хотите рисовать. Затем этот буфер кодируется на ЦП и отправляется на ГП через очередь команд.

Добавьте следующий код внутрь draw(in:) :

Это большое. Вот что происходит в приведенном выше коде:

  1. Убедитесь, что для текущего кадра можно использовать допустимый объект рисования.
  2. MTLRenderPassDescriptor содержит набор вложений, которые являются местом назначения рендеринга для пикселей, созданных в ходе рендеринга.
  3. Установите текстуру из вида в качестве места назначения для рисования.
  4. Очищать каждый пиксель в начале рендеринга.
  5. Укажите цвет, который будет использоваться при очистке прикрепленного цвета. В данном случае это прекрасный 85 % серый.
  6. Попросите очередь команд создать новый буфер команд.
  7. Создайте объект кодировщика, который может кодировать команды рендеринга графики в буфер команд. Вы добавите фактический код рисования после этой инструкции позже.
  8. Объявите, что все команды, созданные этим кодировщиком, завершены.
  9. Зарегистрируйте нарисованную презентацию, чтобы она появилась как можно скорее.
  10. Зафиксировать этот командный буфер для выполнения в очереди команд.

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

Примечание. Если вы используете симулятор, на этом этапе вы получите сообщение об ошибке сборки. Для сборки и запуска приложения вам потребуется совместимое устройство.

Создайте и запустите приложение.

Какой великолепный серый цвет!

Рисование примитивов

Потребуется некоторое время, чтобы нарисовать что-то более осмысленное. Итак, сделайте глубокий вдох и погрузитесь прямо в воду!

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

Откройте ViewController.swift и измените значение свойства Indices следующим образом:

Вы поймете, почему это изменение требуется при рисовании примитивов.

Буферы данных

Чтобы передать данные вершин в графический процессор, необходимо создать два буфера: один для вершин и один для индексов. Это похоже на объект буфера элементов OpenGL (EBO) и объект буфера вершин (VBO).

Добавьте эти свойства в ViewController:

Теперь внутри setupMetal() добавьте внизу следующее:

Это попросит metalDevice создать буферы вершин и индексов, инициализированные вашими данными.

Добавьте следующее:

Сначала он передает буфер вершин графическому процессору, присваивая ему индекс 0. Затем он рисует треугольники, используя indexBuffer . Обратите внимание, что вам нужно указать тип индекса uint32. Вот почему вы изменили тип индексов ранее.

Создайте и запустите приложение.

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

Добавление шейдеров

Создайте новый файл. Нажмите Файл ▸ Создать ▸ Файл…, выберите iOS ▸ Источник ▸ Металлический файл. Нажмите Далее. Назовите его Shaders.metal и сохраните в любом месте.

Metal использует C++ для написания шейдеров. В большинстве случаев он похож на GLSL, используемый для OpenGL.

Чтобы узнать больше о шейдерах, ознакомьтесь со ссылками внизу этого руководства.

Добавьте это в конец файла:

Вы будете использовать эти структуры в качестве входных и выходных данных для вершинного шейдера.

Написание вершинного шейдера

Вершинный шейдер — это функция, которая запускается для каждой рисуемой вершины.

Под структурами добавьте следующий код:

  1. Вершина указывает, что это функция вершинного шейдера. Тип возвращаемого значения для этого шейдера — VertexOut .
  2. Здесь вы получаете буфер вершин, переданный кодировщику команд.
  3. Этот параметр представляет собой идентификатор вершины, для которой был вызван данный шейдер.
  4. Захват входной вершины для текущего идентификатора вершины.
  5. Здесь вы создаете VertexOut и передаете данные из текущего VertexIn. Это просто использование той же позиции и цвета, что и на входе.

На этом работа вершинного шейдера завершена.

Написание фрагментного шейдера

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

Под вершинным шейдером добавьте следующий код:

Фрагментный шейдер получает выходные данные от вершинного шейдера — VertexOut . Затем фрагментный шейдер возвращает цвет текущего фрагмента.

Подключение шейдеров к конвейеру

Шейдеры готовы, но вы еще не подключили их к конвейеру. Для этого вернитесь в ViewController.swift и добавьте это свойство в класс:

Это свойство будет содержать данные шейдеров.

Теперь найдите setupMetal() . Добавьте следующее внизу метода:

Вот что делает код:

Создайте и запустите. Вы должны получить этот красочный экран.

Металлический градиентный фон

Матрицы

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

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

Обратите внимание, что вы по-прежнему будете использовать GLKMatrix4 . Эта часть GLKit не устарела, поэтому ее можно использовать для матриц в Metal.

Теперь откройте ViewController.swift и добавьте два новых свойства:

Вот что делает приведенный выше код:

  1. Создает матрицу для смещения объекта назад на 6 единиц, чтобы он выглядел меньше.
  2. Создает юниформ-буфер, как вы делали это раньше с буфером вершин, но с данными матрицы.
  3. Подключает юниформ-буфер к конвейеру и устанавливает его идентификатор равным 1.

Матрица прогнозов

Пока вы находитесь в ViewController.swift, внутри mtkView(_:drawableSizeWillChange:) добавьте следующее:

Этот код создает матрицу проекции на основе соотношения сторон вида. Затем он присваивается матрице проекции сцены.

После этого ваш квадрат будет выглядеть квадратным, а не растянутым на весь экран. :]

Матрицы в шейдерах

Вы почти у цели! Далее вам нужно будет получить данные матриц в шейдерах. Откройте файл Shaders.metal. В самом верху добавьте новую структуру:

Теперь замените функцию basic_vertex на следующую:

Вот что изменилось:

  1. Получает матрицы в качестве параметра внутри вершинного шейдера.
  2. Извлекает модель представления и матрицы проекций.
  3. Умножает позицию на матрицы проекции и модели представления.

Создайте и запустите приложение. Вы должны увидеть это:

Gradient Static Cube

Запускаем вращение

В реализации OpenGL GLViewController предоставлял lastUpdateDate, который сообщает вам, когда был выполнен последний рендеринг. В Metal вам придется создать это самостоятельно.

Сначала в ViewController добавьте новое свойство:

Добавьте следующий код:

При этом по завершении отрисовки кадра lastUpdateDate обновляется до текущей даты и времени.

Теперь пора крутиться! В draw(in:) замените:

Это увеличивает свойство поворота на величину, пропорциональную времени между последним рендерингом и этим рендерингом. Затем он применяет поворот вокруг оси Z к матрице представления модели.

Создайте и запустите приложение. Вы увидите, как вращается куб. Успех!

Металлический вращающийся куб

Куда идти дальше?

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

Поздравляем! Вы многое узнали об API Metal! Теперь вы понимаете некоторые из наиболее важных концепций Metal, такие как шейдеры, устройства, буферы команд и конвейеры, и у вас есть полезные сведения о различиях между OpenGL и Metal.

Чтобы узнать больше, обязательно ознакомьтесь с этими замечательными ресурсами Apple:

  • Apple’s Metal for OpenGL Developers — отличное видео для всех, кто имеет опыт работы с OpenGL.
  • На странице Apple Metal for Developers есть ссылки на документацию, видео и примеры кода.
  • Руководство Apple по программированию Metal.
  • Руководство Apple по языку Metal Shading.
  • Видео о металле с WWDC 2014.
  • Видео о металле с WWDC 2015.
  • Видео о металле с WWDC 2016.
  • Видео о металле с WWDC 2017.
  • Видео о металле с WWDC 2018.

Вам также может понравиться этот курс Beginning Metal, в котором эти концепции подробно рассматриваются с помощью видеоуроков.

Если вам больше нравится читать, ознакомьтесь с руководством по началу работы с Metal. Полную книгу на эту тему см. в разделе Metal by Tutorials.

Надеюсь, вам понравился этот урок! Если у вас есть комментарии или вопросы, присоединяйтесь к обсуждению на форуме ниже!


Этот год был добавочным для фреймворка Metal. Язык Metal Shading Language (MSL) теперь находится в версии 2.4, однако семейства графических процессоров и таблицы наборов функций не изменились с прошлого года, а семейство графических процессоров Apple7 включает M1. Давайте перейдем ко всем захватывающим дополнениям на WWDC21 и начнем с […]

WWDC20: что нового в Metal и графическом процессоре Apple


WWDC20 стала событием серьезных изменений. Все операционные системы претерпели значительные изменения в дизайне. Новая macOS под названием Big Sur теперь имеет версию 11. Самым большим объявлением стал двухлетний план перехода с системы Intel на кристалле (SoC) на новую SoC Apple Silicon. Новый SoC заменит встроенный графический процессор Intel собственным графическим процессором Apple в новых […]

WWDC19 — Представляем Metal 2.2


Metal 2.2 был анонсирован на прошлой неделе на WWDC 2019. Apple представила его вместе с соответствующими цифрами: Metal теперь может выполнять в 100 раз больше вызовов отрисовки, чем OpenGL. Металл работает примерно на 1.4 миллиарда устройств в настоящее время. Metal может работать со скоростью до 56 TFLOPS одинарной точности. Примечание. Чтобы получить 56 TFLOPS, вам понадобится новый Mac […]

Введение в вычисления с использованием Metal


Вычисления, или GPGPU, в мире программирования графических процессоров — это еще один подход к программированию графического процессора помимо рендеринга. Оба подхода предполагают высокий уровень параллелизма на GPU, разница заключается в более детальном контроле вычислений над тем, как потоки работают. Это полезно в ситуациях, когда вам нужны определенные потоки […]

Использование eGPU с Metal


Для тех (как и я), которым нужна чистая мощность графического процессора, но есть только ноутбук, и они не хотят покупать мощный настольный компьютер, решением может стать внешний графический процессор (eGPU). Хотя eGPU Nvidia в настоящее время не поддерживаются macOS, AMD предлагает множество вариантов графических процессоров. В поисках […]

Трассировка лучей с металлом


Этот пост будет очень коротким по двум причинам: Apple очень хорошо объясняет эту концепцию на этой странице документации. Все, что я сделал, это перенес их код с Objective-C на Swift, поскольку до сих пор я не видел версии Swift. В моей книге Metal by Tutorials будет целая глава, посвященная фреймворку Metal Performance Shaders и трассировке лучей. В […]

Учебник Metal By Tutorials!

Моя книга вышла спустя почти 3 года с тех пор, как я начал над ней работать! Это был такой удивительный путь, который мы, авторы, прошли, написав первую в истории Metal книгу для разработчиков игровых движков. На то, чтобы увидеть его в печатном виде, ушло больше времени, чем я думал, но оно того стоило […]

Metal 2 на графическом процессоре A11


Когда новые модели iPhone с процессором A11 (8, 8 Plus и X) были анонсированы в рамках сентябрьского выступления, была опубликована новая веб-страница GPU Family 4 и серия новых видеороликов Metal с пометкой Fall 2017. Новый процессор под названием A11 Bionic оснащен первым графическим процессором, разработанным Apple, с тремя ядрами. Внутренние тесты показывают, что он на 30% быстрее предыдущего графического процессора внутри A10. Он также имеет новое аппаратное дополнение Neural Engine, […]

Читайте также: