4

.metal 文件中定义的 VertexFunction 和 FragmentFunction 运行良好,但是一旦我按照Apple 的文档指定编译器和链接器选项,它们就变成了 nil :Other Metal Compiler Flags 选项中的 -fcikernel 标志,以及用户定义设置中 MTLLINKER_FLAGS 中的 -cikernel flat。

我需要上面的设置用于带有 MSL(金属着色语言)的 cikernel。事实上,带有 Core Image Kernel Language 的 cikernel 在 12.0 中已弃用。

如何同时使用顶点/片段金属着色器和 MSL cikernel?

let library = self.device?.makeDefaultLibrary()!
let pipeLineDescriptor = MTLRenderPipelineDescriptor()
pipeLineDescriptor.vertexFunction=library.makeFunction(name: "myVertexShader")
pipeLineDescriptor.fragmentFunction=library.makeFunction(name: "myFragmentShader")
4

3 回答 3

4

我想您必须单独编译过滤器内核,而不是使用默认的 Metal 库。

为此,您可以例如给他们另一个文件扩展名,例如.kernel并添加自定义构建规则,如下所示:

在此处输入图像描述

然后添加一个自定义构建阶段,将编译的内核金属库复制到您的应用程序包中:

在此处输入图像描述

要使用正确的金属源初始化CIKernel,您可以执行以下操作:

let url = Bundle(for: type(of: self)).url(forResource: "<#name of your .kernel file#>", withExtension: "metallib")!
let data = try! Data(contentsOf: url)
let kernel = try! CIKernel(functionName: "<#kernel function name#>", fromMetalLibraryData: data)

(请注意,您应该再次从项目设置中删除编译器和 liker 标志,以使您的其他 Metal 源再次正确编译。)

于 2019-08-07T10:32:14.120 回答
1

在 Xcode 11 中有效的 Frank Schlegel 答案的更新,正如 Giraff Wombat 所提到的,金属编译器只是忽略不以.metal. 为了确保 CI 内核文件不受常规金属管道的影响,我制作了扩展名“ .mcikernel”并为构建规则脚本添加:

mkdir -p ${DERIVED_FILES_DIR}/kernels
cp ${INPUT_FILE_PATH} ${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.metal
xcrun metal -fcikernel ${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.metal -c -o ${DERIVED_FILES_DIR}/kernels/${INPUT_FILE_BASE}.air
xcrun metallib -cikernel -o ${DERIVED_FILES_DIR}/kernels/${INPUT_FILE_BASE}.metallib ${DERIVED_FILES_DIR}/kernels/${INPUT_FILE_BASE}.air
于 2020-02-15T09:05:03.010 回答
1

我无法让任何现有的答案正常工作(AlterEgo 答案似乎不完整,就像不显示输入/输出文件设置一样)。

无论如何,WWDC 视频,Apple 推荐以下内容。

创建一个名为 MyKernels.ci.metal 之类的金属文件:

#include <metal_stdlib>
using namespace metal;

#include <CoreImage/CoreImage.h>
 
extern "C" float4 do_nothing(coreimage::sample_t s) {
    return s;
}

接下来添加两个构建规则,它们都取消选中“每个架构运行一次”。规则1:

Source Files with names matching:
*.ci.metal

xcrun metal -c -I $MTL_HEADER_SEARCH_PATHS -fcikernel "${INPUT_FILE_PATH}" -o "${SCRIPT_OUTPUT_FILE_0}"

output files:
$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).air

第二:

Source Files with names matching:
*.ci.air

xcrun metallib -cikernel "${INPUT_FILE_PATH}" -o "${SCRIPT_OUTPUT_FILE_0}"

output files:
$(METAL_LIBRARY_OUTPUT_DIR)/$(INPUT_FILE_BASE).metallib

要使用:

let url = Bundle.main.url(forResource: "MyKernels", withExtension: "ci.metallib")!
let data = try! Data(contentsOf: url)
kernel = try! CIColorKernel(functionName: "do_nothing", fromMetalLibraryData: data)

请注意,不推荐其他建议将fckernelcikernel标志添加到的答案Build Settings。如果使用常规金属,它们将导致问题,并可能导致其他问题。.ci.metal此解决方案将仅在具有扩展名的文件上使用这些标志。

构建规则截图:

在此处输入图像描述

于 2021-05-16T06:46:47.420 回答