2

When I run Portal on my MBP with no external screen connected I get a solid 60 fps. When I connect and mirror another screen (same resolution and game settings) it drops to 30 fps, sometimes 20, and has a very noticeable impact on game experience.

It's the same regardless of which video output port I use. Graphics power saving is disabled.

I have tried to find confirmation that screen mirroring negatively affects performance, but I've only stumbled upon assertions that it doesn't and shouldn't. But I've tested this many times and it's very reproducible.

  • How is mirroring implemented / why does it affect performance this much?
  • Is the only way to get decent game performance to buy an external keyboard and close the lid / tape a magnet to the screen / use terminal hack?

MBP 15" mid 2014

Update on V-sync

As Phong correctly suspected, it's related to vsync. Without it I get some ridiculous 150+ fps and good responsiveness, although I'm reluctant to turn it off because of the tearing.

It's still a bit of a mystery how screen mirroring is interacting with and affecting vsync though.

The MBP screen is 60 Hz, and the external screen also receives a 60 Hz signal. Changing the game resolution doesn't affect the video signal (always 1080p), but matching the output and game resolution (e.g. 720p@60) still gives similar symptoms.

6

Sounds to me like you have Vertical Synchronization enabled. This feature locks your frame rate to a fraction of your display’s refresh rate (1, ½, ⅓…) to prevent visual artifacting (specifically, “tearing”) and runaway frame rates (which may damage a GPU). A pretty good indication of this is a frame rate that jumps from 30 to 60 FPS and back, with nothing in-between.

Mirroring is affecting performance just enough to drop your frame rate below 60 FPS. Even if you would otherwise get 59 FPS, Vertical Synchronization would drop your frame rate to 30 FPS.

This may also result in input lag. Since your screen/cursor is now redrawn half (or one-third) as frequently, the delay between you moving the mouse and seeing the result on the screen would be twice or three-times as long.

Go into Portal’s video settings and Disable Vertical Synchronization. I don’t play Portal, but almost every game has that option. It may be named V-Sync.

You may need to switch from Windowed mode to Full Screen. Since macOS forces V-Sync for the main desktop, V-Sync may still be enforced while playing in a window.

To minimize the adverse effects of disabling V-Sync, many games offer the option to cap your frame rate. If that option is available, try setting a maximum of, eg. 90 FPS or even 60 FPS. This often offers the best of both worlds.

See if a combination of these solutions resolves your problem.

If you’d rather keep V-Sync enabled, many games offer an option to enable Triple-Buffering. This will help smooth out your frame rates (therefore minimizing sudden drops in frame rates). Enabling it may also result in increased input lag, though usually not as severe as one caused by dropping 30 FPS.

One last suggestion would be to try to extend your desktop onto the external display as a separate Space instead (possible with Yosemite and above, I believe). Does your use-case even require Mirroring? I’m not all that familiar with this on the Mac, but I don’t see why this wouldn’t be possible.

Bird’s-eye explanation of what’s causing your frame rate drops with Mirroring:
With Mirroring, your Mac has to display the same frame to your internal display and to your external display. In addition to causing your displays to wait on each other, this involves additional “work” including extra computational time and buffer management (to make sure they’re displaying the same thing at the same time), as well as the round-trip delay over your external cable or worse, Wi-Fi/Bluetooth.

While this is happening, your GPU is rendering the next frame in its internal buffer, but doesn’t send it to your display until it gets the OK (because of V-Sync). During this wait period, your GPU is effectively paused, not rendering additional frames (unless Triple- or N-Buffering is available), which further reduces your frame rate. Then, depending on where the slowest display is at in its refresh cycle, display of the next frame may be delayed yet again to the next fraction.

You have to keep in mind that in order to render your game at 60 FPS, your graphics subsystem only has 33ms to perform all that extra work (minus the time needed by the GPU to render those frames in the first place). The roundtrip to and from your external display alone may take a couple of milliseconds. Synchronization work is in and of itself costly (time-wise). It’s not unfathomable that synchronizing two displays takes more than 20 or 30 milliseconds.

Now, in the previous paragraph I was assuming that your GPU was ready with the next frame by the time your displays were done drawing the current one. Imagine that it wasn’t. Well, now the displays are starved, and they’re the ones that end up waiting on the GPU. You probably end up dropping to the next fraction of your slowest refresh rate. What might mean a 1-2 FPS drop V-Sync Off turns into a 30 FPS with it On.

So you’re trying to synchronize two displays (through Mirroring), then trying to synchronize THOSE against your GPU (through V-Sync). The result is potentially lots and lots and lots of waiting.

It is not unusual to experience some performance degradation when connecting subsystems with disparate performance levels. That is why buffers and asynchronous operations were created.

When synchronizing, a delay anywhere causes delays everywhere.

To maximize performance, best let everyone do their job on their own time.

  • 1
    Thanks for your answer. Relating this to mirroring, I assume you're saying that it's capping the frame rate to the frequency of the slowest video signal? That's a good observation. But l'm still surprised that the mouse seems sluggish and that it drops to < 30 fps in situations that would run at 60 on one monitor – Andreas Dec 30 '16 at 16:57
  • 1
    Every cursor redraw may be delayed until the next frame refresh, which would be twice as long as before (I’m not positive on this one, but it would explain the input sluggishness). I’d say try disabling V-Sync, then see if any related problems persist once your frame rate is restored. Note that with V-Sync on, anything that drops your frame rate below 60 FPS will automatically drop it to 30, even if the frame rate would otherwise be 59. – user11633 Dec 30 '16 at 17:30
  • 1
    Good info, thank you. Regarding windowed mode, it doesn't prevent screen tearing (which I suppose is expected since it would probably run extremely slowly if rendering took a detour through the window manager). – Andreas Dec 30 '16 at 19:01
  • 1
    Right, playing full-screen would only enable V-Sync (if macOS otherwise prevented it). As far as mouse-look goes, it’s still the same idea: since there is a longer delay in drawing the next frame, the result of your mouse action is delayed as well. – user11633 Dec 30 '16 at 19:57
  • 1
    Your theory sounds reasonable. Interesting subject. My usecase doesn't require mirroring, it was just the closest I could get to minimizing resource use. Unfortunately, making an extended desktop didn't work since the cursor gets trapped outside the game (hadn't tried it before TBH, because there are almost always focusing problems like that). – Andreas Dec 30 '16 at 21:28
0

Condensing some info on what worked in the end:

  • Vsync enabled
  • Separate desktops on each monitor
  • Move main desktop (the dock) to the screen you want to play on. Portal can select a monitor in-game, but macOS will screw with the cursor anyway unless you play on the main screen so that option is useless.
  • Dim the other screen down.

Same thing for Portal 2. Unlike the first game it also supports triple buffering.

Using apps like DisableMonitor only complicates things. You somehow end up with the disabled monitor's coordinate system (and desktop background) overlaid onto the enabled one, making cursors appear where they aren't. The developer seems to have taken precautions by the looks of this line: CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID), but that just doesn't seem to stick -- at least not in macOS sierra.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .