Reduce ImageSharp arraypool ballooning (#6768)

Dispose images as soon as practical so we don't balloon its arraypool as much.
This commit is contained in:
metalgearsloth
2026-07-12 16:44:31 +10:00
committed by GitHub
parent 89a054696b
commit 657e9bfb2d
2 changed files with 65 additions and 34 deletions
@@ -325,10 +325,18 @@ namespace Robust.Client.ResourceManagement
// Finalize the atlases.
for (var i = 0; i < imageAtlases.Count; i++)
{
var atlasTexture = Clyde.LoadTextureFromImage(imageAtlases[i], $"Meta atlas {i}");
finalAtlases.Add(atlasTexture);
var imageAtlas = imageAtlases[i];
try
{
var atlasTexture = Clyde.LoadTextureFromImage(imageAtlas, $"Meta atlas {i}");
finalAtlases.Add(atlasTexture);
sawmill.Debug($"(Meta atlas {i}) - cropped utilization: {(float)finalPixels[i] / (maxSize * imageAtlases[i].Height):P2}, fill percentage: {(float)imageAtlases[i].Height / maxSize:P2}");
sawmill.Debug($"(Meta atlas {i}) - cropped utilization: {(float)finalPixels[i] / (maxSize * imageAtlas.Height):P2}, fill percentage: {(float)imageAtlas.Height / maxSize:P2}");
}
finally
{
imageAtlas.Dispose();
}
}
// Finally, reference the actual atlas from the RSIs.
@@ -359,23 +367,30 @@ namespace Robust.Client.ResourceManagement
var errors = 0;
foreach (var data in rsiList)
{
if (data.Bad)
{
errors += 1;
continue;
}
try
{
var rsiRes = new RSIResource();
rsiRes.LoadFinish(this, data);
resList[data.Path] = rsiRes;
if (data.Bad)
{
errors += 1;
continue;
}
try
{
var rsiRes = new RSIResource();
rsiRes.LoadFinish(this, data);
resList[data.Path] = rsiRes;
}
catch (Exception e)
{
sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}");
data.Bad = true;
errors += 1;
}
}
catch (Exception e)
finally
{
sawmill.Error($"Exception while loading RSI {data.Path}:\n{e}");
data.Bad = true;
errors += 1;
data.AtlasSheet?.Dispose();
}
}
@@ -83,27 +83,44 @@ namespace Robust.Client.ResourceManagement
metadata = RsiLoading.LoadRsiMetadata(manifestFile);
}
data.FrameCounts = RsiLoading.CalculateFrameCounts(metadata);
data.Images = RsiLoading.LoadImages(
metadata,
SixLabors.ImageSharp.Configuration.Default,
name =>
{
var texPath = data.Path / (name + ".png");
return manager.ContentFileRead(texPath);
});
Image<Rgba32>[]? images = null;
Image<Rgba32> sheet;
var sheet = RsiLoading.GenerateAtlas(
metadata,
data.FrameCounts,
data.Images,
SixLabors.ImageSharp.Configuration.Default,
out var dimensionX);
try
{
data.FrameCounts = RsiLoading.CalculateFrameCounts(metadata);
images = RsiLoading.LoadImages(
metadata,
SixLabors.ImageSharp.Configuration.Default,
name =>
{
var texPath = data.Path / (name + ".png");
return manager.ContentFileRead(texPath);
});
sheet = RsiLoading.GenerateAtlas(
metadata,
data.FrameCounts,
images,
SixLabors.ImageSharp.Configuration.Default,
out var dimensionX);
data.AtlasSheet = sheet;
data.DimX = dimensionX;
}
finally
{
if (images != null)
{
foreach (var image in images)
{
image.Dispose();
}
}
}
LoadPreTextureCommon(metadata, data);
data.AtlasSheet = sheet;
data.DimX = dimensionX;
data.LoadParameters = metadata.LoadParameters;
data.MetaAtlas = metadata.MetaAtlas;
}
@@ -392,7 +409,6 @@ namespace Robust.Client.ResourceManagement
public int DimX;
public StateReg[] AtlasList = default!;
public int[] FrameCounts = default!;
public Image<Rgba32>[] Images = default!;
public Vector2i FrameSize;
public Dictionary<RSI.StateId, Vector2i[][]> CallbackOffsets = default!;
public Texture AtlasTexture = default!;