Как создать цепочку фильтров в Metal для iOS?

#ios #swift #ios10 #metal

#iOS #swift #ios10 #Металлические

Вопрос:

Я выполнил это руководство Саймона Глэдмана (@flexmonkey) по захвату изображений из AVFoundation и применению фильтра к выходным данным. Тем не менее, я изо всех сил пытаюсь найти способ заменить фильтр размытия моим собственным вычислительным шейдером. Другими словами, мне нужно объединить мой пользовательский шейдер после YCbCrColorConversion упомянутого там фильтра.

 let commandBuffer = commandQueue.makeCommandBuffer()
let commandEncoder = commandBuffer.makeComputeCommandEncoder()
// pipelineState has compiled YCbCrColorConversion filter
commandEncoder.setComputePipelineState(pipelineState)
commandEncoder.setTexture(ytexture, at: 0)
commandEncoder.setTexture(cbcrTexture, at: 1)
commandEncoder.setTexture(drawable.texture, at: 2) // out texture

commandEncoder.dispatchThreadgroups(threadGroups,threadsPerThreadgroup: threadGroupCount)
commandEncoder.endEncoding()

let inPlaceTexture = UnsafeMutablePointer<MTLTexture> .allocate(capacity: 1)
        inPlaceTexture.initialize(to: drawable.texture)

// How to replace this blur with my own filter?????
blur.encodeToCommandBuffer(commandBuffer, inPlaceTexture: inPlaceTexture, fallbackCopyAllocator: nil)

commandBuffer.presentDrawable(drawable)
commandBuffer.commit();
  

Должен ли я создать новый commandBuffer, commandEncoder и отдельный pipelineState, который компилирует вторую функцию ядра? При этом выходные данные первого фильтра будут использоваться в качестве входных данных для второго. Есть ли более эффективный способ сделать это, или это оптимально?

Я новичок в Metal, поэтому высоко ценю любые пояснения о том, как работает конвейер.

Ответ №1:

Вам не нужно создавать новый буфер команд или другой вычислительный кодировщик, но вам нужно создать состояние вычислительного конвейера, которое использует вашу собственную функцию ядра. Вы должны сделать это один раз, во время инициализации, где бы вы в данный момент ни создавали состояние конвейера преобразования YCbCr.

Чтобы связать эффекты вместе, вам нужно создать промежуточную текстуру, которая действует как текстура вывода преобразования YCbCr и ввода вашего ядра. Затем прорисовываемая текстура будет выходной текстурой вашей функции ядра. Вы можете отправлять работу для своего собственного ядра точно так же, как вы в данный момент отправляете работу для преобразования YCbCr (т. Е. с тем же количеством потоков в threadgroup и количеством threadgroup count).

Промежуточная текстура, вероятно, должна иметь те же размеры и формат, что и рисуемая. Вы можете создать ее лениво и сохранить ссылку на нее, повторно создавая ее при изменении размера, который можно отрисовывать.