Объекты ресурса: буферы и текстуры

В этой главе описываются Металлические объекты ресурса (MTLResource) для хранения бесформатной памяти и отформатированных данных изображения. Существует два типа MTLResource объекты:

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

Буферы являются выделениями без типов памяти

A MTLBuffer объект представляет выделение памяти, которая может содержать любой тип данных.

Создание буферного объекта

Следующий MTLDevice методы создают и возвращают a MTLBuffer объект:

  • newBufferWithLength:options: метод создает a MTLBuffer объект с новым выделением ресурсов хранения.

  • newBufferWithBytes:length:options: метод создает a MTLBuffer объект путем копирования данных с существующего хранения (расположенный в адресе CPU pointer) в новое выделение ресурсов хранения.

  • newBufferWithBytesNoCopy:length:options:deallocator: метод создает a MTLBuffer объект с существующим выделением ресурсов хранения и не выделяет нового хранения для этого объекта.

Все буферные методы создания имеют входное значение length указать размер выделения ресурсов хранения, в байтах. Все методы также принимают a MTLResourceOptions объект для options это может изменить поведение создаваемого буфера. Если значение для options 0, значения по умолчанию используются для опций ресурса.

Буферные методы

MTLBuffer протокол имеет следующие методы:

Текстуры являются отформатированными данными изображения

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

MTLPixelFormat указывает организацию отдельных пикселей в a MTLTexture объект. Форматы пикселя обсуждены далее в Форматах пикселя для Текстур.

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

Следующие методы создают и возвращают a MTLTexture объект:

  • newTextureWithDescriptor: метод MTLDevice создает a MTLTexture объект с новым выделением ресурсов хранения для данных изображения текстуры, с помощью a MTLTextureDescriptor объект описать свойства текстуры.

  • newTextureViewWithPixelFormat: метод MTLTexture создает a MTLTexture возразите, что совместно использует то же выделение ресурсов хранения как вызов MTLTexture объект. Так как они совместно используют то же хранение, любые изменения в пикселях нового объекта текстуры отражаются в объекте текстуры вызова, и наоборот. Для недавно создаваемой текстуры, newTextureViewWithPixelFormat: метод дает иное толкование существующим данным изображения текстуры выделения ресурсов хранения вызова MTLTexture возразите, как будто данные хранились в указанном формате пикселя. MTLPixelFormat из новой текстуры объект должен быть совместим с MTLPixelFormat из исходного объекта текстуры. (См. Форматы пикселя для Текстур для подробных данных об обычных, упакованных, и сжатых форматах пикселя.)

  • newTextureWithDescriptor:offset:bytesPerRow: метод MTLBuffer создает a MTLTexture возразите, что совместно использует выделение ресурсов хранения вызова MTLBuffer возразите как его данные изображения текстуры. Поскольку они совместно используют то же хранение, любые изменения в пикселях нового объекта текстуры отражаются в объекте текстуры вызова, и наоборот. Совместное использование хранения между текстурой и буфером может предотвратить использование определенной оптимизации текстурирования, такой как пиксель swizzling или мозаичное размещение.

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

MTLTextureDescriptor определяет свойства, использующиеся для создания a MTLTexture объект, включая его размер изображения (ширина, высота и глубина), формат пикселя, расположение (тип массива или тип куба) и число множественных отображений. MTLTextureDescriptor свойства только используются во время создания a MTLTexture объект. После создания a MTLTexture объект, свойство изменяется в MTLTextureDescriptor объект больше не имеет эффекта на ту текстуру.

Создать одну или более текстур из дескриптора:

  1. Создайте пользовательское MTLTextureDescriptor объект, содержащий свойства текстуры, описывающие данные текстуры:

    • textureType свойство указывает размерность и расположение текстуры (например, массив или куб).

    • width, height, и depth свойства указывают, что множественно отображается размер пикселя в каждой размерности основной текстуры уровня.

    • pixelFormat свойство указывает, как пиксель сохранен в текстуре.

    • arrayLength свойство указывает число элементов матрицы для a MTLTextureType1DArray или MTLTextureType2DArray введите объект текстуры.

    • mipmapLevelCount свойство указывает число уровней множественного отображения.

    • sampleCount свойство указывает число выборок в каждом пикселе.

    • resourceOptions свойство указывает поведение своего выделения памяти.

  2. Создайте текстуру из MTLTextureDescriptor объект путем вызова newTextureWithDescriptor: метод a MTLDevice объект. После создания текстуры вызовите replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage: метод для загрузки данных изображения текстуры, как детализировано в Копировании Данных изображения к и от Текстуры.

  3. Создать больше MTLTexture объекты, можно снова использовать то же MTLTextureDescriptor объект, изменяя значения свойств дескриптора по мере необходимости.

Перечисление 3-1 показывает код для создания дескриптора текстуры txDesc и установка ее свойств для 3D, 64x64x64 текстура.

Перечисление 3-1  , создающее объект текстуры с пользовательским дескриптором текстуры

MTLTextureDescriptor* txDesc = [MTLTextureDescriptor new];
txDesc.textureType = MTLTextureType3D;
txDesc.height = 64;
txDesc.width = 64;
txDesc.depth = 64;
txDesc.pixelFormat = MTLPixelFormatBGRA8Unorm;
txDesc.arrayLength = 1;
txDesc.mipmapLevelCount = 1;
id <MTLTexture> aTexture = [device newTextureWithDescriptor:txDesc];

Работа с частями текстуры

Часть является синглом 1D, 2D, или 3D изображение текстуры и все его связанные множественные отображения. Для каждой части:

  • Размер основного множественного отображения уровня указан width, height, и depth свойства MTLTextureDescriptor объект.

  • Масштабированный размер уровня множественного отображения я указан макс. (1, пол (width / 2i)) x макс. (1, пол (height / 2i)) x макс. (1, пол (depth / 2i)). Максимальный уровень множественного отображения является первым уровнем множественного отображения, где достигается размер 1 x 1 x 1.

  • Число уровней множественного отображения в одной части может быть определено полом (log2 (макс. (width, height, depth))) +1.

Все объекты текстуры имеют по крайней мере одну часть; куб и типы текстуры массива могут иметь несколько частей. В методах, пишущих и читающих данные изображения текстуры, обсужденные в Копировании Данных изображения к и от Текстуры, slice основанное на нуле входное значение. Для 1D, 2D, или 3D текстура, существует только одна часть, таким образом, значение slice должен быть 0. Кубическая текстура имеет шесть общих 2D частей, адресуемых от 0 до 5. Для 1DArray и 2DArray типы текстуры, каждый элемент матрицы представляет одну часть. Например, для 2DArray текстурируют тип с arrayLength = 10, существует 10 общих частей, адресуемых от 0 до 9. Для выбора сингла 1D, 2D, или 3D изображение из полной структуры текстуры, сначала выбирают часть, и затем выбирают уровень множественного отображения в той части.

Создание дескриптора текстуры с удобными методами

Для общих 2D и кубических текстур используйте следующие удобные методы создать a MTLTextureDescriptor объект с несколькими из его значений свойств автоматически установил:

  • texture2DDescriptorWithPixelFormat:width:height:mipmapped: метод создает a MTLTextureDescriptor объект для 2D текстуры. width и height значения определяют размерности 2D текстуры. type свойство автоматически установлено в MTLTextureType2D, и depth и arrayLength установлены в 1.

  • textureCubeDescriptorWithPixelFormat:size:mipmapped: метод создает a MTLTextureDescriptor объект для кубической текстуры, где type свойство установлено в MTLTextureTypeCube, width и height установлены измерить, и depth и arrayLength установлены в 1.

Оба MTLTextureDescriptor удобные методы принимают входное значение, pixelFormat, который определяет формат пикселя текстуры. Оба метода также принимают входное значение mipmapped, который определяет, множественно отображается ли изображение текстуры. (Если mipmapped YES, текстура множественно отображается.)

