SFML community forums

Bindings - other languages => DotNet => Topic started by: Torrunt on November 12, 2018, 09:34:35 am

Title: Semi-random crashes when creating Textures
Post by: Torrunt on November 12, 2018, 09:34:35 am
Originally my game uses sprites/textures exported for 1080p and recently I added support for a high resolution sprite option (4K). I noticed that after a while the game always crashes when trying to load a random texture. I can get the crash to happen almost consistently when entering the final boss area of my game (since it loads quite a lot of large textures in a row there). The game doesn't appear to be using very much memory at all when it crashes and the textures are still quite a lot smaller then the GPU's max texture size, so I'm not sure what the problem is.

The crash is generally from a LoadingFailedException but it also sometimes throws a SEHException:
Quote
An unhandled exception of type 'System.Runtime.InteropServices.SEHException' occurred in sfmlnet-graphics-2.dll
External component has thrown an exception.

An unhandled exception of type 'SFML.LoadingFailedException' occurred in sfmlnet-graphics-2.dll
Failed to load texture from memory
I've gotten a few LoadingFailedException (failed to load texture) crash reports from users in the past as well (using the normal 1080p graphics).

The game loads the textures in via MemoryStreams (extracted from uncompressed zip files) but I also tested loading from filenames and the problem persisted.

Has anyone else had problems like this and/or know how I could fix this?
Title: Re: Semi-random crashes when creating Textures
Post by: Gleade on November 13, 2018, 06:25:52 am
I personally have not seen this exception while using SFML before.

Are you able to provide a complete and minimal example that reproduces the issue?

Edit: Possibly related to https://en.sfml-dev.org/forums/index.php?topic=24449.0 (https://en.sfml-dev.org/forums/index.php?topic=24449.0) what are your texture file types?
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 13, 2018, 09:14:22 am
All the images used are pngs, most with transparency.

I can get the exception simply by making a loop that constantly makes new textures.

Code: [Select]
for (int i = 0; i < 400; i++)
{
    Texture texture = new Texture("test.png");
}

The crash occurs after looping around 40-120 times. I tried with different images, ones with and without transparency, pngs, jpegs and gifs. When it crashes the programs is hardly using any Memory (less than 100MB) and less than 1% of the GPU.

I can stop that test code from crashing if I add all the textures to a list and start disposing them if the list becomes larger than 20. But it should be able to handle much more than that.
Title: Re: Semi-random crashes when creating Textures
Post by: FRex on November 13, 2018, 09:22:17 am
Does it happen from C (CSFML) or C++ (SFML) too?
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 13, 2018, 09:58:41 am
Quote
When it crashes the programs is hardly using any Memory (less than 100MB) and less than 1% of the GPU
What about GPU memory? What's the total size loaded when it crashes (uncompressed, ie. width * height * 4 bytes for each image)?
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 13, 2018, 10:35:50 am
According to Task Manager the GPU Memory doesn't go up much at all (was 1.7/19.0 GB before launch and stayed there). The main image I'm testing with is 4782x2064, and it crashes after loading it for the 40th time.

I tested the same thing in SFML and there was no problems. With CSFML I got this exception:
Quote
Exception thrown at 0x772A17D2 in test.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0133F6D8
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 13, 2018, 11:24:38 am
Is is always after the 40th time, or is it random? std::bad_alloc means that memory allocation failed on the C++ side (SFML), so it's strange that testing it directly with SFML worked. Have you tried multiple times to be sure?
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 13, 2018, 12:01:31 pm
With that particular image it's always after the 40th time. Though another image I tested get's it randomly between the 125th and 130th time.

I can get SFML to load the texture in hundreds of times in a row with no problems at all. Though if I change the code to create and load images instead of textures; I get the std::bad_alloc.

Code: [Select]
// no problems:
for (int i = 0; i < 200; i++)
{
sf::Texture texture;
if (texture.loadFromFile("image.png"))
textures[i] = texture;
}
// crashes after loading 40:
for (int i = 0; i < 200; i++)
{
sf::Image image;
if (image.loadFromFile("image.png"))
images[i] = image;
}
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 13, 2018, 01:31:45 pm
This is expected: when you keep textures in memory, they are stored in GPU RAM and can't cause std::bad_alloc. When you keep images, they are stored in system RAM and eventually cause std::bad_alloc after a while.

But this scenario doesn't match your initial code, where only textures were kept in memory.
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 13, 2018, 02:55:02 pm
Here's the CSFML test code I used which results in the std::bad_alloc:
Code: [Select]
for (int i = 0; i < 200; i++)
{
sfTexture* texture = sfTexture_createFromFile("image.png", NULL);
}

I assume the std::bad_alloc there and the LoadingFailedException I get in the SFML.Net test are related.
It's weird that doing in directly in SFML (C++) works without any problems though...
Title: Re: Semi-random crashes when creating Textures
Post by: FRex on November 13, 2018, 03:20:30 pm
How did you do it in C++? I ask in case maybe you allocate it in loop as a local.

This is really strange since only thing C does differently is allocating a small struct that holds a bool and a pointer:

https://github.com/SFML/CSFML/blob/master/src/SFML/Graphics/TextureStruct.h

https://github.com/SFML/CSFML/blob/master/src/SFML/Graphics/Texture.cpp
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 13, 2018, 05:23:29 pm
The code is pretty much the same for all the tests. I even made it so it adds the textures to an array and the SFML test can still load in hundreds without any problems.

SFML (C++), no issues:
Code: [Select]
for (int i = 0; i < 200; i++)
{
sf::Texture texture;
if (texture.loadFromFile("image.png"))
textures[i] = texture;
}

SFML.Net, eventually results in LoadingFailedException:
Code: [Select]
for (int i = 0; i < 200; i++)
{
    Texture texture = new Texture("image.png");
}

CSFML, eventually results in std::bad_alloc:
Code: [Select]
for (int i = 0; i < 200; i++)
{
sfTexture* texture = sfTexture_createFromFile("image.png", NULL);
}

Same things happens for the SFML.Net and CSFML tests if I add the textures to lists/arrays like the SFML one.
Title: Re: Semi-random crashes when creating Textures
Post by: FRex on November 13, 2018, 06:24:06 pm
Nevermind my previous comment, I didn't look at that assignment. What is textures in your C++ code? And this still is very strange.
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 13, 2018, 06:30:21 pm
It's just an array ( sf::Texture textures[400]; ).
Title: Re: Semi-random crashes when creating Textures
Post by: FRex on November 13, 2018, 06:43:07 pm
Well, the only difference between that and C/.NET is that they allocate dynamically and the CSFML allocates a sf::Texture and a small struct but both sf::Texture and that struct in CSFML are so small they shouldn't even matter so what gives with this memory error..? :o ???
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 15, 2018, 08:38:10 am
I tried the SFML.net (C++) test again today and it resulted in a std::bad_alloc: crash... It makes more sense that it crashes the same as the CSFML and SFML.net tests but why in the hell was it working fine the last couple of days when I tested it?? :S
My Windows updated last night but I'm not sure if that would have affected it at all...


I also tried the SFML.Net test today as a 64bit build (everything before was using 32bit) and it manages to create a lot more textures but it still looks like they are being stored in the system RAM and not the GPU RAM.

(https://i.imgur.com/pKU40sB.png)

The working set keeps rising as more textures are made while the GPU memory doesn't budge at all.
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 15, 2018, 08:48:33 am
10 GB of memory used, whereas you said it was hardly using 100 MB in your first posts. What happened?
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 15, 2018, 08:52:32 am
Well that's using the 64bit version, so that's with hundreds of textures and not just 40 like before. Also I was only looking at Task Manager before (and not the Resource Manager) which still only shows it using less than 100MB.

Edit: The working set for the 32bit version (when it crashes after loading around 40 textures) is 1.5GB
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 15, 2018, 10:16:18 am
Ok, those results seem consitent. Now the question is: why does SFML.Net keep all that stuff in memory? From a quick look at the code, it only calls sfTexture_create from CSFML, which calls Texture::loadFromFile from SFML.

Can you show the complete source code that you used for your latest .Net test?
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 15, 2018, 10:24:52 am
Same code as before, just using the 2.2 64-bit dlls from: https://www.sfml-dev.org/download/sfml.net/
Code: [Select]
using System;
using System.Collections.Generic;
using SFML.Graphics;

namespace TextureCrashTest
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Texture> textures = new List<Texture>();

            for (int i = 0; i < 400; i++)
            {
                Texture texture = new Texture("image.png");
                textures.Add(texture);
                Console.WriteLine(i);
            }
        }
    }
}
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 15, 2018, 10:58:27 am
Are you using version 2.2 of CSFML as well?

