Skip to content

Commit 9a19007

Browse files
committed
Fix memory leaks in Resource and Document caching
Add image/font/fontDefinition caches to Resource to prevent allocating new native objects on every call. Destroy cached Texture2D objects in Document.clearCache() to free GPU memory.
1 parent c383c2e commit 9a19007

2 files changed

Lines changed: 25 additions & 8 deletions

File tree

Runtime/Dom/Document.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ public Dom getDomFromVE(VisualElement ve) {
138138
}
139139

140140
public void clearCache() {
141+
foreach (var tex in _imageCache.Values) {
142+
if (tex != null) Object.Destroy(tex);
143+
}
141144
_imageCache.Clear();
142145
_fontCache.Clear();
143146
_fontDefinitionCache.Clear();

Runtime/Engine/Globals/Resource.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using UnityEngine;
45
using UnityEngine.UIElements;
@@ -8,33 +9,46 @@ namespace OneJS {
89

910
public class Resource {
1011
IScriptEngine _engine;
12+
Dictionary<string, Texture2D> _imageCache = new();
13+
Dictionary<string, Font> _fontCache = new();
14+
Dictionary<string, FontDefinition> _fontDefinitionCache = new();
1115

1216
public Resource(IScriptEngine engine) {
1317
_engine = engine;
1418
}
1519

1620
public Font loadFont(string path) {
17-
path = Path.IsPathRooted(path)
21+
var fullPath = Path.IsPathRooted(path)
1822
? path
1923
: Path.GetFullPath(Path.Combine(_engine.WorkingDir, path));
20-
var font = new Font(path);
24+
if (_fontCache.TryGetValue(fullPath, out var cached))
25+
return cached;
26+
var font = new Font(fullPath);
27+
_fontCache[fullPath] = font;
2128
return font;
2229
}
2330

2431
public FontDefinition loadFontDefinition(string path) {
25-
path = Path.IsPathRooted(path)
32+
var fullPath = Path.IsPathRooted(path)
2633
? path
2734
: Path.GetFullPath(Path.Combine(_engine.WorkingDir, path));
28-
var font = new Font(path);
29-
return FontDefinition.FromFont(font);
35+
if (_fontDefinitionCache.TryGetValue(fullPath, out var cached))
36+
return cached;
37+
var font = loadFont(path);
38+
var fd = FontDefinition.FromFont(font);
39+
_fontDefinitionCache[fullPath] = fd;
40+
return fd;
3041
}
3142

3243
public Texture2D loadImage(string path) {
33-
path = Path.IsPathRooted(path) ? path : Path.Combine(_engine.WorkingDir, path);
34-
var rawData = System.IO.File.ReadAllBytes(path);
35-
Texture2D tex = new Texture2D(2, 2); // Create an empty Texture; size doesn't matter
44+
var fullPath = Path.IsPathRooted(path) ? path : Path.Combine(_engine.WorkingDir, path);
45+
if (_imageCache.TryGetValue(fullPath, out var cached))
46+
return cached;
47+
var rawData = System.IO.File.ReadAllBytes(fullPath);
48+
Texture2D tex = new Texture2D(2, 2);
3649
tex.LoadImage(rawData);
3750
tex.filterMode = FilterMode.Bilinear;
51+
_imageCache[fullPath] = tex;
3852
return tex;
3953
}
4054
}

0 commit comments

Comments
 (0)