Instance Method

encode(commandBuffer:inPlaceTexture:fallbackCopyAllocator:)

This method attempts to apply a kernel in place on a texture.

Declaration

func encode(commandBuffer: MTLCommandBuffer, inPlaceTexture texture: UnsafeMutablePointer<MTLTexture>, fallbackCopyAllocator copyAllocator: MPSCopyAllocator? = nil) -> Bool

Parameters

commandBuffer

A valid command buffer to receive the encoded kernel.

texture

A pointer to a valid texture containing the source image. On success, the image contents and possibly the texture itself will be replaced with the result image.

copyAllocator

An optional block to allocate a new texture to hold the operation results, in case in-place operation is not possible. The allocator may use a different pixel format or size than the original texture. You may enqueue operations on the provided command buffer using the provided compute command encoder to initialize the texture contents.

Return Value

  • true if the operation succeeded (the texture may have been replaced with a new texture if a copy allocator was provided).

  • false if the operation failed (the texture is unmodified).

Discussion

This method attempts to apply the kernel in place on a texture. In-place operation means that the same texture is used both to hold the input image and the results. Operating in-place can be an excellent way to reduce resource utilization, and save time and energy. While simple Metal kernels can not operate in place because textures can not be readable and writable at the same time, some Metal Performance Shaders kernels can operate in place because they use multi-pass algorithms. Whether a kernel can operate in-place can depend on current hardware, OS version, and the parameters and properties passed to it. You should never assume that a kernel will continue to work in place, even if you have observed it doing so before.

If the in-place operation succeeds, this method returns true. If the in-place operation fails and no copy allocator is provided, then this method returns false. Without a fallback copy allocator, in neither case is the pointer held at texture modified.

Failure during in-place operation is very common and will occur inconsistently across different hardware platforms and OS versions. Without a fallback copy allocator, operating in place may require significant error handling code to accompany each call to this method, further complicating your code.

You may find it simplifies your code to provide a fallback copy allocator so that the operation can proceed reliably even when it can not complete in-place. When an in-place filter fails, the copy allocator will be invoked to create a new texture in which to write the results, allowing the filter to proceed reliably out-of-place. The original texture will be released, replaced with a pointer to the new texture and true will be returned. If the copy allocator returns an invalid texture, it is released, texture remains unmodified, and false is returned.

Listing 1

In-Place Operation Example

id <MTLTexture> inPlaceTex = ...;
MPSImageSobel *sobelFiler = [[MPSImageSobel alloc] initWithDevice: my_device];
 
// With a fallback MPSCopyAllocator, failure should only occur in exceptional conditions such as MTLTexture allocation failure or programmer error.
// That is, the operation is roughly as robust as the MPSCopyAllocator.
// Depending on the quality of that, we might decide we are justified here in not checking the return value.
[sobelFilter encodeToCommandBuffer: my_command_buffer inPlaceTexture: &inPlaceTex fallbackCopyAllocator: myAllocator];
// inPlaceTex may be replaced!
 
// If myAllocator was not called:
//      inPlaceTex holds the original texture with the result pixels in it.
// Else:
//      1) myAllocator creates a new texture.
//      2) The new texture pixel data is overwritten by MPSUnaryImageKernel.
//      3) The old texture passed in *inPlaceTex is released once.
//      4) *inPlaceTex = the new texture
//
// In either case, the caller should now hold one reference to the texture now held in inPlaceTex, whether it was replaced or not. Most of the time that means that nothing further needs to be done here, and you can proceed to the next image encoding operation. However, if other agents held references to the original texture, they still hold them and may need to be alerted that the texture has been replaced so that they can retain the new texture and release the old one.
 
[sobelFilter release];  // if not ARC, clean up the MPSImageSobel object

See Also

Methods

typealias MPSCopyAllocator

A block to make a copy of a source texture for filters that can only execute out of place.

func sourceRegion(destinationSize: MTLSize) -> MPSRegion

Determines the region of the source texture that will be read for an encode operation.