You should consider switching to 2.5 for everything; you'll have to recompile a few things, and use PR #157 of SFML.Net, but it might be worth it.
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 15, 2018, 11:02:27 am
I'm using the latest stuff on GitHub. I just downloaded 2.2 to quickly test the 64bit version.
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 15, 2018, 11:16:55 am
So, the exact same code, with everything in version 2.5 (carefully check that, all masters may not be in sync), produces the same result? (except with less images due to less memory space available in 32-bits).
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 15, 2018, 11:22:56 am
Yep, same results no matter which version of SFML/CSFML/SFML.Net I use.
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 16, 2018, 01:13:14 pm
Was messing around with my SFML.Net test again today. I can get it to work correctly if I create a new texture (without passing a file name or stream) then use Texture.Bind and OpenGL (glTexImage2D) to load in the texture. Doing that seems to place the textures in the GPU memory and not the system memory.

Here's the code I used:
(just grabbed the code for image loading via DevIL that I use for another project (https://github.com/Torrunt/vimage))

Code: [Select]
using System;
using System.Collections.Generic;
using System.IO;
using SFML.Window;
using SFML.System;
using SFML.Graphics;
using Tao.OpenGl;
using DevIL.Unmanaged;

namespace TextureCrashTest
{
    class Program
    {
        static void Main(string[] args)
        {
            IL.Initialize();

            RenderWindow Window = new RenderWindow(new VideoMode(1920, 1080), "test", Styles.Default);
            Window.Size = new Vector2u(1920, 1080);
            Window.Position = new Vector2i(100, 100);

            List<Texture> textures = new List<Texture>();

            for (int i = 0; i < 400; i++)
            {
                Texture texture = GetTexture("image.png");
                textures.Add(texture);
                Console.WriteLine(i);
            }
        }

        private static Texture GetTexture(string filename)
        {
            int imageID = IL.GenerateImage();
            IL.BindImage(imageID);

            IL.Enable(ILEnable.AbsoluteOrigin);
            IL.SetOriginLocation(DevIL.OriginLocation.UpperLeft);

            bool loaded = false;
            using (FileStream fileStream = File.OpenRead(filename))
                loaded = IL.LoadImageFromStream(fileStream);
            if (!loaded)
                return null;

            bool success = IL.ConvertImage(DevIL.DataFormat.RGBA, DevIL.DataType.UnsignedByte);
            if (!success)
                return null;

            int width = IL.GetImageInfo().Width;
            int height = IL.GetImageInfo().Height;

            Texture texture = new Texture((uint)width, (uint)height);
            Texture.Bind(texture);
            {
                Gl.glTexImage2D(
                    Gl.GL_TEXTURE_2D, 0, IL.GetInteger(ILIntegerMode.ImageBytesPerPixel),
                    width, height, 0,
                    IL.GetInteger(ILIntegerMode.ImageFormat), ILDefines.IL_UNSIGNED_BYTE,
                    IL.GetData());
            }
            Texture.Bind(null);

            IL.DeleteImages(new ImageID[] { imageID });

            return texture;
        }

    }
}

I might have to just do a work-around like this for my game for now. Though I probably won't use DevIL since my game only needs to load pngs.
Title: Re: Semi-random crashes when creating Textures
Post by: Laurent on November 16, 2018, 01:49:55 pm
This is exactly what SFML is supposed to do :-\

What if you use Texture.Update instead of Texture.Bind + glTexImage2D?
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 16, 2018, 02:18:05 pm
Hmmm... using Texture.Update instead doesn't cause a crash but the GPU memory doesn't go up at all while the system memory does. Though the working set stays around 1.3-1.4GB while containing to load textures past 40.

That's with replacing the Texture.Bind code with: texture.Update(IL.GetImageData());


I'll test out and see what happens when I try to load images in via something different than DevIL.
Title: Re: Semi-random crashes when creating Textures
Post by: Torrunt on November 19, 2018, 11:46:47 am
I managed to get texture loading working fine using this:

Code: [Select]
private static Texture GetTexture(Stream stream, IntRect area = default(IntRect))
{
Image image = new Image(stream);
Texture texture = new Texture(image.Size.X, image.Size.Y);

if (area == default(IntRect))
area = new IntRect(0, 0, (int)image.Size.X, (int)image.Size.Y);

Texture.Bind(texture);
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, area.Width, area.Height, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, image.Pixels);
Gl.glTexSubImage2D(Gl.GL_TEXTURE_2D, 0, area.Left, area.Top, area.Width, area.Height, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, image.Pixels);
Texture.Bind(null);

return texture;
}

I noticed that if I pass null to glTexImage2D instead of the pixel byte array I get the same problem as before.
Seems like SFML in Texture::create, passes null to it as well:
https://github.com/SFML/SFML/blob/ff87e1c92265574f5c9785117b00907b7a61cf7d/src/SFML/Graphics/Texture.cpp#L208

Not sure why that is causing issues, or if that is the true cause or not.