helix-toolkit / helix-toolkit

Helix Toolkit is a collection of 3D components for .NET.
http://helix-toolkit.org/
MIT License
1.88k stars 669 forks source link

Hang when a screen is connected/disconnected #1531

Closed kthyholdt closed 3 years ago

kthyholdt commented 3 years ago

When using SharpDX WPF without SwapChainRendering the GUI will hang at surfaceD3D?.InvalidateD3DImage() in DX11ImageSourceRenderHost PostRender() method. This can be tested with the SimpleDemo Example for WPF, just unplug a screen and it will hang. We have tested it on 3 different machines with different hardware, all running Windows 10, and it happens on all of them.

if I change the SurfaceD3D_IsFrontBufferAvailableChanged method to the following it seems to work,

` private void SurfaceD3D_IsFrontBufferAvailableChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e) { if (EffectsManager == null) { return; }

Logger.Log(HelixToolkit.Logger.LogLevel.Warning, $"SurfaceD3D front buffer changed. Value = {(bool)e.NewValue}");
if ((bool)e.NewValue)
{
    frontBufferChange = false;
    try
    {
            EndD3D();
            if (surfaceD3D != null)
            {
                hasBackBuffer = false;
                surfaceD3D.SetRenderTargetDX11(null);
                // surfaceD3D.IsFrontBufferAvailableChanged -= SurfaceD3D_IsFrontBufferAvailableChanged;
                RemoveAndDispose(ref surfaceD3D);
            }

            EffectsManager.DisposeAllResources();
            EffectsManager.Reinitialize();
    }
    catch (Exception ex)
    {
        Logger.Log(HelixToolkit.Logger.LogLevel.Error, ex.Message);
    }
}
}

`

But I guess someone with actual knowledge of what the code I have removed does might see why this is a bad idea.

kthyholdt commented 3 years ago

The inserted code is bugged, can also be found here: https://paste.ofcode.org/gyUUpQturzhY8vZYnztkwL

eriove commented 3 years ago

I've noticed the same exception. My main screen "disconnects" when it goes into power saving mode, so I get this after every break long enough trigger the power saving mode of the screen. Hopefully your fix might solve it.

holance commented 3 years ago

Is your computer having two gpu?

kthyholdt commented 3 years ago

2 of the 3 computers tested have two gpus. All of them have integrated Intel gpus. And two have Nvidia gpus as well.

holance commented 3 years ago

I believe it is caused by GPU switching during monitor changes.

holance commented 3 years ago

I am having hard time reproduce the issue on two of my laptops with 2 GPUs. Could you put a break point in this function and check whether there is any flag I can use to determine whether the EffectsManager.Device is still valid?

kthyholdt commented 3 years ago

We tested with disabled internal graphics from bios, so only the Nvidia card was active, and it still hangs. Not sure if I understood what you asked for, but here is a screenshot from the properties on EffectsManager.Device from a breakpoint inside SurfaceD3D_IsFrontBufferAvailableChanged when I closed my laptopscreen. This would make it hang with the old function.

image

kthyholdt commented 3 years ago

When researching this I found that disabling Hardware acceleration for WPF according to this link "fixed" the issue, but this affected the FSP and made everything unresponsive. Have you enabled this by any chance?

https://docs.microsoft.com/en-us/dotnet/desktop/wpf/graphics-multimedia/graphics-rendering-registry-settings?view=netframeworkdesktop-4.8#disable-hardware-acceleration-option

holance commented 3 years ago

Could you disable the nvidia graphic card and try if this is still happening?

kthyholdt commented 3 years ago

We just tested this on a computer without Nvidia card. It only has one card, a "Intel Iris Pro Graphics 580". And the same thing happens. With the original SurfaceD3D_IsFrontBufferAvailableChanged it hangs, with the modified it continues to work.

Do you know why the DeviceRemovedReason is used? From what I gather, it looks like this check will return true since the default value for this is Success, and there has not necessarily been a DeviceRemoved error.

kthyholdt commented 3 years ago