Перечисление 3-2 использует texture2DDescriptorWithPixelFormat:width:height:mipmapped: метод для создания дескриптора возражает для a 64x64 Не множественно отображающаяся 2D текстура.

Перечисление 3-2  , создающее объект текстуры с дескриптором текстуры удобства

MTLTextureDescriptor *texDesc = [MTLTextureDescriptor 
         texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm 
         width:64 height:64 mipmapped:NO];
id <MTLTexture> myTexture = [device newTextureWithDescriptor:texDesc];

Копирование данных изображения к и от текстуры

Синхронно скопировать данные изображения в или данные копии от выделения ресурсов хранения a MTLTexture объект, используйте следующие методы:

  • replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage: копирует область пиксельных данных от указателя вызывающей стороны в часть выделения ресурсов хранения указанной части текстуры. replaceRegion:mipmapLevel:withBytes:bytesPerRow: подобный удобный метод, копирующий область пиксельных данных в часть по умолчанию, принимая значения по умолчанию для связанных с частью параметров (т.е. slice = 0 и bytesPerImage = 0).

  • getBytes:bytesPerRow:bytesPerImage:fromRegion:mipmapLevel:slice: получает область пиксельных данных от указанной части текстуры. getBytes:bytesPerRow:fromRegion:mipmapLevel: подобный удобный метод, получающий область пиксельных данных от части по умолчанию, принимая значения по умолчанию для связанных с частью параметров (slice = 0 и bytesPerImage = 0).

Перечисление 3-3 показывает, как вызвать replaceRegion:mipmapLevel:slice:withBytes:bytesPerRow:bytesPerImage: для указания текстуры отображают от исходных данных в системной памяти, textureData, в части 0 и множественно отобразите уровень 0.

Перечисление 3-3  , копирующее данные изображения в текстуру

//  pixelSize is the size of one pixel, in bytes
//  width, height - number of pixels in each dimension
NSUInteger myRowBytes = width * pixelSize;
NSUInteger myImageBytes = rowBytes * height;
[tex replaceRegion:MTLRegionMake2D(0,0,width,height)
    mipmapLevel:0 slice:0 withBytes:textureData
    bytesPerRow:myRowBytes bytesPerImage:myImageBytes];

Форматы пикселя для текстур

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

  • Обычные форматы имеют только регулярные 8-, 16-, или 32-разрядные компоненты цвета. Каждый компонент располагается в увеличении адресов памяти с первым перечисленным компонентом в самом низком адресе. Например, MTLPixelFormatRGBA8Unorm 32-разрядный формат с восемью битами для каждого компонента цвета; самые низкие адреса содержат красный, следующие адреса содержат зеленый и т.д. Напротив, для MTLPixelFormatBGRA8Unorm, самые низкие адреса содержат синий, следующие адреса содержат зеленый и т.д.

  • Упакованные форматы комбинируют многократные компоненты в одно 16-разрядное или 32-разрядное значение, где компоненты сохранены от наименьшего количества до старшего значащего бита (LSB к MSB). Например, MTLPixelFormatRGB10A2Uint 32-разрядный упакованный формат, состоящий из трех 10-разрядных каналов (для R, G, и B) и два бита для альфы.

  • Сжатые форматы располагаются в блоках пикселей, и расположение каждого блока является определенным для того формата пикселя. Сжатые форматы пикселя могут только использоваться для 2D, 2D Массива или типов кубической текстуры. Сжатые форматы не могут использоваться для создания 1D, 2DMultisample или 3D текстуры.

MTLPixelFormatGBGR422 и MTLPixelFormatBGRG422 специальные форматы пикселя, предназначающиеся для хранения пикселей в цветовом пространстве YUV. Эти форматы только поддерживаются для 2D текстур (но ни 2D Массив, ни тип куба), без множественных отображений, и даже width.

