简体   繁体   English

同时使用Metal和SceneKit的问题

[英]Problems using Metal and SceneKit simultaneously

I'm working on a little SceneKit project, and I want to generate my textures programmatically using a Metal Compute pipeline for speed. 我正在一个小型的SceneKit项目上,我想使用Metal Compute管道以编程方式生成我的纹理以提高速度。 I have a basic pipeline set up that generates an MTLTexture and it works, but as soon as I add the SceneKit framework to the project, it fails claiming Function <X> was not found in the library . 我已经建立了生成MTLTexture的基本管道,并且可以正常工作,但是一旦我将SceneKit框架添加到项目中,它就无法声明Function <X> was not found in the library If I remove all references to SceneKit it works again. 如果删除所有对SceneKit的引用,它将再次起作用。

I must be instantiating my library from the correct URL or it wouldn't work without SceneKit. 我必须从正确的URL实例化我的库,否则如果没有SceneKit,它将无法正常工作。 What's blocking it? 是什么阻碍了它? Is there a way around this issue, perhaps using an SCNRenderer? 是否有办法解决此问题,也许使用SCNRenderer?

[Edit] For more clarity, here's how I obtain a reference to my MTLLibrary: [编辑]为了更加清楚,这是我如何获得对MTLLibrary的引用:

    guard let url = Bundle.main.url(forResource: "MyLibrary", withExtension: "metallib") else {
        throw GeneratorError.metalLibraryNotFound
    }
    library = device.makeLibrary(URL: url)

A strong reference is kept by the calling object (along with the MTLDevice ), and it's a singleton so it remains in memory. 强引用由调用对象(以及MTLDeviceMTLDevice ,并且是单例,因此保留在内存中。 To obtain the kernel function itself I then call the following function, which returns an appropriate pipeline state: 为了获得内核函数本身,我然后调用以下函数,该函数返回适当的管道状态:

    guard let function = library.makeFunction(name: functionName) else {
        throw GeneratorError.functionNotFound(functionName)
    }
    return device.makeComputePipelineState(function: function)

Like I say, this works fine until SceneKit is added to the project - and simply adding the framework to the linked frameworks list is enough, I don't have to do anything with it - whereupon it simply can't find any of my functions. 就像我说的那样,在将SceneKit添加到项目中之前,此方法可以正常工作-只需将框架添加到链接的框架列表中就足够了,我无需对其进行任何操作-因此它根本找不到我的任何功能。

I have found out what was causing this issue, but I am still highly confused as to why, so I'd appreciate any further input people have! 我已经找到了造成此问题的原因,但是对于原因我仍然很困惑,因此,我感谢任何其他人提供的信息!

Essentially, I had split my Metal library up amongst several files to make it easier to work on. 实质上,我已经将我的Metal库拆分成几个文件,以使其更易于使用。 One had CIFilter-supported functions in, the other had Metal pipeline kernels. 其中一个具有CIFilter支持的功能,另一个具有Metal管道内核。 Now, I knew that the two were incompatible when both were linked in the main .metal file, so I'd commented one out temporarily but kept it for reference. 现在,我知道当两者都链接到主.metal文件中时,两者是不兼容的,因此我暂时将其中一个注释掉,但保留以供参考。 I also had the linker flag -cikernel in build settings. 在构建设置中,我还具有链接器标志-cikernel

I'd suspected that the linker flag might cause problems, but removing it made things worse. 我怀疑链接器标志可能会引起问题,但是删除它会使情况变得更糟。 Eventually I tried removing the linker flag AND the entire file that I had previously merely commented out. 最终,我尝试删除链接器标志以及之前仅被注释掉的整个文件。 This worked! 这工作了! I guess the compiler must compile ALL .metal files regardless of their inclusion in the main file, and somehow, having CIFilter kernels and texturing kernels in the same library is a big no-no, even though they were not in the same namespace. 我猜编译器必须编译所有.metal文件,而不管它们是否包含在主文件中,并且以某种方式在同一库中包含CIFilter内核和纹理化内核是很大的禁忌,即使它们不在同一命名空间中也是如此。

If anyone knows the reasoning behind this, I'd love to know! 如果有人知道其背后的原因,我很想知道! In the meantime I am simply going to remove all CIFilters and work with pure Metal-based compute pipelines instead. 同时,我只是要删除所有CIFilter,而是使用基于纯Metal的计算管道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM