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

Vsync not applied with OpenGL renderer #16516

Open
digant73 opened this issue Jan 6, 2025 · 21 comments
Open

Vsync not applied with OpenGL renderer #16516

digant73 opened this issue Jan 6, 2025 · 21 comments
Assignees

Comments

@digant73
Copy link
Contributor

digant73 commented Jan 6, 2025

Quick summary

Not a regression (I see it also in old releases).
The Vsync option on the GPU tab is not applied when using OpenGL renderer. It only works with Vulkan renderer

Details

No response

Attach a log file

RPCS3.log.gz

Attach capture files for visual issues

No response

System configuration

No response

Other details

No response

@kd-11
Copy link
Contributor

kd-11 commented Jan 6, 2025

Not our bug. Please make sure to enable vsync on the driver panel.
Vsync in OpenGL is implemented at vendor level, the driver settings override anything we try to do. Also note that we do triple buffer vsync, not true double-buffer sync that caps the framerate. You can change this by disabling opengl triple buffering setting in nvidia control panel or disabling other vsync enhancements like 'fast sync'.

@digant73
Copy link
Contributor Author

digant73 commented Jan 6, 2025

thanks for the info. I used default settings on nvidia panel. Triple buffering was already set to off while Vertical sync was set to Use the 3D application setting so I was expecting vsync engaged by RPCS3.

image

Setting Vertical sync to On works now (as you reported) with OpenGL renderer but it is also applied when using Vulkan renderer independently by the Vsync setting in the GPU tab. If so, it could help to update the hint for that setting

@kd-11
Copy link
Contributor

kd-11 commented Jan 6, 2025

What do you mean exactly by vsync working/not-working in this case btw? I mean what happens when you set it to use 3d application setting? Are you observing actual tearing?

@digant73
Copy link
Contributor Author

digant73 commented Jan 6, 2025

if in nvidia control panel I set Vertical sync to Use the 3D application setting then:

with OpenGL renderer:
Vsync unchecked -> no vsync - PASSED
Vsync checked -> no vsync - KO (I was expecting it working due to the Vertical sync value in nvidia control panel; but you provided the answer)

with Vulkan renderer:
Vsync unchecked -> no vsync - PASSED
Vsync checked -> vsync - PASSED

if in nvidia control panel I set Vertical sync to On then:

with OpenGL renderer:
Vsync unchecked -> vsync - KO (it is now always forced to On as you said)
Vsync checked -> vsync - PASSED

with Vulkan renderer:
Vsync unchecked -> vsync - KO (it is now always forced to On also on Vulkan renderer)
Vsync checked -> vsync - PASSED

I would simply update the hint provided for Vsync in GPU tab reporting that it is properly applied to Vulkan renderer if Vertical sync on nvidia control panel is set to demand the feature to the application while it has no effect (always disabled) on OpenGL renderer.
To enable vsync on OpenGL renderer, Vertical sync on nvidia control panel needs to be set to On but this will force the vsync also on Vulkan renderer even if Vsync on GPU tab is unchecked

@kd-11
Copy link
Contributor

kd-11 commented Jan 6, 2025

@digant73 When you say "no vsync" what do you mean? Are you experiencing visual tearing or is it just fps exceeding the display refresh? OGL triple buffering means the display limit will be exceeded, that is by design.

@kd-11 kd-11 self-assigned this Jan 6, 2025
@digant73
Copy link
Contributor Author

digant73 commented Jan 6, 2025

yes, I mean that I expect to see some tearing while with sync I expect for sure no tearing. The problem is that Vertical sync on nvidia panel is affecting both OpenGL and Vulkan but in different ways according to the value. With value Use the 3D application setting, vsync is always Off for OpenGL while it is properly controlled by RPCS3 with setting Vsync in GPU tab.
Other values On, Off for Vertical sync on nvidia panel are instead applied to both OpenGL and Vulkan so the Vsync setting on GPU tab has no more effect at all even for Vulkan renderer.

Just a question about the triple buffer used when Vsync is engaged, could it affect the pad response on some games? I think for example to Killzone 2 (this game has an heavy feeling of the movement compared to KZ3 on the real PS3). On RPCS3 (I always prefer to enable vsync on all games) the pad is very unresponsive (it feels like input lag is very high), Could a double buffering improve the feeling? If so, could it be possible, with a minor effort on the code, to allow on the GUI the possibility to select double or triple buffering when Vsync is engaged?

@kd-11
Copy link
Contributor

kd-11 commented Jan 6, 2025

Vulkan and OpenGL expose vsync control very differently.
With vulkan, you query the driver on what types of present modes it supports. There are 4 standard-ish modes, FIFO (double buffered vsync), IMMEDIATE (no vsync), FIFO_RELAXED (adaptive vsync) and MAILBOX (fast-vsync, exceeds cap like triple buffer). When you select a mode, the driver has explicit rules from the spec how to behave so it always acts the same way unless the driver is configured to override it.
With OpenGL we just have one function, wglSwapInterval which takes 3 values. 0 = no vsync, -1 = adaptive vsync and 1 = normal double buffered vsync. We request -1 (adaptive) to keep the emulator from crawling to half-rate due to how CPU-based pacing works (it often misses deadlines). The behavior here is very vague and the driver is free to interpret these values as it sees fit. For example, the driver can add triple buffering if it wants to (this is often the case unless you disable in control panel). There is no way to control this from the client side.
If you're seeing tearing then it is more likely that the fps limit is causing problems and triggering adaptive screen tearing to keep up. Try the following:

  1. Find a game that can exceed your display refresh.
  2. Set vsync on and frame limit off.
  3. Check for tearing.

We could replace the vsync toggle with a dropdown with the 3 options. For vulkan we have an option in config that controls whether to apply adaptive or strict double-buffered. Maybe OpenGL can expose this, though utility would be very limited.

@digant73
Copy link
Contributor Author

digant73 commented Jan 6, 2025

but according to what you say about Vulkan (4 modes etc.) it seems that vsync on Vulkan is always controlled by the VSync setting on GPU tab (and of course the capabilities provided by the driver).
This is true when Vertical sync on nvidia control panel is set to Use the 3D application setting.
While this is no more true with other values (On, Off etc.).
E.g. with Off I see tearing with both OpenGL and Vulkan. As far as I understand Vulkan should still apply the Vsync setting on the GPU tab so if it is flagged I should not see tearing but this is not happening.

I would clarify the behavior of Vsync on GPU tab. Something like:

  • Effective for Vulkan when Vertical sync on nvidia control panel is set to Use the 3D application setting.
  • Not effective (in general) for OpenGL (to be sure, it needs to be forced on Vertical sync on nvidia control panel)

@kd-11
Copy link
Contributor

kd-11 commented Jan 6, 2025

but according to what you say about Vulkan (4 modes etc.) it seems that vsync on Vulkan is always controlled by the VSync setting on GPU tab (and of course the capabilities provided by the driver).

This is only true as long as the driver setting is not configured to override it (i.e "use 3d application setting")

As far as I understand Vulkan should still apply the Vsync setting on the GPU tab so if it is flagged I should not see tearing but this is not happening

Same caveat explained above. If you're still seeing tearing that's a driver bug and should be reported to NV, though chances that they'll do anything about it are very low. We've had other reports of vsync not working correctly on NVIDIA in the past but it has always been resolvable by checking driver settings. Either some override is in place or something like VRR is active.

External bug already filed for like 8 years now: https://forums.developer.nvidia.com/t/vsync-behavior-vsync-is-always-adaptive/47600

Related
#4689
#15666

And many others we closed over the years. If you wish to test if any values will work for you, toy around with this line

gl::set_swapinterval(g_cfg.video.vsync ? -1 : 0);
and see if the driver will pick any numbers. Refer to the NVIDIA thread I linked for expected behavior.

@digant73
Copy link
Contributor Author

digant73 commented Jan 6, 2025

thanks. It is more to clarify on the GUI what you stated above. As I reported (as update) in the previous post, an hint like the following could be enough.

Vsync setting on GPU tab depends also on driver's settings. E.g. on nvidia drivers:

  • it is effective for Vulkan when Vertical sync setting on nvidia control panel is set to Use the 3D application setting
  • it is not effective (in general) for OpenGL. To be sure, it needs to be forced on Vertical sync setting on nvidia control panel

@digant73
Copy link
Contributor Author

digant73 commented Jan 6, 2025

We could replace the vsync toggle with a dropdown with the 3 options. For vulkan we have an option in config that controls whether to apply adaptive or strict double-buffered. Maybe OpenGL can expose this, though utility would be very limited.

That will be great IMO so I could make some testing on games currently giving me a bad feeling

@kd-11
Copy link
Contributor

kd-11 commented Jan 6, 2025

thanks. It is more to clarify on the GUI what you stated above. As I reported (as update) in the previous post, an hint like the following could be enough.

This isn't true for other vendors. Only for nvidia because of bad OGL driver.

That will be great IMO so I could make some testing on games currently giving me a bad feeling

You need to first verify that using "1" instead of "-1" does something for your setup. If that works then I can get that done. I remember you're able to compile rpcs3, try setting swap interval to 1 on the line I pointed out earlier. If it works, I'll add the config option to switch between different vsync modes.

@digant73
Copy link
Contributor Author

digant73 commented Jan 7, 2025

thanks. It is more to clarify on the GUI what you stated above. As I reported (as update) in the previous post, an hint like the following could be enough.

This isn't true for other vendors. Only for nvidia because of bad OGL driver.

Yes, for that reason I reported a general warning first and then provided the example for nvidia drivers.

That will be great IMO so I could make some testing on games currently giving me a bad feeling

You need to first verify that using "1" instead of "-1" does something for your setup. If that works then I can get that done. I remember you're able to compile rpcs3, try setting swap interval to 1 on the line I pointed out earlier. If it works, I'll add the config option to switch between different vsync modes.

Yes, I will do. How can I also force FIFO (double buffer) on Vulkan (in VKGSRender.cpp I do not find any usage of g_cfg.video.vsync)?

@kd-11
Copy link
Contributor

kd-11 commented Jan 7, 2025

How can I also force FIFO (double buffer) on Vulkan

This is already implemented. Open config.yml and go to vulkan section, you'll see an option there. It's not exposed in Qt GUI

@digant73
Copy link
Contributor Author

digant73 commented Jan 7, 2025

ok made some testing with both OpenGL and Vulkan renderers.

With OpenGL, using 1 (instead of -1) as in the following code:

gl::set_swapinterval(g_cfg.video.vsync ? 1 : 0);

I have no tearing (of course Vsync setting flagged in GPU tab) while with -1 there is tearing as per this open bug report.

With Vulkan, setting to true the Force FIFO present mode setting as in the following:

Force FIFO present mode: true

I have a better feeling with KZ2 (less lag). It is very similar to what I see in the PS3. Tested also at 30fps as in the console to compare apple with apple. Better feeling (a bit more responsive) also on KZ3 and Resistance series. Tested many times switching between one mode to another.

I do not see any difference on performance

@digant73
Copy link
Contributor Author

digant73 commented Jan 9, 2025

EDIT: made other testing on Vulkan renderer. Maybe a placebo effect with previous testing.
Setting Force FIFO present mode to true seems the same as enabling Vsync on GPU tab with Force FIFO present mode set to default false. I had a look at the code and (based on the comment I read) it seems it is tried to to always use triple buffer.
Maybe I will make some testing forcing the mode from nvidia control panel. I would simply set a vsync with double buffer (not triple)

@kd-11
Copy link
Contributor

kd-11 commented Jan 9, 2025

The way rpcs3 is architected, the number of buffers doesn't matter. Pacing is done driver side. Number of buffers only affects internal behavior (i.e whether we pause RSX emulation to wait for host). If you only have 2 buffers there is a big pause mid-frame during async flip, no real changes expected otherwise other than performance dropping (this was the default initially).
Forcing FIFO enforces true vsync (each frame must be presented, each frame has to wait for a vblank cycle). Vsync toggle on GUI selects the most suitable mode out of whatever your driver chooses to expose. It may or may not match standard FIFO vsync depending on your hardware and drivers.

@kd-11
Copy link
Contributor

kd-11 commented Jan 9, 2025

What I can do for VK is add a config variable in yml to limit number of buffers. I'm not sure if it will really reduce lag or not, but maybe someone finds it useful.
Other than that the vsync options will be restructured to be a dropdown instead of binary toggle.

@digant73
Copy link
Contributor Author

digant73 commented Jan 9, 2025

thanks for the clarifications. I think that the dropdown for vsync is a better choice than the current checkbox only.
In my mind I see three possible values:

no-vsync
vsync double buffer
vsync triple buffer

My previous post was related to what I saw in swapchain.hpp. I also see that the selected values on the GUI are then filtered out according to the capabilities retrieved interrogating the vendor's drivers. So it is possible that the value selected on the GUI could potentially be set to another value but the user will not be aware of that. I think that a possible better solution for a further PR could be to validate the settings (and eventually set to default supported values) that will be displayed in the GUI (read from config.yml or custom config.yml for a specific game) before displaying the values in the GUI. I see that this is made for some settings such as TSX Instructions, Thread Scheduler, Graphics Device etc. (e.g. if I copy a config.yml generated from my laptop having TSX support to my desktop PC not having TSX support then in the GUI the TSX Scheduler setting is properly greyed out. If that validation could be extended to all settings I think it will be another nice improvement. But that is only my thought.
That improvement maybe could be applied (probably not for OpenGL as per you clarification) on the dropdown in case one of the possible values is not applicable on that target HW

@kd-11
Copy link
Contributor

kd-11 commented Jan 10, 2025

Only possible values with rpcs3 are:

  • No vsync
  • Adaptive sync on OGL (tearing if fps is below desktop refresh)
  • Fast sync on Vulkan (pick latest available slot, repeat frame if full)
  • Full vsync (slow slot-based queue with stalling when full)

@digant73
Copy link
Contributor Author

they are good to me IMO.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants