未找到 iOS Metal 默认库
Posted
技术标签:
【中文标题】未找到 iOS Metal 默认库【英文标题】:iOS Metal default library not found 【发布时间】:2016-07-12 06:57:24 【问题描述】:我尝试在一个简单的应用程序中使用 ios Metal,但是当我调用 device.newDefaultLibrary() 函数时,我在运行时遇到错误:
/BuildRoot/Library/Caches/com.apple.xbs/Sources/Metal/Metal-56.7/Framework/MTLLibrary.mm:1842: 断言“未找到金属默认库”失败
有人知道问题出在什么云上吗?我遵循了本教程:https://www.raywenderlich.com/77488/ios-8-metal-tutorial-swift-getting-started 代码有点旧,但只需稍作改动即可工作。这是我的 viewController 代码:
import UIKit
import Metal
import QuartzCore
class ViewController: UIViewController
//11A
var device: MTLDevice! = nil
//11B
var metalLayer: CAMetalLayer! = nil
//11C
let vertexData:[Float] = [
0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0]
var vertexBuffer: MTLBuffer! = nil
//11F
var pipelineState: MTLRenderPipelineState! = nil
//11G
var commandQueue: MTLCommandQueue! = nil
//12A
var timer: CADisplayLink! = nil
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//11A
device = MTLCreateSystemDefaultDevice()
//11B
metalLayer = CAMetalLayer() // 1
metalLayer.device = device // 2
metalLayer.pixelFormat = .BGRA8Unorm // 3
metalLayer.framebufferOnly = true // 4
metalLayer.frame = view.layer.frame // 5
view.layer.addSublayer(metalLayer) // 6
//11C
let dataSize = vertexData.count * sizeofValue(vertexData[0]) // 1
vertexBuffer = device.newBufferWithBytes(vertexData, length: dataSize, options: MTLResourceOptions.CPUCacheModeDefaultCache) // 2
//11F
// 1
let defaultLibrary = device.newDefaultLibrary() //The error is generating here
let fragmentProgram = defaultLibrary!.newFunctionWithName("basic_fragment")
let vertexProgram = defaultLibrary!.newFunctionWithName("basic_vertex")
// 2
let pipelineStateDescriptor = MTLRenderPipelineDescriptor()
pipelineStateDescriptor.vertexFunction = vertexProgram
pipelineStateDescriptor.fragmentFunction = fragmentProgram
pipelineStateDescriptor.colorAttachments[0].pixelFormat = .BGRA8Unorm
// 3
do
try pipelineState = device.newRenderPipelineStateWithDescriptor(pipelineStateDescriptor)
catch _
print("Failed to create pipeline state, error")
//11G
commandQueue = device.newCommandQueue()
//12A
timer = CADisplayLink(target: self, selector: Selector("gameloop"))
timer.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
//MARK: Custom Methodes
//12A
func render()
//12C
let commandBuffer = commandQueue.commandBuffer()
//12B
let drawable = metalLayer.nextDrawable()
let renderPassDescriptor = MTLRenderPassDescriptor()
renderPassDescriptor.colorAttachments[0].texture = drawable!.texture
renderPassDescriptor.colorAttachments[0].loadAction = .Clear
renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColor(red: 0.0, green: 104.0/255.0, blue: 5.0/255.0, alpha: 1.0)
//12D
let renderEncoderOpt = commandBuffer.renderCommandEncoderWithDescriptor(renderPassDescriptor)
renderEncoderOpt.setRenderPipelineState(pipelineState)
renderEncoderOpt.setVertexBuffer(vertexBuffer, offset: 0, atIndex: 0)
renderEncoderOpt.drawPrimitives(.Triangle, vertexStart: 0, vertexCount: 3, instanceCount: 1)
renderEncoderOpt.endEncoding()
//12E
commandBuffer.presentDrawable(drawable!)
commandBuffer.commit()
func gameloop()
autoreleasepool
self.render()
我使用装有 iOS 9.3 的 iPhone 5s 设备进行测试。
【问题讨论】:
您需要为库创建自己的文件路径,尤其是当您在游乐场尝试时。看看my tutorial 了解如何解决这个问题。 @Marius,不确定这与这里是否相关,因为 OP 表示他正在设备上运行。在我看来,着色器文件根本没有被编译到应用程序包中。 @warrenm 你是对的,我错过了问题末尾的那个细节。 【参考方案1】:只有在您的应用目标的编译源构建阶段至少有一个.metal
文件时,默认库才会包含在您的应用中。我假设您已经按照教程的步骤创建了 Metal 着色器源文件并添加了顶点和片段函数,因此您只需在构建阶段设置中使用 +
图标将该文件添加到您的编译中阶段:
【讨论】:
奇怪,我有一个框架,其中添加了 .metal 文件。然后我将此框架添加到我的目标中,我得到了崩溃。修复崩溃的唯一方法是将 .metal 文件添加到我的目标。但是,当我的框架中有这些文件时,我为什么要这样做呢? 我相信当您调用newDefaultLibrary
时,Metal 只会在应用程序的主包中查找 default.metallib
。您可能需要获取对框架包的引用,然后改用newDefaultLibraryWithBundle:...
API。如果您仍然有困难,请考虑提出一个新问题。以上是关于未找到 iOS Metal 默认库的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 上的 Metal 中未触发 addPresentedHandler