The Metal framework function MTLLibrary.makeDefaultLibrary()
loads "your app’s default Metal library." However, it doesn't specify where it finds this default library.
When I build an example command line project, like marzvrover/Performing-Calculations-on-a-GPU, Xcode creates the file default.metallib
alongside the executable. This file needs to be present or makeDefaultLibrary()
fails.
I am trying to build my own project from the command line using swiftc
and the Metal command line tools directly. when I build my own project from the command line, I link my compiled shaders together into default.metallib
:
$ xcrun -sdk macosx metal -c add.metal -o add.ir
$ xcrun -sdk macosx metal-ar r default.metallib add.ir
$ swiftc -framework Metal -o tool main.swift
Yet, makeDefaultLibrary()
is still failing. Why can it be loaded by a program built by Xcode, but not my program compiled "manually"?
The MTLDevice.makeDefaultLibrary(bundle:)
function will throw an error which describes the problem. If I switch to this code, I can see the error message:
do {
try self.device.makeDefaultLibrary(bundle: Bundle.main)
} catch {
print("Unexpected error: \(error)")
}
If the file is missing, the error is:
Error Domain=MTLLibraryErrorDomain Code=6 "no default library was found" UserInfo={NSLocalizedDescription=no default library was found}
However in my case, it was telling me the file is invalid:
Error Domain=MTLLibraryErrorDomain Code=1 "Invalid library file" UserInfo={NSLocalizedDescription=Invalid library file}
The problem was because I produced an invalid .metallib
file with the metal-ar
— which outputs archives, not libraries — instead of metallib
. See Building a Shader Library by Precompiling Source File.
$ xcrun -sdk macosx metal -c add.metal -o add.ir
+$ xcrun -sdk macosx metallib -o default.metallib add.ir
$ swiftc -framework Metal -o tool main.swift