Sprite Kit in full screen on OSX slows to a crawl

I was really hoping to use SpriteKit in my app but am finding that the FPS drops from near 60 to 30 or less when the NSWindow that contains the scene is sized to fit more than around 50% of the screen on my MacBook Pro 17" under El Capitan 10.11.4 (yes I know it's old hardware but this is a problem specific to full screen mode and users could reasonably be expected to have similar aged machines - I could do the dev work on a MacPro but if that's turns out to be the only solution then it would be too restrictive).


I've set up a scene in my own app with just one sprite that revolves constantly but to be absolutely sure it's nothing I'm doing, I tried to make the window fullscreen in the template app that Xcode generates when you choose a SpriteKit project (using Swift). There a StackOverflow positing here that indicates an incredibly similar problem.


I can't believe people are expected to use graphics in small windows on their machines so others mustn't be finding the same issue. Is there a parameter/flag that I need to set in order to maintain FPS when the window is large?


Thanks in advance!

Replies

Hi todd_d, this issue sounds bug-worthy. Would you file a report using Apple Bug Reporter and post-back the resulting Bug ID #? I'd like to run this by the Sprite Kit engineering team (though it might end up in the AppKit area, areas of fullscreen being maintained by them). It would also be helpful to include two zipped Time Profiler traces that compare both cases; this could easily reveal code path differences that imply a culprit; they could also narrow down ideas for workarounds (e.g. what's the slow thing we could potentailly substitute or avoid using in the time-being)

This problem still exists today in the latest version of macOS Catalina. I've spent the past week trying to find a reason why my iOS app that I'm porting to macOS has all these issues when I run it full-screen on my brand new Macbooks Air 2020 (core i7, 16GB).


The app runs fine until I set it to full-screen. I note that my app is a SceneKit app, with a SpriteKit overlaySKScene. The SceneKit assets all seem to perform fine, but the SpriteKit assets spasmodically draw with the wrong textures, and this only happens when the app is utilising full-screen.


I've employed some of the tecniques in the link provided above (I'd found it independantly), notably:


self.view.window!.styleMask = NSBorderlessWindowMask
self.view.window!.level = Int(CGWindowLevelForKey(Int32(kCGMainMenuWindowLevelKey))) + 1
self.view.window!.opaque = true
self.view.window!.hidesOnDeactivate = true
let size = NSScreen.mainScreen()!.frame.size
NSMenu.setMenuBarVisible(false)
self.view.window!.setFrame(CGRect(x: 0, y: 0, width: size.width, height: size.height+1), display:true)


This certainly makes a big difference, the glitching of textures stops 99.9% of the time, however I'm left with about 20 unused pixels at the bottom of the screen.


Given this question was asked in 2016, and the linked SO post suggests the issue was corrected in 2016, I'm wondering why I'm still seeing it in 2020. I note that the same problem occurs on my older Macbook Pro (2013, core i5, 2.3GHz) running Mojave.


I don't accept that it's just that the hardware isn't up to it. If the app can run smoothly in the iOS simulator, which adds an extra layer of OS level code to the app, then it should be able to run natively on the machine, no matter the window size.


I note that in the solution above, if I comment out the line:


NSMenu.setMenuBarVisible(false)


then the problem resurfaces. There is some odd optimisation being done by macOS around (near) full screen apps and the way they use the menu bar screen real-estate that cripples SpriteKit apps (and possibly others).


Games on Apple Arcade seem to run OK, so there must be a way for this all to work. It would be nice not to hack up a workaround though.


Here are some screenshots showing the issue.


First, with the above solution and the menu bar set to not-visible, all runs beautifully, but I can't get the window to position itself so that it actually covers the entire screen. You can still see Xcode running behind it:



Next, the image below shows what I get by commenting out the line so that even though the menu bar isn't in fact visible, it's causing a serious drop in the frame rate, and then as the final image shows, when ever I actually do something in the app that triggers some SpriteKit animations, the SKSpriteNodes within the SpriteKit overlay are drawn for a few frames using the wrong textures: