How to Chain Filters in Metal for iOS

How to chain filters in Metal for iOS?

You don't need to create a new command buffer or another compute encoder, but you do need to create a compute pipeline state that uses your own kernel function. You should do this once, during initialization, wherever you're currently creating the YCbCr conversion pipeline state.

To chain the effects together, you'll need to create an intermediate texture that acts as the output texture of the YCbCr conversion and the input of your kernel. The drawable texture will then be the output texture of your kernel function. You can dispatch the work for your own kernel just as you're currently dispatching the work for the YCbCr conversion (i.e. with the same number of threads per threadgroup and threadgroup count).

The intermediate texture should probably be of the same dimensions and format as the drawable. You can create it lazily and hold a reference to it, re-creating it when the drawable size changes.

Specify sampling method in Metal Core Image Kernel

Yes, there is! You can use a CISampler that you can pass to your kernel instead of a CIImage:

let sampler = CISampler(image: image, options: [
kCISamplerWrapMode: kCISamplerWrapClamp,
kCISamplerFilterMode: kCISamplerFilterLinear
])

You can also set kCISamplerAffineMatrix in the options to define a transform that is applied to the coordinates when sampling (normalized is the default behavior, I think).

Alternatively, you can use these convenience helpers on CIImage to set the wrap and filter modes:

// for linear & clamp-to-edge
let newImage = image.samplingLinear().clampedToExtent()
// for nearest & clamp-to-black (actually transparent, not black)
let newImage = image.samplingNearest().cropped(to: aRect)

Using these methods you can also force built-in filters to use the corresponding modes.

Metal iOS for beginners

Here you will find apple documentation, sample code, and videos. link

This website is will help you to understand metal: link

Metal in playground with Swift: link

Performance Improvements of CIFilter Chain?

You should use a CIContext to render the image:

var context = CIContext() // create this once and re-use it for each image

func render(image ciImage: CIImage) -> UIImage? {
let cgImage = context.createCGImage(ciImage, from: ciImage.extent)
return cgImage.map(UIImage.init)
}

It's important to create the CIContext only once since it's expensive to create because it's holding and caching all (Metal) resources needed for rendering the image.



Related Topics



Leave a reply



Submit