fix(D.5.1): dispose IconComposer + RenderSurface GL handles (review)
Two GL texture leaks plugged, both found in code review of 6e82807:
1. _handlesByRenderSurfaceId (pre-existing gap): populated by
GetOrUploadRenderSurface for UI sprites but absent from Dispose's
Phase 3 sweep. Added foreach/_gl.DeleteTexture/Clear in Dispose.
2. _adhocHandles (new): the public UploadRgba8(byte[],int,int,bool)
wrapper used by IconComposer stored composited icon handles nowhere,
so they leaked. Added _adhocHandles list; wrapper now appends the
returned GL name before returning. Dispose sweeps + clears the list.
Tracking is intentionally in the PUBLIC wrapper only — the private
UploadRgba8(DecodedTexture,bool) is shared by all keyed-cache paths
and tracking there would cause double-deletes.
No behavior change to icon rendering. No GL-context unit test added
(no context in test projects); correctness is by-inspection + green
suite (2598 passing).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6e82807863
commit
e9a5248972
1 changed files with 27 additions and 2 deletions
|
|
@ -37,6 +37,12 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
private readonly Dictionary<uint, uint> _handlesByRenderSurfaceId = new();
|
||||
private readonly Dictionary<uint, (int w, int h)> _rsSizeById = new();
|
||||
|
||||
// Ad-hoc handles produced by the public UploadRgba8(byte[],int,int,bool) wrapper
|
||||
// (used by IconComposer for composited item icons). These are NOT stored in any
|
||||
// of the keyed caches above, so Dispose must sweep this list to avoid leaking
|
||||
// GL texture objects until process exit.
|
||||
private readonly List<uint> _adhocHandles = new();
|
||||
|
||||
private readonly Wb.BindlessSupport? _bindless;
|
||||
|
||||
// Bindless / Texture2DArray parallel caches. Keys mirror the legacy three
|
||||
|
|
@ -543,9 +549,16 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
}
|
||||
|
||||
/// <summary>Uploads a raw RGBA8 byte array as a Texture2D. Used by
|
||||
/// <see cref="AcDream.App.UI.IconComposer"/> to upload CPU-composited icon layers.</summary>
|
||||
/// <see cref="AcDream.App.UI.IconComposer"/> to upload CPU-composited icon layers.
|
||||
/// The returned handle is tracked in <see cref="_adhocHandles"/> and deleted by
|
||||
/// <see cref="Dispose"/>. Callers must NOT also store the handle in any of the
|
||||
/// keyed caches — that would cause a double-delete on Dispose.</summary>
|
||||
public uint UploadRgba8(byte[] rgba, int width, int height, bool nearest = false)
|
||||
=> UploadRgba8(new DecodedTexture(rgba, width, height), nearest);
|
||||
{
|
||||
uint h = UploadRgba8(new DecodedTexture(rgba, width, height), nearest);
|
||||
_adhocHandles.Add(h);
|
||||
return h;
|
||||
}
|
||||
|
||||
private uint UploadRgba8(DecodedTexture decoded, bool nearest = false)
|
||||
{
|
||||
|
|
@ -656,5 +669,17 @@ public sealed unsafe class TextureCache : Wb.ITextureCachePerInstance, IDisposab
|
|||
_gl.DeleteTexture(_magentaHandle);
|
||||
_magentaHandle = 0;
|
||||
}
|
||||
|
||||
// RenderSurface (UI sprite) handles — pre-existing gap: this dict was populated
|
||||
// by GetOrUploadRenderSurface but was not swept here before this fix.
|
||||
foreach (var h in _handlesByRenderSurfaceId.Values)
|
||||
_gl.DeleteTexture(h);
|
||||
_handlesByRenderSurfaceId.Clear();
|
||||
|
||||
// Ad-hoc handles from the public UploadRgba8(byte[],int,int,bool) wrapper
|
||||
// (IconComposer composited icons). Not stored in any keyed cache.
|
||||
foreach (var h in _adhocHandles)
|
||||
_gl.DeleteTexture(h);
|
||||
_adhocHandles.Clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue