AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
26.09k stars 2.26k forks source link

Support 120 fps for Win32RenderingMode.Wgl #16417

Open MeltyPlayer opened 4 months ago

MeltyPlayer commented 4 months ago

Is your feature request related to a problem? Please describe.

Currently, Win32Platform is hardcoded to run at 60fps here: https://github.com/AvaloniaUI/Avalonia/blob/c47fd63e6246789d95bcff626746c7ed63f96e35/src/Windows/Avalonia.Win32/Win32Platform.cs#L88

Describe the solution you'd like

LinuxFramebufferPlatform currently supports customizable FPS: https://github.com/AvaloniaUI/Avalonia/blob/c47fd63e6246789d95bcff626746c7ed63f96e35/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatformOptions.cs#L12 https://github.com/AvaloniaUI/Avalonia/blob/c47fd63e6246789d95bcff626746c7ed63f96e35/src/Linux/Avalonia.LinuxFramebuffer/LinuxFramebufferPlatform.cs#L65-L67

It'd be nice if Win32Platform had this same support, primarily to support high-framerate displays (i.e. 120+ fps) but also to potentially cap at lower framerates for lower spec hardware (i.e. 30 fps).

Describe alternatives you've considered

No response

Additional context

Since this appears to have been a very tiny change for Linux, it seems like this would be very simple to implement. Given that this hasn't been added yet, I wanted to reach out to ask if there were any concerns that were blocking this--for example, perhaps Avalonia isn't optimized enough yet to support high FPS, or behavior is buggy at higher framerates?

I have a fork that adds this functionality in, so if there were no concerns I'd be happy to submit a PR for this feature: https://github.com/AvaloniaUI/Avalonia/compare/master...MeltyPlayer:Avalonia:master

rabbitism commented 4 months ago

Related https://github.com/AvaloniaUI/Avalonia/issues/14073#issuecomment-1873488557

maxkatz6 commented 4 months ago

Currently, Win32Platform is hardcoded to run at 60fps here:

It's not. It uses display VSync by default, where you can't change framerate, it can go far higher than 60fps normally. You can disable it in CompositionMode option, but it's not advised. Adding FPS option might be confusing, as changing its value won't affect majority of Avalonia apps.

60 is only forced when other render timers are used, like a fallback for older systems or when ShouldRenderOnUIThread is used.

LinuxFramebufferPlatform currently supports customizable FPS:

Framebuffer doesn't have any vsync, so that's the only option there, yes.

MeltyPlayer commented 4 months ago

Currently, Win32Platform is hardcoded to run at 60fps here:

It's not. It uses display VSync by default, where you can't change framerate, it can go far higher than 60fps normally. You can disable it in CompositionMode option, but it's not advised. Adding FPS option might be confusing, as changing its value won't affect majority of Avalonia apps.

60 is only forced when other render timers are used, like a fallback for older systems or when ShouldRenderOnUIThread is used.

LinuxFramebufferPlatform currently supports customizable FPS:

Framebuffer doesn't have any vsync, so that's the only option there, yes.

Ah, thanks for the clarification!

Based on my experience, it really did feel like Avalonia was locked at 60 fps, since even the smallest possible OpenGL app (i.e. just clearing the screen) would only run at 60 fps. However, I tried out the Avalonia sample projects and noticed those were indeed running at 120 fps.

I've narrowed down the issue I was seeing to the following code in the AppBuilder:

.With(new Win32PlatformOptions {
    RenderingMode = [Win32RenderingMode.Wgl],
})

When the RenderingMode is set to Win32RenderingMode.Wgl, the highest my app can go is 60 fps; when this is removed, it can go up to 120 fps. It looks like you mentioned this in a different issue actually, I just hadn't noticed that when I was first investigating this. https://github.com/AvaloniaUI/Avalonia/discussions/13125#discussioncomment-7205156

maxkatz6 commented 4 months ago

Yeah, you are correct. Wgl won't support CompositionMode vsync. We might need to use wglSwapIntervalEXT in order to support similar behavior there. If not, it's better to add FPS config selector to new WglOptions class or similar and not common Win32PlatformOptions.

Btw, why do you need WGL? Normally, we don't recommend it, unless it's necessary for your dependencies.

MeltyPlayer commented 4 months ago

Ah, sounds good! Yes, it doesn't necessarily need to be in Win32PlatformOptions, just wherever would be best for Avalonia in the long term.

I need Wgl because my Avalonia app uses OpenTK to render a 3D view, I've hooked into Avalonia's OpenGL logic using an approach similar to this library: https://github.com/SamboyCoding/OpenTKAvalonia

Any other Win32RenderingMode results in memory access violations when starting the app; the README for the above project states this is due to the following:

Note that, in order for events to be called on Windows, Avalonia must be able to load the OpenGL bindings, which requires switching the default rendering mode.

Without this, your control simply will never receive any of the OpenTK events (Initialization, Teardown, and Render).

maxkatz6 commented 4 months ago

Note that, in order for events to be called on Windows, Avalonia must be able to load the OpenGL bindings, which requires switching the default rendering mode.

Is it still true with Angle OpenGL though, which is default? Normal OpenGlControlBase works there just fine.

kekekeks commented 4 months ago

WGL isn't really supported as the primary backend. If you need to present non-ANGLE OpenGL rendering, use WGL_NV_DX_interop2, ID3D11Texture and https://github.com/AvaloniaUI/Avalonia/issues/9925