Another Crash... :(

Okay, so my game is crashing on some computers and I don’t know the reason for it…
Crashes seem to be related to OpenTK/Graphics/Textures and System.TypeInitializationException.


Here’s first error, it might have some typos because I wrote it by hand

    Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often indication that other memory is corrupt.
    at OpenTK.Graphics.OpenGL.GL.GetTexImage[T4](TextureTarget target, Int32 level, PixelFormat format, PixelType type, T4[] pixels)
    at Microsoft.Xna.Framework.Graphics.Texture2D.PlatformGetData[t](Int32 level, Int32 arraySlice, Nullable 1 rect, T[] data, Int32 startIndex, Int32 elementCount)
    at Microsoft.Xna.Framework.Graphics.Texture2D.GetData[T](Int32 level, Int32 arraySlice, Nullable 1 rect, T[] data, Int32 startIndex, Int32 elementCount)
    at Microsoft.Xna.Framework.Graphics.Texture2D.GetData[T](T[] data)
    at MyGame.ContentHandler.RecolorTextureAsWhite(Texture2D sourceTexture) in 
    (filename + line number + jumps through the code here)

…and here’s the function, sourceTexture is not null or default(Texture2D), its checked before calling this function

    public Texture2D RecolorTextureAsWhite(Texture2D sourceTexture)
    {
        Texture2D recoloredTexture = new Texture2D(sourceTexture.GraphicsDevice, sourceTexture.Width, sourceTexture.Height);

        Color[] data = new Color[sourceTexture.Width * sourceTexture.Height];
        sourceTexture.GetData(data);

        for (int i = 0; i < data.Length; i++)
        {
            if (data[i].A > 100)
            {
                data[i] = Color.White;
            }
            else
            {
                data[i] = Color.Transparent;
            }
        }
        recoloredTexture.SetData(data);
        return recoloredTexture;
    }

Another mysterious error:

   Unhandled Exception: System.TypeInitializationException: The type initializer for 'MyGame.Objects.ExplosionEffect' threw an exception. ---> System.InvalidOperationException: This image format is not supported ---> System.OutOfMemoryException: Out of memory.

Is sourceTexture still valid at that point? What code calls this method? Is it on the main thread?

You forgot to specify the type of pixel format.
typically just Color.

t.GetData<Color>(color_ary);

That might also be why your getting the inital error or if you did something funny like previously disposed it.

In that case you should be checking the texture for t.IsDisposed() == true and probably call new on the texture but then again maybe you should handle that outside this method if thats the case.

just typed this out should be right.

   Color[] color_ary;   
   public void AlterTexture(ref Texture2D t)
   {
        color_ary = new Color[t.Width * t.Height];
        t.GetData<Color>(color_ary);
        //
        // your color array manipulation
        // ...
        // set the data back
        t.SetData<Color>(color_ary);
    }

Look and see if the get set data has extra parameters for setting getting the data buffers as well i would make sure your create texture2d call (if you need to use it that way), is using the full overload or at least with the pixel format overload and check it against what your current graphics adapter has for values.
But ya disposing stuff yourself can get real tricky too on copy’s you make if this is like a paint progi.

Im guessing you are doing some sort of paint editing or one time call ?
This is no good for real time updating.

The C# compiler is usually smart enough to figure out the generic argument from the type of the parameter in these cases.

Is that really true ?

This image format is not supported —>
System.TypeInitializationException: The type initializer

Well it was the first thing i thought when i saw the above.
Send a rgba32 color array to a rgb24 texture mode and bammo your writing into protected memory though that might not be exactly whats happening i was thinking it was very possibly similar. Other then that i don’t see anything wrong with that code itself. He will have to post more info if that’s not it.

I’m using only one thread, so it can’t be related to that.
Textures aren’t disposed at any point by my code, and all textures are in rgba32 format. I also added IsDisposed check to the code but it still won’t work. The code is run only once, not every frame.

Unhandled Exception: System.InvalidOperationException: This image format is not supported ---> System.Out0fMemoryException: Out of memory. 

at System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData) 
at Microsoft.Xna.Framework.Graphics.Texture2D.PlatformFromStream(GraphicsDevice graphicsDevice, Stream stream) 

