iOS 框架:当在客户端代码上设置 cikernel 标志时,MTLLibrary newFunctionWithName 失败

iOS framework: MTLLibrary newFunctionWithName fails when cikernel flag is set on client code

我有一个使用 Metal 的 iOS 框架;它按如下方式设置管道描述符:

...
_metalVars.mtlLibrary = [_metalVars.mtlDevice newLibraryWithFile:libraryPath error:&error];

id <MTLFunction> vertexFunction = [_metalVars.mtlLibrary newFunctionWithName:@"vertexShader"];
id <MTLFunction> fragmentFunction = [_metalVars.mtlLibrary newFunctionWithName:@"fragmentShader"];

MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];

MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineStateDescriptor.label = @"MyPipeline";
pipelineStateDescriptor.vertexFunction = vertexFunction;
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
pipelineStateDescriptor.vertexDescriptor = mtlVertexDescriptor;
pipelineStateDescriptor.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm; 

_metalVars.mtlPipelineState = [_metalVars.mtlDevice newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error];
...

此框架由 iOS 应用程序使用,并且在标记

之前一直运行良好
-fcikernel

设置在其他金属编译器标志下,并且

-cikernel

在其他金属链接器标志下,在客户端应用程序的构建设置中。 (根据 https://developer.apple.com/documentation/coreimage/cikernel/2880194-kernelwithfunctionname. 在客户端设置标志)

随着客户端应用程序中的这些更改,上述框架代码片段现在在上述代码片段的最后一行失败,在调用 newRenderPipelineStateWithDescriptor 时出现错误

validateWithDevice:2556: failed assertion `Render Pipeline Descriptor Validation
vertexFunction must not be nil

并且我已经验证框架现在为

处的顶点函数返回 nil
id <MTLFunction> vertexFunction = [_metalVars.mtlLibrary newFunctionWithName:@"vertexShader"];

但如果我删除客户端应用程序上的标志,则工作正常。

问题: 1.) 我知道金属着色器是预编译的;为什么更改 client 代码上的构建设置会导致 unchanged 框架中的运行时失败? 2.) 如何解决这个问题?

这些标志用于编译用 Metal 编写的 Core Image 内核。他们以与“常规”金属着色器代码不兼容的方式更改了代码的翻译方式。

在项目级别设置 Core Image 标志的问题是所有 .metal 文件都会受到影响,无论它们是否包含 Core Image 内核或常规着色器代码。

最好的解决方法是对包含 Core Image Metal 内核的文件使用不同的文件扩展名,例如 .ci.metal。然后可以使用自定义构建规则将这些内核与 Metal 代码库的其余部分分开编译。 我推荐 this session 来自 WWDC 2020,它详细描述了这个过程。