Under SDL3.4.10, I have received a couple of reports of performance trouble in my SDL3/OpenGL game. I haven’t been able to reproduce the problems myself, but here are the clues I’m working with:
Both people reporting issues are running on Windows.
Both are running large 4k LG monitors, one running at 165hz, one at 240hz.
Both are running the game in SDL’s Borderless Fullscreen Desktop mode.
My game’s built-in FPS logging function shows that the FPS doesn’t appear to drop below an average of 140 fps for either person. (except for one user who briefly had a period at 30fps for no obvious reason)
Both are receiving an absurd number of SDL_EVENT_WINDOW_EXPOSED events; These events are coming through at a rate of about one every 30-40ms for many minutes at a time (albeit not continuously, but perhaps for half the runtime of the game they’re receiving these events continuously at a rate of about 30 per second)
Does anybody have any ideas what could create SDL_EVENT_WINDOW_EXPOSED events at such a regular frequency? From reading the code it looks like we just receive one every time SDL receives a WM_PAINT message from Windows, but I don’t know what would actually generate so many of them so rapidly. Would it just be another window moving in front of ours? (which I guess would be weird but possible for fullscreen desktop mode)
Would something like Discord’s new “transparent window that we draw in front of borderless fullscreen games” overlay maybe generate that sort of behaviour if it was animating something in front of the game window?
We don’t do anything with the EXPOSED event except note that we’ve received it; we just do regular OpenGL stuff by calling SDL_GL_SwapWindow() once per frame and entirely ignore the EXPOSED event, but.. it’s the obvious strange thing that links these two players who are reporting performance troubles.
Does anybody have insights or ideas or things I should ask the users to try to get more data? Big thanks in advance for any help or ideas anybody can offer!
I have a guess, but not a Windows computer to test it on:
There’s a system-settings option to “Auto-hide” the main menu bar, and most high-end Windows implementations have “animated window actions” turned on by default. This generally makes the menu bar slide into and off screen, and each step of the animation could trigger the window exposed event in your program.
Perhaps this menu bar is being triggered, but the visual component is being hidden by an “always on top” attribute of fullscreen-desktop mode, or the player is using the bottom of the screen to hide the mouse while playing. This might cause some further complicated interaction for the system.
If you have a Windows PC, perhaps test the above setup and see if you can replicate the issue with those settings. (By hitting the bottom of the screen with the mouse)
Assuming that the above is the problem, I have some possible work-arounds:
If you have contact with these users, ask them to turn off animated windows in their system settings. Hopefully you get feedback from them if it does the trick.
Set a small time-out counter in the window exposed event handler, if this event is detected a lot, like 5 or 10 times in one second, then switch to a true fullscreen mode rather than fullscreen-desktop. I’m guessing about this as well, but I think a true fullscreen mode would halt the menu bar from being activated.
The big downside to the second option is that the user will likely see the screen flash or do other goofy stuff as the mode resets the screen resolution .
Set up a mouse-warp that keeps the mouse 10 or 20 pixels above the bottom of the screen. (Hoping to avoid activating the menu bar repeatedly) - if the mouse has a lot of down-time in the game, you might auto-hide the cursor after a second or two of inactivity (Use the mouse-motion event to re-show it).
If any of the above fix the issue, then please file an issue report at SDL’s official github, including what action worked.
I’ve done a test of this theory here, and no; when the game is in a fullscreen desktop mode, moving the mouse to the bottom of the window does not appear to trigger any SDL_WINDOW_EXPOSED events (which in turn means, if I’m reading the code correctly, that SDL isn’t receiving WM_PAINT messages from the OS)
It was a good idea, but.. I can’t seem to replicate it here!