Skip to content

Commit 7659e4d

Browse files
authored
refactor string caching out of data cache (#1649)
1 parent 0cc5984 commit 7659e4d

8 files changed

Lines changed: 141 additions & 101 deletions

File tree

Core/Layer/Worlds/WorldLayer.Render.Hud.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ private RenderableString SetRenderableString(ReadOnlySpan<char> charSpan, Render
772772
if (!HasTicks)
773773
return renderableString;
774774

775-
renderableString.Set(World.ArchiveCollection.DataCache, charSpan, GetFontOrDefault(font),
775+
renderableString.Set(charSpan, GetFontOrDefault(font),
776776
fontSize, drawColor: drawColor);
777777
if (useDoomScale)
778778
renderableString.DrawArea = new(renderableString.DrawArea.Width, (int)(renderableString.DrawArea.Height * DoomVerticalScale));

Core/Layer/Worlds/WorldLayer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private void World_LevelExiting(object? sender, EventArgs e)
147147
}
148148

149149
private RenderableString InitRenderableString(TextAlign align = TextAlign.Left) =>
150-
new(World.ArchiveCollection.DataCache, string.Empty, DefaultFont, 12, align: align, shouldFree: false);
150+
new(string.Empty, DefaultFont, 12, align: align, shouldFree: false);
151151

152152
private Font GetFontOrDefault(string name)
153153
{

Core/Render/OpenGL/GLHudRenderContext.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ public void Text(string text, string font, int fontSize, Vec2I origin, out Dimen
207207
return;
208208

209209
int scaledFontSize = (int)(fontSize * scale);
210-
RenderableString renderableString = m_archiveCollection.DataCache.GetRenderableString(text, fontObject, scaledFontSize, textAlign, maxWidth);
210+
var renderableString = RenderableString.Get(text, fontObject, scaledFontSize, textAlign, maxWidth);
211211
drawArea = renderableString.DrawArea;
212212

213213
Vec2I pos = GetDrawingCoordinateFromAlign(origin.X, origin.Y, drawArea.Width, drawArea.Height,
@@ -234,7 +234,7 @@ public void Text(ReadOnlySpan<char> text, string font, int fontSize, Vec2I origi
234234

235235
int scaledFontSize = (int)(fontSize * scale);
236236

237-
RenderableString renderableString = m_archiveCollection.DataCache.GetRenderableString(text, fontObject, scaledFontSize, textAlign, maxWidth, color);
237+
var renderableString = RenderableString.Get(text, fontObject, scaledFontSize, textAlign, maxWidth, color);
238238
drawArea = renderableString.DrawArea;
239239

240240
Vec2I pos = GetDrawingCoordinateFromAlign(origin.X, origin.Y, drawArea.Width, drawArea.Height,
@@ -257,9 +257,9 @@ public Dimension MeasureText(ReadOnlySpan<char> text, string font, int fontSize,
257257
return default;
258258

259259
int scaledFontSize = (int)(fontSize * scale);
260-
RenderableString renderableString = m_archiveCollection.DataCache.GetRenderableString(text, fontObject, scaledFontSize, TextAlign.Left, maxWidth);
260+
var renderableString = RenderableString.Get(text, fontObject, scaledFontSize, TextAlign.Left, maxWidth);
261261
var drawArea = renderableString.DrawArea;
262-
m_archiveCollection.DataCache.FreeRenderableString(renderableString);
262+
renderableString.Free();
263263
return drawArea;
264264
}
265265

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
using Helion.Graphics;
2+
using Helion.Graphics.Fonts;
3+
using Helion.Render.Common.Enums;
4+
using Helion.Util.Container;
5+
using System;
6+
7+
namespace Helion.Render.OpenGL.Texture.Fonts;
8+
9+
public partial class RenderableString
10+
{
11+
private static readonly DynamicArray<RenderableString> StringCache = new(64);
12+
private static readonly DynamicArray<DynamicArray<ColorRange>> ColorRangeCache = new(32);
13+
private static readonly DynamicArray<DynamicArray<RenderableGlyph>> GlyphsCache = new(256);
14+
private static readonly DynamicArray<DynamicArray<RenderableSentence>> SentencesCache = new(64);
15+
16+
public static RenderableString Get(ReadOnlySpan<char> str, Font font, int fontSize, TextAlign align = TextAlign.Left,
17+
int maxWidth = int.MaxValue, Color? drawColor = null)
18+
{
19+
lock (StringCache)
20+
{
21+
if (StringCache.Length > 0)
22+
{
23+
var renderableString = StringCache.RemoveLast();
24+
renderableString.Set(str, font, fontSize, align, maxWidth, drawColor);
25+
return renderableString;
26+
}
27+
}
28+
29+
return new RenderableString(str, font, fontSize, align, maxWidth, drawColor);
30+
}
31+
32+
public void Free()
33+
{
34+
if (!ShouldFree)
35+
return;
36+
37+
FreeData();
38+
StringCache.Add(this);
39+
}
40+
41+
private void FreeData()
42+
{
43+
for (int i = 0; i < Sentences.Length; i++)
44+
FreeGlyphs(Sentences[i].Glyphs);
45+
FreeSentences(Sentences);
46+
47+
Sentences = null!;
48+
Font = null!;
49+
}
50+
51+
private static DynamicArray<ColorRange> GetColorRange()
52+
{
53+
lock (ColorRangeCache)
54+
{
55+
if (ColorRangeCache.Length > 0)
56+
return ColorRangeCache.RemoveLast();
57+
}
58+
59+
return new DynamicArray<ColorRange>(32);
60+
}
61+
62+
private static void FreeColorRange(DynamicArray<ColorRange> colors)
63+
{
64+
colors.Clear();
65+
lock (ColorRangeCache)
66+
{
67+
ColorRangeCache.Add(colors);
68+
}
69+
}
70+
71+
private static DynamicArray<RenderableSentence> GetSentences()
72+
{
73+
lock (SentencesCache)
74+
{
75+
if (SentencesCache.Length > 0)
76+
return SentencesCache.RemoveLast();
77+
}
78+
79+
return new DynamicArray<RenderableSentence>();
80+
}
81+
82+
private static void FreeSentences(DynamicArray<RenderableSentence> list)
83+
{
84+
list.Clear();
85+
lock (SentencesCache)
86+
{
87+
SentencesCache.Add(list);
88+
}
89+
}
90+
91+
private static DynamicArray<RenderableGlyph> GetGlyphs()
92+
{
93+
lock (GlyphsCache)
94+
{
95+
if (GlyphsCache.Length > 0)
96+
return GlyphsCache.RemoveLast();
97+
}
98+
99+
return new DynamicArray<RenderableGlyph>(256);
100+
}
101+
102+
private static void FreeGlyphs(DynamicArray<RenderableGlyph> list)
103+
{
104+
list.Clear();
105+
lock (GlyphsCache)
106+
{
107+
GlyphsCache.Add(list);
108+
}
109+
}
110+
}

Core/Render/OpenGL/Texture/Fonts/RenderableString.cs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Linq;
43
using Helion.Geometry;
54
using Helion.Geometry.Boxes;
65
using Helion.Geometry.Vectors;
76
using Helion.Graphics;
87
using Helion.Graphics.Fonts;
9-
using Helion.Graphics.Geometry;
108
using Helion.Render.Common.Enums;
119
using Helion.Util;
1210
using Helion.Util.Container;
@@ -16,12 +14,10 @@ namespace Helion.Render.OpenGL.Texture.Fonts;
1614
/// <summary>
1715
/// A collection of render information that can be used to draw a string.
1816
/// </summary>
19-
public class RenderableString
17+
public partial class RenderableString
2018
{
2119
public static readonly Color DefaultColor = Color.White;
2220

23-
private static readonly DynamicArray<ColorRange> ColorRanges = new();
24-
2521
/// <summary>
2622
/// The font used when rendering this.
2723
/// </summary>
@@ -42,7 +38,6 @@ public class RenderableString
4238
/// <summary>
4339
/// Creates a rendered string that is ready to be passed to a renderer.
4440
/// </summary>
45-
/// <param name="dataCache">The DataCache to use.</param>
4641
/// <param name="font">The font to use.</param>
4742
/// <param name="str">The colored string to process.</param>
4843
/// <param name="fontSize">The height of the characters, in pixels. If
@@ -52,40 +47,40 @@ public class RenderableString
5247
/// <param name="align">Alignment (only needed if there are multiple
5348
/// lines, otherwise it does not matter).</param>
5449
/// <param name="maxWidth">How wide before wrapping around.</param>
55-
public RenderableString(DataCache dataCache, ReadOnlySpan<char> str, Font font, int fontSize, TextAlign align = TextAlign.Left,
50+
public RenderableString(ReadOnlySpan<char> str, Font font, int fontSize, TextAlign align = TextAlign.Left,
5651
int maxWidth = int.MaxValue, Color? drawColor = null, bool shouldFree = true)
5752
{
5853
ShouldFree = shouldFree;
5954
Font = font;
60-
Sentences = PopulateSentences(dataCache, str, font, fontSize, maxWidth, drawColor);
55+
Sentences = PopulateSentences(str, font, fontSize, maxWidth, drawColor);
6156
DrawArea = CalculateDrawArea(Sentences);
6257
AlignTo(align);
6358
RecalculateGlyphLocations();
6459
}
6560

66-
public void Set(DataCache dataCache, ReadOnlySpan<char> str, Font font, int fontSize, TextAlign align = TextAlign.Left,
61+
public void Set(ReadOnlySpan<char> str, Font font, int fontSize, TextAlign align = TextAlign.Left,
6762
int maxWidth = int.MaxValue, Color? drawColor = null)
6863
{
6964
// This is kind of a hack. If reusing this string the underlying data needs to freed.
7065
if (!ShouldFree)
71-
dataCache.FreeRenderableStringData(this);
66+
FreeData();
7267

7368
Font = font;
74-
Sentences = PopulateSentences(dataCache, str, font, fontSize, maxWidth, drawColor);
69+
Sentences = PopulateSentences(str, font, fontSize, maxWidth, drawColor);
7570
DrawArea = CalculateDrawArea(Sentences);
7671
AlignTo(align);
7772
RecalculateGlyphLocations();
7873
}
7974

80-
public static DynamicArray<RenderableSentence> PopulateSentences(DataCache dataCache, ReadOnlySpan<char> str, Font font, int fontSize,
75+
public static DynamicArray<RenderableSentence> PopulateSentences(ReadOnlySpan<char> str, Font font, int fontSize,
8176
int maxWidth, Color? drawColor)
8277
{
8378
int currentWidth = 0;
8479
int currentHeight = 0;
8580
int drawAreaWidth = 0;
8681
int drawAreaHeight = 0;
8782

88-
var sentences = dataCache.GetRenderableSentences();
83+
var sentences = GetSentences();
8984
if (str.Length == 0)
9085
return sentences;
9186

@@ -132,7 +127,7 @@ public static DynamicArray<RenderableSentence> PopulateSentences(DataCache dataC
132127

133128
if (currentSentence == null)
134129
{
135-
currentSentence = dataCache.GetRenderableGlyphs();
130+
currentSentence = GetGlyphs();
136131
currentSentence.EnsureCapacity(str.Length);
137132
}
138133

@@ -150,6 +145,8 @@ public static DynamicArray<RenderableSentence> PopulateSentences(DataCache dataC
150145
}
151146
}
152147

148+
FreeColorRange(colorRanges);
149+
153150
CreateAndAddSentenceIfPossible(sentences, ref currentSentence, ref drawAreaWidth, ref drawAreaHeight, ref currentWidth, ref currentHeight);
154151
return sentences;
155152
}
@@ -172,38 +169,38 @@ private static void CreateAndAddSentenceIfPossible(DynamicArray<RenderableSenten
172169

173170
private static DynamicArray<ColorRange> GetColorRanges(ReadOnlySpan<char> str, Color? drawColor)
174171
{
175-
ColorRanges.Clear();
172+
var colorRanges = GetColorRange();
176173
if (drawColor != null)
177174
{
178-
ColorRanges.Add(new ColorRange(0, str.Length, drawColor.Value));
179-
return ColorRanges;
175+
colorRanges.Add(new ColorRange(0, str.Length, drawColor.Value));
176+
return colorRanges;
180177
}
181178

182-
ColorRanges.Add(new ColorRange(0, DefaultColor));
179+
colorRanges.Add(new ColorRange(0, DefaultColor));
183180

184181
bool success = FindNextColorIndex(str, 0, out int startIndex, out int endIndex);
185182
while (success)
186183
{
187-
ColorRange currentColorInfo = ColorRanges[ColorRanges.Length - 1];
184+
ColorRange currentColorInfo = colorRanges[colorRanges.Length - 1];
188185
currentColorInfo.EndIndex = startIndex;
189-
ColorRanges[ColorRanges.Length - 1] = currentColorInfo;
186+
colorRanges[colorRanges.Length - 1] = currentColorInfo;
190187

191188
Color color = ColorDefinitionToColor(str.Slice(startIndex, endIndex - startIndex));
192-
ColorRanges.Add(new ColorRange(endIndex, color));
189+
colorRanges.Add(new ColorRange(endIndex, color));
193190
startIndex = endIndex + 1;
194191
success = FindNextColorIndex(str, startIndex, out startIndex, out endIndex);
195192
}
196193

197194
// Since we never set the very last element's ending point due to
198195
// the loop invariant, we do that now.
199-
var last = ColorRanges[ColorRanges.Length - 1];
196+
var last = colorRanges[colorRanges.Length - 1];
200197
last.EndIndex = str.Length;
201-
ColorRanges[ColorRanges.Length - 1] = last;
198+
colorRanges[colorRanges.Length - 1] = last;
202199

203200
if (last.StartIndex == last.EndIndex)
204-
ColorRanges.Length--;
201+
colorRanges.Length--;
205202

206-
return ColorRanges;
203+
return colorRanges;
207204
}
208205

209206
private static bool FindNextColorIndex(ReadOnlySpan<char> str, int index, out int startIndex, out int endIndex)

Core/Render/Renderer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Helion.Render.OpenGL.Renderers.Legacy.World.Automap;
1818
using Helion.Render.OpenGL.Renderers.Legacy.World.Shader;
1919
using Helion.Render.OpenGL.Shared;
20+
using Helion.Render.OpenGL.Texture.Fonts;
2021
using Helion.Render.OpenGL.Texture.Legacy;
2122
using Helion.Render.OpenGL.Util;
2223
using Helion.Resources.Archives.Collection;
@@ -847,8 +848,7 @@ private void HandleDrawShape(DrawShapeCommand cmd)
847848
private void HandleDrawText(DrawTextCommand cmd)
848849
{
849850
m_hudRenderer.DrawText(cmd.Text, cmd.DrawArea, cmd.Alpha, cmd.DrawColorMap);
850-
var dataCache = m_archiveCollection.DataCache;
851-
dataCache.FreeRenderableString(cmd.Text);
851+
cmd.Text.Free();
852852
}
853853

854854
private void HandleRenderAutomapCommand(DrawWorldCommand cmd, Rectangle viewport)

0 commit comments

Comments
 (0)