看起来[[stitchable]]
Metal Core Image 内核由于未找到 Core Imagesampler.coord()
和符号而无法在编译时链接,或者如果我添加其他 Metal 链接器标志(这对于可缝合内核来说并不是必需的),则sampler.sample(coord)
无法在运行时加载。-fcikernel
这是github上测试项目的完整链接。欢迎下载并玩一玩。
我发现罪魁祸首是 Metal 文件中的这一行,链接器无法解析:
float2 srcCoord = inputImage.coord();
我的代码摘录:
import CoreImage
class FilterTwo: CIFilter {
var inputImage: CIImage?
var inputParam: Float = 0.0
static var kernel: CIKernel = { () -> CIKernel in
let url = Bundle.main.url(forResource: "default",
withExtension: "metallib")!
let data = try! Data(contentsOf: url)
let kernelNames = CIKernel.kernelNames(fromMetalLibraryData: data)
NSLog("Kernels \(kernelNames)")
return try! CIKernel(functionName: "secondFilter", fromMetalLibraryData: data) //<-- This fails!
}()
override var outputImage : CIImage? {
guard let inputImage = inputImage else {
return nil
}
return FilterTwo.kernel.apply(extent: inputImage.extent, roiCallback: { (index, rect) in
return rect }, arguments: [inputImage])
}
}
这是金属文件:
#include <CoreImage/CoreImage.h> // includes CIKernelMetalLib.h
using namespace metal;
[[ stitchable ]] half4 secondFilter (coreimage::sampler inputImage, coreimage::destination dest)
{
float2 srcCoord = inputImage.coord();
half4 color = half4(inputImage.sample(srcCoord));
return color;
}
这是用法:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let filter = FilterTwo()
filter.inputImage = CIImage(color: CIColor.red)
let outputImage = filter.outputImage!
NSLog("Output \(outputImage)")
}
}
和输出:
StitchableKernelsTesting/FilterTwo.swift:15: Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=CIKernel Code=1 "(null)" UserInfo={CINonLocalizedDescriptionKey=Function does not exist in library data. …•∆}
Kernels []
reflect Function 'secondFilter' does not exist.
尽管使用 CI 内核的构建过程要容易得多
[[ stitchable ]]
,但您仍然需要告诉 Metal 链接器链接到 Core Image。这是在WWDC21 会议上有关该主题时提到的。为此,您需要将该
-framework CoreImage
标志添加到“其他金属链接器标志”,如下所示。请注意,您需要将其添加在两个单独的行中,否则它将无法工作。