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

Download this comprehensive Mobile Testing Reference Guide to help prioritize which mobile devices and OSs to test against, brought to you in partnership with Sauce Labs.

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!

Analysts agree that a mix of emulators/simulators and real devices are necessary to optimize your mobile app testing - learn more in this white paper, brought to you in partnership with Sauce Labs.

Topics:
mobile ,swift ,ios ,metal

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}