我正在使用Metal编写iOS应用。在MTKViewDelegate绘制过程中的某个时候,我创建了一个渲染过程描述符并在屏幕上渲染了东西,

let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
encoder.setViewport(camera.viewport)
encoder.setScissorRect(camera.scissorRect)


在我的绘图功能开始时,我有一个信号量,即在Xcode中的Metal游戏模板中找到的相同代码,然后进行检查以确认视图的大小没有改变。如果有,我将重新创建缓冲区,

    let w = _gBuffer?.width ?? 0
    let h = _gBuffer?.height ?? 0
    if let metalLayer = view.layer as? CAMetalLayer {
        let size = metalLayer.drawableSize
        if w != Int(size.width) || h != Int(size.height ){
            _gBuffer = GBuffer(device: device, size: size)
        }
    }


一切正常,并且在我的iPhone6上旋转正常。但是,当我尝试使用iPad Pro时,当我尝试旋转设备时,它始终会生成SIGABRT。调试器告诉我编码器为空。我也在控制台中得到了这个异常,

MTLDebugRenderCommandEncoder.mm:2028: failed assertion `(rect.x(1024) + rect.width(1024))(2048) must be <= 1536'


因为我要更新mtkView中的“相机”,所以必须发生例外,

func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
    camera.setBounds(view.bounds)
}


当我在未连接调试器的情况下运行时,它不会崩溃。
我猜mtkView是异步调用的,在调用mtkView时我应该做一些事情来停止渲染,但是互斥锁应该在库中,而不是在我的代码中?尽管从同一个线程(调试器中的线程1)调用了draw和mtkView……如果我逐步调试在draw和mtkView中放置断点,似乎我是手动同步的,并且不会崩溃。我有点迷路了...

完整的源代码在这里:https://github.com/endavid/VidEngine

有任何想法吗?

最佳答案

异常消息是提示。我为编码器为空而分心。我猜一旦引发异常,它就会变为null,但是问题不在编码器中。

camera.setBounds(view.bounds)中的代码未更新scissorRect ...
我有一个CADisplayLink,它以不同的速率更新CPU对象,当它检测到更改时,scissorRect就会在那里更新。

我在mtkView()中添加了对完整相机更新的调用,崩溃现在已经消失了:)

10-08 06:25