Metal file as part of an iOS framework

前端 未结 3 2001
终归单人心
终归单人心 2021-02-05 19:08

I am trying to create a framework that works with METAL Api (iOS). I am pretty new to this platform and I would like to know how to build the framework to work with .metal files

3条回答
  •  说谎
    说谎 (楼主)
    2021-02-05 19:30

    As someone looking to include metal shader functions in a SceneKit / ARKit related framework, the available answers led me in the wrong direction. There is a much simpler solution that uses makeDefaultLibrary(bundle: Bundle) (iOS 10+) to access the functions included in a framework's .metal dependencies. Adding here for people in a similar position.

    TL;DR, Access a Framework's MTLLibrary like this:

            //Get the framework bundle by using `Bundle(for: type(of: self))` from inside any framework class.
            //Then use the bundle to define an MTLLibrary.
            let frameworkBundle = Bundle(for: type(of: self))
            let device = MTLCreateSystemDefaultDevice()
            do {
                let bundleLib = try device?.makeDefaultLibrary(bundle: frameworkBundle)
                print(bundleLib.functionNames) //we can access our framework's metal functions! No build tricks/workarounds.
            } catch {
                print("Couldn't locate default library for bundle: \(frameworkBundle)")
                print( error )
            }
    

    Xcode creates a default library of shader functions at build time by compiling .metal dependencies. This is true of both framework targets and app targets, so the real question is, how do I access my framework’s default library?

    It’s possible to access a framework’s default library using the using the makeDefaultLibrary(bundle: Bundle) method on MTLDevice. The sample code above shows more detail.

    For Scenekit/ARKit with SCNProgram

    The bundle library can be set as an SCNProgram’s library property, and then fragment and shader functions can be defined just as if the .metal file was included in the main project:

            //The SCNProgram that will use our framework's metal functions
            var program = SCNProgram()
    
            //Use the framework's bundle to define an MTLLibrary.
            let frameworkBundle = Bundle(for: type(of: self))
            let device = MTLCreateSystemDefaultDevice()
            do {
                let bundleLib = try device?.makeDefaultLibrary(bundle: frameworkBundle)
    
                //set the SCNProgram's library, and define functions as usual
                program.library = bundleLib
                program.fragmentFunctionName = "yourCustomFrameworkFragmentFunction"
                program.vertexFunctionName = "yourCustomFrameworkVertexFunction"
            } catch {
                print("Couldn't locate default library for bundle: \(frameworkBundle)")
                print( error )
            }
    

提交回复
热议问题