您好我正在尝试开始在iOS上学习一些与swift相结合的金属。目前我只是想让应用程序使用CAMetalLayer而不是普通的CALayer打开自定义UIView。我在以下行收到BAD_ACCESS错误:self.metalLayer.device = self.device
以下代码是UIView的子类,它是从故事板而不是普通的UIView加载的。我正在遵循以下示例,它是在Objective-C中,我试图在swift中实现相同的目标。现在有点亏本。有什么想法吗?
import UIKit
import Metal
class MBEMetalView: UIView {
var device: MTLDevice
var metalLayer: CAMetalLayer {
return CAMetalLayer(layer: self.layer)
}
override class func layerClass() -> AnyClass {
return CAMetalLayer.self
}
required init?(coder aDecoder: NSCoder) {
self.device = MTLCreateSystemDefaultDevice()!
super.init(coder: aDecoder)
self.metalLayer.device = self.device
self.metalLayer.pixelFormat = MTLPixelFormat.BGRA8Unorm
}
override func didMoveToWindow() {
self.redraw()
}
func redraw() {
var drawable: CAMetalDrawable? = self.metalLayer.nextDrawable()
var texture: MTLTexture? = drawable?.texture
var passDescriptor: MTLRenderPassDescriptor = MTLRenderPassDescriptor.self()
passDescriptor.colorAttachments[0].texture = texture
passDescriptor.colorAttachments[0].loadAction = MTLLoadAction.Clear
passDescriptor.colorAttachments[0].storeAction = MTLStoreAction.Store
passDescriptor.colorAttachments[0].clearColor = MTLClearColor.init(red: 1, green: 0, blue: 0, alpha: 1)
var commandQueue: MTLCommandQueue = self.device.newCommandQueue()
var commandBuffer: MTLCommandBuffer = commandQueue.commandBuffer()
var commandEncoder: MTLCommandEncoder = commandBuffer.renderCommandEncoderWithDescriptor(passDescriptor)
commandEncoder.endEncoding()
commandBuffer.presentDrawable(drawable!)
commandBuffer.commit()
}
}
@alex_p告诉我,我每次调用metalLayer的readonly可计算函数都给了我一个新的CAMetalLayer,所以我改变了我的代码,但现在我得到了以下SIGABRT错误
以下行/BuildRoot/Library/Caches/com.apple.xbs/Sources/Metal/Metal-55.1.1/ToolsLayers/Debug/MTLDebugDevice.mm:629: failed assertion "iosurface must not be nil."
:var drawable: CAMetalDrawable? = self.metalLayer.nextDrawable()
我目前的代码是:
import UIKit
import Metal
class MBEMetalView: UIView {
var device: MTLDevice? = MTLCreateSystemDefaultDevice()
var metalLayer: CAMetalLayer = CAMetalLayer()
var commandQueue: MTLCommandQueue! = nil
override class func layerClass() -> AnyClass {
return CAMetalLayer.self
}
required init?(coder aDecoder: NSCoder) {
self.commandQueue = self.device!.newCommandQueue()
super.init(coder: aDecoder)
self.metalLayer.device = self.device
self.metalLayer.pixelFormat = MTLPixelFormat.BGRA8Unorm
}
override func didMoveToWindow() {
self.redraw()
}
func redraw() {
var drawable: CAMetalDrawable? = self.metalLayer.nextDrawable()
let texture: MTLTexture? = drawable!.texture
let passDescriptor: MTLRenderPassDescriptor = MTLRenderPassDescriptor.self()
passDescriptor.colorAttachments[0].texture = texture
passDescriptor.colorAttachments[0].loadAction = MTLLoadAction.Clear
passDescriptor.colorAttachments[0].storeAction = MTLStoreAction.Store
passDescriptor.colorAttachments[0].clearColor = MTLClearColor.init(red: 1, green: 0, blue: 0, alpha: 1)
let commandBuffer: MTLCommandBuffer = commandQueue.commandBuffer()
let commandEncoder: MTLCommandEncoder = commandBuffer.renderCommandEncoderWithDescriptor(passDescriptor)
commandEncoder.endEncoding()
commandBuffer.presentDrawable(drawable!)
commandBuffer.commit()
}
}