Current TesselatedTextGeometry already has a local cache:
var geometryCache: [Character: GeometryData]
var characterPathsCache: [Character: [Polyline2D]]
That helps a bit, but it is weak because:
- Character is not enough. Same character can map to different glyphs depending on font, style, ligature shaping, fallback font, etc.
- It is per geometry instance, so multiple text nodes do not share work.
- fontSize changes clear the cache, even though glyph outlines could be cached in normalized font units and scaled later.
- It still recombines/copies glyph geometry into one large mesh every update.
- CoreText layout still runs per text update.
A cleaner model:
-
Global or context-level glyph outline/mesh cache
Key by something like:
- font PostScript name / CTFont identity
- glyph id (CGGlyph)
- tessellation settings: angleLimit, curve tolerance, winding/triangulation mode
- maybe variable font axes if relevant
-
Cache glyph geometry in font units
Store the triangulated/path geometry once in normalized units. Then font size becomes a transform/scale, not a reason to re-triangulate.
-
Separate layout from glyph mesh generation
CoreText still computes glyph IDs and positions for the string. But once layout gives you:
- glyph id
- font/run
- position
then mesh assembly should mostly be “append cached glyph mesh with offset/scale.”
-
Avoid rebuilding one huge CPU mesh when possible
The even more scalable version is an instanced glyph renderer:
- one cached glyph mesh per glyph
- per-character instance data contains offset, scale, maybe color/index
- draw grouped by glyph/material
This avoids copying all glyph vertices every time text positions change.
For your Instruments result, the immediate win is likely: move from Character cache to glyph+font+tessellation cache, ideally shared across TesselatedTextGeometry instances. The bigger architectural win is treating text as layout records + cached
glyph meshes, not regenerating a monolithic mesh every update.
Current TesselatedTextGeometry already has a local cache:
var geometryCache: [Character: GeometryData]
var characterPathsCache: [Character: [Polyline2D]]
That helps a bit, but it is weak because:
A cleaner model:
Global or context-level glyph outline/mesh cache
Key by something like:
Cache glyph geometry in font units
Store the triangulated/path geometry once in normalized units. Then font size becomes a transform/scale, not a reason to re-triangulate.
Separate layout from glyph mesh generation
CoreText still computes glyph IDs and positions for the string. But once layout gives you:
then mesh assembly should mostly be “append cached glyph mesh with offset/scale.”
Avoid rebuilding one huge CPU mesh when possible
The even more scalable version is an instanced glyph renderer:
This avoids copying all glyph vertices every time text positions change.
For your Instruments result, the immediate win is likely: move from Character cache to glyph+font+tessellation cache, ideally shared across TesselatedTextGeometry instances. The bigger architectural win is treating text as layout records + cached
glyph meshes, not regenerating a monolithic mesh every update.