-
Notifications
You must be signed in to change notification settings - Fork 1.2k
WPF Rendering issue on any machine #4276
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
Comments
Duplicate of #2158 ? |
@Erapchu: Thank you for the report and investigation. Are you okay with us closing this as a duplicate? Thanks. |
Of course. But I want to know why it's happen and how to resolve for now. Future - update will be applied to new .NET version? Not for old like .NET framework? |
I did some investigations. |
Setting up BitmapCache to root Grid of the window and Ctrl + Alt + Del invokes problem even if first window was showed, but not focused. |
We are also stuck with this problem, before in Windows 7 it was much less problematic, we only had to force an invalidate visual and it seemed to fix the issue. But in Windows 10 now it is much worst, I can't believe Microsoft does not fix such a huge bug. We can't disable the bitmap cache and can't disable HW acceleration, because we have a very big complex application, we can't simply close and re-open the window. And knowing that the original bug since windows 7 was never work on ... I have very low expectation from Microsoft, so we had to find a work around. So, if anyone is looking for an other workaround... it's a bit nasty but I think it is the only way to recover while keeping your current WPF window open, if you can run with admin privilege, you have to kill dwm.exe everything will flicker and recover. If you can't run as admin, you have to create a GPU virus and hang it out in an infinite loop, that trigger the hang device watch dog of Windows that unload and reload this device, here is how to do it programmatically, last answer here: https://gamedev.stackexchange.com/questions/108141/how-can-i-test-dxgi-error-device-removed-error-handling This work surprising well, after all the screen flicker for couple of seconds everything is back working. Now our only last issue is to detect when we have to run that virus, we can detect the session unlock but not the UAC security prompt (only work with admin right) |
@HyksosSowo the only one solution is don't hide windows, but close and re-open them. Close it completely when bitmapcache is in visual tree |
Hey, we've been running into this issue for a while as well and have finally come to a stable (but not ideal) solution to this issue. I couldn't tell you why this works unfortunately (but hopefully it can help narrow down the issue). It's also worth noting that if you're creating
I hope this helps someone out there, as it was a huge pain to find! |
Can still reproduce in .NET8. I'm trying to mitigate the issue by invalidating all UIElement.CacheMode within a window. But as soon as you restore any CacheMode, WM_PAINT frenzy start all over again. And if you don't restore CacheMode you're still getting half frozen DropDown elements. Hook WndProchwndSource = PresentationSource.FromVisual(this) as HwndSource;
hwndSource.AddHook(WndProc); On WM_PAINT, store non-null CacheMode, and set to nullconst int WM_PAINT = 0x000F;
private Timer WM_PAINT_TIMER;
private Dictionary<UIElement, CacheMode> cacheModes = new();
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_PAINT:
{
// Loop through all visual elements in the window
foreach (var element in WPFUtils.FindVisualChildren<UIElement>(this))
{
if (element.CacheMode is null)
continue;
// Store the previous CacheMode value
cacheModes[element] = element.CacheMode.Clone();
// Set the CacheMode to null
element.CacheMode = null;
}
WM_PAINT_TIMER.Stop();
WM_PAINT_TIMER.Start();
}
break;
}
return IntPtr.Zero;
}; Restore non-null CacheModeprivate void WM_PAINT_TIMER_Tick(object? sender, EventArgs e)
{
// UI thread
Application.Current.Dispatcher.Invoke(() =>
{
// Set the CacheMode back to the previous value
foreach (UIElement element in cacheModes.Keys)
element.CacheMode = cacheModes[element];
});
} FindVisualChildren// Helper method to find all visual children of a given type
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent) where T : DependencyObject
{
if (parent != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is T)
{
yield return (T)child;
}
foreach (var childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
} |
@Erapchu we can't close the window. We also can't use the transparency trick as our WPF window is inside a HwndSource. The GPU virus is still the only solution that reliably work. |
@HyksosSowo try to disable hardware acceleration for that window https://stackoverflow.com/questions/2169600/how-hardware-acceleration-can-be-disabled-in-wpf |
Obviously it works but it's like turning off a few cylinder of your engine because it misbehaves. It suxx... |
We are not using WPF for simple dialog box, we are using it to load huge animated graphics, we can't use software rendering... and the funny thing is to get good performance we need HW acceleration + bitmap cache or else it suxx. |
I also faced same issue, I am using many HLSL shaders and D3DImage in my WPF UI. Only solution I came up with is to create a empty D3DImage and assign IsFrontBufferAvailableChanged event. internal void IsFrontBufferAvailableChanged_Event (object sender, DependencyPropertyChangedEventArgs e)
{
if (D3DImageSource.IsFrontBufferAvailable)
{
// Recover from software rendering and switch back to HW acceleration
System.Windows.Media.RenderOptions.ProcessRenderMode = RenderMode.Default;
}
else
{
// Will stop WM_PAINT flood
System.Windows.Media.RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
}
} Keep this D3DImage somewhere hidden in your window, This works fine and will invalidate Some finds I faced during working on this issue using injectors and reverse engineering :
NEW UPDATE Here's a solid solution and it also smooth out animations : |
Problem description:
WPF windows stop rendering at all when use BitmapCache on any window's control or root control and first shown WPF window was hidden by set Visibility to Hidden or call Hide() method.
Actual behavior:
There's no exceptions or fatal crashes. All WPF windows that use BitmapCache just stop rendering at all! While FIRST hidden window will not be shown.
Expected behavior:
WPF Windows should render normally.
Minimal repro:
Please follow this steps to catch problem on your machine or build any project below. Please, help me resolve it.
https://github.com/Erapchu/GhostWindows
https://github.com/Erapchu/GhostWindowsCore
In App.xaml.cs OnStartup overrided method:
var window1 = new MainWindow(); window1.Show(); await Task.Delay(1000); window1.Hide(); var window2 = new MainWindow(); window2.Show();
The text was updated successfully, but these errors were encountered: