Правильное использование MPSImageGaussianPyramid с металлом - PullRequest
0 голосов
/ 02 января 2019

Я хотел бы использовать MPSImageGaussianPyramid, но я очень новичок в использовании Металла и с мипмапами. Я хотел бы использовать фильтр для создания пирамиды изображений для методов обработки изображений.

Исходя из того, что я могу собрать, MPSImageGaussianPyramid создает изображение с разметкой, однако в моем коде мне трудно даже убедиться, что я вижу вывод правильно. Есть ли примеры, где этот фильтр использовался правильно? Мои вопросы:

  1. Как получить доступ к отображенным изображениям после применения фильтра?

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

  3. Будет ли это растровое изображение быстрее, чем создание пирамиды вручную с помощью пользовательских фильтров?

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

1 Ответ

0 голосов
/ 02 января 2019

Несколько советов по работе с ядрами MPS в целом и фильтрами пирамид изображения в частности:

  • Если вы собираетесь использовать ядро ​​более одного раза, кэшируйте его ииспользуйте его вместо того, чтобы создавать ядро ​​каждый раз, когда вам нужно кодировать.
  • Попробуйте установить для свойства edgeMode ядра значение .clamp при понижающей дискретизации, поскольку выборка выходит за пределы (как это делает пирамида Гаусса)на первом шаге) по умолчанию вернет черный и введет искусственно темные пиксели.
  • При кодировании ядра гауссовой пирамиды всегда используйте метод «на месте», не предоставляя запасной распределитель:

kernel.encode(commandBuffer: commandBuffer, inPlaceTexture: &myTexture)

Как вы заметили, запуск ядра пирамиды изображений приводит к получению доступных уровней mip понижаемой дискретизации текстуры.Это означает, что для текстуры, которую вы предоставляете, уже должно быть выделено столько уровней mip, сколько вы хотите заполнить.Таким образом, вы должны убедиться, что дескриптор, который вы используете для создания вашей текстуры, имеет соответствующий mipmapLevelCount (это обеспечивается вспомогательным методом texture2DDescriptorWithPixelFormat и может управляться косвенно с помощью опции .allocateMipmaps с MTKTextureLoader).

Предполагая, что теперь вы знаете, как кодировать ядро ​​и получить желаемые результаты в вашей текстуре, вот несколько ответов на ваши вопросы:

1.Как можно получить доступ к изображениям с mip-отображением после применения фильтра?

Вы можете неявно использовать mipmaps в шейдере при рендеринге с использованием сэмплера, который имеет фильтр mip, или вы можете явно сэмплироватьот определенного уровня MIP путем передачи параметра lod_option типа level в функцию sample:

constexpr sampler mySampler(coord::normalized, filter::linear, mip_filter::linear);
float4 color = myTexture.sample(mySampler, texCoords, level(selectedLod))

Это работает в вычислительных ядрах, а также в функциях рендеринга.Используйте MIP-фильтр nearest или округляйте выбранный LOD, если вы хотите производить выборку с одного уровня MIP, а не трилинейную MIP-фильтрацию.

2.Можно ли скопировать изображения с mip-отображением в другое изображение для обработки?

Поскольку текстура, которая подвергается понижающей дискретизации ядром пирамиды изображений, уже должна иметь флаг использования .pixelFormatView, вы можете создать просмотр текстуры для текстуры с переворотом, которая выбирает один или несколько уровней.Например, если вы хотите выбрать первый и более высокий уровни MIP (отбрасывая базовый уровень), вы можете сделать это следующим образом:

let textureView = myTexture.makeTextureView(pixelFormat: myTexture.pixelFormat,
    textureType: myTexture.textureType,
    levels: Range<Int>(uncheckedBounds: (1, myTexture.mipmapLevelCount)),
    slices: Range<Int>(uncheckedBounds: (0, 1)))

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

Вы можете обернуть MTLTexture в MPSImage, если хотите использовать API, которые работают с изображениямиа не текстуры:

let image = MPSImage(texture: myTexture, featureChannels: 4)

3.Будет ли это растровое изображение быстрее, чем создание пирамиды вручную с помощью пользовательских фильтров?

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

...