Несколько форматов пикселя хранят компоненты цвета sRGB значениями цветового пространства (например, MTLPixelFormatRGBA8Unorm_sRGB или MTLPixelFormatETC2_RGB8_sRGB). Когда работа выборки ссылается на текстуру с sRGB форматом пикселя, Металлическая реализация преобразовывает sRGB компоненты цветового пространства в линейное цветовое пространство, прежде чем работа выборки будет иметь место. Преобразование из sRGB компонента, S, к линейному компоненту, L, следующие:

  • Если S <= 0.04045, L = S/12.92

  • Если S> 0.04045, L = ((S+0.055)/1.055) 2.4

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

  • Если L <= 0.0031308, S = L * 12.92

  • Если L> 0.0031308, S = (1.055 * L0.41667) - 0.055

Для получения дополнительной информации о формате пикселя для рендеринга, посмотрите Создание Дескриптора Передачи Рендеринга.

Создание объекта состояний сэмплера для поиска текстуры

A MTLSamplerState объект определяет обращение, фильтрация и другие свойства, использующиеся, когда графика или вычисляют функцию, выполняют операции выборки текстуры на a MTLTexture объект. Дескриптор сэмплера определяет свойства объекта состояния сэмплера. Создать объект состояния сэмплера:

  1. Вызовите newSamplerStateWithDescriptor: метод a MTLDevice объект создать a MTLSamplerDescriptor объект.

  2. Установите требуемые значения в MTLSamplerDescriptor объект, включая фильтрацию опций, способов адресации, максимальной анизотропии и параметров уровня детализации.

  3. Создайте a MTLSamplerState объект от дескриптора сэмплера путем вызова newSamplerStateWithDescriptor: метод MTLDevice возразите, что создал дескриптор.

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

Перечисление 3-4 является примером кода, создающим a MTLSamplerDescriptor и конфигурирует его для создания a MTLSamplerState. Значения не по умолчанию установлены для фильтра и свойств режима адреса объекта дескриптора. Тогда newSamplerStateWithDescriptor: метод использует дескриптор сэмплера для создания объекта состояния сэмплера.

Перечисление 3-4  , создающее объект состояния сэмплера

// create MTLSamplerDescriptor
MTLSamplerDescriptor *desc = [[MTLSamplerDescriptor alloc] init];
desc.minFilter = MTLSamplerMinMagFilterLinear;
desc.magFilter = MTLSamplerMinMagFilterLinear;
desc.sAddressMode = MTLSamplerAddressModeRepeat;
desc.tAddressMode = MTLSamplerAddressModeRepeat;
//  all properties below have default values
desc.mipFilter        = MTLSamplerMipFilterNotMipmapped;
desc.maxAnisotropy    = 1U;
desc.normalizedCoords = YES;
desc.lodMinClamp      = 0.0f;
desc.lodMaxClamp      = FLT_MAX;
// create MTLSamplerState
id <MTLSamplerState> sampler = [device newSamplerStateWithDescriptor:desc];

Поддержание когерентности между CPU и памятью GPU

И CPU и GPU могут получить доступ к базовой системе хранения для a MTLResource объект. Однако GPU управляет асинхронно от узла CPU, поэтому помните следующее при использовании узла CPU для доступа к хранению для этих ресурсов.

При выполнении a MTLCommandBuffer объект, MTLDevice объект, как только гарантируют, будет наблюдать любые изменения, внесенные узлом CPU к выделению ресурсов хранения любого MTLResource на объект ссылается это MTLCommandBuffer возразите, были ли (и только если) те изменения внесены узлом CPU перед MTLCommandBuffer объект фиксировался. Т.е. MTLDevice объект не мог бы наблюдать изменения в ресурсе, который узел CPU делает после соответствия MTLCommandBuffer объект фиксировался (т.е. status свойство MTLCommandBuffer объект MTLCommandBufferStatusCommitted).

Точно так же после MTLDevice объект выполняет a MTLCommandBuffer объект, узел CPU, как только гарантируют, будет наблюдать любые изменения MTLDevice объект делает к выделению ресурсов хранения любого ресурса ссылаемый тем буфером команд, если буфер команд завершил выполнение (т.е. status свойство MTLCommandBuffer объект MTLCommandBufferStatusCompleted).