I have an (animated) UIView-Hierarchy and I want to periodically render the UIView content into a MTLTexture for further processing.
What I have tried, is to subclass my parent UIView and
override public class var layerClass: Swift.AnyClass {
return CAMetalLayer.self
}
but the texture from nextDrawable() is black and does not show the view content.
Any ideas how to get a MTLTexture containing the view content ?
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
}
}