[Toolkit WPF] Memory Leaks, Undesired Outcomes and Exceptions #380
Comments
When an app is shut down - all resources are freed by the OS anyway, so I don't see a big problem here. The only applicable scenario - when there are several dispatchers in several threads - but usually this means that the solution is overengineered.
No demos are the unbeatable truth. DirectX is quite an advanced tech and it is expected to developers to think for the architecture themselves and see the issues - like you did.
I agree, this could be a good improvement. Also D3D9 runtime can be initialized only once per thread with some sort of reference counting mechanism - i.e. if there are multiple SharpDXElements - it will be initialized only once.
There is no reason, this should be fixed.
This was implemented like this because SharpDXElement is disposable and is single-use only, if improvements you mentioned above will be made - the Game dependency property can be moved to this class. You did a really good analysis, I will see when I can do all these improvements, however currently my free time is quite limited. |
Without handling the event "Dispatcher.ShutdownStarted" I was getting 3 warnings about possible leaks. |
Hi @ArtiomCiumac , Nice! Looks like you did a fair bit of work there. (I didn't realise it would require so much). Thanks for all the help with this. I will try to pull this down tonight or tomorrow and test it out. I still didn't manage to workout why AvalonDock makes DirectX angry. I will try to give this a bit more investigation this weekend as well. I doubt I'll be lucky enough that these changes fixed that as well. Cheers, |
Hi @ArtiomCiumac , Doesn't quite work :( Because the "back buffer" is been cleaned up on Unload but not re-created on Load. I "fixed it" by changing the "GameWindowDesktopWpf.HandleElementLoaded" method to be like:
Not sure if that is the right/best way to do this. Cheers, |
At first I thought these changes had fixed the problem with AvalonDock. It did improve, anchorables could be torn-off and docked without problems. The hiding/showing of anchorables seemed to work most of the time, but I still got it to crash. Seemed to be a timing thing (how quickly I tried to show after hiding). But it also crashes when shutting down. It runs the game loop after the graphics device has been disposed. Maybe it does some weird threading or child window things. I might have to go spelunking through their code :( |
Turns out you have to call Game.Exit() before you dispose. Makes sense. That fixes the crash on close. Still working on the Show/Hide problem. |
I think disposing a game should safely close it even if Exit was not called, this should be fixed. |
I do have a test project specifically for testing these changes. Just trying to find somewhere online to put it. Wish you could just attach zips to issues. |
@dfkeenan, just upload it to onedrive (former skydrive) or dropbox. |
Hi @ArtiomCiumac , Sorry I took so long to get back. I have put my test app here ge.tt for the time being. I was doing my tests after I made the changes specified above ("GameWindowDesktopWpf.HandleElementLoaded"). It references the SharpDX assemblies using the targets files from the SharpDX repository folder. Let me know if you have any troubles Cheers, |
Apologies for such long delay, now I have a little bit more time and checked your demo project. |
Hi @ArtiomCiumac, no need for apologies. I will do a pull and try it out soon. |
Hi @ArtiomCiumac , I can still get it to crash unfortunately. If you unpin the tabs so they collapse to one side and you resize one then switch back and forth between active tabs it crashes. I made a problem step recording of it to help try and demonstrate http://ge.tt/9kT3eyn1/v/0?c Cheers, |
Hi @ArtiomCiumac , I think I might have found another problem with the WPF platform. :( It appears that if you load textures (via the content manager at least) you get the "Warning: Live ComObject [0xXXXXXXX], potential memory leak" message when closing down. Cheers, |
Right, I reproduced the issue and, well, we are trying to combine the uncombinable here. The only feasible solution would be to decouple completely D3D9 management from the SharpDXElement lifetime, but developer will need to either call manually something like |
Hi @ArtiomCiumac , You are right, moving D3D9 management out of the SharpDXElement might be the best option. My proposed solution would be to:
With this design the lifetime of the D3D11Image instance could be managed by the game class as well. This way the game class could be resposible for all D3D management and the SharpDXElement could be reduced to simply have the resposibility of rendering the D3D11Image to screen, resize notification etc. If this sounds like an ok plan I could probably try to put something together over the next few days (or on the next weekend). Cheers, |
Not sure if it is correct to let |
@ArtiomCiumac , By moving the D3D9 stuff into the GameWindowDesktopWpf, I meant just move the "private static readonly ThreadLocal<RefCounter> d3d9 = new ThreadLocal<RefCounter>(() => new RefCounter());" and realated classes. |
ok, I got the idea - let's give it a try. 2014-07-15 9:00 GMT+01:00 dfkeenan notifications@github.com:
|
Alright, I'll try to make a start soon. |
@dfkeenan, please let me know if this issue is fixed and can be closed as the pull request above has been merged. |
Hi @ArtiomCiumac , I think the work we have done has solved the problems. I am happy for you to close this issue. (I can always raise another one or reopen this one if I find more problems later :D ). Thanks for all your help. Cheers, |
ok, I'm closing this issue. |
Hi,
I have been playing with some WPF stuff and looking at examples and have been having some issues so I thought I would discuss it here before I change anything.
Memory Leaks:
SharpDXElement Disposes itself when unloaded which is fine. But the Unloaded event is not fired when an application is closed so this causes some leaks. The best fix I could fined was making the SharpDXElement also handle the event "Dispatcher.ShutdownStarted".
The "MiniCube.SwitchContext.WPF.MVVM" demo also has memory leaks because the games are not Disposed. I am not sure if this should be treated as demo/guidance issue or changes should be made to how the WPF integration cleans itself up.
Undesired Outcomes:
WPF elements can be Loaded/Unloaded many times in there life span but because the SharpDXElement disposes itself in the Unloaded event the next time it is "Loaded" it is effectively dead/useless. I propose we change the SharpDXElement so the Direct3D9 setup happens in Loaded and still clean up resources in Unload but perhaps not mark it has "Disposed".
Exceptions:
The call to the DeviceEx constructor in SharpDXElement can throw exceptions (D3DERR_NOTAVAILABLE/NotAvailable) in certain situations. I get it to happen when the SharpDXElement is hosted in an AvalonDock LayoutAnchorable that is collapsed and you hover over the tab to show it. I am not sure what the actual cause this or what (crazy/awesome) stuff AvalonDock does. I am currently trying to see if I can get it to happen without using AvalonDock.
Other stuff:
I noticed that the method "GameWindowDesktopWpf.HandleElementLoaded" uses it's own search mechanism to find the window. Is there any reason you didn't just use the built in method like "window = Window.GetWindow(element);".
In the "MiniCube.SwitchContext.WPF.MVVM" demo the "GameView" class has a custom dependancy property "GameProperty" is there any reason why this couldn't be baked into the SharpDXElement.
Cheers,
dfkeenan
P.S. Sorry kind of long. 😄
The text was updated successfully, but these errors were encountered: