Правильное использование MPSImageGaussianPyramid с металлом
Я хотел бы использовать MPSImageGaussianPyramid
но я очень плохо знаком с использованием металла и с мипмапами. Я хотел бы использовать фильтр для создания пирамиды изображений для методов обработки изображений.
Из того, что я могу собрать, MPSImageGaussianPyramid
создает изображение с разметкой, но в моем коде мне трудно даже убедиться, что я вижу вывод правильно. Есть ли примеры, где этот фильтр использовался правильно? Мои вопросы:
Как получить доступ к отображенным изображениям после применения фильтра?
Можно ли скопировать изображения с mipmapped в другое изображение для обработки?
Будет ли это растровое изображение быстрее, чем создание пирамиды вручную с помощью пользовательских фильтров?
Спасибо, и позже я приведу пример кода, который я не смог заставить работать.
1 ответ
Несколько советов по работе с ядрами MPS в целом и фильтрами пирамид изображения в частности:
- Если вы собираетесь использовать ядро более одного раза, кэшируйте его и используйте повторно, а не создавайте ядро каждый раз, когда вам нужно кодировать.
- Рассмотрите возможность настройки
edgeMode
свойство ядра для.clamp
при пониженной дискретизации, поскольку выборка за пределами границ (как это делает пирамида Гаусса на первом шаге) по умолчанию возвращает черный цвет и вводит искусственно темные пиксели. - При кодировании ядра гауссовой пирамиды всегда используйте метод "на месте", не предоставляя запасной распределитель:
kernel.encode(commandBuffer: commandBuffer, inPlaceTexture: &myTexture)
Как вы заметили, запуск ядра пирамиды изображений приводит к получению доступных уровней mip понижаемой дискретизации текстуры. Это означает, что для текстуры, которую вы предоставляете, уже должно быть выделено столько уровней mip, сколько вы хотите заполнить. Таким образом, вы должны убедиться, что дескриптор, который вы используете для создания текстуры, имеет соответствующий mipmapLevelCount
(это обеспечивается texture2DDescriptorWithPixelFormat
удобный метод, и может контролироваться косвенно с помощью .allocateMipmaps
вариант с MTKTextureLoader
).
Предполагая, что вы теперь знаете, как кодировать ядро и получать желаемые результаты в вашей текстуре, вот несколько ответов на ваши вопросы:
1. Как можно получить доступ к отображенным изображениям после применения фильтра?
Вы можете неявно использовать 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. Можно ли скопировать изображения со смещением в другое изображение для обработки?
Поскольку текстура, которая подвергается понижающей дискретизации ядром пирамиды изображений, уже должна иметь .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 настроены для каждого поколения устройств и имеют многочисленные эвристические параметры, которые оптимизируют скорость выполнения и использование энергии.