Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL2: Framerate issues on Mac OS X without external monitor #1032

Closed
ghost opened this issue May 9, 2019 · 13 comments
Closed

SDL2: Framerate issues on Mac OS X without external monitor #1032

ghost opened this issue May 9, 2019 · 13 comments
Labels
display pygame.display
Milestone

Comments

@ghost
Copy link

ghost commented May 9, 2019

I have a strange framerate issue on Mac OS X when using pygame2.
When I run a program on my MacBookPro without any external monitor, the performance is horrible.
This is using a simple 1080p monitor connected to my old MacBookPro with a 1280 x 800 screen.

  • If I unplug the external monitor and start the program (using only the MacBook display), I get fluctuating performance with an average of 30fps all the time.

  • If I use the external monitor, it's 60fps, almost as steady as pygame1. So it's much worse without the external monitor plugged in.

Where the pygame window is doesn't matter, only the fact that it is plugged in.

If I start the program when the external monitor is plugged in, the performance will stay good even if I unplug it. It will also stay bad if I start it without the external monitor and plug it back in after.

The same programs with SDL1 are 60fps all the time without any drops, even when I have 100+ sprites moving at the same time.

I also did tests with the new textures and renderers to see if it would help but it doesn't change anything.

  • With the MacBookPro monitor only I get the same bad performance that fluctuates between 30 and 100+ fps for small amounts of time

  • With the external monitor, I get a steady 60 fps on both versions... but not more, even if I don't limit the fps.

Test using surfaces:

import pygame
import sys

pygame.init()
window = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()

square = pygame.Surface((10, 10))
square.fill((255, 0, 0))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    window.blit(square, (0, 0))
    pygame.display.flip()
    clock.tick()
    print(int(clock.get_fps()))

Test using textures and renderers:

import pygame
from pygame._sdl2 import Window, Texture, Renderer
import sys

pygame.init()
window = Window('TESTSDL2', size=(800, 600))
renderer = Renderer(window)
clock = pygame.time.Clock()

square = pygame.Surface((10, 10))
square.fill((255, 0, 0))
square_texture = Texture.from_surface(renderer, square)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
            
    renderer.clear()
    renderer.copy(square_texture, dstrect=(0, 0, 10, 10))
    renderer.present()
    clock.tick()
    print(int(clock.get_fps()))

Pygame 2.0.0.dev1, SDL 2.0.9, python 3.7.3, MacOS 10.14.4

@illume
Copy link
Member

illume commented May 10, 2019

Thanks for providing a couple of different test cases.

  • Currently pygame 2 with sdl2 does not have vsync enabled by default, but we probably will enable that by default. Using something like clock.tick(60) is probably a good idea.
  • the performance on Mac will change on SDL 2.0.10 because it is switching to the Metal renderer by default (that is the plan, we will see for sure once the release happens). The SDL 2.0.9 is supposed to have various bugs and improvements which are fixed in the coming release.
  • sounds like the external monitor being plugged in may enable vsync. There are some issues with this in SDL2 on the most recent MacOS version.
  • perhaps it's something to do with hidpi or the format of the pixels (some pixel formats are more optimized with different graphics cards, and plugging in an external monitor can enable the discrete GPU in the macbooks... see the activity monitor to see if the GPU is being used).
  • SDL_HINT_RENDER_DRIVER=metal python rendererexample.py

It might be worth reporting a bug to the SDL people. Especially if you can reproduce the issue with a normal SDL C program to make it easier for them. Or add the clock.tick, and wait for the metal renderer to be released in SDL 2.0.10 (which hopefully fixes these issues).

@ghost
Copy link
Author

ghost commented May 10, 2019

Thanks for taking the time to answer.

Adding clock.tick(60) does make it more stable, but it still won't go higher than 30fps without the external monitor.

It probably doesn't have anything to do with high dpi or discrete GPU being activated because the MacBook I use doesn't have them. It's an old 13" with only the Intel integrated graphics, but it's still supported by Apple and can run Metal. I guess that people with more powerful hardware may not see the issue if the frame rate drop doesn't make it too slow. Let's hope switching to Metal by default in the next SDL release will fix the issues.

edit:
I just tried setting SDL_HINT_RENDER_DRIVER to metal and software with the renderer example and it doesn't do anything, either because it's not affecting the SDL or perhaps because it's always using the software renderer for some reason... Is there a way to see what driver SDL is using using Pygame2?

I also tried switching on vsync with SDL_HINT_RENDER_VSYNC=1 without any effect.

@kfu02
Copy link

kfu02 commented May 15, 2019

I have this same issue too: clock.tick(60) and clock.tick(30) are both still worse when I have no external monitor plugged in.

EDIT: This problem disappears when instantiating the pygame display in fullscreen rather than windowed mode, as suggested here: https://www.reddit.com/r/pygame/comments/8e1eqs/really_slow_on_osx/

EDIT 2: After some more digging I found this, https://stackoverflow.com/questions/31685936/pygame-application-runs-slower-on-mac-than-on-pc, which worked for me. The idea is to set pygame to open in "low resolution" because the Retina display of the MBP slows its processes down.

@notpygame
Copy link
Contributor

Thanks @kfu02 . Can you please confirm which pygame and SDL version you are using?

@kfu02
Copy link

kfu02 commented May 15, 2019

Pygame 1.9.6, python 3.6.5, SDL2 (2.0.8).

@ghost
Copy link
Author

ghost commented May 15, 2019

The problems linked by @kfu02 above are related to Pygame1 with SDL 1. It does seem that the Retina display was causing some problems, bit it isn't the case in this situation as I don't have a high dpi display. The performance on Mac was always worse, but the specific problem here is that it is way worse with SDL2, specifically when I have no external monitor.

@kfu02 Because pygame 1.9.6 still comes with SDL1, I assume you compiled it yourself with SDL2 instead of using Pygame2.0.0.dev1? If that's the case, is the performance better when using SDL1 on the Mac?

@notpygame
Copy link
Contributor

notpygame commented May 16, 2019

@galexandreg are you able to reproduce the issue with this simple C SDL2 program?
https://github.com/illume/pygame4000/blob/master/code/sdl2_basics_tutorial_fundamentals/hey.c

brew install sdl2
wget https://raw.githubusercontent.com/illume/pygame4000/master/code/sdl2_basics_tutorial_fundamentals/hey.c
gcc -o hey hey.c `sdl2-config --cflags --libs`
./hey

If so, then we can make a very nice bug report to the SDL folks :)

You could also try the SDL2 from hg with some commands like this (be careful to understand these commands as it might break programs you are using)

brew uninstall --ignore-dependencies sdl2
brew install sdl2 --head
wget https://raw.githubusercontent.com/illume/pygame4000/master/code/sdl2_basics_tutorial_fundamentals/hey.c
gcc -o hey hey.c `sdl2-config --cflags --libs`
./hey

@ghost
Copy link
Author

ghost commented May 16, 2019

I kind of feel bad about this, but I don't want to simply ignore it and pretend I forgot about it.

The thing is, I am completely new to programming and I only do this as a hobby on my spare time. I never used Brew before and I don't have the Apple development tools installed (gcc isn't installed by default on OS X right?).
As much as I would love to help, I also don't want to test stuff I don't really understand yet. If I get there in my learning process soon enough, I will certainly test it and share the results here.

I also wonder if it would be even worth the effort to fix. If the issue only affects non-retina internal Mac displays (or maybe even my specific monitor/graphics hardware combination), the problem will fix itself when Apple stops supporting these older models (probably in the next year or two...)

@illume
Copy link
Member

illume commented May 27, 2019

@galexandreg hey hey. Don't feel bad.

Thanks heaps for reporting this :)

I'll try and reproduce the issue, and send it to the SDL folks.

@illume illume added this to the 2.0 milestone Jun 18, 2019
@illume illume added the 2.0 label Jun 18, 2019
@ghost
Copy link
Author

ghost commented Jul 19, 2019

When testing issue #1169, I realized that the frame rate problem not only occurs without an external monitor, but also if the only monitor is the external one (by closing the laptop screen, it seems do disable the internal one.)

So the problem isn't related to the resolution of the external screen being more "standard" or some other functionality I don't know about. Strangely enough, the frame rate is good and stable only if I have 2 monitors available. If I have only one, whether it's the internal or the HD one, it doesn't work.

@ghost
Copy link
Author

ghost commented Oct 7, 2019

The issue is fixed in Pygame2.0.0dev4 with SDL 2.0.10. The framerate is now stable at 60FPS, external monitor or not, like it was with the SDL1 versions.

@ghost ghost closed this as completed Oct 7, 2019
@illume
Copy link
Member

illume commented Oct 8, 2019

Wonderful :)

@ghost
Copy link
Author

ghost commented Sep 17, 2021

I had the same problem today and I wonder if something changed again or if I was wrong last time... maybe I forgot to test properly 🤔 I don't know...

Anyway it looks like it's a vsync issue because I dont have the problem when using pygame.SCALED and vsync=True. When I'm not, the performance is horrible unless I have two monitors. Somehow, it seems to enable vsync.

Anyway, I thought it could be useful to add this information here in case others have the same problem in the future.
If the performance on mac seems really bad by default, try using pygame.SCALED and enabling vsync.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
display pygame.display
Projects
None yet
Development

No branches or pull requests

4 participants