I am currently finalizing my Swift Student Challenge submission, and Metal shaders are an essential part of my app. However, during submission, I noticed a note explaining: "Note: Xcode app playgrounds are run in Simulator", which is not possible for my app, as it also requires the camera of a physical device to function. So, I am currently transferring my app from Xcode into Swift Playgrounds, which I presume will run on physical devices.
However, I noticed that Swift Playgrounds do not yet support Metal shaders directly, so I am now pre-compiling my shaders to load them at runtime instead. Note that all the code below was run either in the terminal or in Xcode.
I have already compiled my Metal shaders with:
xcrun -sdk iphoneos metal -o Shaders.ir -c Shaders.metal
xcrun -sdk iphoneos metallib Shaders.ir -o Shaders.metallib
Which seems to have run without any problems.
When I run:
let shaderPath = Bundle.main.path(forResource: "Shaders", ofType: "metallib")
let shaderURL = URL(fileURLWithPath: shaderPath!)
let shaderData = try! Data(contentsOf: shaderURL)
do {
let device = MTLCreateSystemDefaultDevice()!
let library = try shaderData.withUnsafeBytes { bytes -> MTLLibrary? in
let dispatchData = DispatchData(bytes: bytes)
return try device.makeLibrary(data: dispatchData as __DispatchData)
}
print(library!.functionNames)
} catch {
print(error.localizedDescription)
}
My Metal shader functions are printed correctly in the console. However, based on my research, it seems like a MTLLibrary cannot be converted into a SwiftUI ShaderLibrary.
That is why I am now looking at these two initializers:
ShaderLibrary(url: URL)
ShaderLibrary(data: Data)
Which state: Creates a new Metal shader library from the contents of url/data, which must be the contents of precompiled Metal library. Functions compiled from the returned library will only be cached as long as the returned library exists., which I believe should work for my use case.
However, the problem arises when I run this code:
let shaderPath = Bundle.main.path(forResource: "Shaders", ofType: "metallib")
let shaderURL = URL(fileURLWithPath: shaderPath!)
let library = ShaderLibrary(url: shaderURL)
My app consistently seems to crash on the ShaderLibrary initialization, rendering the app unusable. Why does ShaderLibrary(url: shaderURL) cause a crash, even though my .metallib file is valid? Are there additional requirements for loading a ShaderLibrary that I may have missed?