Possible Texture dispose bug

Today I had to debug my application for some hours. Somehow it managed to create a stackoverflow. Finally I was able to track the problem down.

  1. Load a texture 2D
  2. Draw the texture 2D
  3. Dispose the texture 2D
  4. Load the texture 2D

After step 4, the texture is still disposed, even if we talk about a new object from Content.Load.

My Code: http://collabedit.com/wj363

So I do have a recursive function. But since I load disposed textures again, the recursive function should exit after one loop. (And yes, it does if I do not dispose anything) But if I dare to dispose one texture, it is always disposed, even if I load it again.

Don’t manually dispose of assets loaded through the ContentManager. The ContentManager owns these resources and takes care of disposing them when it gets disposed.

The asset remains in a list of loaded assets in the ContentManager. When you load an asset the second time, it looks in its own list of loaded assets and returns the reference to the same asset it loaded previously. If you manually dispose of the asset, the asset still remains in ContentManager’s list and it will still get returned if you load that asset again through the same ContentManager.

1 Like

Thanks. Because I have to load and unload many textures, I am going to dispose textures to reduse memory.

Shouldn’t the ContentManager realise that the texture is disposed and reload it again? How should we handle a massive texture intensive game on low ram machines?

You can use multiple content managers to dispose of only a part of your loaded assets when you dispose one of the CMs.

Its amazing how many AAA games just simply dump all loaded assets and then reload everything during loading screens, its one of the reasons why some have long load times (though not the only reason).

The main games that don’t do this are games with dynamic loading, such as open-world games, but they all have custom written loading systems since they build them specifically for what they are doing.

I’d suggest creating multiple content managers (like Jiagg suggests) and separate what you load into them by what you are using the assets for, something like this:

  1. Content you’ll never unload until the program ends, e.g. assets for menu screens.
  2. Content that won’t need to be changed often but will occasionally. e.g. the player character.
  3. Content you’ll frequently be unloading and reloading. e.g. assets specific to each stage.

You can go further and have more, but you should think about what you want to do with the assets and group them together by what you’re doing with them and when you’ll want to unload them.

The furthest you could go is having a separate content manager for each and every asset, but that would kinda defeat the point of using the content manager.

Another option would be to look up the source code for the content manager and write your own custom version.

Thanks. To use different content managers seems to be the solution I am looking for.
For me it is just unclear that I am able to dispose a texture but wont be able to reload it again.

You can also add the request to unload textures to the monogame wishlist which usually is pinned on the forums but it just disappeared today :slight_smile:

Honestly, not being able to unload resources from ContentManager was one of the worst points of XNA.
On some kind of games you won’t notice problems with it (basically when loading all the stuff at the start and then playing like N minutes, like a FPS or racing game), but on some other kind of games it’s just atrocious (i.e. I’m working in a jRPG where you can spend 2 seconds or 3 screens on each screen for a long number of screens. In my first naive attemp, I ended up using more time to load resources than going through those screens when the media was slow, i.e. some android devices)

p.s. once I even thought to use one ContentManager for every asset :joy:

Ok, thanks. How did you solve the problem? Use different ContentManagers?
I am going to upload that request. Loading all resources at the start of the game works for maybe the most games. But as you already wrote, not for all games. Atm I am developing a mobile game with different screens with different assets. I have to load an unload resources, else the game wont even work on a 1GB RAM device.

And there is the next thing I want to point out. On a 512MB RAM machine I get instantly a “not enough memory” exception. Even if all my resources are below 100MB in total. The “compression” of MonoGame inflate the resources to a total of 200MB. (Shouldn’t compression lower the filesize?) And even if all the resources are 200MB huge, still enough for a 500MB device. (Lets remove 300MB for the OS)

Overall, the content management system seems to be very poor.

What is the target machine here?

To make any comment on this, we would need to know what file formats the source assets use and what options are used in the content pipeline. If the source assets are PNG files, they cannot be compared to the size of the assets loaded by MonoGame as PNG cannot be used by the GPU directly.

XNB file compression is solely for making the file size smaller. It does not reduce memory size of the asset.

Do you enable texture compression? The default processing for textures produces 32-bit Color textures, which are full size, plus mipmaps which add another 33%. These are the default parameters because they give the best quality and work on all platforms. You can enable texture compression for your target platform for a 8x or 16x reduction in texture size, but take note that you will lose some quality as texture detail will be lost in the compression process. You can also turn off mipmaps, but again there is the acceptance that performance and visuals may be negatively affected.

Remember that our first priority in developing MonoGame was compatibility with XNA. Our content system is directly compatible with the content system used in XNA. You can derive your own ContentManager and override the ReadAsset method to provide your own management of disposable assets.

The problem with a content manager which doesn’t allow you to free resources is that you have to select different strategies depending on your kind of game. My problem was loading time and not memory constraints so it won’t work for you, as you have the opposite problem :slight_smile:

JFTR I’m just using a different ContentManager for each screen, and preload/cache them when entering a certain region. It’s like keeping an sliding window. Time loading is higher once, but once everything is loaded it runs quite faster, and there’s never a “high time pause” to reload all assets.
But to be honest, I still don’t like it. It’s possible that I’ll end up writing a custom content manager, but I don’t know how yet.

I totally agree, unfortunately this is inheritance from XNA, not on MonoGame’s fault… That’s why I said to propose it at the wishlist, it may be “wrong” now but may get better in the future! :slight_smile:

Mobile Emulator (10.0.10586.0 WVGA 512MB RAM)

Ok, thanks. I will keep that in mind. My settings are as following (.png file)

Yep, already did

TextureFormat of Color is full 32-bit colour. Set TextureFormat to Compressed to use DXT texture compression. This will get a 16x reduction when the texture has no alpha, or 8x reduction when the texture has alpha. You will lose some quality due to the lossy compression, but try it and see.

Tried it, but I get following exception when I run the game. It happens at:

texture.GetData(Color);

Exception thrown: 'System.AccessViolationException' in SharpDX.dll The program '[5304] SwordRush.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.

Also not all textures can be compressed. Most of them fail with following exception

That exception during compression (the second one) is a known bug that only occurs when processing large amounts of textures. It is a locking issue in a used library if i remember correctly. Just build the failed ones again. It will work.
The bug should already be fixed on the dev branch.