Swift包含金属着色器到库中[使用swift包管理器]

时间:2018-01-13 19:42:00

标签: swift metal swift-package-manager

我一直在使用Xcode项目,但现在我开始在其他平台上运行我想要的项目,所以我使用Swift Package Manager来生成项目,但是我面临一个问题,我的库需要包含一个金属着色器文件(也是一个openGL着色器文件),但我对如何实现这一点毫无头绪。

我的项目有2个部分,包含图形内容的库和可执行文件是我的实际应用程序,所以我想将我的图形库导入到我的应用程序中,但问题是金属着色器文件不包含在Xcode项目似乎也没有编译/包含在库的捆绑文件中,因此我可以在运行时加载并在需要时使用它。

另外,如果你认为我做错了事,请指点我。

此致

4 个答案:

答案 0 :(得分:3)

将您的 Shaders.metal 文件放入 Metal 目录。然后在 Package.swift

中向目标添加资源
.target(
   name: "TargetName",
   dependencies: [
     .product(name: "AnotherModule", package: "AnotherPackage")
   ],
   resources: [
     .copy("Metal/")
   ]
)

现在您可以访问您的图书馆了:

let url = Bundle.module.url(forResource: "Shaders", withExtension: "metal", subdirectory: "Metal")!
let source = try String(contentsOf: url)
let library = try device.makeLibrary(source: source, options: nil)

甚至更好(但仅适用于单个着色器文件):

.target(
   name: "TargetName",
   dependencies: [
     .product(name: "AnotherModule", package: "AnotherPackage")
   ],
   resources: [
     .process("Metal/Shaders.metal")
   ]
)

现在您可以访问您的图书馆了:

let library = try device.makeDefaultLibrary(bundle: Bundle.module)

答案 1 :(得分:2)

在Xcode 12 (swift-tools-version:5.3)中,可以使用h["monday"]["morning"].append("Ben") 方法在Swift软件包中使用.metal文件。

Swift软件包的结构应类似于:

h["monday"]["morning"] = []
h["monday"]["morning"].append("Ben")

文件MTLDevice.makeDefaultLibrary(bundle:)应该包含Metal源代码,文件-Sources -MetalShaders -MetalShaders.metal -MetalShaders.swift -Tests -MetalShadersTests -MetalShadersTests.swift 应该包含必要的设置代码。 MetalShaders.metal初始内容的一个示例如下:

MetalShaders.swift

使用这种方法,可以通过从swift包中导入目标,就像导入其他框架或包一样,从依赖于Swift包的Xcode项目中访问MetalShaders.swift变量。 / p>

// A metal device for access to the GPU.
public var metalDevice: MTLDevice!

// A metal library.
public var packageMetalLibrary: MTLLibrary!

// Function to perform the initial setup for Metal processing on the GPU
public func setupMetal() {
    // Create metal device for the default GPU:
    metalDevice = MTLCreateSystemDefaultDevice()
    
    // Create the library of metal functions
    // Note: Need to use makeDefaultLibrary(bundle:) as the "normal"
    //       call makeDefaultLibrary() returns nil.
    packageMetalLibrary = try? metalDevice.makeDefaultLibrary(bundle: Bundle.module)

    // List the available Metal shader functions
    print(packageMetalLibrary.functionNames)

    //
    // ... add additional setup code here ...
    // 

}

由于从iOS 10 / macOS 10.12开始可以使用方法packageMetalLibrary,因此可以在早期版本的Xcode上使用此方法,但是需要实现import MetalShaders 扩展名,但并非必须如此。清除是否可行。

答案 2 :(得分:1)

let source = """

    #include <metal_stdlib>
    using namespace metal;

    struct Vertex {...
"""
let library = try device.makeLibrary(source: source options: nil)
print(library.functionNames)

Metal的类允许在运行时从String构建着色器库。 https://developer.apple.com/documentation/metal/libraries 希望能有所帮助。

答案 3 :(得分:0)

似乎现在无法做到这一点。当找到解决方法或Apple修复此问题时,我会更新此信息。

https://bugs.swift.org/browse/SR-2866

编辑:我找到的临时解决方案是创建bash script,编辑工作区设置以更改构建路径,然后将metallib文件编译/复制到可执行路径(didn还没试过看看如何通过SPM或类似的方式分发库,现在只能使用同一文件夹中的代码(即Sources / MyEngine&lt; - (此文件夹有金属着色器),Sources / MyGame )。