You can check ImageIO whether ImageIO supports the format you want to export to:
Call CGImageDestinationCopyTypeIdentifiers() from ImageIO module to get a list of all the UTI that the CGImageDestination supports.
For example, these are the types ImageIO supports on my machine:
(
"public.jpeg",
"public.png",
"com.compuserve.gif",
"public.tiff",
"public.jpeg-2000",
"com.apple.atx",
"org.khronos.ktx",
"org.khronos.ktx2",
"org.khronos.astc",
"com.microsoft.dds",
"public.heic",
"public.heics",
"com.microsoft.ico",
"com.microsoft.bmp",
"com.apple.icns",
"com.adobe.photoshop-image",
"com.adobe.pdf",
"com.truevision.tga-image",
"com.ilm.openexr-image",
"public.pbm",
"public.pvr"
)
Then, use CGImage to output it:
let texture: MTLTexture = ... // input texture
let ciContext = CIContext(mtlDevice: texture.device)
let ciImage = CIImage(mtlTexture: texture, options: nil) // you might need to add `.oriented(.downMirrored)` here
let colorspace = CGColorSpace(name: CGColorSpace.sRGB)
let cgImage = ciContext.createCGImage(ciImage, from: .init(origin: .zero, size: .init(width: texture.width, height: texture.height)), format: .RGBA8, colorSpace: colorspace)!
let uniformType: UTType = ... // uniform type from CGImageDestinationCopyTypeIdentifiers
let outputURL: URL = ... // the url
try FileManager.default.createDirectory(at: outputURL.deletingLastPathComponent(), withIntermediateDirectories: true) // you might needs this to create intermediate directories
let destination = CGImageDestinationCreateWithURL(outputURL as CFURL, uniformType.identifier as CFString, 1, nil)!
CGImageDestinationAddImage(destination, cgImage, nil)
let imageOutputSuccessfully = CGImageDestinationFinalize(destination)