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

WPF - Putting a window into fullscreen severely degrades performance #3626

Open
ajbadaj opened this issue Oct 10, 2020 · 19 comments
Open

WPF - Putting a window into fullscreen severely degrades performance #3626

ajbadaj opened this issue Oct 10, 2020 · 19 comments
Labels
Performance Performance related issue
Milestone

Comments

@ajbadaj
Copy link

ajbadaj commented Oct 10, 2020

  • .NET Core Version: 3.1.302
  • Windows version: Windows 10
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: I do not know
  • Is this bug related specifically to tooling in Visual Studio (e.g. XAML Designer, Code editing, etc...)? No
  • Security issues and bugs should be reported privately, learn more via our responsible disclosure guidelines.

Problem description:
I am building a .NET Framework 4.7.2 application. This is an issue I've noticed for several years though, so going back a few versions.

Essentially, I put a window into "fullscreen" mode by setting WindowStyle=None and WindowState=Maximized and Topmost=True. I do not know of another way to do that. Being in fullscreen results in a moderate loss of performance.

In my case, specifically, I have images on a canvas, and I am zooming (via mouse wheel) and dragging them around. I notice when my app is in fullscreen the dragging can lag severely, and the zooming chunks very heavily.

Actual behavior:
Fullscreen reduces performance.

Expected behavior:
Fullscreen does not reduce performance. In fact, historically with DirectX applications, performance is increased.

Minimal repro:

  • Create a wpf application
  • Build it to do something slightly resource-intensive, (in my case I have an application that is moving images around on a canvas w/ zoom, etc.)
  • Run application (in my case I have tried running Release x86 & Release x64 to the same effect)
  • Perform the resource-intense operation (in my case dragging image around on cavnas + zoom w/ mouse wheel) - noticing that it works smoothly
  • Put it into fullscreen via WindowStyle=None & WindowState=Maximized & Topmost=True
  • Re-perform the resource-intense operation, notice it does not work smoothly
@ClosetBugSlayer
Copy link

It feels like WPF's problem is that it allocates too many VRAM buffers for its compositing, Somebody needs to deep-dive the primitives code.

@ryalanms ryalanms added the Performance Performance related issue label Oct 16, 2020
@ajbadaj
Copy link
Author

ajbadaj commented Oct 29, 2020

In my current use case, I just noticed that the "AnyCPU" configuration is performing much better than x64 configuration. Obviously performance degradation in x64 vs a 32-bit version is the opposite of what you would expect.

For reference, in my project, I have...

===Any CPU===
Platform Target: Any CPU
Prefer 32-bit: true

===x64===
Platform Target: x64
Prefer 32-bit: false (only option obviously)

Seemingly same results with/without debugger, release or debug.

@Landius4
Copy link

Faced the same issue today, sad story
@ajbadaj does this fix the performance issue, or just ease it a bit? I mean Build config

@Landius4
Copy link

Landius4 commented Oct 30, 2020

@ajbadaj https://stackoverflow.com/questions/47043036/wpf-fullscreen-window-3d-rendering-performance check this, maybe it's related to that window is slightly bigger than your display/screen?

@Landius4
Copy link

Moreover, I can provide a piece of sh.. code which helped me:
public void MaximizeToScreen(Window window, System.Windows.Forms.Screen screen) { if (screen != null) { window.WindowState = System.Windows.WindowState.Normal; window.Left = screen.WorkingArea.Left + 50; window.Top = screen.WorkingArea.Top + 50; window.WindowState = System.Windows.WindowState.Maximized; window.Height = screen.WorkingArea.Height - 50; window.Width = screen.WorkingArea.Width - 50; } }

Doubt that this is the best solution, also I use System.Windows.Forms to switch monitors, but this 50 px I add or sub help. And even don't affect the window size, it's still fullscreen but no lag.

@ajbadaj
Copy link
Author

ajbadaj commented Oct 30, 2020

@Landius4

Question 1) Does it fix perf fully to switch build configurations.
I can't say if it would be completely better, but for my scenario it's enough where I would mark it as complete if it did that in x64.

Other point about working area, etc. The issue isn't that I can't calculate a working area, I am already essentially doing what you're suggesting though in a different way, but I'm still not convinced it is the source of the lag (it does not scale up with window size), and the extra 100px^2 wouldn't make much of a difference.

For reference, my scenario is that I'm building a composite image scene of a varying amount (typically 20-50) of images of various sizes, some very large (over 5k pixels in the largest dimension), some moderately small (64px in the largest dimension), all in a canvas with panning/zooming/etc. It works smoothly in WindowState.Normal mode, even if I size the window to be similar to what it would be in fullscreen, it just has issues in fullscreen (and now I've discovered primarily in x64 fullscreen).

@ajbadaj
Copy link
Author

ajbadaj commented Nov 24, 2020

This miiigght be better in .net 5. I have to do more extensive tests, but preliminary results are that I'm impressed!

@connordear
Copy link

connordear commented Jan 12, 2021

I have built very similar functionality in my WPF application and can confirm the issue persisted in Framework 4.8. I also tried migrating to .Net 5 but still experienced similar issues.

The performance issue first came to me as noticing that on some machines the performance was only smooth when the app window became deactivated (e.g. alt+tabbing out). I believe these may be correlated? #3982

EDIT:
I was able to restore performance in fullscreen mode (WindowState="Maximized" WindowStyle="None") by modifying the WindowChrome WindowThickness:

See post further below for my updated soln.

This link described another rendering problem, and related it to the ActualHeight/ActualWidth reported properties being larger than the set resolution.

I'm wondering if these are performance issues related to the application extending beyond the display and then causing issues with certain video drivers.

@dsun1
Copy link

dsun1 commented Jul 12, 2021

I believe I'm encountering the same problem in an application I'm working on.

Using WPF performance suite, I can see the FPS almost exactly halves when fullscreen compared with an almost fullscreen window.

This also happens when I have a window that isn't fullscreen, but is split between two monitors. Funnily enough this doesn't happen between my 4k laptop screen and 1440p monitor, but does happen between two identical 1440p monitors?

I notice the HW IRTs per frame almost exactly doubles at the same time. This leads me to guess WPF is rendering the same window twice for some reason, thus the framerate halves. This also makes sense with the observation that it happens if I have the app on two monitors. Probably some sort of Windows bug that causes apps to sometimes render twice on multi monitor setups(sometimes)?

Using the above solution does not help for me as I think some part of the client area is still extending into another monitor, but removing windowchrome entirely and having the built-in chrome stops the fullscreen lag from happening, however the program FPS still halves when split across my two 1440p screens.

Just my two cents and observations.

@connordear
Copy link

@dsun1 I actually did have this issue come back actually (mine was only appearing on specific hardware) and had to fully change the way I was handling fullscreen in order to get it to work.

Instead of using WindowState="Maximized" WindowStyle="None", I used:

    ...
    WindowStyle="SingleBorderWindow"
    WindowState="Normal"
    ...
     <Window.Style>
          <Style TargetType="{x:Type local:ApplicationView}">
              <Setter Property="WindowChrome.WindowChrome">
                  <Setter.Value>
                      <WindowChrome
                          ResizeBorderThickness="0"
                          CaptionHeight="0"
                          CornerRadius="0"
                          GlassFrameThickness="0"
                          />
                  </Setter.Value>
              </Setter>
          </Style>
      </Window.Style>

And then bound my height/width of the view to the size of the screen to achieve fullscreen. IIRC the WindowStyle="SingleBorderWindow" needed to be anything other than None. My application will always be bound to a single monitor so I don't have the multiple monitor issue, but I wonder if changing WindowStyle to something else may also help your issue. Nice observations about the specific FPS numbers.

@legistek
Copy link

Does this issue occur for you all if set your display settings to only use a single monitor? In other words does the issue occur only when you have 2 or more monitors in extended desktop mode?

If so then this is a very old issue that has to do with the fact that "maximized" windows actually spill over by a few pixels onto the second monitor, which destroys Direct3D (the core of WPF) performance. The only solution is to manually set your window bounds to equal the size of the Screen - NOT to use the Maximized state.

@lindexi
Copy link
Contributor

lindexi commented Aug 14, 2021

@ajbadaj Using WindowStyle=None & WindowState=Maximized & Topmost=True does not seem to be a good way.

Could you try my demo code to enter full screen?

My demo: https://github.com/lindexi/lindexi_gd/tree/5b0440c6617b87cdd9953dc68e706b22c5939ccb/KenafearcuweYemjecahee


Update:

This feature was merged to https://github.com/HandyOrg/HandyControl

And you can use it by install https://www.nuget.org/packages/HandyControl


Update:

Adding ITaskbarList2::MarkFullscreenWindow : https://github.com/lindexi/lindexi_gd/tree/46e400d9d4601730c1f5c974ea568416453fe48d/KenafearcuweYemjecahee

@ajbadaj
Copy link
Author

ajbadaj commented Aug 18, 2021

@connordear - that's a cool solution! As you said, focused on single monitor which is a bit tough, but it will certainly avoid the problem!

@ajbadaj
Copy link
Author

ajbadaj commented Aug 18, 2021

@lindexi - I will give it a go when I have some time, I peeked at it just now and I like the idea!

@ajbadaj
Copy link
Author

ajbadaj commented Aug 18, 2021

@legistek - I think that is likely, but I'm not positive as I am taking steps to avoid that already as it's not aesthetically a great situation either. Maybe what I'm doing isn't enough to actually avoid it though, it's worth a shot - I'll give that a go!

@legistek
Copy link

not aesthetically a great situation either.

Oh that's an understatement! I have to do window sizing and manipulation completely from scratch. Everything down to double-clicking on the caption bar "maximizes". It's a horror show. But it was all I could come up with. If you find another solution would be very curious to see.

@ryalanms ryalanms added this to the Future milestone Aug 27, 2021
@s-struk
Copy link

s-struk commented Dec 4, 2023

Try to set CoreCompatibilityPreferences.EnableMultiMonitorDisplayClipping=true before initializing app.
You can set this property using manifest file as well.

@legistek
Copy link

legistek commented Feb 1, 2024

@s-struk that seems to cause the application to completely freeze when it uses WebView2.

@lindexi
Copy link
Contributor

lindexi commented Jun 1, 2024

@lindexi - I will give it a go when I have some time, I peeked at it just now and I like the idea!

Do you test my demo? Thank you.

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

No branches or pull requests

9 participants