Организация команды и модель выполнения

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

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

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

В любом моменте времени только единственный кодер команды может быть активным и добавить команды в буфер команд. Каждый кодер команды должен быть закончен, прежде чем другой кодер команды может быть создан для использования с тем же буфером команд. Одно исключение к “одному активному кодеру команды для каждого буфера команд” правило MTLParallelRenderCommandEncoder протокол, обсужденный в Кодировании Единственной Передачи Рендеринга Используя Многократные Потоки.

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

Рисунок 2-1 показывает, как очередь команды, буфер команд и объекты кодера команды тесно связаны. Каждый столбец компонентов наверху схемы (буфер, текстура, сэмплер, глубина и состояние шаблона, конвейерное состояние) представляет ресурсы и состояние, которые являются определенными для определенного кодера команды.

  Отношения металлического объекта рисунка 2-1

Объект устройства представляет GPU

A MTLDevice объект представляет GPU, который может выполнить команды. MTLDevice протокол имеет методы, чтобы создать новые очереди команды, выделить буферы из памяти, создать текстуры и сделать запросы о возможностях устройства. Для получения предпочтительного системного устройства системы в системе вызовите MTLCreateSystemDefaultDevice функция.

Переходные и непереходные объекты в металле

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

Буфер команд и объекты кодера команды являются переходными и разработаны для единственного использования. Они очень недороги, чтобы выделить и освободить, таким образом, их возврат методов создания автовыпустил объекты.

Следующие объекты не являются переходными. Снова используйте эти объекты в производительности чувствительный код и избегите создавать их неоднократно.

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

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

Для создания очереди команды вызовите любого newCommandQueue метод или newCommandQueueWithMaxCommandBufferCount: метод a MTLDevice объект. В целом очереди команды, как ожидают, будут долгосрочны, таким образом, они не должны будут быть неоднократно созданы и уничтожаться.

Буфер команд

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

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

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

Создание буфера команд

Создать a MTLCommandBuffer объект, вызовите commandBuffer метод MTLCommandQueue. A MTLCommandBuffer объект может только фиксироваться в MTLCommandQueue возразите, что создал его.

Буферы команд, создаваемые commandBuffer метод сохраняет данные, которые необходимы для выполнения. Для определенных сценариев, где Вы содержите сохранение к этим объектам в другом месте на время выполнения a MTLCommandBuffer объект, можно вместо этого создать буфер команд путем вызова commandBufferWithUnretainedReferences метод MTLCommandQueue. Используйте commandBufferWithUnretainedReferences метод только для чрезвычайно критических по отношению к производительности приложений, которые могут гарантировать, что решающие объекты имеют ссылки в другом месте в приложении до выполнения буфера команд, завершается. Иначе, объект, больше не имеющий другие ссылки, может быть преждевременно выпущен, и результаты выполнения буфера команд не определены.

Выполнение команд

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

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

  • commit метод заставляет буфер команд выполняться как можно скорее, но после того, как фиксируются любые ранее ставившие в очередь буферы команд в той же очереди команды. Если буфер команд ранее не ставился в очередь, commit делает подразумеваемое enqueue вызвать.

Для примера использования enqueue с многократными потоками посмотрите Многократные Потоки, Буферы команд и Кодеры Команды.

Регистрация блоков обработчика для выполнения буфера команд

MTLCommandBuffer методы упомянули ниже выполнение команды контроля. Запланированные и завершенные обработчики вызываются в порядке выполнения на неопределенном потоке. Любой код, который Вы выполняете в этих обработчиках, должен завершиться быстро; если дорогая или блокирующая работа должна быть выполнена, задержите ту работу к другому потоку.

  • addScheduledHandler: метод регистрирует блок кода, который вызовут, когда планируется буфер команд. Буфер команд считают запланированным когда любые зависимости между работой, представленной другим MTLCommandBuffer объекты или другой APIs в системе удовлетворены. Можно зарегистрировать многократные запланированные обработчики для буфера команд.

  • waitUntilScheduled метод синхронно ожидает и возвращается после того, как буфер команд планируется и все обработчики, зарегистрированные addScheduledHandler: метод завершается.

  • addCompletedHandler: метод регистрирует блок кода, который сразу вызовут после того, как устройство завершит выполнение буфера команд. Можно зарегистрировать многократные завершенные обработчики для буфера команд.

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

presentDrawable: метод является особым случаем завершенного обработчика. Этот удобный метод представляет содержание визуализуемого ресурса (a CAMetalDrawable объект), когда планируется буфер команд. Для получения дополнительной информации о presentDrawable: метод, посмотрите Интеграцию с Базовой Анимацией: CAMetalLayer.

Контроль состояния выполнения буфера команд

Только для чтения status свойство содержит a MTLCommandBufferStatus перечисление значений, перечисленное в Command Buffer Status Codes это отражает текущий этап планирования во времени жизни этого буфера команд.

Если выполнение заканчивается успешно, значение только для чтения error свойство nil. Если выполнение перестало работать, то status установлен в MTLCommandBufferStatusError, и error свойство может содержать значение, перечисленное в Command Buffer Error Codes это указывает причину отказа.

Кодер команды

Кодер команды является временным объектом, который Вы используете один раз для записи команд и состояния в единственный буфер команд в формате, который может выполнить GPU. Много методов объекта кодера команды добавляют команды для буфера команд. В то время как кодер команды активен, он имеет исключительное право добавить команды для своего буфера команд. Как только Вы заканчиваете кодировать команды, вызовите endEncoding метод. Для записи дальнейших команд создайте новый кодер команды.

Создание объекта кодера команды

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

Кодер команды рендеринга

Графический рендеринг может быть описан с точки зрения передачи рендеринга. A MTLRenderCommandEncoder объект представляет состояние рендеринга и команды рисования, связанные с единственной передачей рендеринга. A MTLRenderCommandEncoder требует связанного MTLRenderPassDescriptor (описанный в Создании Дескриптора Передачи Рендеринга), который включает цвет, глубину и присоединения шаблона, служащие местами назначения для рендеринга команд. MTLRenderCommandEncoder имеет методы к:

  • Укажите графические ресурсы, такие как буфер и текстурируйте объекты, содержащие вершину, фрагмент, или текстурирующие данные изображения

  • Укажите a MTLRenderPipelineState объект, содержащий скомпилированное состояние рендеринга, включая программы построения теней фрагмента и вершину

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

  • Нарисуйте 3D примитивы

Для получения дальнейшей информации о MTLRenderCommandEncoder протокол, посмотрите Графический Рендеринг: Кодер Команды Рендеринга.

Вычислите кодер команды

Для параллельных вычислений данных, MTLComputeCommandEncoder протокол обеспечивает методы для кодирования команд в буфере команд, который может указать вычислить функцию и ее параметры (например, текстура, буфер и состояние сэмплера) и диспетчеризировать вычислить функцию для выполнения. Для создания вычислить объекта кодера команды используйте computeCommandEncoder метод MTLCommandBuffer. Для получения дальнейшей информации о MTLComputeCommandEncoder методы и свойства, посмотрите, что Параллель данных Вычисляет Обработку: Вычислите Кодер Команды.

Кодер команды копирования битового массива

MTLBlitCommandEncoder протокол имеет методы, добавляющие команды для операций копирования в памяти между буферами (MTLBuffer) и текстуры (MTLTexture). MTLBlitCommandEncoder протокол также обеспечивает методы для заполнения текстур сплошным цветом, и генерировать множественно отображается. Для создания объекта кодера команды копирования битового массива используйте blitCommandEncoder метод MTLCommandBuffer. Для получения дальнейшей информации о MTLBlitCommandEncoder методы и свойства, посмотрите Операции Буфера и Текстуры: Кодер Команды Копирования битового массива.

Многократные потоки, буферы команд и кодеры команды

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

Если Вы хотите параллелизировать кодирование буфера команд, то можно создать многократные буферы команд одновременно, и кодировать каждому с отдельным потоком. Если Вы знаете заранее, в каком порядке буфер команд должен выполниться, то enqueue метод MTLCommandBuffer может объявить порядок выполнения в очереди команды, не будучи должен ожидать команд, которые будут кодироваться и фиксироваться. Иначе, когда буфер команд фиксируется, он присваивается место в очереди команды после любых ранее ставивших в очередь буферов команд.

Во время только один поток ЦП может получить доступ к буферу команд. Многопоточные приложения могут использовать один поток на буфер команд для создания многократных буферов команд параллельно.

Рисунок 2-2 показывает пример с тремя потоками. Каждый поток имеет свой собственный буфер команд. Для каждого потока один кодер команды за один раз имеет доступ к своему связанному буферу команд. Рисунок 2-2 также показывает каждому получению буфера команд команды от различных кодеров команды. Когда Вы закончите кодировать, вызовите endEncoding метод кодера команды и новый объект кодера команды могут тогда начать кодировать команды к буферу команд.

  Буферы команд металла рисунка 2-2 с многократными потоками

A MTLParallelRenderCommandEncoder объект позволяет единственной передаче рендеринга быть разбитой через многократные кодеры команды и присвоенной разделить потоки. Для получения дополнительной информации о MTLParallelRenderCommandEncoder, посмотрите Кодирование Единственной Передачи Рендеринга Используя Многократные Потоки.