I was able to get the DeviceState from DX11ImageSource when this happens with device.CheckDeviceState((IntPtr)null); When it hangs the DeviceState is DeviceState.PresentModeChanged.

holance commented 3 years ago

@kthyholdt Could you help me to apply the changes in PR #1533 and test if it works?

eriove commented 3 years ago

If needed I can test this the next time I'm in the office (the only place where I can reliably reproduce it). I was planning to go there on Monday but will most likely have to cancel that.

If this works for you, just go ahead and merge. I'll test next time in the office and if it doesn't work it was most likely something related, but not exactly the same. In that case I'll just open a new issue.

holance commented 3 years ago

Let's wait for verification before merging.

oyvindse commented 3 years ago

I'm having the same issue on my setup. I tested with your PR applied, but that did not seem to fix the problem for me. I'm still able to reproduce the error by unplugging one of my monitors, or by pressing "win+p" and change modes between duplicate/extended displays.

eriove commented 3 years ago

I couldn't go the the office today, not sure when the next opportunity will be, will keep tracking this issue and check once I go there

kthyholdt commented 3 years ago

@holance I've tested the pull request, and the issue persists. I found out that by enabling the StopRendering(); that was commented out in the same function, there were some improvement to some cases. But there seems to be a lot of different behavior. With the StopRendering() enabled I only have issues when opening the laptop lid while there is one other screen connected, closing the lid is fine. Or when changing modes as @oyvindse mentioned with Win+P between duplicated and extended displays. The issue when disconnecting and connecting a cable seems to be gone.

It seems that when DeviceState is PresentMode it works as it should now. But when changing between duplicate and extended the DeviceState is Ok and it will raise the Event IsFrontBufferAvailableChanged 3 times with IsFrontBufferAvailable beeing false, true then false again. After that the screen turns black, but the program is responding.

smischke commented 3 years ago

Might be related to #963, #1259.

holance commented 3 years ago

