Графический рендеринг: кодер команды рендеринга
В этой главе описываются, как создать и работать с MTLRenderCommandEncoder
и MTLParallelRenderCommandEncoder
объекты, использующиеся для кодирования команд рендеринга графики в буфер команд. MTLRenderCommandEncoder
команды описывают конвейер рендеринга графики, как замечено на рисунке 5-1.
A MTLRenderCommandEncoder
объект представляет единственный кодер команды рендеринга. A MTLParallelRenderCommandEncoder
объект позволяет единственной передаче рендеринга быть поврежденной во много отдельные MTLRenderCommandEncoder
объекты, каждый из которых может быть присвоен различному потоку. Команды от различных кодеров команды рендеринга тогда объединены в цепочку вместе и выполнены в непротиворечивом, предсказуемом порядке, как описано в Многократных Потоках для Передачи Рендеринга.
Создавая и Используя кодер команды рендеринга
Для создания инициализируйте и используйте единственный кодер команды рендеринга:
Создайте a
MTLRenderPassDescriptor
объект определить набор присоединений, служащих местом назначения рендеринга для графических команд в буфере команд для той передачи рендеринга. Как правило, Вы создаете aMTLRenderPassDescriptor
возразите один раз и повторное использование это каждый раз, когда Ваше приложение представляет кадр. Посмотрите Создание Дескриптора Передачи Рендеринга.Создайте a
MTLRenderCommandEncoder
объект путем вызоваrenderCommandEncoderWithDescriptor:
методMTLCommandBuffer
с указанным рендерингом передают дескриптор. Посмотрите Используя Дескриптор Передачи Рендеринга для Создания Кодера Команды Рендеринга.Создайте a
MTLRenderPipelineState
объект определить состояние конвейера рендеринга графики (включая программы построения теней, смешивание, мультивыборку и тестирование видимости) для один или больше рисует вызовы. Для использования этого конвейерного состояния рендеринга для рисования примитивов вызовитеsetRenderPipelineState:
методMTLRenderCommandEncoder
. Для получения дополнительной информации посмотрите Создание Конвейерного состояния Рендеринга.Текстуры набора, буферы и сэмплеры, которые будут использоваться кодером команды рендеринга, как описано в Указании Ресурсов для Кодера Команды Рендеринга.
Вызвать
MTLRenderCommandEncoder
методы для указания дополнительного состояния стандартной функции, включая глубину и состояние шаблона, как объяснено в Операциях состояния Стандартной функции.Наконец, вызвать
MTLRenderCommandEncoder
методы для рисования графических примитивов, как описано в Рисовании Геометрических Примитивов.
Создание дескриптора передачи рендеринга
A MTLRenderPassDescriptor
объект представляет место назначения для закодированных команд рендеринга, которое является набором присоединений. Свойства дескриптора передачи рендеринга могут включать массив до четырех присоединений для цветных пиксельных данных, одного присоединения для пиксельных данных глубины и одного присоединения для пиксельных данных шаблона. renderPassDescriptor
удобный метод создает a MTLRenderPassDescriptor
объект с цветом, глубиной и присоединяемыми свойствами шаблона с присоединяемым состоянием по умолчанию. visibilityResultBuffer
свойство указывает буфер, где устройство может обновить, чтобы указать, передают ли какие-либо выборки глубину и получают тесты с помощью шаблона — для подробных данных, посмотрите Операции состояния Стандартной функции.
Каждое отдельное присоединение, включая текстуру, которая будет записана в, представлено присоединяемым дескриптором. Для присоединяемого дескриптора формат пикселя связанной текстуры должен быть выбран соответственно для хранения цвета, глубины или данных шаблона. Для цветного присоединяемого дескриптора, MTLRenderPassColorAttachmentDescriptor
, используйте цветной-renderable формат пикселя. Для присоединяемого дескриптора глубины, MTLRenderPassDepthAttachmentDescriptor
, используйте формат пикселя глубины-renderable, такой как MTLPixelFormatDepth32Float
. Для присоединяемого дескриптора шаблона, MTLRenderPassStencilAttachmentDescriptor
, используйте формат пикселя шаблона-renderable, такой как MTLPixelFormatStencil8
.
Объем памяти, который текстура фактически использует на пиксель на устройстве, не всегда соответствует размер формата пикселя текстуры в Металлическом коде платформы, потому что устройство добавляет дополнение для выравнивания или других целей. Посмотрите Металлическую Ссылку Констант для того, сколько памяти фактически используется для каждого формата пикселя.
Ограничения на размер и число присоединений описаны в Металлических Возможностях и Ограничениях.
Загрузка и действия хранилища
loadAction
и storeAction
свойства присоединяемого дескриптора указывают действие, выполняющееся или в запуске или в конце передачи рендеринга. (Для MTLParallelRenderCommandEncoder
, загрузка и действия хранилища происходят на границах полной команды, не для каждого из MTLRenderCommandEncoder
объекты. Для получения дополнительной информации посмотрите Многократные Потоки для Передачи Рендеринга.)
Возможный loadAction
значения включают:
MTLLoadActionClear
, который пишет то же значение в каждый пиксель в указанном присоединяемом дескрипторе. Для большего количества подробности об этом действии посмотрите Указание Ясного Действия Загрузки.MTLLoadActionLoad
, который сохраняет существующее содержание текстуры.MTLLoadActionDontCare
, который позволяет каждому пикселю в присоединении брать любое значение в начале передачи рендеринга.
Если Ваше приложение представит все пиксели присоединения для данного кадра, используйте действие загрузки по умолчанию MTLLoadActionDontCare
. MTLLoadActionDontCare
действие позволяет GPU избегать загружать существующее содержание текстуры, гарантируя лучшую производительность. Иначе, можно использовать MTLLoadActionClear
действие для очистки предыдущего содержания присоединения, или MTLLoadActionLoad
действие для сохранения их. MTLLoadActionClear
действие также избегает загружать существующее содержание текстуры, но оно несет расходы заполнения места назначения со сплошным цветом.
Возможный storeAction
значения включают:
MTLStoreActionStore
, который сохраняет конечные результаты передачи рендеринга в присоединение.MTLStoreActionMultisampleResolve
, то, которое разрешает мультидемонстрационные данные от цели рендеринга в единственные демонстрационные значения, хранит их в текстуре, указанной присоединяемым свойствомresolveTexture
, и оставляет содержание присоединения неопределенным. Для получения дополнительной информации посмотрите Пример: Создание Дескриптора Передачи Рендеринга для Мультивыбранного Рендеринга.MTLStoreActionDontCare
, который оставляет присоединение в неопределенном состоянии после того, как передача рендеринга будет завершена. Это может улучшить производительность, поскольку она позволяет реализации избежать любой работы, необходимой для сохранения результатов рендеринга.
Для цветных присоединений, MTLStoreActionStore
действие является действием хранилища по умолчанию, потому что приложения почти всегда сохраняют значения итогового цвета в присоединении в конце рендеринга передачи. Для глубины и присоединений шаблона, MTLStoreActionDontCare
действие хранилища по умолчанию, потому что те присоединения обычно не должны быть сохранены после того, как передача рендеринга завершена.
Указание ясного действия загрузки
Если loadAction
свойство присоединяемого дескриптора установлено в MTLLoadActionClear
, тогда очищающееся значение записано в каждый пиксель в указанном присоединяемом дескрипторе в начале передачи рендеринга. Очищающееся свойство значения зависит от типа присоединения.
Для
MTLRenderPassColorAttachmentDescriptor
,clearColor
содержит aMTLClearColor
значение, состоящее из четырех двойной точности компоненты RGBA с плавающей точкой и использующееся для очистки цветного присоединения.MTLClearColorMake
функция создает ясную ценность цвета от красного, зеленого, синего цвета, и альфа-компоненты. Ясный цвет по умолчанию (0.0, 0.0, 0.0, 1.0), или непрозрачный черный цвет.Для
MTLRenderPassDepthAttachmentDescriptor
,clearDepth
содержит одну двойную точность значение очистки с плавающей точкой в диапазоне [0.0, 1.0], который используется для очистки присоединения глубины. Значение по умолчанию 1.0.Для
MTLRenderPassStencilAttachmentDescriptor
,clearStencil
содержит одно 32-разрядное целое без знака, использующееся для очистки присоединения шаблона. Значение по умолчанию 0.
Пример: создание дескриптора передачи рендеринга с действиями загрузки и хранилища
Перечисление 5-1 создает простой дескриптор передачи рендеринга с присоединениями глубины и цветом. Во-первых, два объекта текстуры создаются, один с цветным-renderable форматом пикселя и другим с форматом пикселя глубины. Затем renderPassDescriptor
удобный метод MTLRenderPassDescriptor
создает дескриптор передачи рендеринга по умолчанию. Тогда к цвету и присоединениям глубины получают доступ через свойства MTLRenderPassDescriptor
. Текстуры и действия установлены в colorAttachments[0]
, который представляет первое цветное присоединение (в индексе 0 в массиве) и присоединение глубины.
Перечисление 5-1 , создающее дескриптор передачи рендеринга с присоединениями цвета и глубины
MTLTextureDescriptor *colorTexDesc = [MTLTextureDescriptor |
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm |
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO]; |
id <MTLTexture> colorTex = [gDevice newTextureWithDescriptor:colorTexDesc]; |
MTLTextureDescriptor *depthTexDesc = [MTLTextureDescriptor |
texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float |
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO]; |
id <MTLTexture> depthTex = [gDevice newTextureWithDescriptor:depthTexDesc]; |
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor]; |
renderPassDesc.colorAttachments[0].texture = colorTex; |
renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; |
renderPassDesc.colorAttachments[0].storeAction = MTLStoreActionStore; |
renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0,1.0,0.0,1.0); |
renderPassDesc.depthAttachment.texture = depthTex; |
renderPassDesc.depthAttachment.loadAction = MTLLoadActionClear; |
renderPassDesc.depthAttachment.storeAction = MTLStoreActionStore; |
renderPassDesc.depthAttachment.clearDepth = 1.0; |
Пример: создание дескриптора передачи рендеринга для мультивыбранного рендеринга
Использовать MTLStoreActionMultisampleResolve
действие, необходимо установить texture
свойство к текстуре мультидемонстрационного типа, и resolveTexture
свойство будет содержать результат мультидемонстрационной работы решения. (Если texture
не поддерживает мультивыборку, тогда результат мультидемонстрационного действия решения не определен.) resolveLevel
, resolveSlice
, и resolveDepthPlane
свойства могут также использоваться для мультидемонстрационной работы решения для указания уровня множественного отображения, части куба и плоскости глубины мультидемонстрационной текстуры, соответственно. В большинстве случаев, значения по умолчанию для resolveLevel
, resolveSlice
, и resolveDepthPlane
применимы. В Перечислении 5-2 присоединение первоначально создается и затем loadAction
, storeAction
, texture
, и resolveTexture
свойства установлены поддерживать мультидемонстрационное решение.
Свойства установки перечисления 5-2 для присоединения с мультидемонстрационным решением
MTLTextureDescriptor *colorTexDesc = [MTLTextureDescriptor |
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm |
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO]; |
id <MTLTexture> colorTex = [gDevice newTextureWithDescriptor:colorTexDesc]; |
MTLTextureDescriptor *msaaTexDesc = [MTLTextureDescriptor |
texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm |
width:IMAGE_WIDTH height:IMAGE_HEIGHT mipmapped:NO]; |
msaaTexDesc.textureType = MTLTextureType2DMultisample; |
msaaTexDesc.sampleCount = sampleCount; // must be > 1 |
id <MTLTexture> msaaTex = [gDevice newTextureWithDescriptor:msaaTexDesc]; |
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor]; |
renderPassDesc.colorAttachments[0].texture = msaaTex; |
renderPassDesc.colorAttachments[0].resolveTexture = colorTex; |
renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; |
renderPassDesc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve; |
renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0,1.0,0.0,1.0); |
Используя дескриптор передачи рендеринга для создания кодера команды рендеринга
После того, как Вы создадите дескриптор передачи рендеринга и укажете его свойства, используйте renderCommandEncoderWithDescriptor:
метод a MTLCommandBuffer
объект создать кодер команды рендеринга, как показано в Перечислении 5-3.
Перечисление 5-3 , создающее кодер команды рендеринга с дескриптором передачи рендеринга
id <MTLRenderCommandEncoder> renderCE = [commandBuffer |
renderCommandEncoderWithDescriptor:renderPassDesc]; |
Отображение представленного содержания с базовой анимацией
Базовая Анимация определяет CAMetalLayer
класс, разработанный для специализированного поведения поддержанного уровнем представления, содержание которого представляется с помощью Металла. A CAMetalLayer
объект представляет информацию о геометрии содержания (позиция и размер), его визуальные атрибуты (цвет фона, граница и тень), и ресурсы, используемые Металлом для представления содержания в цветном присоединении. Это также инкапсулирует синхронизацию представления содержания так, чтобы содержание могло быть выведено на экран, как только это доступно или в требуемое время. (Для получения дополнительной информации о Базовой Анимации, см. Базовое Руководство по программированию Анимации и Базовую Поваренную книгу Анимации.)
Базовая Анимация также определяет CAMetalDrawable
протокол для объектов, которые являются визуализуемыми ресурсами. CAMetalDrawable
протокол расширяется MTLDrawable
и продает объект, соответствующий MTLTexture
протокол, таким образом, это может использоваться в качестве места назначения для рендеринга команд. Представлять в a CAMetalLayer
объект, необходимо получить новое CAMetalDrawable
объект для каждой передачи рендеринга, доберитесь MTLTexture
возразите, что это продает, и используйте ту текстуру для создания цветного присоединения. В отличие от цветных присоединений, создание и уничтожение глубины или присоединения шаблона являются дорогостоящими. Если Вы нуждаетесь или в глубине или получаете присоединения с помощью шаблона, создаете их один раз и затем снова используете их каждый раз, когда кадр представляется.
Как правило, Вы используете layerClass
метод для обозначения CAMetalLayer
как отступающий тип слоя для Вашего собственного подкласса UIView, как показано в Перечислении 5-4. Иначе, можно создать a CAMetalLayer
с init
метод и включает уровень в существующее представление.
Перечисление 5-4 Используя CAMetalLayer как отступающий уровень для подкласса UIView
+ (id) layerClass { |
return [CAMetalLayer class]; |
} |
Для отображения содержания, представленного Металлом в уровне, необходимо получить визуализуемый ресурс (a CAMetalDrawable
объект) от CAMetalLayer
возразите и затем используйте тот ресурс в качестве цветного присоединения в Вашем конвейере рендеринга. Сделать это, Вы первые свойства набора CAMetalLayer
объект, которые описывают drawable ресурсы, которые он продает, затем вызовите nextDrawable
метод каждый раз Вы начинаете представлять новый кадр. Если CAMetalLayer
свойства не установлены, nextDrawable
сбои вызова метода. Следующий CAMetalLayer
свойства описывают drawable объект:
device
свойство объявляетMTLDevice
возразите, что ресурс создается из.pixelFormat
свойство объявляет формат пикселя текстуры. Поддерживаемые значенияMTLPixelFormatBGRA8Unorm
(значение по умолчанию) иMTLPixelFormatBGRA8Unorm_sRGB
.drawableSize
свойство объявляет размерности текстуры в пикселях устройства. Чтобы гарантировать что Ваше содержание рендеринга приложения в точных размерностях дисплея (не требуя дополнительного этапа выборки на некоторых устройствах), возьмите целевой экранnativeScale
илиnativeBounds
свойство во внимание при вычислении желаемого размера для уровня.framebufferOnly
свойство объявляет, может ли текстура использоваться только в качестве присоединения (YES
) или ли это может также использоваться для выборки текстуры и пиксельных операций чтения-записи (NO
). ЕслиYES
, расположенный на слое объект может оптимизировать текстуру для дисплея. Для большинства приложений рекомендуемое значениеYES
.presentsWithTransaction
свойство объявляет, обновляются ли изменения в представленном ресурсе уровня со стандартными Базовыми механизмами транзакций Анимации (YES
) или обновляются асинхронно к обновлениям обычного слоя (NO
, значение по умолчанию).
Если nextDrawable
метод успешно выполняется, он возвращает a CAMetalDrawable
объект со следующими свойствами только для чтения:
texture
свойство содержит объект текстуры. Вы используете это в качестве присоединения при создании конвейера рендеринга (MTLRenderPipelineColorAttachmentDescriptor
объект).layer
свойство указывает наCAMetalLayer
возразите что ответственный за отображение drawable.
Для отображения содержания drawable объекта после, рендеринг завершен, необходимо представить его Базовой Анимации путем вызова drawable объекта present
метод. Для синхронизации представления drawable с завершением буфера команд, ответственного за его рендеринг, можно вызвать любого presentDrawable:
или presentDrawable:atTime:
удобный метод для aMTLCommandBuffer
объект. Эти методы используют запланированный обработчик (см. Регистрирующиеся Блоки Обработчика для Выполнения Буфера команд) вызывать drawable’s present
метод, покрывающий большинство сценариев. presentDrawable:atTime:
когда drawable представлено, метод обеспечивает дальнейшее управление.
Создание конвейерного состояния рендеринга
Использовать a MTLRenderCommandEncoder
объект закодировать команды рендеринга, необходимо сначала указать a MTLRenderPipelineState
объект определить состояние графики для любого рисует вызовы. Конвейерный объект состояния рендеринга является долгосрочным постоянным объектом, который может быть создан за пределами кодера команды рендеринга, кэшировался заранее и снова использовал через несколько кодеров команды рендеринга. Когда описание того же набора состояния графики, многократное использование ранее создаваемого конвейерного объекта состояния рендеринга могут избежать дорогих операций, переоценивающих и переводящих указанное состояние в команды GPU.
Конвейерное состояние рендеринга является неизменным объектом. Для создания конвейерного состояния рендеринга Вы сначала создаете и конфигурируете непостоянное MTLRenderPipelineDescriptor
объект, описывающий атрибуты конвейерного состояния рендеринга. Затем Вы используете дескриптор для создания a MTLRenderPipelineState
объект.
Создание и конфигурирование конвейерного дескриптора рендеринга
Для создания конвейерного состояния рендеринга сначала создайте a MTLRenderPipelineDescriptor
объект, имеющий свойства, описывающие графику, представляющую конвейер, утверждает, что Вы хотите использовать во время передачи рендеринга, как изображено на рисунке 5-2. colorAttachments
свойство нового MTLRenderPipelineDescriptor
объект содержит массив MTLRenderPipelineColorAttachmentDescriptor
объекты и каждый дескриптор представляют цветное присоединяемое состояние, указывающее операции смешения и факторы для того присоединения, как детализировано в Конфигурировании Смешивающий Конвейерный Присоединяемый Дескриптор Рендеринга. Присоединяемый дескриптор также указывает формат пикселя присоединения, которое должно соответствовать формат пикселя для текстуры конвейерного дескриптора рендеринга с соответствующим присоединяемым индексом, или ошибка происходит.
Установите эти свойства для MTLRenderPipelineDescriptor
объект:
Установите
depthAttachmentPixelFormat
свойство для соответствия формата пикселя для текстурыdepthAttachment
вMTLRenderPassDescriptor
.Установите
stencilAttachmentPixelFormat
свойство для соответствия формата пикселя для текстурыstencilAttachment
вMTLRenderPassDescriptor
.Для указания вершины или программы построения теней фрагмента в конвейерном состоянии рендеринга установите
vertexFunction
илиfragmentFunction
свойство, соответственно. УстановкаfragmentFunction
кnil
отключает растеризацию пикселей в указанное цветное присоединение, обычно использующееся для рендеринга только для глубины или для вывода данных в буферный объект от вершинного шейдера.Если вершинный шейдер имеет параметр с входными атрибутами на вершину, установите
vertexDescriptor
свойство для описания организации данных вершины в том параметре, как описано в Дескрипторе Вершины для Организации Данных.Значение по умолчанию
YES
дляrasterizationEnabled
свойство достаточно для большинства типичных задач рендеринга. Использовать только этап вершины графического конвейера (например, для сбора данных, преобразованных в вершинный шейдер), устанавливают это свойство вNO
.Если присоединяемая мультивыборка поддержек (т.е. присоединение является a
MTLTextureType2DMultisample
введите текстуру), тогда многократные выборки могут быть созданы на пиксель. Чтобы определить как объединение фрагментов для предоставления пиксельной страховой защиты используйте следующийMTLRenderPipelineDescriptor
свойства.sampleCount
свойство определяет число выборок для каждого пикселя. КогдаMTLRenderCommandEncoder
создается,sampleCount
поскольку текстуры для всех присоединений должны соответствовать этоsampleCount
свойство. Если присоединение не может поддерживать мультивыборку, тоsampleCount
1, который является также значением по умолчанию.Если
alphaToCoverageEnabled
установлен вYES
, тогда вывод фрагмента альфа-канала дляcolorAttachments[0]
читается и используется для определения маски покрытия.Если
alphaToOneEnabled
установлен вYES
, тогда фрагмент альфа-канала оценивает заcolorAttachments[0]
вызываются к 1,0, который является самым большим представимым значением. (Другие присоединения незатронуты.)
Создание конвейерного состояния рендеринга от дескриптора
После создания конвейерного дескриптора рендеринга и указания его свойств, используйте его для создания MTLRenderPipelineState
объект. Поскольку создание конвейерного состояния рендеринга может потребовать дорогой оценки состояния графики и возможной компиляции указанных графических программ построения теней, можно использовать или блокирование или асинхронный метод запланировать такую работу в пути который лучшие адаптации проект приложения.
Для синхронного создания конвейерного объекта состояния рендеринга вызовите любого
newRenderPipelineStateWithDescriptor:error:
илиnewRenderPipelineStateWithDescriptor:options:reflection:error:
метод aMTLDevice
объект. В то время как Металл оценивает информацию о состоянии графики дескриптора и компилирует код программы построения теней для создания конвейерного объекта состояния, эти методы блокируют текущий поток.Для асинхронного создания конвейерного объекта состояния рендеринга вызовите любого
newRenderPipelineStateWithDescriptor:completionHandler:
илиnewRenderPipelineStateWithDescriptor:options:completionHandler:
метод aMTLDevice
объект. Эти методы сразу возвращаются — Металл асинхронно оценивает информацию о состоянии графики дескриптора и компилирует код программы построения теней для создания конвейерного объекта состояния, затем вызывает обработчик завершения для обеспечения новогоMTLRenderPipelineState
объект.
Когда Вы создаете a MTLRenderPipelineState
объект можно также принять решение создать отражательные данные, показывающие подробные данные функции программы построения теней конвейера и ее параметров. newRenderPipelineStateWithDescriptor:options:reflection:error:
и newRenderPipelineStateWithDescriptor:options:completionHandler:
методы предоставляют эти данные. Избегите получать отражательные данные, если они не будут использоваться. Для получения дополнительной информации о том, как проанализировать отражательные данные, посмотрите Определение Функциональных Подробных данных во Время выполнения.
После создания a MTLRenderPipelineState
объект, вызовите setRenderPipelineState:
метод MTLRenderCommandEncoder
для соединения рендеринга конвейерно обрабатывают состояние с кодером команды для использования в рендеринге.
Перечисление 5-5 демонстрирует создание конвейерного вызванного объекта состояния рендеринга pipeline
.
Перечисление 5-5 , создающее простое конвейерное состояние
MTLRenderPipelineDescriptor *renderPipelineDesc = |
[[MTLRenderPipelineDescriptor alloc] init]; |
renderPipelineDesc.vertexFunction = vertFunc; |
renderPipelineDesc.fragmentFunction = fragFunc; |
renderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm; |
// Create MTLRenderPipelineState from MTLRenderPipelineDescriptor |
NSError *errors = nil; |
id <MTLRenderPipelineState> pipeline = [device |
newRenderPipelineStateWithDescriptor:renderPipelineDesc error:&errors]; |
assert(pipeline && !errors); |
// Set the pipeline state for MTLRenderCommandEncoder |
[renderCE setRenderPipelineState:pipeline]; |
Переменные vertFunc
и fragFunc
функции программы построения теней, указанные как свойства конвейерного вызванного дескриптора состояния рендеринга renderPipelineDesc
. Вызов newRenderPipelineStateWithDescriptor:error:
метод MTLDevice
возразите синхронно использует конвейерный дескриптор состояния для создания конвейерного объекта состояния рендеринга. Вызов setRenderPipelineState:
метод MTLRenderCommandEncoder
указывает MTLRenderPipelineState
возразите для использования с кодером команды рендеринга.
Конфигурирование смешивающий конвейерный присоединяемый дескриптор рендеринга
Смешивание использует высоконастраиваемую работу смешения для смешивания вывода, возвращенного функцией фрагмента (источник) с пиксельными значениями в присоединении (место назначения). Операции смешения определяют, как источник и целевые значения объединены с факторами смешения.
Для конфигурирования смешивания для цветного присоединения установите следующий MTLRenderPipelineColorAttachmentDescriptor
свойства:
Чтобы позволить смешаться, установить
blendingEnabled
кYES
. Смешивание отключено по умолчанию.writeMask
идентифицирует, какие цветовые каналы смешиваются. Значение по умолчаниюMTLColorWriteMaskAll
позволяет всем цветовым каналам быть смешанными.rgbBlendOperation
иalphaBlendOperation
отдельно присвойте операции смешения для RGB и данных фрагмента Альфы с aMTLBlendOperation
значение. Значение по умолчанию для обоих свойствMTLBlendOperationAdd
.sourceRGBBlendFactor
,sourceAlphaBlendFactor
,destinationRGBBlendFactor
, иdestinationAlphaBlendFactor
присвойте источник и целевые факторы смешения.
Понимание смешивающихся факторов и операций
Четыре фактора смешения относятся к постоянному значению совмещенного цвета: MTLBlendFactorBlendColor
, MTLBlendFactorOneMinusBlendColor
, MTLBlendFactorBlendAlpha
, и MTLBlendFactorOneMinusBlendAlpha
. Вызовите setBlendColorRed:green:blue:alpha:
метод MTLRenderCommandEncoder
указать постоянный цвет и альфа-значения, используемые с этими факторами смешения, как описано в Операциях состояния Стандартной функции.
Некоторые операции смешения комбинируют значения фрагмента путем умножения исходных значений на источник MTLBlendFactor
значение (сократил SBF), умножая целевые значения на целевой фактор смешения (DBF), и комбинируя результаты с помощью арифметики, обозначенной MTLBlendOperation
значение. (Если работа смешения также MTLBlendOperationMin
или MTLBlendOperationMax
, SBF и факторы смешения DBF проигнорированы.), Например, MTLBlendOperationAdd
для обоих rgbBlendOperation
и alphaBlendOperation
свойства определяют следующую аддитивную работу смешения для значений Альфы и RGB:
RGB = (Source.rgb *
sourceRGBBlendFactor
) + (Dest.rgb *destinationRGBBlendFactor
)Альфа = (Source.a *
sourceAlphaBlendFactor
) + (Dest.a *destinationAlphaBlendFactor
)
В поведении смешения по умолчанию источник полностью перезаписывает место назначения. Это поведение эквивалентно установке обоих sourceRGBBlendFactor
и sourceAlphaBlendFactor
к MTLBlendFactorOne
, и destinationRGBBlendFactor
и destinationAlphaBlendFactor
к MTLBlendFactorZero
. Это поведение выражено математически как:
RGB = (Source.rgb * 1.0) + (Dest.rgb * 0.0)
A = (Source.a * 1.0) + (Dest.a * 0.0)
Другая обычно используемая работа смешения, где исходная альфа определяет, сколько из целевого цвета остается, может быть выражена математически как:
RGB = (Source.rgb * 1.0) + (Dest.rgb * (1 - Source.a))
A = (Source.a * 1.0) + (Dest.a * (1 - Source.a))
Используя пользовательскую конфигурацию смешивания
Перечисление 5-6 показывает код для пользовательской конфигурации смешивания, с помощью работы смешения MTLBlendOperationAdd
, исходный фактор смешения MTLBlendFactorOne
, и целевой фактор смешения MTLBlendFactorOneMinusSourceAlpha
. colorAttachments[0]
a MTLRenderPipelineColorAttachmentDescriptor
объект со свойствами, указывающими смешивающуюся конфигурацию.
Перечисление 5-6 , указывающее пользовательскую конфигурацию смешивания
MTLRenderPipelineDescriptor *renderPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; renderPipelineDesc.colorAttachments[0].blendingEnabled = YES; renderPipelineDesc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd; renderPipelineDesc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd; renderPipelineDesc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorOne; renderPipelineDesc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne; renderPipelineDesc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; renderPipelineDesc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha; NSError *errors = nil; id <MTLRenderPipelineState> pipeline = [device newRenderPipelineStateWithDescriptor:renderPipelineDesc error:&errors]; |
Указание ресурсов для кодера команды рендеринга
MTLRenderCommandEncoder
методы, обсужденные в этом разделе, указывают ресурсы, использующиеся в качестве параметров за вершину и функции программы построения теней фрагмента, указанные vertexFunction
и fragmentFunction
свойства в a MTLRenderPipelineState
объект. Эти методы присваивают ресурс программы построения теней (буферы, текстуры и сэмплеры) к соответствующему табличному индексу параметра (atIndex
) в кодере команды рендеринга, как показано на рисунке 5-3.
Следующий setVertex*
методы присваивают один или несколько ресурсов соответствующим параметрам функции вершинного шейдера.
Они setFragment*
методы так же присваивают один или несколько ресурсов соответствующим параметрам функции программы построения теней фрагмента.
Существует максимум 31 записи в буферной таблице параметра, 31 записи в таблице параметра текстуры и 16 записей в таблице параметра состояния сэмплера.
Спецификаторы атрибута, указывающие расположения ресурса в Металлическом исходном коде языка штриховки, должны соответствовать табличные индексы параметра в Металлических методах платформы. В Перечислении 5-7, два буфера (posBuf
и texCoordBuf
) с индексами 0 и 1, соответственно, определяются для вершинного шейдера.
Платформа металла перечисления 5-7: указание ресурсов для функции вершины
[renderEnc setVertexBuffer:posBuf offset:0 atIndex:0]; |
[renderEnc setVertexBuffer:texCoordBuf offset:0 atIndex:1]; |
В Перечислении 5-8 функциональная подпись имеет соответствующие параметры со спецификаторами атрибута buffer(0)
и buffer(1)
.
Металл перечисления 5-8 штриховка языка: соответствие аргументов функции вершины табличные индексы параметра платформы
vertex VertexOutput metal_vert(float4 *posData [[ buffer(0) ]], |
float2 *texCoordData [[ buffer(1) ]]) |
Точно так же в Перечислении 5-9, буфере, текстуре и сэмплере (fragmentColorBuf
, shadeTex
, и sampler
, соответственно), все с индексом 0, определяются для программы построения теней фрагмента.
Платформа металла перечисления 5-9: указание ресурсов для функции фрагмента
[renderEnc setFragmentBuffer:fragmentColorBuf offset:0 atIndex:0]; |
[renderEnc setFragmentTexture:shadeTex atIndex:0]; |
[renderEnc setFragmentSamplerState:sampler atIndex:0]; |
В Перечислении 5-10 функциональная подпись имеет соответствующие параметры со спецификаторами атрибута buffer(0)
, texture(0)
, и sampler(0)
, соответственно.
Металл перечисления 5-10 штриховка языка: соответствие аргументов функции фрагмента табличные индексы параметра платформы
fragment float4 metal_frag(VertexOutput in [[stage_in]], float4 *fragColorData [[ buffer(0) ]], texture2d<float> shadeTexValues [[ texture(0) ]], sampler samplerValues [[ sampler(0) ]] ) |
Дескриптор вершины для организации данных
В Металлическом коде платформы может быть тот MTLVertexDescriptor
для каждого конвейерного состояния, описывающего организацию ввода данных к вершинному шейдеру, функционируют, и делится информацией расположения ресурса между языком штриховки и кодом платформы.
В Металлическом коде языка штриховки вводы на вершину (такие как скаляры или векторы целого числа или значений с плавающей точкой) могут быть организованы в одной структуре, которая может быть передана в одном параметре, объявляющемся с [[ stage_in ]]
спецификатор атрибута, как замечено в VertexInput
структура для функции вершины в качестве примера vertexMath
в Перечислении 5-11. Каждое поле входной структуры на вершину имеет [[ attribute(index) ]]
спецификатор, указывающий индекс в таблице параметра атрибута вершины.
Металл перечисления 5-11 штриховка языка: вводы функции вершины с индексами атрибута
struct VertexInput { float2 position [[ attribute(0) ]]; float4 color [[ attribute(1) ]]; float2 uv1 [[ attribute(2) ]]; float2 uv2 [[ attribute(3) ]]; }; struct VertexOutput { float4 pos [[ position ]]; float4 color; }; vertex VertexOutput vertexMath(VertexInput in [[ stage_in ]]) { VertexOutput out; out.pos = float4(in.position.x, in.position.y, 0.0, 1.0); float sum1 = in.uv1.x + in.uv2.x; float sum2 = in.uv1.y + in.uv2.y; out.color = in.color + float4(sum1, sum2, 0.0f, 0.0f); return out; } |
Для обращения к вводу функции программы построения теней от Металлического кода платформы опишите a MTLVertexDescriptor
возразите и затем набор это как vertexDescriptor
свойство MTLRenderPipelineState
. MTLVertexDescriptor
имеет два свойства: attributes
и layouts
.
attributes
свойство MTLVertexDescriptor
a MTLVertexAttributeDescriptorArray
объект, определяющий, как каждый атрибут вершины организован в буфере, отображающемся на аргументе функции вершины. attributes
свойство может доступ к поддержке к многократным атрибутам (таким как координаты вершины, поверхность normals и координаты текстуры), которые чередованы в том же буфере. Порядок элементов в коде языка штриховки не должен быть сохранен в буфере в коде платформы. Каждый дескриптор атрибута вершины в массиве имеет следующие свойства, предоставляющие информацию функции вершинного шейдера, чтобы определить местоположение и загрузить данные параметра:
bufferIndex
, который является индексом к буферной таблице параметра, указывающей которыйMTLBuffer
получен доступ. Буферная таблица параметра обсуждена в Указании Ресурсов для Кодера Команды Рендеринга.format
, который указывает, как данные должны быть интерпретированы в коде платформы. Если тип данных не является точным соответствием типа, он может быть преобразован или расширен. Например, если тип языка штриховкиhalf4
и платформаformat
MTLVertexFormatFloat2
, тогда, когда данные используются в качестве параметра функции вершины, они могут быть преобразованы от плавания до половины и расширены с двух до четырех элементов (с 0,0, 1.0 в последних двух элементах).offset
, который указывает, где данные могут быть найдены от запуска вершины.
Рисунок 5-4 иллюстрирует a MTLVertexAttributeDescriptorArray
в Металлическом коде платформы, реализующем чередованный буфер, соответствующий вводу к функции вершины vertexMath
в штриховке язык кодируют в Перечислении 5-11.
Перечисление 5-12 показывает Металлический код платформы, соответствующий чередованному буферу, показанному на рисунке 5-4.
Платформа металла перечисления 5-12: Используя дескриптор вершины для доступа к чередованным данным
id <MTLFunction> vertexFunc = [library newFunctionWithName:@"vertexMath"]; MTLRenderPipelineDescriptor* pipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; MTLVertexDescriptor* vertexDesc = [[MTLVertexDescriptor alloc] init]; vertexDesc.attributes[0].format = MTLVertexFormatFloat2; vertexDesc.attributes[0].bufferIndex = 0; vertexDesc.attributes[0].offset = 0; vertexDesc.attributes[1].format = MTLVertexFormatFloat4; vertexDesc.attributes[1].bufferIndex = 0; vertexDesc.attributes[1].offset = 2 * sizeof(float); // 8 bytes vertexDesc.attributes[2].format = MTLVertexFormatFloat2; vertexDesc.attributes[2].bufferIndex = 0; vertexDesc.attributes[2].offset = 8 * sizeof(float); // 32 bytes vertexDesc.attributes[3].format = MTLVertexFormatFloat2; vertexDesc.attributes[3].bufferIndex = 0; vertexDesc.attributes[3].offset = 6 * sizeof(float); // 24 bytes vertexDesc.layouts[0].stride = 10 * sizeof(float); // 40 bytes vertexDesc.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex; pipelineDesc.vertexDescriptor = vertexDesc; pipelineDesc.vertexFunction = vertFunc; |
Каждый MTLVertexAttributeDescriptor
объект в attributes
массив MTLVertexDescriptor
объект соответствует индексируемому элементу структуры в VertexInput
в функции программы построения теней. attributes[1].bufferIndex = 0
указывает использование буфера в индексе 0 в таблице параметра. (В этом примере, каждом MTLVertexAttributeDescriptor
имеет то же bufferIndex
, таким образом, каждый обращается к тому же буферу вершины в индексе 0 в таблице параметра.) offset
значения указывают расположение данных в вершине, таким образом, attributes[1].offset = 2 * sizeof(float)
определяет местоположение запуска соответствующих данных 8 байтов от запуска буфера. format
значения выбраны для соответствия типа данных в функции программы построения теней, таким образом, attributes[1].format = MTLVertexFormatFloat4
указывает использование четырех значений с плавающей точкой.
layouts
свойство MTLVertexDescriptor
a MTLVertexBufferLayoutDescriptorArray
. Для каждого MTLVertexBufferLayoutDescriptor
в layouts
, свойства указывают, как вершина и приписывает данные, выбираются от соответствия MTLBuffer
в таблице параметра, когда Металл рисует примитивы. (Для больше при рисовании примитивов, посмотрите Рисующие Геометрические Примитивы.) stepFunction
свойство MTLVertexBufferLayoutDescriptor
определяет, выбрать ли данные атрибута для каждой вершины для некоторого числа экземпляров, или только один раз. Если stepFunction
установлен выбрать данные атрибута для некоторого числа экземпляров, тогда stepRate
свойство MTLVertexBufferLayoutDescriptor
определяет сколько экземпляров. stride
свойство указывает расстояние между данными двух вершин в байтах.
Рисунок 5-5 изображает MTLVertexBufferLayoutDescriptor
это соответствует коду в Перечислении 5-12. layouts[0]
указывает, как данные вершины выбираются от соответствующего индекса 0 в буферной таблице параметра. layouts[0].stride
указывает расстояние 40 байтов между данными двух вершин. Значение layouts[0].stepFunction
, MTLVertexStepFunctionPerVertex
, указывает, что данные атрибута выбираются для каждой вершины при рисовании. Если значение stepFunction
MTLVertexStepFunctionPerInstance
, stepRate
свойство определяет, как часто выбираются данные атрибута. Например, если stepRate
1, данные выбираются для каждого экземпляра; если stepRate
2, для каждых двух экземпляров, и т.д.
Выполнение операций кодера команды рендеринга стандартной функции
Используйте их MTLRenderCommandEncoder
методы для установки значений состояния графики стандартной функции:
setViewport:
указывает область, в координатах экрана, который является местом назначения для проекции виртуального 3D мира. Область просмотра 3D, таким образом, она включает значения глубины; для подробных данных посмотрите Работу с Системами координат Области просмотра и Пикселя.setTriangleFillMode:
определяет, растеризировать ли треугольные и треугольные примитивы полосы со строками (MTLTriangleFillModeLines
) или как заполненные треугольники (MTLTriangleFillModeFill
). Значение по умолчаниюMTLTriangleFillModeFill
.setCullMode:
иsetFrontFacingWinding:
используются вместе, чтобы определить, если и как применяется отбор. Можно использовать отбор для удаления невидимой поверхности на некоторых геометрических моделях, таких как ориентируемая сфера, представленная с заполненными треугольниками. (Поверхность является ориентируемой, если ее примитивы последовательно рисуются или в по часовой стрелке или в против часовой стрелки упорядочивают.)Значение
setFrontFacingWinding:
указывает, подошли ли обращенному к передней стороне примитиву к концу его вершины по часовой стрелке (MTLWindingClockwise
) или против часовой стрелки (MTLWindingCounterClockwise
) порядок. Значение по умолчаниюMTLWindingClockwise
.Значение
setCullMode:
определяет, выполнить ли отбор (MTLCullModeNone
, если отключенный отбор) или который тип примитивных отобрать (MTLCullModeFront
илиMTLCullModeBack
).
Используйте следующий MTLRenderCommandEncoder
методы для кодирования команд изменения состояния стандартной функции:
setScissorRect:
указывает, что 2D режет ножницами прямоугольник. Фрагменты, лежащие вне указанного, режут ножницами прямоугольник, отбрасываются.setDepthStencilState:
устанавливает глубину и тестовое состояние шаблона, как описано подробно и состояния Шаблона.setStencilReferenceValue:
указывает ссылочное значение шаблона.setDepthBias:slopeScale:clamp:
указывает корректировку к сравнению схем затенения к выводу значений глубины из программ построения теней фрагмента.setVisibilityResultMode:offset:
определяет, контролировать ли, если любые выборки передают глубину и получают тесты с помощью шаблона. Если установлено вMTLVisibilityResultModeBoolean
, тогда, если какие-либо выборки передают глубину и получают тесты с помощью шаблона, ненулевое значение записано в буфер, указанныйvisibilityResultBuffer
свойствоMTLRenderPassDescriptor
, как описано в Создании Дескриптора Передачи Рендеринга.Можно использовать этот режим для выполнения тестирования поглощения газов. Если Вы рисуете ограничительную рамку и никакую демонстрационную передачу, то можно прийти к заключению, что любые объекты в той ограничительной рамке закрываются и таким образом не требуют рендеринга.
setBlendColorRed:green:blue:alpha:
указывает постоянный совмещенный цвет и альфа-значения, как детализировано в Конфигурировании Смешивающий Конвейерный Присоединяемый Дескриптор Рендеринга.
Работа с системами координат области просмотра и пикселя
Металл определяет свою систему Normalized Device Coordinate (NDC) как 2x2x1 куб с его центром в (0, 0, 0.5). Левые и нижняя часть для x и y, соответственно, системы NDC указаны как-1. Право и вершина для x и y, соответственно, системы NDC указаны как +1.
Область просмотра указывает трансформацию от NDC до координат окна. Металлическая область просмотра является 3D трансформацией, указанной setViewport:
метод MTLRenderCommandEncoder
. Источник координат окна находится в верхнем левом углу.
В Металле пиксельные центры смещаются (0.5, 0.5). Например, пиксель в источнике имеет свой центр в (0.5, 0.5); центр смежного пикселя с его правой стороны от него (1.5, 0.5). Это - также истина для текстур.
Выполнение операций глубины и шаблона
Глубина и операции шаблона являются операциями фрагмента, которые Вы указываете следующим образом:
Укажите пользовательское
MTLDepthStencilDescriptor
объект, содержащий настройки для состояния глубины/шаблона. Создание пользовательскогоMTLDepthStencilDescriptor
объект может потребовать создания один или дваMTLStencilDescriptor
объекты, которые применимы к обращенным к передней стороне примитивам и обращенным к задней стороне примитивам.Создайте a
MTLDepthStencilState
объект путем вызоваnewDepthStencilStateWithDescriptor:
методMTLDevice
с глубиной/шаблоном утверждают дескриптор.Для установки состояния глубины/шаблона вызовите
setDepthStencilState:
методMTLRenderCommandEncoder
сMTLDepthStencilState
.Если тест шаблона используется, вызвать
setStencilReferenceValue:
указать ссылочное значение шаблона.
Если тест глубины включен, конвейерное состояние рендеринга должно включать присоединение глубины для поддержки записи значения глубины. Для выполнения теста шаблона конвейерное состояние рендеринга должно включать присоединение шаблона. Для конфигурирования присоединений посмотрите Создание и Конфигурирование Конвейерного Дескриптора Рендеринга.
Если Вы будете изменять состояние глубины/шаблона регулярно, то можно хотеть снова использовать объект дескриптора состояния, изменяя его значения свойств по мере необходимости для создания большего количества объектов состояния.
Используйте свойства a MTLDepthStencilDescriptor
возразите следующим образом для установки состояния шаблона и глубины:
Чтобы позволить писать глубину оценивают присоединению глубины, устанавливают
depthWriteEnabled
кYES
.depthCompareFunction
указывает, как выполняется тест глубины. Если значение глубины фрагмента не проходит тест глубины, фрагмент отбрасывается. Например, обычно используемыйMTLCompareFunctionLess
функционируйте значения фрагмента причин, которые являются еще дальше от средства просмотра, чем (ранее записаны) значение пиксельной глубины, чтобы не пройти тест глубины; т.е. фрагмент считают закрытым более ранним значением глубины.frontFaceStencil
иbackFaceStencil
свойства каждый указывает отдельноеMTLStencilDescriptor
объект для передней стороны - и обращенные к задней стороне примитивы. Для использования того же шаблона утверждают и для передней стороны - и для обращенных к задней стороне примитивов, можно присвоить то жеMTLStencilDescriptor
обоимfrontFaceStencil
иbackFaceStencil
свойства. Для явного отключения теста шаблона для одного или обеих поверхностей установите соответствующее свойство вnil
, значение по умолчанию.
Явное отключение состояния шаблона не необходимо. Металл определяет, разрешить ли тест шаблона на основе того, сконфигурирован ли дескриптор шаблона для допустимой работы шаблона.
Перечисление 5-13 показывает пример создания и использования a MTLDepthStencilDescriptor
объект для создания a MTLDepthStencilState
объект, тогда использующийся с кодером команды рендеринга. В этом примере к состоянию шаблона для обращенных к передней стороне примитивов получают доступ от frontFaceStencil
свойство глубины/шаблона утверждает дескриптор. Тест шаблона явно отключен для обращенных к задней стороне примитивов.
Создание перечисления 5-13 и Используя Дескриптор Глубины/Шаблона
MTLDepthStencilDescriptor *dsDesc = [[MTLDepthStencilDescriptor alloc] init]; |
if (dsDesc == nil) |
exit(1); // if the descriptor could not be allocated |
dsDesc.depthCompareFunction = MTLCompareFunctionLess; |
dsDesc.depthWriteEnabled = YES; |
dsDesc.frontFaceStencil.stencilCompareFunction = MTLCompareFunctionEqual; |
dsDesc.frontFaceStencil.stencilFailureOperation = MTLStencilOperationKeep; |
dsDesc.frontFaceStencil.depthFailureOperation = MTLStencilOperationIncrementClamp; |
dsDesc.frontFaceStencil.depthStencilPassOperation = |
MTLStencilOperationIncrementClamp; |
dsDesc.frontFaceStencil.readMask = 0x1; |
dsDesc.frontFaceStencil.writeMask = 0x1; |
dsDesc.backFaceStencil = nil; |
id <MTLDepthStencilState> dsState = [device |
newDepthStencilStateWithDescriptor:dsDesc]; |
[renderEnc setDepthStencilState:dsState]; |
[renderEnc setStencilReferenceValue:0xFF]; |
Следующие свойства определяют тест шаблона в MTLStencilDescriptor
:
readMask
битовая маска; GPU вычисляет поразрядный AND этой маски и со ссылочным значением шаблона и с сохраненным значением шаблона. Тест шаблона является сравнением между получающимся ссылочным значением маскированным и хранимой суммой маскированной.writeMask
битовая маска, ограничивающая, какие значения шаблона записаны в присоединение шаблона операциями шаблона.stencilCompareFunction
указывает, как тест шаблона выполняется для фрагментов. В Перечислении 5-13 функция сравнения шаблонаMTLCompareFunctionEqual
, если ссылочное значение маскированное равно значению шаблона маскированному, уже сохраненному в расположении фрагмента, таким образом, тест шаблона передает.stencilFailureOperation
,depthFailureOperation
, иdepthStencilPassOperation
укажите, что сделать к значению шаблона, сохраненному в присоединении шаблона для трех различных тестовых результатов: если тест шаблона перестал работать, если тестовые передачи шаблона и глубина тестируют сбои, или если и шаблон и тесты глубины успешно выполняются, соответственно. В предыдущем примере значение шаблона неизменно (MTLStencilOperationKeep
) если тест шаблона перестал работать, но он постепенно увеличивается, если тест шаблона передает, если значение шаблона уже не является возможным максимумом (MTLStencilOperationIncrementClamp
).
Рисование геометрических примитивов
После установления конвейерного состояния и состояния стандартной функции можно вызвать следующий MTLRenderCommandEncoder
методы для рисования геометрических примитивов. Они рисуют ссылочные ресурсы методов (такие как буферы, содержащие координаты вершины, координаты текстуры, поверхность normals и другие данные) выполнить конвейер с функциями программы построения теней и другим состоянием, с которым Вы ранее установили MTLRenderCommandEncoder
.
drawPrimitives:vertexStart:vertexCount:instanceCount:
рендеринг много экземпляров (instanceCount
) из примитивов с помощью данных вершины в непрерывных элементах матрицы, начиная с первой вершины в элементе матрицы в индексеvertexStart
и окончание в элементе матрицы в индексеvertexStart + vertexCount - 1
.drawPrimitives:vertexStart:vertexCount:
совпадает с предыдущим методом сinstanceCount
из 1.drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:instanceCount:
рендеринг много экземпляров (instanceCount
) из примитивов с помощью индексного списка, указанного вMTLBuffer
объектindexBuffer
.indexCount
определяет число индексов. Индексный список запускается в индексе, который являетсяindexBufferOffset
байтовое смещение в данных вindexBuffer
.indexBufferOffset
должно быть кратное число размера индекса, определяющегосяindexType
.drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:
подобно предыдущему методу сinstanceCount
из 1.
Для каждого примитивного упомянутого выше метода рендеринга первое входное значение определяет тип примитива с одним из MTLPrimitiveType
значения. Другие входные значения определяют, какие вершины используются для сборки примитивов. Для всех этих методов, instanceStart
входное значение определяет первую инстанцию для рисования, и instanceCount
входное значение определяет сколько экземпляров для рисования.
Как ранее обсуждено, setTriangleFillMode:
определяет, представляются ли треугольники, как заполнено или каркас, и setCullMode:
и setFrontFacingWinding:
настройки определяют, отбирает ли GPU треугольники во время рендеринга. Для получения дополнительной информации посмотрите Операции состояния Стандартной функции).
При рендеринге a MTLPrimitiveTypePoint
примитивный, код языка программы построения теней для функции вершины должен обеспечить [[ point_size ]]
атрибут или размер точки не определен. Для получения дополнительной информации на всех Металлических атрибутах точки языка штриховки, посмотрите Металлическое Руководство по Языку Штриховки.
Окончание передачи рендеринга
Для завершения передачи рендеринга вызвать endEncoding
на кодере команды рендеринга. После окончания предыдущего кодера команды можно создать новый кодер команды любого типа для кодирования дополнительных команд в буфер команд.
Пример кода: рисование треугольника
Следующие шаги, проиллюстрированные в Перечислении 5-14, описывают основную процедуру для рендеринга треугольника.
Создайте a
MTLCommandQueue
и используйте его для создания aMTLCommandBuffer
.Создайте a
MTLRenderPassDescriptor
это указывает набор присоединений, служащих местом назначения для закодированных команд рендеринга в буфере команд.В этом примере только первое цветное присоединение устанавливается и используется. (Переменная
currentTexture
как предполагается, содержит aMTLTexture
это используется для цветного присоединения.) ТогдаMTLRenderPassDescriptor
используется для создания новогоMTLRenderCommandEncoder
.Создайте два
MTLBuffer
объекты,posBuf
иcolBuf
, и вызовитеnewBufferWithBytes:length:options:
для копирования координаты вершины и вершины окрашивают данные,posData
иcolData
, соответственно, в буферный накопитель.Вызовите
setVertexBuffer:offset:atIndex:
методMTLRenderCommandEncoder
дважды указать координаты и цвета.atIndex
входное значениеsetVertexBuffer:offset:atIndex:
метод соответствует атрибутуbuffer(atIndex)
в исходном коде функции вершины.Создайте a
MTLRenderPipelineDescriptor
и установите вершину и функции фрагмента в конвейерном дескрипторе:Создайте a
MTLLibrary
с исходным кодом отprogSrc
, который, как предполагается, является строкой, содержащей Металлический исходный код шейдера.Тогда вызовите
newFunctionWithName:
методMTLLibrary
создатьMTLFunction
vertFunc
это представляет вызванную функциюhello_vertex
и создатьMTLFunction
fragFunc
это представляет вызванную функциюhello_fragment
.Наконец, установите
vertexFunction
иfragmentFunction
свойстваMTLRenderPipelineDescriptor
с нимиMTLFunction
объекты.
Создайте a
MTLRenderPipelineState
отMTLRenderPipelineDescriptor
путем вызоваnewRenderPipelineStateWithDescriptor:error:
или похожий методMTLDevice
. ТогдаsetRenderPipelineState:
методMTLRenderCommandEncoder
использует создаваемое конвейерное состояние для рендеринга.Вызовите
drawPrimitives:vertexStart:vertexCount:
методMTLRenderCommandEncoder
добавлять команды для выполнения рендеринга заполненного треугольника (типMTLPrimitiveTypeTriangle
).Вызовите
endEncoding
метод для окончания кодирования для этой передачи рендеринга. И вызовитеcommit
методMTLCommandBuffer
выполнить команды на устройстве.
Код металла перечисления 5-14 для рисования треугольника
id <MTLDevice> device = MTLCreateSystemDefaultDevice(); |
id <MTLCommandQueue> commandQueue = [device newCommandQueue]; |
id <MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer]; |
MTLRenderPassDescriptor *renderPassDesc |
= [MTLRenderPassDescriptor renderPassDescriptor]; |
renderPassDesc.colorAttachments[0].texture = currentTexture; |
renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; |
renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0,1.0,1.0,1.0); |
id <MTLRenderCommandEncoder> renderEncoder = |
[commandBuffer renderCommandEncoderWithDescriptor:renderPassDesc]; |
static const float posData[] = { |
0.0f, 0.33f, 0.0f, 1.f, |
-0.33f, -0.33f, 0.0f, 1.f, |
0.33f, -0.33f, 0.0f, 1.f, |
}; |
static const float colData[] = { |
1.f, 0.f, 0.f, 1.f, |
0.f, 1.f, 0.f, 1.f, |
0.f, 0.f, 1.f, 1.f, |
}; |
id <MTLBuffer> posBuf = [device newBufferWithBytes:posData |
length:sizeof(posData) options:nil]; |
id <MTLBuffer> colBuf = [device newBufferWithBytes:colorData |
length:sizeof(colData) options:nil]; |
[renderEncoder setVertexBuffer:posBuf offset:0 atIndex:0]; |
[renderEncoder setVertexBuffer:colBuf offset:0 atIndex:1]; |
NSError *errors; |
id <MTLLibrary> library = [device newLibraryWithSource:progSrc options:nil |
error:&errors]; |
id <MTLFunction> vertFunc = [library newFunctionWithName:@"hello_vertex"]; |
id <MTLFunction> fragFunc = [library newFunctionWithName:@"hello_fragment"]; |
MTLRenderPipelineDescriptor *renderPipelineDesc |
= [[MTLRenderPipelineDescriptor alloc] init]; |
renderPipelineDesc.vertexFunction = vertFunc; |
renderPipelineDesc.fragmentFunction = fragFunc; |
renderPipelineDesc.colorAttachments[0].pixelFormat = currentTexture.pixelFormat; |
id <MTLRenderPipelineState> pipeline = [device |
newRenderPipelineStateWithDescriptor:renderPipelineDesc error:&errors]; |
[renderEncoder setRenderPipelineState:pipeline]; |
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle |
vertexStart:0 vertexCount:3]; |
[renderEncoder endEncoding]; |
[commandBuffer commit]; |
В перечислении 5-14, a MTLFunction
объект представляет вызванную функцию программы построения теней hello_vertex
. setVertexBuffer:offset:atIndex:
метод MTLRenderCommandEncoder
используется для указания ресурсов вершины (в этом случае, два буферных объекта), которые передаются как параметры в hello_vertex
. atIndex
входное значение setVertexBuffer:offset:atIndex:
метод соответствует атрибуту buffer(atIndex)
в исходном коде функции вершины, как показано в Перечислении 5-15.
Перечисление 5-15 соответствующее объявление функции программы построения теней
vertex VertexOutput hello_vertex( |
const global float4 *pos_data [[ buffer(0) ]], |
const global float4 *color_data [[ buffer(1) ]]) |
{ |
... |
} |
Кодирование единственной передачи рендеринга Используя многократные потоки
В некоторых случаях производительность Вашего приложения может быть ограничена рабочей нагрузкой единственного CPU кодирования команд для единственной передачи рендеринга. Однако попытка обойти это узкое место путем разделения рабочей нагрузки на многократные передачи рендеринга, закодированные на многократных потоках ЦП, может также неблагоприятно повлиять на производительность, потому что каждая передача рендеринга требует, чтобы ее собственное промежуточное присоединяемое хранилище и действия загрузки сохранили целевое содержание рендеринга.
Вместо этого используйте a MTLParallelRenderCommandEncoder
объект, управляющий многократным подчиненным MTLRenderCommandEncoder
объекты, совместно использующие тот же буфер команд и представляющие дескриптор передачи. Параллельный кодер команды рендеринга гарантирует, чтобы присоединяемая загрузка и действия хранилища произошли только в запуске и конце всей передачи рендеринга, не в запуске и конце каждого подчиненного набора кодера команды рендеринга команд. С этой архитектурой можно присвоить каждого MTLRenderCommandEncoder
возразите против его собственного потока параллельно безопасным и очень производительным способом.
Для создания параллельного кодера команды рендеринга используйте parallelRenderCommandEncoderWithDescriptor:
метод a MTLCommandBuffer
объект. Для создания подчиненных кодеров команды рендеринга вызовите renderCommandEncoder
метод MTLParallelRenderCommandEncoder
возразите один раз для каждого потока ЦП, от которого Вы хотите выполнить кодирование команды. Все подчиненные кодеры команды, создаваемые из того же параллельного кодера команды рендеринга, кодируют команды к тому же буферу команд. Команды кодируются к буферу команд в порядке, в котором создаются кодеры команды рендеринга. Для окончания кодирования для определенного кодера команды рендеринга вызовите endEncoding
метод MTLRenderCommandEncoder
. После окончания кодирования на всех кодерах команды рендеринга, создаваемых параллельным кодером команды рендеринга вызовите endEncoding
метод MTLParallelRenderCommandEncoder
закончить передачу рендеринга.
Перечисление 5-16 показывает MTLParallelRenderCommandEncoder
создание три MTLRenderCommandEncoder
объекты: rCE1
, rCE2
, и rCE3
.
Перечисление 5-16 параллельный кодер рендеринга с тремя кодерами команды рендеринга
MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor renderPassDescriptor]; renderPassDesc.colorAttachments[0].texture = currentTexture; renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear; renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0.0,0.0,0.0,1.0); id <MTLParallelRenderCommandEncoder> parallelRCE = [commandBuffer parallelRenderCommandEncoderWithDescriptor:renderPassDesc]; id <MTLRenderCommandEncoder> rCE1 = [parallelRCE renderCommandEncoder]; id <MTLRenderCommandEncoder> rCE2 = [parallelRCE renderCommandEncoder]; id <MTLRenderCommandEncoder> rCE3 = [parallelRCE renderCommandEncoder]; // not shown: rCE1, rCE2, and rCE3 call methods to encode graphics commands // // rCE1 commands are processed first, because it was created first // even though rCE2 and rCE3 end earlier than rCE1 [rCE2 endEncoding]; [rCE3 endEncoding]; [rCE1 endEncoding]; // all MTLRenderCommandEncoders must end before MTLParallelRenderCommandEncoder [parallelRCE endEncoding]; |
Порядок, в котором кодеры команды вызывают endEncoding
не относится к порядку, в котором команды кодируются и добавляются к MTLCommandBuffer
. Для MTLParallelRenderCommandEncoder
, MTLCommandBuffer
всегда содержит команды в порядке, что подчиненные кодеры команды рендеринга создавались, как замечено на рисунке 5-6.