C# texture memory leaking; do I need to manually call VisualServer.FreeRid()?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Andrew Aldridge

I’m working on a Godot 3.1.1 project which, in C#, instantiates subclasses of Spatial, each with its own ImageTexture created at runtime. My understanding is that subclasses of Resource (such as ImageTexture) are supposed to be freed automatically, but this doesn’t seem to be the case; the Godot editor’s monitor shows texture memory increasing monotonically unless I manually call VisualServer.FreeRID for each ImageTexture.

The following is a minimal reproduction; every half second, a new Chunk is added to the scene with a new uncompressed 2048x2048 texture, and the previous Chunk is removed from the scene. Texture memory seems to never be freed, and soon over a gigabyte is consumed.

using Godot;

class Chunk : Spatial
{
    public Chunk()
    {
        var groundImage = new Image();
        groundImage.Create(2048, 2048, false, Image.Format.Rgb8);

        var groundTexture = new ImageTexture();
        groundTexture.CreateFromImage(groundImage);

        var groundMaterial = new SpatialMaterial();
        groundMaterial.SetTexture(SpatialMaterial.TextureParam.Albedo, groundTexture);

        var groundMesh = new QuadMesh();
        groundMesh.SetMaterial(groundMaterial);

        var ground = new MeshInstance();
        ground.Mesh = groundMesh;

        AddChild(ground);
    }
}

public class MainScene : Spatial
{
    void MakeATexture()
    {
        var newChunk = new Chunk();
        AddChild(newChunk);

        if (GetChildCount() > 2)
        {
            // Schedules the previous node to be removed from the
            // scene. Shouldn't this result in freeing the node's
            // texture?
            GetChild(1).QueueFree();
        }
    }

    public override void _Ready()
    {
        var timer = new Timer();
        AddChild(timer);
        timer.WaitTime = 0.5f;
        timer.ProcessMode = Timer.TimerProcessMode.Physics;
        timer.Connect("timeout", this, "MakeATexture");
        timer.Start();
    }
}

Am I misunderstanding something?

I’m getting the same problem with capturing screenshots but in my case the memory leak persists even if I manually execute VisualServer.FreeRID.

ansorre | 2020-08-09 19:23