I am having hard time reproduce any of the issues :( Could you guys try to upgrade the graphics card driver and test if there is any differences?

eriove commented 3 years ago

Which Windows version are you using? I'm using 1809 (LTS). We seem to have different GPUs (I have a AMD Radeon Pro WX 3100) so driver seems less likely, hence it could be a Windows version difference as well. I seem to recall that something in the graphics driver model had an overhaul, but I can't remember at which version.

holance commented 3 years ago

Are all of you using desktop computer? I only have laptops with discrete graphics card.

eriove commented 3 years ago

I'm working on a desktop computer, but @kthyholdt mentions a lid so I'm assuming he is testing on a laptop.

I don't get the problem when connected with RDP, only when I'm physically at my desktop computer.

kthyholdt commented 3 years ago

I have a laptop (DELL Precision 7550), we have also tested this with same results on a NUC (Intel Skull Canyon) and on a desktop.

oyvindse commented 3 years ago

I've tested on a desktop computer and a Intel NUC (mini PC) with integrated graphics card

eriove commented 3 years ago

What are you Windows versions (run winver.exe)?

kthyholdt commented 3 years ago

Windows 10, Version 20H2 (OS Build 19042.804). Also tested with latest version of the graphics driver.

eriove commented 3 years ago

Windows 10, Version 20H2 (OS Build 19042.804)

Then my theory failed immediately. I have Version 1809 (OS Build 17763.1757)

kthyholdt commented 3 years ago

We were starting to think this was a regional issue, since everyone that reported this appears to be from Scandinavia. So we had someone test it in Serbia, and the same thing happens. They made it crash when switching between Duplicate and "PC screen only". It did not crash when changing between extended and duplicate on their desktops. Maybe you can try that @holance?

We also tested this on multiple other machines, and all of them were able to reproduce it.

holance commented 3 years ago

Unfortunately, not luck to reproduce the issue yet. @kthyholdt @eriove What's the dot net version on your computer?

eriove commented 3 years ago

Unfortunately, not luck to reproduce the issue yet. @kthyholdt @eriove What's the dot net version on your computer?

>dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.103
 Commit:    72dec52dbd

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.17763
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.103\

Host (useful for support):
  Version: 5.0.3
  Commit:  c636bbdc8a

.NET SDKs installed:
  3.1.406 [C:\Program Files\dotnet\sdk]
  5.0.103 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

I get the same error with .NET Framework and .NET5. I'm trying to debug it now

eriove commented 3 years ago

I've been to the office today and have been able to test #1533. As far as I can tell the pull request resolves our problem. There has been no crashes with that branch, but consistent crashes running from master.

gregorsGit commented 3 years ago

Hi, I have the same issue with external monitors. I can reproduce the crash when switching between two resolutions with the extend or duplicate projector feature. Are the resolutions equal, I get no crash. The patch is not working for me. The only solution I found is to remove the StartRending() case in the SurfaceD3D_IsFrontBufferAvailableChanged(). Like the solution from @kthyholdt ` frontBufferChange = false; try {

                    //if (EffectsManager.Device.DeviceRemovedReason.Success && surfaceD3D != null && surfaceD3D.IsDeviceStateOk())
                    //{
                    //    StartRendering();
                    //}
                    //else
                    //{
                        EndD3D();
                        if (surfaceD3D != null)
                        {
                            hasBackBuffer = false;
                            surfaceD3D.SetRenderTargetDX11(null);
                            surfaceD3D.IsFrontBufferAvailableChanged -= SurfaceD3D_IsFrontBufferAvailableChanged;
                            RemoveAndDispose(ref surfaceD3D);
                        }

                        EffectsManager.DisposeAllResources();
                        EffectsManager.Reinitialize();
                    //}
                }`

I use only the onboard Intel-HD Graphics to reproduce it. All other GPU´s are disabled. That might help.

holance commented 3 years ago

Is the crashed an exception or just black screen? @gregorsGit

gregorsGit commented 3 years ago

Sometimes I get a black screen and see the process is on a lock in InvalidateD3DImage(). And on the next display-switch I get this crash. This exception was originally thrown at this call stack: System.Windows.Media.Composition.DUCE.Channel.SyncFlush() System.Windows.Interop.HwndTarget.UpdateWindowSettings(bool, System.Windows.Media.Composition.DUCE.ChannelSet?) System.Windows.Interop.HwndTarget.UpdateWindowPos(System.IntPtr) System.Windows.Interop.HwndTarget.HandleMessage(MS.Internal.Interop.WindowMessage, System.IntPtr, System.IntPtr) System.Windows.Interop.HwndSource.HwndTargetFilterMessage(System.IntPtr, int, System.IntPtr, System.IntPtr, ref bool) MS.Win32.HwndWrapper.WndProc(System.IntPtr, int, System.IntPtr, System.IntPtr, ref bool) MS.Win32.HwndSubclass.DispatcherCallbackOperation(object) System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, object, int) System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object, System.Delegate, object, int, System.Delegate) System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, object, int)

Sometimes this crash comes directly. I switch between FHD and 4K resolution. The surfaceD3D.IsDeviceStateOk() is always true.

holance commented 3 years ago

This seems to be a bug from dot net. Which dot net version installed on your machine? @gregorsGit

gregorsGit commented 3 years ago

Currently installed "classic" .NET Versions in the system: 2.0.50727.4927 Service Pack 2 3.0.30729.4926 Service Pack 2 3.5.30729.4926 Service Pack 1 4.0.0.0 4.8.03761

holance commented 3 years ago

@kthyholdt @gregorsGit @eriove @oyvindse Hi all, I was finally able to reproduce some of the cases on monitor switch. I updated the PR to improve the recovery. Please try again.

gregorsGit commented 3 years ago

I tested this PR now. Can´t get a black-screen or a crash, when switching resolutions or connecting an external pisplay. This is great for me. I´m happy.

Thanks.

kthyholdt commented 3 years ago

@holance I'm not able to get this to crash with all sorts of combinations. So this seems to work great! I'm also happy! Good job.

oyvindse commented 3 years ago

Looks like your updated PR fixed the issue on my computer as well. Thankss a lot!