Thanks to Matthijs Hollemanns who pointed me into the right direction with some code, I came up with the following UIView extension, which does the job in about 12 ms per frame on an iPhone8plus for a full screen resolution.
extension UIView {
func takeTextureSnapshot(device: MTLDevice) -> MTLTexture? {
let width = Int(bounds.width)
let height = Int(bounds.height)
if let context = CGContext(data: nil,
width: width,
height: height,
bitsPerComponent: 8,
bytesPerRow: 0,
space: CGColorSpaceCreateDeviceRGB(),
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue),
let data = context.data {
layer.render(in: context)
let desc = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm,
width: width,
height: height,
mipmapped: false)
if let texture = device.makeTexture(descriptor: desc) {
texture.replace(region: MTLRegionMake2D(0, 0, width, height),
mipmapLevel: 0,
withBytes: data,
bytesPerRow: context.bytesPerRow)
return texture
}
}
return nil
}
}