【问题标题】:Swift include metal shader into library [Using swift package manager]Swift 将金属着色器包含到库中 [使用 swift 包管理器]
【发布时间】:2018-01-13 19:42:00
【问题描述】:

我一直在使用 Xcode 项目,但现在我正在启动一个我希望将来在其他平台上运行的项目,所以我正在使用 Swift Package Manager 来生成项目,但我遇到了一个问题,我的库需要包含一个金属着色器文件(也是一个 openGL 着色器文件),但我不知道如何做到这一点。

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

另外,如果您认为我做的事情完全错误,请指出我。

问候

【问题讨论】:

  • 我不确定我是否理解您的问题 - 我从未使用过 Swift 包管理器。 (1) 你的 Swift “库” 是框架目标吗? (2) 这些着色器是您需要访问的“文件”吗? (3) 你能把这些文件变成一个bundle,然后手动将它们包含在Xcode项目中吗?如果您对这三个问题的回答都是“是”,我相信我可以帮助您。
  • (1) Swift库是默认类型的(我觉得只能是动态的也可以是静态的,所以必须是dylib之类的。(2)我认为必须直接编译的metal文件进入metallib,你不需要直接在你的代码中引用它,只需将顶点函数和片段函数设置到金属初始化(MTLLibrary)中。(3)我不太确定如果我捆绑文件是否会保留重新创建 Xcode 项目(添加一些新的依赖项时我需要重新创建 Xcode 项目(或者至少我这样做)
  • 是的……总而言之,我对你正在做的事情表现出我的缺乏经验。我以为是不一样的。我有使用CIKernels 的项目(和我import 的框架)是GLSL 代码文件。当它是一个框架时,应用程序只需要import。听起来我对你没有帮助,对不起。
  • 你写的“我认为金属文件必须直接编译成metallib,你不需要在你的代码中直接引用它,只需将顶点函数和片段函数设置到金属初始化(MTLLibrary ”。那么哪个代码引用了它?是可执行文件中的代码必须执行金属初始化吗?
  • 它是一个库(游戏引擎),我想通过 SPM 分发它,因此着色器位于游戏引擎上。我刚刚发现金属着色器被编译为 metallib 文件,所以我最终创建了一个 bash 脚本,查看我的答案以获取更多信息,但我仍然对结果不满意,但现在我仍然可以处理项目而无需为此担心太多,以后肯定我会找到解决方案或其他人会提供更好的方法。

标签: swift metal swift-package-manager


【解决方案1】:

将您的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)

【讨论】:

  • 就是这样
【解决方案2】:

在 Xcode 12 中 (swift-tools-version:5.3) 可以通过 MTLDevice.makeDefaultLibrary(bundle:) 方法在 Swift 包中使用 .metal 文件。

Swift 包的结构应该类似于:

-Sources
    -MetalShaders
        -MetalShaders.metal
        -MetalShaders.swift
-Tests
    -MetalShadersTests
        -MetalShadersTests.swift

文件MetalShaders.metal 应包含Metal 源代码,文件MetalShaders.swift 应包含必要的设置代码。 MetalShaders.swift 的初始内容的一个示例如下:

// 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 ...
    // 

}

使用这种方法,然后可以从依赖于 Swift 包的 Xcode 项目中访问 packageMetalLibrary 变量,方法是从 swift 包中导入目标,方法与导入其他框架或包的方式相同。

import MetalShaders

可能可以在早期版本的 Xcode 中使用这种方法,因为方法 MTLDevice.makeDefaultLibrary(bundle:) 自 iOS 10 / macOS 10.12 起可用,但需要实现 Bundle.module 扩展,目前尚不清楚这是否会工作。

【讨论】:

    【解决方案3】:
    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 希望对您有所帮助。

    【讨论】:

    • 请简要说明你的答案
    • 不在此处编辑您的答案并添加必要的描述
    【解决方案4】:

    目前似乎无法做到这一点。当找到解决方法或 Apple 解决此问题时,我会更新此内容。

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

    编辑:我发现的一个临时解决方案是创建一个 bash script 编辑工作区设置以更改构建路径,然后将 metallib 文件编译/复制到可执行路径(没有尝试查看如何通过 SPM 或类似的方式分发库,现在仅适用于同一文件夹中的代码(即 Sources/MyEngine

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 2019-01-24
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 1970-01-01
      • 2020-01-01
      • 1970-01-01
      • 2014-12-05
      相关资源
      最近更新 更多