Metal:为MSL cikernel设置编译器和链接器选项后,.metal文件中定义的vertexFunction变为nil

时间:2019-08-07 09:43:58

标签: swift metal cifilter cikernel

.metal文件中定义的VertexFunction和FragmentFunction很好地工作,但是一旦我在Apple's doc之后指定了Compiler和Linker选项,它们就变成了零:在Other Metal Compiler Flags选项中使用-fcikernel标志,在MTLLINKER_FLAGS中使用-cikernel flat用户定义的设置。

我需要使用MSL(金属阴影语言)的香ci的上述设置。实际上,使用Core Image Kernel Language的cikernel在12.0中已弃用。

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

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

3 个答案:

答案 0 :(得分:0)

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

为此,例如,您可以给他们另一个文件扩展名,例如.kernel,然后添加自定义的 Build Rule ,如下所示:

enter image description here

然后添加一个自定义的 Build Phase ,将已编译的内核metallib复制到您的应用包中:

enter image description here

要使用正确的金属源初始化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源再次正确编译。)

答案 1 :(得分:0)

Frank Schlegel的答案的更新版本适用于Xcode 11,正如Giraff Wombat所提到的,金属编译器只是忽略不以[WebMethod] public static string get_PendingOrder() { JavaScriptSerializer serializer = new JavaScriptSerializer(); string strOrderList = serializer.Serialize(_listOrderMasterDTO); return strOrderList; } private void fill_PendingOrder() { try { var ActiveDate = DateTime.Now; var startOfMonth = new DateTime(ActiveDate.Year, ActiveDate.Month, 1); DateTime dtFromDate = Functions.ConvertToDateTime(m_strStartDate); DateTime dtToDate = Functions.ConvertToDateTime(m_strEndDate); _listOrderMasterDTO = new OrderMasterService().GetOrderMasterByDateAndSubCatIdList(dtFromDate, dtToDate, "", 0, Convert.ToString(txtCategory.Items[txtCategory.SelectedIndex].Text), Convert.ToString(Session["g_DBNAME"])); } catch (Exception ex) { Module.ShowError(ex, this, this.Page.GetType()); } } protected void btnSearch_Click(object sender, EventArgs e) { try { fill_PendingOrder(); System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("$(function(){"); sb.Append("reload_data();"); sb.Append("});"); ScriptManager.RegisterStartupScript(this, this.Page.GetType(), "", sb.ToString(), true); } catch (Exception ex) { Module.ShowError(ex, this, this.Page.GetType()); } } 结尾的输入文件。为了确保CI内核文件不会出现在常规金属管道之外,我进行了扩展“ .metal”,并放置了构建规则脚本:

.mcikernel

答案 2 :(得分:0)

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

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

创建一个名为 MyKernels.ci.metal 之类的 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 的其他答案。如果使用常规 Metal 和可能的其他问题,它们将导致问题。此解决方案只会在带有 .ci.metal 扩展名的文件上使用这些标志。

构建规则的屏幕截图:

enter image description here