SKView's texture(from) throwing a Metal validation error

I'm using `SpriteKit` to animate a complicated scene with 100 or so nodes on screen. I use `SKView`'s `.texture(from: node)` to copy the contents of nodes into SKTextures for various uses, and it mostly works great. But when the animation gets really active, I'll suddenly get a crash.


I can replicate the issue by repeatedly calling `.texture(from)` with a simple sprite node. Code below. Create a new Xcode project using the "Single View App" template, set the class of the `ViewController`'s `View` to `SKView` in the storyboard, and replace the contents of `ViewController.swift` with:


import SpriteKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let view = self.view as? SKView else { return }
        let node:SKNode = SKSpriteNode(color: UIColor.white, size: CGSize(width: 750, height: 750))
        for i in 0...50 {
            print(i)
            let _ = view.texture(from: node)
        }
    }
}


In the simulator this runs fine, counts to 50 and quits. But on the device (iPhone 7 Plus, iOS 11.0.1) it counts to 28 and throws:


validateRenderPassDescriptor:611: failed assertion `No rendertargets set in RenderPassDescriptor.'


Googling this error turns up nothing. I assume SpriteKit is using a Metal RenderPassDescriptor under the hood, but I don't know how to debug that.


Changing the size of the node affects the number of iterations before crashing, but even with very small nodes it eventually throws.


I would appreciate any ideas on why this is happening and how to fix it.

Replies

You might try running texture(from:) in a DispatchQueue (and setting a completion flag) and/or invoking the texture(from:) an ordained callback like update(). This is mentioned here,


"Use SpriteKit Objects Within the Ordained Callbacks" https://developer.apple.com/documentation/spritekit/skscenedelegate


and also,


https://developer.apple.com/library/content/technotes/tn2451/_index.html#//apple_ref/doc/uid/DTS40017609-CH1-ORDAINEDCALLBACKS


Hope that helps!

Metal API Validation is a Debug build only Run option. It can be disabled in the Xcode project's scheme:


Xcode toolbar Target selection > Edit Scheme... > Metal API Validation (it's down and to the right of GPU Frame Capture) > change `Enabled` to `Disabled`


However, this workaround might be ignoring a real issue either caused by an app code mistake, or an issue in the SpriteKit framework. If you want a chance at the real issue getting reviewed and potentially fixed, file a bug report and attach your project on the Apple Bug Reporter.


You may also try rokamo's suggestion regarding moving of code within the Scene's overriden -update callback (per the TN2451 document) - it's a good debugging suggestion.