SceneKit app seriously hangs when run in fullscreen

I've been running my SceneKit game for many weeks in Xcode without performance issues. The game itself is finished, so I thought I could go on with publishing it on the App Store, but when archiving it in Xcode and running the archived app, I noticed that it seriously hangs.

The hangs only seem to happen when I run the game in fullscreen mode. I tried disabling game mode, but the hangs still happen. Only when I run in windowed mode the game runs smoothly.

Instruments confirms that there are many serious hangs, but it also reports that CPU usage is quite low during those hangs, on average about 15%. From what I know, hangs happen when the main thread is busy, but how can that be when CPU usage is so low, and why does it only happen in fullscreen mode for release builds?

I was able to recreate the issue with a small sample project that repeatedly calls SCNView.projectPoint(_:) in a block dispatched to the main actor inside the SCNSceneRendererDelegate.renderer(_:didApplyAnimationsAtTime) method.

In my personal project, the issue happens when calling that method 6 times (in order to position 6 sprites in the overlay SpriteKit scene that should follow objects in the SceneKit scene), but in the sample I call it 200 times to reliably reproduce the issue.

As mentioned previously, the hangs only happen when running the app in fullscreen, but I noticed that when moving the mouse to the top of the screen to show the menu bar, the game runs smoothly. As soon as the menu bar disappears again, or if I click a main menu item to show the submenu, the game immediately hangs again and shows maybe 2 or even less frames per second. Sometimes the hangs continue happening unless I show the menu bar again, but sometimes the game begins running smoothly again after a couple seconds.

This is again confirmed by Instruments.

Interestingly, if I comment out the line

Task { @MainActor in

and the corresponding closing curly bracket 4 lines down, there is no hang anymore, not in fullscreen, and not when clicking the main menu:

Is this an issue with SCNView.projectPoint(_:)? Or with the delegate method? Or with doing SceneKit things on the main thread? I thought that we're supposed to add nodes and do modifications on the main thread, so how could I avoid thread races if in this delegate method the only solution is not to use the main thread?

class GameViewController: NSViewController, SCNSceneRendererDelegate {
    
    var scnView: SCNView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let scene = SCNScene(named: "art.scnassets/ship.scn")!
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
        ship.runAction(.customAction(duration: 999, action: { node, t in
            Task { @MainActor in
                node.eulerAngles.y = t
            }
        }))
        let scnView = self.view as! SCNView
        self.scnView = scnView
        scnView.scene = scene
        scnView.delegate = self
    }
    
    func renderer(_ renderer: any SCNSceneRenderer, didApplyAnimationsAtTime time: TimeInterval) {
        Task { @MainActor in
            for _ in 0..<200 {
                let _ = scnView?.projectPoint(SCNVector3(x: 0, y: 0, z: 0))
            }
        }
    }
}

Note: occasionally the hang doesn't happen while debugging the app in Xcode, but until now it always happened when profiling the app in Instruments.

SceneKit app seriously hangs when run in fullscreen
 
 
Q