金属 API 视图没有渲染过程描述符
Metal API View has no Render Pass Descriptor
我目前正在尝试在 Xcode 中构建一个不使用 IB 的金属应用程序(纯粹以编程方式,没有故事板),并且我在使用 MTKView Delegate 进行渲染时遇到了一些问题。
我创建了以下 3 个 类
应用委托:
import Cocoa
import MetalKit
class AppDelegate: NSObject, NSApplicationDelegate
{
var newWindow: NSWindow?
var controller: ViewController?
func applicationDidFinishLaunching(_ notification: Notification) {
newWindow = NSWindow(contentRect: NSMakeRect(10, 10, 300, 300), styleMask: [.miniaturizable, .closable, .resizable, .titled], backing: .buffered, defer: false)
controller = ViewController()
let content = newWindow!.contentView! as NSView
let view = controller!.view
content.addSubview(view)
newWindow!.makeKeyAndOrderFront(nil)
}
}
视图控制器:
import Cocoa
import MetalKit
class ViewController: NSViewController {
var renderer: Renderer?
override func loadView() {
view = MTKView.init()
}
override func viewDidLoad() {
guard let metalView = view as? MTKView else {
fatalError("Cant Get Metal View")
}
super.viewDidLoad()
renderer = Renderer(metalView: metalView)
}
}
Renderer.swift:
import MetalKit
class Renderer: NSObject {
static var device: MTLDevice!
static var commandQueue: MTLCommandQueue!
var mesh: MTKMesh!
var vertexBuffer: MTLBuffer!
var pipelineState: MTLRenderPipelineState!
init(metalView: MTKView) {
guard
let device = MTLCreateSystemDefaultDevice(),
let commandQueue = device.makeCommandQueue() else {
fatalError("GPU not available")
}
Renderer.device = device
Renderer.commandQueue = commandQueue
metalView.device = device
let mdlMesh = Primative.makeCube(device: device, size: 1)
do {
mesh = try MTKMesh(mesh: mdlMesh, device: device)
} catch let error {
print(error.localizedDescription)
}
vertexBuffer = mesh.vertexBuffers[0].buffer
let library = device.makeDefaultLibrary()
let vertexFunction = library?.makeFunction(name: "vertex_main")
let fragmentFunction = library?.makeFunction(name: "fragment_main")
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.vertexFunction = vertexFunction
pipelineDescriptor.fragmentFunction = fragmentFunction
pipelineDescriptor.vertexDescriptor =
MTKMetalVertexDescriptorFromModelIO(mdlMesh.vertexDescriptor)
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
do {
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
} catch let error {
fatalError(error.localizedDescription)
}
super.init()
metalView.clearColor = MTLClearColor(red: 1.0, green: 1.0,
blue: 0.8, alpha: 1.0)
metalView.delegate = self
}
}
extension Renderer: MTKViewDelegate {
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
// Creating Render Pass Descriptor
if let descriptor = view.currentRenderPassDescriptor
{
print("Drawing")
}
else {
print("Not Drawing")
}
}
}
这三个 类 渲染 Window 很好,
的输出
Not Drawing
表明这个值总是空的,但它每一帧都在做一些事情。
我尝试过的东西
- 创建我自己的渲染过程描述符:这导致了 sig 错误。
- 查看了view,肯定是认了一个MTKView
我知道如果我使用基于文件中的情节提要的项目,这是可行的,但我希望了解如何在没有它的情况下完成它。
任何帮助将不胜感激
来自 MTKView.currentRenderPassDescriptor
的文档:
This property is nil
if the view’s device
property isn’t set or if
currentDrawable
is nil
.
您需要给 MTKView
一个金属设备才能使用。 IB 可能默认给它 MTLCreateSystemDefaultDevice()
,但是当您以编程方式创建视图时,您需要手动执行:
override func loadView() {
view = MTKView(frame: .zero, device: MTLCreateSystemDefaultDevice())
}
视图的宽度和高度为0
。在将视图添加到 applicationDidFinishLaunching
中的 window 之前设置框架大小。
controller = ViewController()
let content = newWindow!.contentView! as NSView
let view = controller!.view
view.frame = content.bounds
content.addSubview(view)
我目前正在尝试在 Xcode 中构建一个不使用 IB 的金属应用程序(纯粹以编程方式,没有故事板),并且我在使用 MTKView Delegate 进行渲染时遇到了一些问题。
我创建了以下 3 个 类
应用委托:
import Cocoa
import MetalKit
class AppDelegate: NSObject, NSApplicationDelegate
{
var newWindow: NSWindow?
var controller: ViewController?
func applicationDidFinishLaunching(_ notification: Notification) {
newWindow = NSWindow(contentRect: NSMakeRect(10, 10, 300, 300), styleMask: [.miniaturizable, .closable, .resizable, .titled], backing: .buffered, defer: false)
controller = ViewController()
let content = newWindow!.contentView! as NSView
let view = controller!.view
content.addSubview(view)
newWindow!.makeKeyAndOrderFront(nil)
}
}
视图控制器:
import Cocoa
import MetalKit
class ViewController: NSViewController {
var renderer: Renderer?
override func loadView() {
view = MTKView.init()
}
override func viewDidLoad() {
guard let metalView = view as? MTKView else {
fatalError("Cant Get Metal View")
}
super.viewDidLoad()
renderer = Renderer(metalView: metalView)
}
}
Renderer.swift:
import MetalKit
class Renderer: NSObject {
static var device: MTLDevice!
static var commandQueue: MTLCommandQueue!
var mesh: MTKMesh!
var vertexBuffer: MTLBuffer!
var pipelineState: MTLRenderPipelineState!
init(metalView: MTKView) {
guard
let device = MTLCreateSystemDefaultDevice(),
let commandQueue = device.makeCommandQueue() else {
fatalError("GPU not available")
}
Renderer.device = device
Renderer.commandQueue = commandQueue
metalView.device = device
let mdlMesh = Primative.makeCube(device: device, size: 1)
do {
mesh = try MTKMesh(mesh: mdlMesh, device: device)
} catch let error {
print(error.localizedDescription)
}
vertexBuffer = mesh.vertexBuffers[0].buffer
let library = device.makeDefaultLibrary()
let vertexFunction = library?.makeFunction(name: "vertex_main")
let fragmentFunction = library?.makeFunction(name: "fragment_main")
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.vertexFunction = vertexFunction
pipelineDescriptor.fragmentFunction = fragmentFunction
pipelineDescriptor.vertexDescriptor =
MTKMetalVertexDescriptorFromModelIO(mdlMesh.vertexDescriptor)
pipelineDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat
do {
pipelineState = try device.makeRenderPipelineState(descriptor: pipelineDescriptor)
} catch let error {
fatalError(error.localizedDescription)
}
super.init()
metalView.clearColor = MTLClearColor(red: 1.0, green: 1.0,
blue: 0.8, alpha: 1.0)
metalView.delegate = self
}
}
extension Renderer: MTKViewDelegate {
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
// Creating Render Pass Descriptor
if let descriptor = view.currentRenderPassDescriptor
{
print("Drawing")
}
else {
print("Not Drawing")
}
}
}
这三个 类 渲染 Window 很好,
的输出Not Drawing
表明这个值总是空的,但它每一帧都在做一些事情。
我尝试过的东西
- 创建我自己的渲染过程描述符:这导致了 sig 错误。
- 查看了view,肯定是认了一个MTKView
我知道如果我使用基于文件中的情节提要的项目,这是可行的,但我希望了解如何在没有它的情况下完成它。
任何帮助将不胜感激
来自 MTKView.currentRenderPassDescriptor
的文档:
This property is
nil
if the view’sdevice
property isn’t set or ifcurrentDrawable
isnil
.
您需要给 MTKView
一个金属设备才能使用。 IB 可能默认给它 MTLCreateSystemDefaultDevice()
,但是当您以编程方式创建视图时,您需要手动执行:
override func loadView() {
view = MTKView(frame: .zero, device: MTLCreateSystemDefaultDevice())
}
视图的宽度和高度为0
。在将视图添加到 applicationDidFinishLaunching
中的 window 之前设置框架大小。
controller = ViewController()
let content = newWindow!.contentView! as NSView
let view = controller!.view
view.frame = content.bounds
content.addSubview(view)