Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Metal Performance Shaders & Fallback Copy Allocators

DZone's Guide to

Metal Performance Shaders & Fallback Copy Allocators

This tutorial demonstrates implementing Metal Performance Shaders to filter textures in place in Swift 2.0.

· Mobile Zone ·
Free Resource

One of the options available when using Metal Performance Shaders is to filter textures in place. This is discussed inWhat's New in Metal Part 2, but the actual implementation is slightly glossed over. Worse than that, fallback copy allocators didn't actually work until the latest iOS 9 beta build, so if you've been struggling, here's a quick blog post to help.

When filtering a source texture and populating a destination texture, encodeToCommandBuffer() has this signature:

    encodeToCommandBuffer(commandBuffer, sourceTexture: srcTexture, destinationTexture: targetTexture)

However, with the following syntax, we can apply a filter to a texture in place:

    encodeToCommandBuffer(commandBuffer, inPlaceTexture: inPlaceTexture, fallbackCopyAllocator: copyAllocator)

Some filters, such as MPSImageMedian are unable to filter in place and in this situation, we need to create an instance of MPSCopyAllocator which will create a texture and ensure the in-place version of encodeToCommandBuffer will always succeed. There isn't actually a descriptorFromTexture() method available (as shown in the WWDC video), so the correct Swift definition of copyAllocator is:

    let copyAllocator: MPSCopyAllocator =
    {
        (kernel: MPSKernel, buffer: MTLCommandBuffer, sourceTexture: MTLTexture) -> MTLTexture in

        let descriptor = MTLTextureDescriptor.texture2DDescriptorWithPixelFormat(sourceTexture.pixelFormat,
            width: sourceTexture.width,
            height: sourceTexture.height,
            mipmapped: false)

        let targetTexture: MTLTexture = buffer.device.newTextureWithDescriptor(descriptor)

        return targetTexture

    }

...and now the following will work:

    let median = MPSImageMedian(device: device!, kernelDiameter: 3)

    median.encodeToCommandBuffer(commandBuffer, inPlaceTexture: inPlaceTexture, fallbackCopyAllocator: copyAllocator)

Easy!

Topics:
mobile ,swift ,ios ,metal

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}