at Microsoft.Xna.Framework.Graphics.Texture2D.FromStream(GraphicsDevice graphicsDevice, Stream stream) 
--- End of inner exception stack trace ---
at Microsoft.Xna.Framework.Graphics.Texture2D.FromStream(GraphicsDevice graphicsDevice, Stream stream) 
at Microsoft.Xna.Framework.Content.ContentManager.ReadRawAsset[T](String assetName, String originalAssetName) 
at Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T](String assetName, Action 1 recordDisposableObject) 
at Microsoft.Xna.Framework.Content.ContentManager.Load[T](String assetName) 

That error points to line

        Texture2D newTexture = Content.Load<Texture2D>(path + name);

the “name” variable is texture’s file name without extension, and path is the folder the texture is in, formatted Textures//Something//, so the line is Texture2D newTexture = Content.Load(Textures//Folder//filename);

Some of my folders have files with same name as texture, but end with .xml,

It seems that at least one of my friends uses Asian localisation of Windows, path in error message has ¥ instead of traditional / or \.

The game works on my computer and all the computers I have tested it, but it won’t work on few of my friends computers… this is frustrating! Are you guys sure this is not bug in MonoGame?

Even better, one of the older builds works fine on my friend’s computer but I haven’t made changes in Content Handling.

With generic methods such as void Texture2D.SetData<T>(T data), it is fine because it works out T from the type of the data parameter. With generic functions like T ContentManager.Load<T>(string assetName), it needs the generic argument specified because it cannot unambiguously work it out simply by what it is assigning the return value to.

Is this callstack from the inner exception of that shown in the original post? TypeInitializationException usually means the constructor of an object threw an exception. This callstack tells me that you have a raw image in your Content folder (did not go through the content pipeline) that you are trying to load through ContentManager. What type of image file is it? The exception tells us that the .NET Framework does not know how to handle that image format.

Note that raw images cannot be loaded through ContentManager in the current MonoGame code. So it’s probably time to learn how to use the content pipeline.

You should be, because your RecolorTextureAsWhite() method is manually creating a Texture2D that you are managing, so it is up to you to call Dispose() on that texture. Textures loaded through ContentManager are managed by ContentManager, so you should never call Dispose() on any resource loaded by ContentManager.

This makes a lot more sense now seeing its related to the load content method.

You can get this This image format is not supported if you simply try to load say a .bmp into monogame as well. Right now MG can only load jpg or png as images loaded from stream due to crossplatform concerns.

You can get a System.Out0fMemoryException: Out of memory. if your try to load a image larger then a card supports or as well with reach for xna mg i think to this is 2048 x 2048 and even on specific older cards using hi def.

If neither is the case and it is doing it after your app is running for a bit it might be dispose related.
but it sounds like its probably one of the above first two conditions instead since you said its a one shot thing.

Crash happens when loading / initializing the game, not during run-time.

All of the textures are .png 32bpp with same Color Profile, and largest image height I have is 1064px, all widths are below 1000px.
I am not using Content Pipeline for textures, but use it for audio and fonts. All the textures have “Content” in build action and are always copied to output directory.

I have few different ways to load my Content, and one of them is used to load global assets like backgrounds, and it isn’t throwing the exception even though it is called before the ones that cause it.

As for the Dispose(), I’m not calling it at any point because I need those textures for creating effects like afterimages. Am I supposed to dispose them when I close the game?

Edit: I’m currently using MonoGame 3.5 DesktopGL project with Visual Studio 2015, should I try out Development Build and see if it fixes the problem?

Loading and initializing is still considered “run-time”. Run-time is anytime from launching your application to when your application is terminated.

With what we now know, the exception in the original post, it looks like the loading of a PNG image is failing because it simply runs out of memory. While PNG images may be small on disk (from the zip compression), they are stored in memory as full 32-bits per pixel. This is where the content pipeline could help because many of these textures could be compressed, taking up less system memory during the load and less memory on the GPU.

The object that called RecolorTextureAsWhite() and holds the Texture2D reference will need to implement the Dispose pattern and call Dispose() on the texture because Texture2D holds references to unmanaged resources that must be released on the same thread as the renderer. Leaving the garbage collector to dispose of these unmanaged resources results in the Texture2D finalizer trying to clean things up, but this is being done on the garbage collector’s thread, and OpenGL does not play nicely with multiple threads.

Im thinking this is something simple that’s just hard to spot. Is your friend sending you these error logs ?
If one were to try to load a xml file thru the content manager i imagine it would not be in the proper format however i would expect you would get a file not found before that. There really isn’t a lot of information to go on here.

You said before you were loading the textures from stream yet above i see your loading content thru the content manager just not as compiled xnb files.

That error points to line

    Texture2D newTexture = Content.Load<Texture2D>(path + name);

the “name” variable is texture’s file name without extension, and
path is the folder the texture is in, formatted Textures//Something//,
so the line is Texture2D newTexture =
Content.Load(Textures//Folder//filename);

Some of my folders have files with same name as texture, but end with .xml,

I suggest you also separate were the xml files and image files are stored just to make sure.
As well as output each filepath to console or a log file as you load them

It does sound like something other then a image is being sent to your content load method.

It seems that at least one of my friends uses Asian localisation of
Windows, path in error message has ¥ instead of traditional / or .

However wouldn’t this give a bad path or file not found error as well.

You should probably try it this way as well. Make a simple test app that just loads some images the way you have done it but just a skeleton version of it and see if that loads for him. As well as one that is similar to what is shown below.

The below is one example of loading fromstream then using dispose, content load is not used at all.
I just wrote it out and added to the bottom of a game1 in a new project.
I placed the method TestLoadAltered into game1’s load method tested and it works fine.

Not all of it is required like the system diagnostic debug asserts or the console writelines.

//using System;
//using System.IO;
//using System.Diagnostics;
//using System.Collections.Generic;
//using Microsoft.Xna.Framework;
//using Microsoft.Xna.Framework.Graphics;
//using Microsoft.Xna.Framework.Input;

    Texture2D myImage; 
    public void TestLoadAndAlter()
    {
        Console.WriteLine(" Content dir: " + Path.Combine(Environment.CurrentDirectory, Content.RootDirectory.ToString()));
        myImage = LoadFromStream( Content.RootDirectory, "MyImage.png");
        AlterTexture(ref myImage);
    }
    public Texture2D LoadFromStream(string nonContentPath, string fileName)
    {
        string filepath = Path.Combine(Environment.CurrentDirectory, nonContentPath, fileName);
        Console.WriteLine(" Loading" + filepath);
        Texture2D t;
        if (System.IO.File.Exists(filepath))
        {
            FileStream fs = new FileStream(filepath, FileMode.Open);
            t = Texture2D.FromStream(GraphicsDevice , fs);
            fs.Flush();
            fs.Close();
        }
        else
        {
            Debug.Assert(false, "LoadFromStream Failed -> The file was not found in the expected directory \n" + filepath);
            t = null;
        }
        return t;
    }
    public void AlterTexture(ref Texture2D t)
    {
        Debug.Assert(t.IsDisposed == false, "We are attempting to reference a disposed texture Crash and Burn!");
        Texture2D t2 = new Texture2D(GraphicsDevice, t.Width, t.Height);
        Color[] color_ary = new Color[t.Width * t.Height];
        t.GetData<Color>(color_ary);
        for (int i = 0; i < color_ary.Length; i++) 
        { 
            if (color_ary[i].A > 100)
            {color_ary[i] = Color.White;}
            else
            {color_ary[i] = Color.Transparent;}
        }
        // this is a good place to set data dispose and update it all
        t2.SetData<Color>(color_ary);
        // dispose old data refernce while we have it.
        t.Dispose();
        // swap to the new valid instantiated reference.
        t = t2;
    }

Yeah, I use Content Manager for textures, I meant that I don’t compile them to .XNBs.
And yes, I got those error logs from friend because I can’t produce the error myself.

After christmas I’ll try out adding “.png” in Content.Load(filename.png) to make sure that it isn’t loading .XMLs. It just doesn’t make sense to me, because I think (not 100% sure) that I’m using those functions before the crash happens.

Another thing to note, my main content loader function that loads maps and initializes gameobjects is called after splash screen(s), not in LoadContent().