对于我的项目(作为框架编译),我有一个文件ops.metal

kernel void add(device float *lhs [[buffer(0)]],
                device float *rhs [[buffer(1)]],
                device float *result [[buffer(2)]],
                uint id [[ thread_position_in_grid ]])
{
    result[id] = lhs[id] + rhs[id];
}

以及以下SWIFT代码:
@available(OSX 10.11, *)
public class MTLContext {
    var device: MTLDevice!
    var commandQueue:MTLCommandQueue!
    var library:MTLLibrary!
    var commandBuffer:MTLCommandBuffer
    var commandEncoder:MTLComputeCommandEncoder

    init() {
        if let defaultDevice = MTLCreateSystemDefaultDevice() {
            device = defaultDevice
            print("device created")
        } else {
            print("Metal is not supported")
        }

        commandQueue = device.makeCommandQueue()

        library = device.newDefaultLibrary()
        if let defaultLibrary = device.newDefaultLibrary() {
            library = defaultLibrary
        } else {
            print("could not load default library")
        }

        commandBuffer = commandQueue.makeCommandBuffer()
        commandEncoder = commandBuffer.makeComputeCommandEncoder()
    }

    deinit {
        commandEncoder.endEncoding()
    }
}

当我试图在单元测试中创建MTLContext的实例时,会创建设备,但无法创建默认库(“could not load default library”)。我已经检查了编译的框架在default.metallib中是否有Resources(这是newDefaultLibrary的最常见原因)。
不幸的是,我还没有找到在金属材质球文件中创建computekernels的任何工作示例(有一些示例使用性能材质球,但它们不需要在材质球文件中生成内核)。
任何建议都将不胜感激!

最佳答案

newDefaultLibrary()从当前运行的应用程序的主捆绑包加载。它不搜索任何嵌入式框架或其他库位置。
如果要使用编译到嵌入式框架中的metallib,最简单的方法是获取对其包含的Bundle的引用,并请求该包的默认库:

let frameworkBundle = Bundle(for: SomeClassFromMyShaderFramework.self)
guard let defaultLibrary = try? device.makeDefaultLibrary(bundle: frameworkBundle) else {
    fatalError("Could not load default library from specified bundle")
}

这确实要求在包含着色器的框架中至少有一个公开可见的类,但这可以简单到仅为执行包查找而声明空类:
public class SomeClassFromMyShaderFramework {}

10-08 11:23