Skip to content

Instantly share code, notes, and snippets.

@scornflake
Created March 28, 2023 06:32
Show Gist options
  • Save scornflake/4738673eea3fffc112ee2f1c6dd41c7f to your computer and use it in GitHub Desktop.
Save scornflake/4738673eea3fffc112ee2f1c6dd41c7f to your computer and use it in GitHub Desktop.
Sample CA -> metal texture
import Metal
import MetalKit
// Create a MTLTexture for rendering
let textureDescriptor = MTLTextureDescriptor()
textureDescriptor.pixelFormat = .bgra8Unorm
textureDescriptor.width = Int(layer.bounds.width)
textureDescriptor.height = Int(layer.bounds.height)
let texture = device.makeTexture(descriptor: textureDescriptor)!
// Create a CAMetalRenderCommandEncoder
let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = texture
renderPassDescriptor.colorAttachments[0].loadAction = .clear
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1)
let commandBuffer = commandQueue.makeCommandBuffer()!
let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)!
// Create a CALayer and render it to the CAMetalRenderCommandEncoder
let metalLayer = CAMetalLayer()
metalLayer.framebufferOnly = true
metalLayer.pixelFormat = .bgra8Unorm
metalLayer.frame = layer.bounds
metalLayer.drawsAsynchronously = true
layer.addSublayer(metalLayer)
let drawable = metalLayer.nextDrawable()!
renderEncoder.setRenderPipelineState(pipelineState)
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
renderEncoder.setFragmentTexture(drawable.texture, index: 0)
renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
// Finish rendering and get the contents of the MTLTexture
renderEncoder.endEncoding()
commandBuffer.commit()
commandBuffer.waitUntilCompleted()
let bytesPerRow = 4 * Int(layer.bounds.width)
let imageData = UnsafeMutableRawPointer.allocate(byteCount: bytesPerRow * Int(layer.bounds.height), alignment: 1)
texture.getBytes(imageData, bytesPerRow: bytesPerRow, from: MTLRegionMake2D(0, 0, textureDescriptor.width, textureDescriptor.height), mipmapLevel: 0)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue)
let context = CGContext(data: imageData, width: Int(layer.bounds.width), height: Int(layer.bounds.height), bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)!
let cgImage = context.makeImage()!
let uiImage = UIImage(cgImage: cgImage)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment