OpenGL + vsync: FPS halved during heavy actor load (?)

Discuss anything ZDoom-related that doesn't fall into one of the other categories.
User avatar
Nash
 
 
Posts: 17283
Joined: Mon Oct 27, 2003 12:07 am
Twitch ID: nashmuhandes
Github ID: nashmuhandes
Location: Kuala Lumpur, Malaysia

OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Nash »

When using OpenGL hardware rendering and VSync, on my 144hz monitor, the game's FPS will be capped to 72 FPS during what I suspect is heavy actor load - but it's a bit more complicated than "too many actors on at once". Thinker times are generally low, but there's a LOT of active spawning and despawning happening, so I suppose sometimes the game gets stalled in a micro, sub-frame way (I probably got the terminologies wrong but I hope this makes sense).

In short, game usually stays at 144 FPS locked but depending on actor activity, the FPS will suddenly lock to half my refresh rate (72 FPS).

When tuning VSync OFF - it is revealed that general FPS is quite high (200 - 300), but there can be frame spikes where the FPS will dip SLIGHTLY below 144 FPS. I suspect that these "half FPS with VSync" happens when the framerate dips below 144, regardless of HOW MANY frames - it could be something as trivial as 142 FPS - what's really puzzling me is that instead of handling 142 FPS, well, the game just tanks the framerate all the way down to 72 FPS and stays locked there until actor processing becomes lighter. o_O

This problem doesn't exist in Vulkan.

Anyone know what's going on here?
User avatar
Player701
 
 
Posts: 1398
Joined: Wed May 13, 2009 3:15 am
Discord: Player701#8214
Graphics Processor: nVidia with Vulkan support
Location: Russia

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Player701 »

I think this is called "adaptive V-Sync": its purpose is to avoid screen tearing when your FPS dips below your monitor's refresh rate. For that, the graphics driver will keep the FPS to satisfy to the following formula: FPS*N=R, where N is a whole number and R is your refresh rate. E.g. if the game can maintain 144 FPS or higher, it will be 144, below that it will be 72, then 48, then 36, then 24, and so on. Adaptive V-Sync can be configured somewhere in the graphics control panel.

Note that if you have an NVIDIA graphics card and a G-SYNC or G-SYNC Compatible monitor, you do not need adaptive V-Sync: use normal V-Sync in concert with G-SYNC. The former ensures your FPS does not go above your maximum refresh rate, and the latter turns down the refresh rate itself when the FPS drops. I'm speaking from my own experience as an NVIDIA user. AMD hardware should probably have something similar (IIRC it's called FreeSync, and most G-SYNC Compatible monitors also support it).
dpJudas
 
 
Posts: 2860
Joined: Sat May 28, 2016 1:01 pm

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by dpJudas »

Vulkan has a lot more control over how vsync should behave compared to OpenGL. Specifically, it uses the VK_PRESENT_MODE_FIFO_RELAXED_KHR mode when vsync is enabled:

VK_PRESENT_MODE_FIFO_RELAXED_KHR specifies that the presentation engine generally waits for the next vertical blanking period to update the current image. If a vertical blanking period has already passed since the last update of the current image then the presentation engine does not wait for another vertical blanking period for the update, meaning this mode may result in visible tearing in this case. This mode is useful for reducing visual stutter with an application that will mostly present a new image before the next vertical blanking period, but may occasionally be late, and present a new image just after the next vertical blanking period. An internal queue is used to hold pending presentation requests. New requests are appended to the end of the queue, and one request is removed from the beginning of the queue and processed during or after each vertical blanking period in which the queue is non-empty.

Unfortunately for OpenGL the only vsync extension available is already implemented by GZDoom. There's no way to specify that you want adaptive vsync there. I'm not sure which of the present modes OpenGL actually uses, but it might be VK_PRESENT_MODE_FIFO_KHR.

Btw for vsync off the behavior also differs between the backends. In vulkan I opted for VK_PRESENT_MODE_MAILBOX_KHR rather than VK_PRESENT_MODE_IMMEDIATE_KHR as I don't see any advantage in actually seeing the tearing.

Edit: at the end of that present modes page it actually says this:

For reference, the mode indicated by VK_PRESENT_MODE_FIFO_KHR is equivalent to the behavior of {wgl|glX|egl}SwapBuffers with a swap interval of 1, while the mode indicated by VK_PRESENT_MODE_FIFO_RELAXED_KHR is equivalent to the behavior of {wgl|glX}SwapBuffers with a swap interval of -1 (from the {WGL|GLX}_EXT_swap_control_tear extensions).

So basically it should be using the same present mode - unless there's now a bug in the OpenGL backend that didn't set it to -1, or that the display driver is buggy and doesn't do it even when instructed to.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 47988
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Graf Zahl »

On OpenGL it is a lot more complex because among other things it is important where you call glFinish(). Since every driver implements it differently you got one nice case of very undefined behavior here.
User avatar
Nash
 
 
Posts: 17283
Joined: Mon Oct 27, 2003 12:07 am
Twitch ID: nashmuhandes
Github ID: nashmuhandes
Location: Kuala Lumpur, Malaysia

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Nash »

I see. I'm on an nvidia RTX 2080, but my monitor doesn't have G-Sync (it only supports FreeSync).

I'll play around in the nvidia control panel to see if I can find a way to disable adaptive sync.

(on the other hand; this actually highlights a separate but possibly-related problem with my script code - been ranting about this on Discord the past hour or so, LOL - I have a lot of work to do on the script side as well... need to start thinking about optimization)
User avatar
Chris
Posts: 2841
Joined: Thu Jul 17, 2003 12:07 am
Graphics Processor: ATI/AMD with Vulkan Support

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Chris »

Player701 wrote:I think this is called "adaptive V-Sync": its purpose is to avoid screen tearing when your FPS dips below your monitor's refresh rate. For that, the graphics driver will keep the FPS to satisfy to the following formula: FPS*N=R, where N is a whole number and R is your refresh rate. E.g. if the game can maintain 144 FPS or higher, it will be 144, below that it will be 72, then 48, then 36, then 24, and so on.
That's normal v-sync. If the game is able to present each frame within 1/fps seconds of the last, it'll maintain that FPS. But if frames take a bit more than 1/fps seconds, the frame will have to wait until the next fixed video sync/refresh, which cuts FPS in half as you'll only show a new frame every other refresh.

Adaptive sync (G-Sync for nVidia or FreeSync for AMD) instead allows the device to dynamically change its refresh rate according to how fast new frames are being generated by the graphics card (which is in turn done in response to the game presenting new frames). So if you have a 144hz monitor and the game takes less than 1/144th of a second to present new frames, it'll maintain 144 FPS. If it takes a bit more than 1/144th of a second to present a new frame, the card/monitor can seamlessly switch to 120hz, so rather than the FPS dropping all the down to 72 FPS, it only drops to 120 FPS. Then if the game can start presenting frames faster than 1/144th of a second again, it switches back to 144hz. When there's intermittent CPU spikes that may cause one or two frames to take a little bit more time than normal, this more granular switching can result in shorter and less severe frame rate dips.
User avatar
Player701
 
 
Posts: 1398
Joined: Wed May 13, 2009 3:15 am
Discord: Player701#8214
Graphics Processor: nVidia with Vulkan support
Location: Russia

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Player701 »

Hmmm, I always thought adaptive V-Sync and G-Sync were different. At least they are in my NVIDIA control panel: "adaptive" can be chosen as one of the possible values for V-Sync in application or global 3D settings, while G-Sync is in another section entirely, and can only be enabled or disabled globally, not on a per-app basis.
User avatar
Chris
Posts: 2841
Joined: Thu Jul 17, 2003 12:07 am
Graphics Processor: ATI/AMD with Vulkan Support

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Chris »

Player701 wrote:Hmmm, I always thought adaptive V-Sync and G-Sync were different. At least they are in my NVIDIA control panel: "adaptive" can be chosen as one of the possible values for V-Sync in application or global 3D settings, while G-Sync is in another section entirely, and can only be enabled or disabled globally, not on a per-app basis.
That might be related to EXT_swap_control_tear, which is also sometimes called "adaptive v-sync". That is different, and works by performing v-sync as long as the frame is presented within the 1/fps time frame to have tear-free frames, but if the image is late, it's displayed right away without v-sync (causing a visible tear).
User avatar
Player701
 
 
Posts: 1398
Joined: Wed May 13, 2009 3:15 am
Discord: Player701#8214
Graphics Processor: nVidia with Vulkan support
Location: Russia

Re: OpenGL + vsync: FPS halved during heavy actor load (?)

Post by Player701 »

Ah, that's how I thought it worked by default. Guess I must've mixed them up then. Thanks for clarification!

Return to “General”