Skip to content

Commit 2d7509e

Browse files
MaxHeimbrockclaude
andauthored
Fix leaked textures on resolution change and quit (#277)
Video sources (WebCameraSource, CameraVideoSource, ScreenVideoSource) reallocated their RenderTexture/Texture2D/NativeArray on resize without releasing the previous instances, leaving the old GPU and native allocations to leak. Dispose() also did not free the RenderTexture/_tempTexture in the camera source paths. Meet sample's MeetManager.OnDestroy did not clean up tracks and streams when the scene is destroyed while still connected, leaking everything CleanUpAllTracks would have released. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4648cc0 commit 2d7509e

4 files changed

Lines changed: 75 additions & 1 deletion

File tree

Runtime/Scripts/CameraVideoSource.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ public override void Stop()
5151
ClearRenderTexture();
5252
}
5353

54+
protected override void Dispose(bool disposing)
55+
{
56+
if (disposing && _renderTexture != null)
57+
{
58+
_renderTexture.Release();
59+
UnityEngine.Object.Destroy(_renderTexture);
60+
_renderTexture = null;
61+
}
62+
base.Dispose(disposing);
63+
}
64+
5465
private void ClearRenderTexture()
5566
{
5667
if (_renderTexture)
@@ -71,6 +82,18 @@ protected override bool ReadBuffer()
7182
{
7283
if (_renderTexture == null || _renderTexture.width != GetWidth() || _renderTexture.height != GetHeight())
7384
{
85+
// Free previously allocated GPU/native resources before reallocating;
86+
// otherwise the old textures and NativeArray leak on every resolution change.
87+
if (_renderTexture != null)
88+
{
89+
_renderTexture.Release();
90+
UnityEngine.Object.Destroy(_renderTexture);
91+
}
92+
if (_previewTexture != null)
93+
UnityEngine.Object.Destroy(_previewTexture);
94+
if (_captureBuffer.IsCreated)
95+
_captureBuffer.Dispose();
96+
7497
var targetFormat = Utils.GetSupportedGraphicsFormat(SystemInfo.graphicsDeviceType);
7598
var compatibleFormat = SystemInfo.GetCompatibleFormat(targetFormat, FormatUsage.ReadPixels);
7699
_textureFormat = GraphicsFormatUtility.GetTextureFormat(compatibleFormat);

Runtime/Scripts/ScreenVideoSource.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ public override void Stop()
4545
ClearRenderTexture();
4646
}
4747

48+
protected override void Dispose(bool disposing)
49+
{
50+
if (disposing && _renderTexture != null)
51+
{
52+
_renderTexture.Release();
53+
UnityEngine.Object.Destroy(_renderTexture);
54+
_renderTexture = null;
55+
}
56+
base.Dispose(disposing);
57+
}
58+
4859
private void ClearRenderTexture()
4960
{
5061
if (_renderTexture)
@@ -65,6 +76,18 @@ protected override bool ReadBuffer()
6576
{
6677
if (_renderTexture == null || _renderTexture.width != GetWidth() || _renderTexture.height != GetHeight())
6778
{
79+
// Free previously allocated GPU/native resources before reallocating;
80+
// otherwise the old textures and NativeArray leak on every resolution change.
81+
if (_renderTexture != null)
82+
{
83+
_renderTexture.Release();
84+
UnityEngine.Object.Destroy(_renderTexture);
85+
}
86+
if (_previewTexture != null)
87+
UnityEngine.Object.Destroy(_previewTexture);
88+
if (_captureBuffer.IsCreated)
89+
_captureBuffer.Dispose();
90+
6891
var targetFormat = Utils.GetSupportedGraphicsFormat(SystemInfo.graphicsDeviceType);
6992
var compatibleFormat = SystemInfo.GetCompatibleFormat(targetFormat, FormatUsage.ReadPixels);
7093
_textureFormat = GraphicsFormatUtility.GetTextureFormat(compatibleFormat);

Runtime/Scripts/WebCameraSource.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ public WebCameraSource(WebCamTexture texture, VideoBufferType bufferType = Video
4747
Dispose(false);
4848
}
4949

50+
protected override void Dispose(bool disposing)
51+
{
52+
if (_tempTexture != null)
53+
{
54+
_tempTexture.Release();
55+
UnityEngine.Object.Destroy(_tempTexture);
56+
_tempTexture = null;
57+
}
58+
base.Dispose(disposing);
59+
}
60+
5061
private Color32[] _readBuffer;
5162

5263
// Read the texture data into a native array asynchronously
@@ -64,7 +75,16 @@ protected override bool ReadBuffer()
6475
_previewTexture.width != width ||
6576
_previewTexture.height != height)
6677
{
67-
// Required when using Allocator.Persistent
78+
// Free previously allocated GPU/native resources before reallocating;
79+
// otherwise the old textures and NativeArray leak on every resolution change.
80+
if (_previewTexture != null)
81+
UnityEngine.Object.Destroy(_previewTexture);
82+
if (_tempTexture != null)
83+
{
84+
_tempTexture.Release();
85+
UnityEngine.Object.Destroy(_tempTexture);
86+
_tempTexture = null;
87+
}
6888
if (_captureBuffer.IsCreated)
6989
_captureBuffer.Dispose();
7090

Samples~/Meet/Assets/Runtime/MeetManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ private void Update()
8181

8282
private void OnDestroy()
8383
{
84+
// Without this, scene change / app quit while connected leaves all tracks,
85+
// streams, and their backing GPU/native resources allocated.
86+
if (_room != null)
87+
{
88+
_room.Disconnect();
89+
_room = null;
90+
}
91+
CleanUpAllTracks();
8492
_webCamTexture?.Stop();
8593
}
8694

0 commit comments

Comments
 (0)