Skip to content
This repository has been archived by the owner on Mar 30, 2019. It is now read-only.

Re-calling LoadContent on resume for Windows Phone is suboptimal #283

Closed
mikeoliphant opened this issue Feb 18, 2014 · 11 comments
Closed

Re-calling LoadContent on resume for Windows Phone is suboptimal #283

mikeoliphant opened this issue Feb 18, 2014 · 11 comments
Labels

Comments

@mikeoliphant
Copy link

The current behavior to handle graphics resources needing to be reloaded on resume for Windows Phone seems to be to re-call LoadContent. This is likely to cause problems for all but the simplest projects. Not all content needs to be reloaded, for one thing - just content related to the graphics device.

It would be much nicer if the SharpDX content manager could handle this automatically. XNA for WP7 did, as does the MonoGame implementation that uses SharpDX.

@xoofx
Copy link
Member

xoofx commented Feb 18, 2014

LoadContent is called when the device is lost (I know that on XNA, at least Desktop, it is the way it is handled). On WP8 using DirectX11.1, the device is lost when resuming the app. So the LoadContent requires to be called when recovering a new GraphicsDevice.

LoadContent is not only responsible to LoadContent from the ContentManager, but you can create your own resources (RenderTargets...etc.) that need to be re-created, This kind of resources are usually created in LoadContent, can be parameter dependent (based on the new GraphicsDevice) so the LoadContent should be recalled to recreate them as well as loading regular content from the ContentManager.

I don't know about XNA on WP8 as they have access to a legacy API that could allow them to not have the graphics device to be killed. For MonoGame on WP8, I don't know their implem, but I don't understand how they would be able to restore the full game content without recalling LoadContent when restoring a GraphicsDevice.

Also, could you elaborate on "This is likely to cause problems for all but the simplest projects", not sure what are the problems, SharpDX samples in the toolkit is using this and it is working fine?

@mikeoliphant
Copy link
Author

I've developed XNA projects on Xbox, WP7 and PC and I've never seen LoadContent called more than once.

From looking at the MonoGame source code, it looks like they keep track of the way the content was loaded initially, and then re-load it the same way on resume. I ended up doing something similar, but it was only possible because I have my own content loading abstraction layer.

Sure, the SharpDX samples work, but they are very simple. In a real game, graphics assets are hooked into all sorts of complex game objects.

@xoofx
Copy link
Member

xoofx commented Feb 18, 2014

Yes, because on XNA WP7, PC, the device is never destroyed, so the resources are still in GPU memory. They didn't have to reload anything. The Toolkit on PC doesn't have such a problem because it is unlikely that a graphics device reset is going to occur (only if you install a graphics device driver when playing your game, or doing some heavy GPU that are taking too long and forcing the driver to reset its state)

On WP8, you are forced by the OS API to recreate the GraphicsDevice. This is not SharpDX that decided this (and that sucks, I agree), but you have no other choices than recreating from scratch.

If you had to do this in C++, you would have to handle this in the same way. I don't know MonoGame, but there implem is most likely wrong if they are not re-calling LoadContent, because if all custom content (like RenderTarget2D.New) cannot be recreated magically without calling it.

@mikeoliphant
Copy link
Author

I agree that dynamically generated content presents more of a problem. Render targets that are just used in a per-frame graphics pipeline would be fine, though. Those that store data across frames would be a problem, but calling LoadContent probably won't help in that case - they usual get their data during gameplay, not on initial load.

But 99% of circumstances could be handled by just automatically reloading textures from the source files. Then you could maybe have a specific method that is called on resume so that people can handle patching up any dynamic content.

@xoofx
Copy link
Member

xoofx commented Feb 18, 2014

I found this line in MonoGame where they are indeed reloading content, but quid of a custom graphics device object like a RenderTarget2D created in a LoadContent? There implem is just a small hack to mimic XNA behavior on WP7, but is most likely going to crash with custom content not loaded through the content manager (unless I have really missed something in their code, but I can't see how this is possible). This is really not the way to handle this on WP8. As I said, XNA on WP7 was lucky to not have this problem, but with current WP8 API, a resume is causing a device recreation,

@xoofx
Copy link
Member

xoofx commented Feb 18, 2014

Also, what is exactly the problem of having the LoadContent being recalled automatically? It is much easier to have a one way path instead of having different paths like LoadContentOnce, LoadContentDynamic. You could decide on a game resume to not load the same content...etc.

@xoofx
Copy link
Member

xoofx commented Feb 18, 2014

On a last note, from the XNA Game.LoadContent documentation itself:

This method is called by Initialize. Also, it is called any time the game content needs to be reloaded, such as when the DeviceReset event occurs

On WP8, a device reset is actually occurring. I don't think it is good to hide this event to the developer and changing the semantic of the method just because on XNA WP7 they didn't have the device reset on resuming.

@mikeoliphant
Copy link
Author

I think XNA had the same issue of resetting the graphics device, but it (mostly) handled it transparently behind the scenes. Render targets are a special case, which it looks like they handled by having a flag get set if the contents were lost due to a device reset:

http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.graphics.rendertarget2d.iscontentlost.aspx

As to why having LoadContent called again is a problem, here is an example. I load my sounds in LoadContent. They don't get lost during a WP8 resume, so there is no reason to dispose/reload them. In fact, the currently playing sounds continue exactly where they left off on a restore. The game would break if I were to reload them. WP8 resumes to the exact point execution was halted - it isn't a "start over".

For textures that have been dynamically created or modified, I'm not sure what the general solution is. I just know that calling LoadContent again doesn't help - they weren't necessarily initially created or modified during LoadContent.

@mikeoliphant
Copy link
Author

Regarding the Game.LoadContent documentation, I can only assume that it is out of date and was never corrected. I guarantee you that 99% of XNA games would break if LoadContent was called a second time in the middle of execution.

I think the behavior changed in XNA 2.0 - here is a good description of what they did to handle the problems we are talking about:

http://blogs.msdn.com/b/shawnhar/archive/2007/12/12/virtualizing-the-graphicsdevice-in-xna-game-studio-2-0.aspx

@xoofx
Copy link
Member

xoofx commented Feb 18, 2014

Oh, ok, thanks for the link, didn't know about that.

I agree that the solution of virtualizing is the "simplest" one, but there is currently no infrastructure for it in the Toolkit right now. The patch is not easy so It will take some time to make it properly (it requires to pool all objects created with a GraphicsDevice, and then possibly re-patching all underlying DirectX native pointer object like a SharpDX.Direct3D11.DeviceContext...etc.). Thought, not sure if I have enough spare time to work on it right now, but will try to evaluate the number of things to change.

@mikeoliphant
Copy link
Author

Glad we're on the same page! It is a difficult problem to solve well, but I think XNA did a really good job.

As I said earlier, I've implemented my own solution on top of SharpDX so I'm ok. It is also really only an issue on Windows Phone, and I'm not sure how many people are using SharpDX for WP8.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants