love icon indicating copy to clipboard operation
love copied to clipboard

Unlocked vsync when in a different space on macOS

Open vaner-org opened this issue 4 years ago • 6 comments

There's a strange one here.

When a love2d window is in a different space on macOS, so on another desktop, or if you have it running on your desktop and switch to a full screened app, CPU and GPU load are doubled (or tripled). This is could be up to 30-40% CPU from under 6% otherwise, on a quad core machine and 100% GPU up from 30% on a discrete AMD card: all with no game loaded.

The CPU issue was also replicated on any game I tested, where if a game is in the same space (with or without focus) CPU usage on my machine is always under 10%, but on a different space (without focus, obviously), it climbs up to 40 or 50%, every time. The GPU doubling issue is present on every game run with hiDPI.

This was tested on a 2015 and 2019 MBP with discrete graphics, on Mojave and Catalina both.

To test: Open Activity Monitor, select Window > CPU History and GPU History. Then open any love2d game with hiDPI or just the no game app. See the the normal load on the monitors. Then open Mission Control, create a new desktop, and drag the love2d window into Desktop 2. Now come back to Desktop 1, and see the change in load.

vaner-org avatar Oct 14 '20 21:10 vaner-org

From what I remember, the OS doesn't enforce vsync in opengl windows that aren't in focus.

slime73 avatar Oct 14 '20 21:10 slime73

From what I remember, the OS doesn't enforce vsync in opengl windows that aren't in focus.

That's crazy that that's default behaviour. Is there any way around this?

vaner-org avatar Oct 14 '20 21:10 vaner-org

Is there any way around this?

As a developer you can't rely on a specific vsync rate regardless (because graphics drivers tend to give users the option to force vsync on or off, and because monitors use all sorts of different refresh rates - I have a 60hz and a 120hz monitor connected to my PC).

A typical approach to lowering CPU/GPU load while a game isn't in focus is to use love.timer.sleep to pause for a few ms every frame while the window isn't in focus or isn't visible.

macOS also provides apps some extra information about window visibility (whether it's completely covered by other windows or not), but love doesn't expose that at the moment unfortunately.

slime73 avatar Oct 15 '20 20:10 slime73

A typical approach to lowering CPU/GPU load while a game isn't in focus is to use love.timer.sleep to pause for a few ms every frame while the window isn't in focus or isn't visible.

I've been looking in the love forums and every one has their own way of handling this, which I've had some trouble implementing and seeing consistent results. Is there any optimal way you recommend? Does does the sleep function need to be handled within love.update or can love.run be modified instead?

macOS also provides apps some extra information about window visibility (whether it's completely covered by other windows or not), but love doesn't expose that at the moment unfortunately.

What's odd here is that it's specifically being on another space that uncaps vysync. When I'm on on the desktop but unfocused, it's all normal. Also, somehow demo-ing my game on Zoom screen sharing makes it go crazy, 100-200% CPU usage and max GPU always, even love is in focus, on the desktop or full-screened.

vaner-org avatar Oct 23 '20 13:10 vaner-org

I have since arrived at a solution with this code, a 30fps cap when unfocused.

function love.focus(f)
    focus = f
end

function love.update(dt)
    if not focus then love.timer.sleep(0.03) end
end

As a developer you can't rely on a specific vsync rate regardless

I think it would be helpful for love.window.setVsync to accept enums instead of -1, 0, 1 and accept numbers to force a specific frame rate, but since the sleep function is more than good enough to solve this, feel free to close. I still feel this should be prevented though, since anyone that doesn't implement this runs the risk of making their games impossible to leave running in the background.

I remember writing to a developer once about their love game's performance spikes many years ago, and they had no idea why this was happening since they didn't own a Mac machine.

vaner-org avatar May 23 '21 20:05 vaner-org

The latest version of SDL seems to address this for OpenGL by using a different method for vsync. But love 12's metal backend doesn't have access to that method right now so it's still an issue there.

I wonder if I can design something in SDL to expose what we'd need to take advantage of it with Metal.

slime73 avatar Jan 15 '23 17:01 slime73