Problems with Gameloop when using VSync in windowed mode - c#

I readed some articles about RenderLoop inside C# using SharpDX but all has the same problem.
Using this loops it's fine for rendering at V-Sync rate except when some events happens.
For example dragging the window or right clicking mouse over window bar(opening menu) will stop the Loop. There is a way to avoid this? I want(even not refreshing the control) a stable 60 FPS loop.
I am rendering on a Control(Panel) and i need this.

The OP has surely resolved this issue by now, but since there are no answers after 3 months, here is mine:
Don't use SharpDx VSync when running in a window -- it's not meant for that, and will certainly cause contention & deadlocks. VSync is only helpful when you own the entire screen.
Just present your swapChain and let the window manager show it when it can, and you'll get the highest frame rate you can feed.
This same thing bit me a while back, and although I didn't find the answer anywhere in the documentation, it's obvious when you think about it: it would be impossible for windows to manage the desktop if each window tried to coordinate with VSync independently.
bool vSync = false; // vSync should not be used in windowed modes -- may cause UI deadlocks when resizing form windows
swapChain.Present(vSync ? 1 : 0, PresentFlags.None, new PresentParameters()); // requires v11.1

Related

Is there a way to reduce or prevent form flickering when using WPF?

I'm actually having 2 different flickering issues:
(1) When I create a form with border style set to none, anytime I resize the window there is a good amount of flickering along the edges of the form. This is especially noticeable if I try to resize the form from the top left corner.
(2) When I minimize the form and restore it from the taskbar, for a (very) brief second in the top left corner where the title would normally be you can see a rectangle shape flicker. I think this might be normal windows behavior but it has just become more noticeable due to WPF removing the windows minimize/maximize animations. If I can't fix the flickering directly this way, is it possible to restore the min/max animations without using hacky solutions such as setting the bordersize just before the form minimizes?
Thanks for reading!
I was fighting the same issue you mention in #1 and it is not specific to borderless WPF forms (though it appears to be dependent on both draw timing and window styles, both of which may change when you change border types). It happens with native apps and apps with full borders as well.
In Windows 10 you can actually see the same type of flickering in Windows Explorer itself when you use the left and/or top window borders.
From my investigations there appear to be at least two overlapping causes, one that dates from pre-Aero days and one that was added on top by Aero. The pre-Aero cause has a workaround but the Aero one still only has a partial solution. Please see this roundup Question/Answer which brings together 10 years of posts on this topic and offers some new insights (too long to paste the content here in this question). Enjoy:
How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?
Yes, I know on SO the convention is to mark the original question as a dup rather than linking from one question to another, however this case is a bit unusual. My roundup post refers to more than 30 questions on this topic and brings together the most important ideas from them, but it does not include all the ideas from the original questions...that would be impractical. So I don't actually want to see the original questions marked as dups, nor mine, since either way, useful info would be lost. That is because window resize is a broad topic; this Q covers some aspects, my Q covers others.

CPU Throttling Issues with WPF

I am working on an application in WPF using Vlc.DotNet. I was having an issue with the video playing back with a terrible frame rate on my laptop.
After some research I identified that the issue is related to the CPU throttling down. If the laptop power profile is in BatterySaver mode it has the issue. If I switch it to performance, everything works fine. It seems to me like in BatterySaver mode it allows the processor to throttle down, and for some reason doesn't throttle back up correctly when the application needs it to. Is there anyway I can fix this issue?
I tried setting the priority with the code below and it didn't seem to make a difference.
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Vlc.DotNet updates and ImageSource with the next rendered image. I have this source bound to an Image on the GUI that displays it. I used the WPF Performance Kit and can see what is happening, but not why. As soon as it starts playing, AKA updating the image on the GUI at 30fps, the frame rate of the entire application drops down to around 5fps.
Have you tried switching to software rendering to avoid the bottleneck of CPU power downs? I know WPF uses a separate thread for rendering and I'm not sure if you can even access it from Process.Threads. What I've done in the past is attach to the power mode changed event and switched the mode dynamically like this so power mode changes don't switch to hardware rendering. Not sure if this will work as I don't what your specific bottleneck is, but hopefully this points you in a good direction.

WPF: GDI drawing in other process flickers

There are quite some topics available about GDI drawing and flickering issues, but I haven´t been able to find any regarding drawing in an other process.
The issue
Basically I´m trying to draw to a Hwnd using Graphics.FromHwnd. This works perfectly, but there is a lot of flickering involved. The application I´m trying to draw on is a game (not made by me) and has quite a high refresh rate, unlike forms.
Attempts
I´ve tried doing the drawing both using a GDI.Rectangle function that used the HDC to draw and using Graphics.DrawRectangle to draw to the Hwnd. I don't notice a difference in performance but 'Graphics' seems a bit easier in use since it doesn't need gdi32.dll to draw shapes, unlike GDI.
I've also tried doublebuffering but yet again I do not notice any difference.
To me it seems that the doublebuffering is not working because of the fact that I'm trying to draw in such a high refresh rate window.
Question
Is it possible to get the window's refresh rate and use that for a timer to update the graphic?
is it possible to make graphics 'stick' until updated so they don't automatically disappear?
If anyone knows how to do this, or knows other solutions to get rid of the flickering I would appreciate the help!
Thanks in advance.
After doing some research I've come to the conclusion that using a transparent window will suit my case best. Here's how I came to that conclusion:
I've used an application to read window events to check if there was any continuous event stream that could be the window invalidation, but there wasn't.
I did find out a way that should make it possible to actually read when the game invalidates the window, but it's kind of a hack: It's possible to replace the game's d3d9.dll file with your own, calling all the original functions, but catching the events. I don't have any details on how or even if it works since having to distribute a dll to end-users is not an option for me, not to mention that this is in fact hacking.

Performance Issues with SharpDX and D3DImage

I have a control that uses D3DImage to host a SharpDX DirectX9 surface and allows use to pan, zoom, and interact with world objects and the result is really awesome. Performance is actually an amazing consistent 60fps EXCEPT when the window is minimized and brought back up or the user locks and then unlocks the screen. When the window regains focus the fps drop to about 25-30fps. I can "fix" the issue by unloading and loading the control back into its container and then BOOM, 60fps.
I call the main render function using a DispatcherTimer set at 10ms. Before, I was using the CompositionTarget.Rendering event but performance wasn't as good as using the DispatcherTimer. I fairly certain that I'm handling lost resources correctly. Any ideas about these missing frames per second?
EDIT: I am having this same exact problem. Unfortunately, doing an automatic device reset doesn't fix the issue but if I have a button that executes the same reset method then my fps goes back to normal.
Locking / Unlocking the screen causes a device lost. But you probably know that.
Anyway I use D3DImage in WPF as well. My performance problems ended when I called
D3DImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero)
on each device lost. I used to have responsiveness issues after a device lost until I realized WPF was still holding a reference to a texture. Of course you should later re-set the backbuffer when you have an updated texture.
Although it is unclear what exactly is going wrong behind the scenes, it is clear that D3DImage keeps a refcount to your texture, which can prohibit a successful recovery in the case of a device lost. In my case, we simply had no updates.
Sorry for the anectodal answer... But until a real D3DImage expert enters the room, it's better than nothing.
P.S. I am using SlimDX but I don't think it matters... For all that I know SharpDX is a fork of SlimDX.
There's an overload to SetBackBuffer that takes an additional Boolean flag:
D3DImage.SetBackBuffer(D3DResourceType, IntPtr, Boolean)
When you call the SetBackBuffer(D3DResourceType, IntPtr) overload, or call the SetBackBuffer(D3DResourceType, IntPtr, Boolean) overload with the enableSoftwareFallback parameter set to false, the [WPF] rendering system releases its reference to the back buffer when the front buffer becomes unavailable and nothing is displayed.
I'm no expert either, but I would guess that this is what's happening; Because you didn't set that flag to 'true', WPF is calling Release() on what happens to be the last COM ref count for your D3D surface as soon as it exits the lock. This would seem to require that you be maintaining an additional ref count of your own.
For one thing, I've noticed that, even after getting your "used" surface "back" from a WPF lock/unlock round-trip, you need to still not release it until your next surface takes its place (i.e. in a successful call to d3dimg.SetBackBuffer). Otherwise, you'll get flickering when the WPF window is dragged around the screen. Given that that's the only reliable method I've discovered for detecting when WPF is truly done with your buffer, it does seem pointless for WPF to be concerned with AddRef'ing or Release'ing it.
What's generally confusing with D3DImage is that the IDirect3DDevice9 that's running WPF is not really associated with the IDirect3DDevice9 that generated the surface you're putting forth as a back buffer... for WPF. The whole Lock/Unlock business is presumably for WPF's benefit, and has nothing to do with your own (possibly lockable?) IDirect3DSurface9 rendertarget's survival.
Beware!If using D3DImage.TryLock, beware of its, um... shall we say, unconventional semantics: You must call Unlock even in the case where TryLock returns false. For more information, see https://stackoverflow.com/a/39581727/147511.

WPF video tearing on Windows XP

I've created a WPF application using C# that renders about 50 3D elements and animates the camera in order to move around the scene.
While it all works, I've noticed as the camera moves, ugly video tearing occurs.
I'm well aware of the standard cause of tearing, ie the application is updating frames at a different rate from the monitor/adapter vertical sync.
I've also read that the default screen update rate in WPF is 60 frames per second and that on XP WPF updates without regard to the montior v-sync.
For certain scenes the tearing is less noticeable, but often it is distracting enough to be a real problem.
I'm really hoping there is a resolution, after all Windows Forms has had double buffering for years. Moving to WPF is actally a backward step for many types of application if there is no resolution.
So, on Windows XP, how can I configure WPF to remove tearing?
I'm looking for more helpful answers then "move to Vista". This is simply out of the question for many of the future users of this application.
No answers yet, surely with the number of WPF developers out there someone else has seen this problem?
In the meantime I've investigated/read some more and have come across the Timeline.DesiredFrameRate property.
With my display running at 50hz vertical refresh I tried setting this to 50 FPS in the hope this would brings things in sync. Unfortunately this had no effect on the tearing.
However, I did have to apply it to a single specific animation I created (in code) using BeginAnimation(). I'm not sure how this would affect a "global" framerate at all.
Instead, I would have expected to need to do this at a more global level, say on the viewport, however I couldn't find DesiredFramerate property on the viewport object.
Another area to look at could be the RenderCapability.Tier but I haven't had the time to look in detail yet.
[Update]
No solution but a useful tip. To set the DesiredFramerate globally (ie for all animations in the viewport) you can override the PropertyMetadata for the
Timeline.DesiredFrameRateProperty dependency property:
// Set the global desired framerate to 50 frames per second
Startup += delegate(object sender, StartupEventArgs e)
{
Timeline.DesiredFrameRateProperty.OverrideMetadata(typeof(Timeline),
new PropertyMetadata(50));
};
It's best to place this in the constructor of the standard WPF Application class.
Unfortunately this didn't solve my problem because even setting it to FPS, it must not be synced accurately enough with monitor v-sync.
It is handy to know about though, particularly if you have slow moving animations and want to save CPU usage by setting the FPS much lower then the default 60fps.
[Update]
Setting the DesireFrameRate to some very high value such as 100+ seems to reduce but not remove the flicker. One big drawback however is that the CPU (on my 4 yo PC) goes to 35%.

Categories