我正在做一个SceneKit小项目,我想使用Metal Compute管道以编程方式生成我的纹理以提高速度。我已经建立了生成MTLTexture的基本管道,并且可以运行,但是一旦我将SceneKit框架添加到项目中,它就无法声明Function <X> was not found in the library
。如果删除所有对SceneKit的引用,它将再次起作用。
我必须从正确的URL实例化我的库,否则如果没有SceneKit,它将无法正常工作。是什么阻碍了它?是否可以通过SCNRenderer解决此问题?
[编辑]为了更加清楚,这是我如何获得对MTLLibrary的引用:
guard let url = Bundle.main.url(forResource: "MyLibrary", withExtension: "metallib") else {
throw GeneratorError.metalLibraryNotFound
}
library = device.makeLibrary(URL: url)
强引用由调用对象(以及MTLDevice
)保留,并且是单例,因此保留在内存中。为了获得内核函数本身,我然后调用以下函数,该函数返回适当的管道状态:
guard let function = library.makeFunction(name: functionName) else {
throw GeneratorError.functionNotFound(functionName)
}
return device.makeComputePipelineState(function: function)
就像我说的那样,在将SceneKit添加到项目中之前,它可以正常工作-只需将框架添加到链接的框架列表就足够了,我无需对其进行任何操作-因此,它根本找不到任何内容我的功能。
答案 0 :(得分:0)
我已经找到了造成此问题的原因,但是对于为什么我仍然感到困惑,因此,我感谢人们提供的任何其他信息!
从本质上讲,我已经将我的Metal库拆分成几个文件,以便于使用。其中一个具有CIFilter支持的功能,另一个具有Metal管道内核。现在,我知道当两者都链接到主.metal
文件中时,两者是不兼容的,因此我暂时将其中一个注释掉,但保留以供参考。在构建设置中,我还具有链接器标志-cikernel
。
我怀疑链接器标志可能会引起问题,但是删除它会使情况变得更糟。最终,我尝试删除链接器标志以及之前仅被注释掉的整个文件。这工作了!我猜编译器必须编译所有.metal
文件,而不管它们是否包含在主文件中,并且以某种方式在同一库中具有CIFilter内核和纹理化内核是一个很大的禁忌,即使它们不在同一个文件中命名空间。
如果有人知道其背后的原因,我很想知道!同时,我只是要删除所有CIFilter,而改为使用基于纯Metal的计算管道。