提问者建议的方法不可能奏效(因此,缺乏示例代码)。金属着色器(.Metal)只是一组函数,而不是MTLLibrary(.metallib)生成的。下面是从角色编译金属着色器的工作代码(
const char *
)数组(与不同
NSString
在运行时编译金属着色器
以下示例还可用于为用户提供着色器编辑器,并允许您仅更新应用程序的着色器部分,而无需用户更新整个应用程序:
NSError* error = NULL;
const char* vshSource =
"using namespace metal;\n"
"typedef struct {\n"
" packed_float2 position;\n"
" packed_float2 texcoord;\n"
"} Vertex;\n"
"typedef struct {\n"
" float3x3 matrix;\n"
" float3 offset;\n"
"} ColorConversion;\n"
"typedef struct {\n"
" float4 position [[position]];\n"
" float2 texcoord;\n"
"} Varyings;\n"
"vertex Varyings vertexPassthrough(\n"
"device Vertex* verticies [[ buffer(0) ]],\n"
"unsigned int vid [[ vertex_id ]]\n"
") {\n"
" Varyings out;\n"
" device Vertex& v = verticies[vid];\n"
" out.position = float4(float2(v.position), 0.0, 1.0);\n"
" out.texcoord = v.texcoord;\n"
" return out;\n"
"}\n";
const char* fshSource =
"using namespace metal;\n"
"typedef struct {\n"
"packed_float2 position;\n"
"packed_float2 texcoord;\n"
"} Vertex;\n"
"typedef struct {\n"
"float3x3 matrix;\n"
"float3 offset;\n"
"} ColorConversion;\n"
"typedef struct {\n"
"float4 position [[position]];\n"
"float2 texcoord;\n"
"} Varyings;\n"
"fragment half4 fragmentColorConversion(\n"
"Varyings in [[ stage_in ]],\n"
"texture2d<float, access::sample> textureBGRA [[ texture(0) ]],\n"
"constant ColorConversion &colorConversion [[ buffer(0) ]]\n"
") {\n"
"constexpr sampler s(address::clamp_to_edge, filter::linear);\n"
"return half4(half3(textureBGRA.sample(s, in.texcoord).rgb), 1.0);\n"
"}\n";
id <MTLFunction> vertexProgram;
id <MTLLibrary> vertexLibrary = [_device newLibraryWithSource:[NSString stringWithUTF8String:vshSource] options:NULL error:&error];
if (NULL != vertexLibrary)
{
vertexProgram = [vertexLibrary newFunctionWithName:@"vertexPassthrough"];
} else {
NSLog(@"Error compiling vertex program: %@", error.description);
}
id <MTLFunction> fragmentProgram;
id <MTLLibrary> fragmentLibrary = [_device newLibraryWithSource:[NSString stringWithUTF8String:fshSource] options:NULL error:&error];
if (NULL != fragmentLibrary)
{
fragmentProgram = [fragmentLibrary newFunctionWithName:@"fragmentColorConversion"];
} else {
NSLog(@"Error compiling fragment program: %@", error.description);
}
以下是苹果开发者文档出版物的摘录;尽管这些信息相对来说比较初级,但在交流其主题时,请将其作为您和您的观众共享的公共框架的基础。
Creating Libraries During the App Build Process
出于同样的原因,公认的答案是完全错误的;而且,关于性能权衡的说法也值得怀疑。以下是关于编译金属着色器和创建金属库的唯一明确声明,然后是实际代码:
函数和库
本章介绍如何将MTLFunction对象创建为
参考金属着色器或计算函数以及如何组织
和使用MTLLibrary对象访问函数。
MTLFunction对象表示写入的单个函数
金属着色语言,并在GPU上作为
语言,请参见《金属着色语言指南》。
在金属运行时和图形或
用金属着色语言编写的计算函数,指定一个
纹理、缓冲区和采样器的参数索引。参数索引
标识所引用的纹理、缓冲区或采样器
对于渲染过程,可以指定MTLFunction对象作为
MTLRenderPipelineDescriptor对象中的顶点或片段着色器,如
详细信息请参见创建渲染管道状态。对于计算过程,您
创建MTLComputePipelineState时指定MTLFunction对象
对象,如指定计算状态中所述
库是功能的存储库
MTLLibrary对象表示一个或多个MTL函数的存储库
物体。单个MTLFunction对象表示一个金属函数
这是用着色语言写的。在金属着色中
语言源代码,任何使用金属函数的函数
限定符(顶点、片段或内核)可以用
库中的MTLFunction对象。没有这些元素的金属函数
函数限定符不能直接由MTLFunction表示
对象,尽管它可以由着色器中的另一个函数调用。
库中的MTLFunction对象可以从以下任意一种创建:
这些来源:
-
编译到二进制库中的金属着色语言代码
在应用程序构建过程中格式化。
-
与在运行时编译着色器源代码相比,在应用程序构建过程中编译着色器语言源文件并构建库(.metallib文件)可以获得更好的应用程序性能。您可以在Xcode内或使用命令行实用程序构建库。
使用Xcode构建库
中的任何着色器源文件
您可以使用MTLDevice的newDefaultLibrary方法从金属框架代码中访问它。
使用命令行实用程序构建库
图8-1显示了构成编译器的命令行实用程序
金属着色器源代码的工具链。当你包括。金属锉刀
您可以在运行时在应用程序中访问。
要在不使用Xcode的情况下将着色器源编译到库中,请执行以下操作:
-
使用金属工具编译每一个。金属锉成单锉。air文件,其中存储着色器语言代码的中间表示(IR)。
-
-
使用metallib工具构建金属。来自IR的metallib库文件。air文件或存档。metalar文件。
示例:使用命令行实用程序构建库文件
xcrun -sdk macosx metal MyLibrary.metal -o MyLibrary.air
xcrun -sdk macosx metallib MyLibrary.air -o MyLibrary.metallib
要在框架代码中访问生成的库,请调用newLibraryWithFile:error:method:
NSError *libraryError = NULL;
NSString *libraryFile = [[NSBundle mainBundle] pathForResource:@"MyLibrary" ofType:@"metallib"];
id <MTLLibrary> myLibrary = [_device newLibraryWithFile:libraryFile error:&libraryError];
if (!myLibrary) {
NSLog(@"Library error: %@", libraryError);
}