Графический рендеринг: кодер команды рендеринга
В этой главе описываются, как создать и работать с 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свойство. Если присоединение не может поддерживать мультивыборку, тоsampleCount1, который является также значением по умолчанию.Если
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и платформаformatMTLVertexFormatFloat2, тогда, когда данные используются в качестве параметра функции вершины, они могут быть преобразованы от плавания до половины и расширены с двух до четырех элементов (с 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создатьMTLFunctionvertFuncэто представляет вызванную функциюhello_vertexи создатьMTLFunctionfragFuncэто представляет вызванную функцию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.
