AVCustomEdit-Swift/APLMetalRenderer.swift
/* |
Copyright (C) 2017 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Metal base class renderer sets up Metal for rendering, it also loads, compiles and links the vertex and fragment shaders. |
*/ |
import Foundation |
import CoreGraphics |
import CoreVideo |
import MetalKit |
class APLMetalRenderer: AnyObject { |
/// A `MTLDevice` object instance representing a GPU that can execute commands. |
let device: MTLDevice |
/// A `MTLCommandQueue` object used to queue the command buffers for the Metal device to execute. |
let commandQueue: MTLCommandQueue |
/// `CVMetalTextureCache` object used for rendering of textures associated with video frames. |
var textureCache: CVMetalTextureCache? |
init?() { |
// Ask for the default Metal device; this represents our GPU. |
guard let defaultMetalDevice = MTLCreateSystemDefaultDevice() else { |
print("Metal is not supported on this device.") |
return nil |
} |
device = defaultMetalDevice |
// Create the command queue to submit work to the GPU. |
commandQueue = device.makeCommandQueue() |
// Create a new texture cache to use to create textures from the pixel buffers for the movie frames. |
guard CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, device, nil, &textureCache) == kCVReturnSuccess |
else { return nil } |
} |
func buildTextureForPixelBuffer(_ pixelBuffer: CVPixelBuffer) -> MTLTexture? { |
let width = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0) |
let height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0) |
guard let metalTextureCache = textureCache else { return nil } |
var texture: CVMetalTexture? |
/* |
CVMetalTextureCacheCreateTextureFromImage is used to create a Metal texture (CVMetalTexture) from a |
CVPixelBuffer (or more precisely, a texture from the IOSurface that backs a CVPixelBuffer). |
Note: Calling CVMetalTextureCacheCreateTextureFromImage does not increment the use count of the |
IOSurface; only the CVPixelBuffer, and the CVMTLTexture own this IOSurface. At least one of the two |
must be retained until Metal rendering is done. The MTLCommandBuffer completion handler is good for |
this purpose. |
*/ |
let status = |
CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, metalTextureCache, pixelBuffer, nil, |
MTLPixelFormat.bgra8Unorm, width, height, 0, &texture) |
if status == kCVReturnSuccess { |
guard let textureFromImage = texture else { return nil } |
guard let metalTexture = CVMetalTextureGetTexture(textureFromImage) else { return nil } |
return metalTexture |
} else { return nil } |
} |
func renderPixelBuffer(_ destinationPixelBuffer: CVPixelBuffer, |
usingForegroundSourceBuffer foregroundPixelBuffer: CVPixelBuffer, |
andBackgroundSourceBuffer backgroundPixelBuffer: CVPixelBuffer, |
forTweenFactor tween: Float) { |
// Subclasses must implement this function. |
} |
} |
Copyright © 2017 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2017-08-17