diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2021-06-30 15:50:51 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-09-29 11:39:47 +0000 |
commit | 310d59b40c565f61cdcff805674c57caaa44aafb (patch) | |
tree | 5c8b0f30fa1247b75ef243da9af6ff2f1c5cbd83 /tests/auto/quick | |
parent | 0533725c60198aeced54ad53454a09a3b3691394 (diff) |
Reduce QGlyphRun memory usage and speed up large Text instances
To render the plain text of _War and Peace_ took 6.4GB of memory before
(Linux 64-bit debug developer build); and now it's 1.1GB initially.
More optimization is possible: sizeof(TexturedPoint2D) = 16, and we
store a 16-bit index, so 3158176 glyphs ought to take about 60MB (but
takes 200MB in practice); but we also store QGlyphRuns, which are
actually redundant after the SG is populated. We need them in case the
text can be edited, restyled, re-wrapped etc.
QSGDistanceFieldGlyphNode::updateGeometry() enforces a limit of 65532
vertices per node (0xFFFF is not allowed as an index value, because it's
reserved to indicate primitive restart; and glyphs are quads). But it
was making copies of the remaining QPointF positions and quint32 glyph
indices and giving those recursively to the subnodes, so every subnode
was storing all of those for itself and all of _its_ subnodes, even
though it only needs max 16383 of them. Now, in the RootGlyphNode,
m_glyphs stores the glyphs that node will render (as before); but in
each subnode, we use QGlyphRun::setRawData() to populate m_glyphs with a
range from the index and position arrays from the root node.
setRawData() just sets the pointers to those arrays; so to avoid any
chance of dangling pointers, we need to keep those vectors, which live
in the GlyphInfo structs in m_glyphsInOtherTextures. That's the reason
the glyphsInOtherTextures hash, which was temporary before, is now kept
(although the dangling pointers somehow didn't cause any crash).
In the first loop over indices in updateGeometry(), each SubGlyphNode
will break out of the loop as soon as it has created enough
TexturedPoint2D and index instances for itself, because it no longer
needs to redo the rest of the loop over indices that was done in the
RootGlyphNode; this speeds up the rendering of large text.
Creation of subnodes is now iterative rather than recursive, which
saves stack space, and also looks better in the QSG_RENDERER_DEBUG=dump
output: you can see that each RootGlyphNode has one level of direct
children (161 of them for _War and Peace_). In a future change, perhaps
we could create those dynamically when the user flicks down to them,
and reclaim memory from children that are no longer shown; but that
would not be possible if they were all nested inside each other.
Amends aeb1d48c9938241b1ffcf8e42e3864595e90b168
Task-number: QTBUG-60491
Task-number: QTBUG-90734
Change-Id: Iff981b9ba86acc01775fd72e3ce79ea9e33d9061
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(cherry picked from commit 75a9b09d93b9462b77347d1992371a189037bc62)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests/auto/quick')
0 files changed, 0 insertions, 0 deletions