diff options
-rw-r--r-- | core/templates/lru.h | 4 | ||||
-rw-r--r-- | scene/3d/label_3d.cpp | 21 | ||||
-rw-r--r-- | scene/3d/label_3d.h | 24 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.cpp | 21 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.h | 26 |
5 files changed, 65 insertions, 31 deletions
diff --git a/core/templates/lru.h b/core/templates/lru.h index 48ba318b12..55130cbeb0 100644 --- a/core/templates/lru.h +++ b/core/templates/lru.h @@ -35,7 +35,7 @@ #include "hash_map.h" #include "list.h" -template <class TKey, class TData> +template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>> class LRUCache { private: struct Pair { @@ -52,7 +52,7 @@ private: typedef typename List<Pair>::Element *Element; List<Pair> _list; - HashMap<TKey, Element> _map; + HashMap<TKey, Element, Hasher, Comparator> _map; size_t capacity; public: diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 0849b2c631..1ae59451a1 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -370,15 +370,8 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, bool msdf = TS->font_is_multichannel_signed_distance_field(p_glyph.font_rid); - uint64_t mat_hash; - if (tex != RID()) { - mat_hash = hash_one_uint64(tex.get_id()); - } else { - mat_hash = hash_one_uint64(0); - } - mat_hash = hash_fmix32(hash_murmur3_one_64(p_priority | (p_outline_size << 31), mat_hash)); - - if (!surfaces.has(mat_hash)) { + SurfaceKey key = SurfaceKey(tex.get_id(), p_priority, p_outline_size); + if (!surfaces.has(key)) { SurfaceData surf; surf.material = RenderingServer::get_singleton()->material_create(); // Set defaults for material, names need to match up those in StandardMaterial3D @@ -407,9 +400,9 @@ void Label3D::_generate_glyph_surfaces(const Glyph &p_glyph, Vector2 &r_offset, surf.z_shift = p_priority * pixel_size; } - surfaces[mat_hash] = surf; + surfaces[key] = surf; } - SurfaceData &s = surfaces[mat_hash]; + SurfaceData &s = surfaces[key]; s.mesh_vertices.resize((s.offset + 1) * 4); s.mesh_normals.resize((s.offset + 1) * 4); @@ -464,7 +457,7 @@ void Label3D::_shape() { aabb = AABB(); // Clear materials. - for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) { + for (const KeyValue<SurfaceKey, SurfaceData> &E : surfaces) { RenderingServer::get_singleton()->free(E.value.material); } surfaces.clear(); @@ -594,7 +587,7 @@ void Label3D::_shape() { offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing + font->get_spacing(TextServer::SPACING_BOTTOM)) * pixel_size; } - for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) { + for (const KeyValue<SurfaceKey, SurfaceData> &E : surfaces) { Array mesh_array; mesh_array.resize(RS::ARRAY_MAX); mesh_array[RS::ARRAY_VERTEX] = E.value.mesh_vertices; @@ -1018,7 +1011,7 @@ Label3D::~Label3D() { TS->free_rid(text_rid); RenderingServer::get_singleton()->free(mesh); - for (KeyValue<uint64_t, SurfaceData> E : surfaces) { + for (KeyValue<SurfaceKey, SurfaceData> E : surfaces) { RenderingServer::get_singleton()->free(E.value.material); } surfaces.clear(); diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h index 7766bca068..7ac38a9f3c 100644 --- a/scene/3d/label_3d.h +++ b/scene/3d/label_3d.h @@ -76,7 +76,29 @@ private: RID material; }; - HashMap<uint64_t, SurfaceData> surfaces; + struct SurfaceKey { + uint64_t texture_id; + int32_t priority; + int32_t outline_size; + + bool operator==(const SurfaceKey &p_b) const { + return (texture_id == p_b.texture_id) && (priority == p_b.priority) && (outline_size == p_b.outline_size); + } + + SurfaceKey(uint64_t p_texture_id, int p_priority, int p_outline_size) { + texture_id = p_texture_id; + priority = p_priority; + outline_size = p_outline_size; + } + }; + + struct SurfaceKeyHasher { + _FORCE_INLINE_ static uint32_t hash(const SurfaceKey &p_a) { + return hash_murmur3_buffer(&p_a, sizeof(SurfaceKey)); + } + }; + + HashMap<SurfaceKey, SurfaceData, SurfaceKeyHasher> surfaces; HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER; VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER; diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index f4fd81b25f..9fa483bf36 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -2190,12 +2190,12 @@ RibbonTrailMesh::RibbonTrailMesh() { /* TextMesh */ /*************************************************************************/ -void TextMesh::_generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_gl) const { - if (cache.has(p_hash)) { +void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_gl) const { + if (cache.has(p_key)) { return; } - GlyphMeshData &gl_data = cache[p_hash]; + GlyphMeshData &gl_data = cache[p_key]; Dictionary d = TS->font_get_glyph_contours(p_gl.font_rid, p_gl.font_size, p_gl.index); Vector2 origin = Vector2(p_gl.x_off, p_gl.y_off) * pixel_size; @@ -2437,11 +2437,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { continue; } if (glyphs[i].font_rid != RID()) { - uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id()); - hash = hash_murmur3_one_32(glyphs[i].index, hash); - - _generate_glyph_mesh_data(hash, glyphs[i]); - GlyphMeshData &gl_data = cache[hash]; + GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index); + _generate_glyph_mesh_data(key, glyphs[i]); + GlyphMeshData &gl_data = cache[key]; p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); i_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); @@ -2496,10 +2494,9 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { continue; } if (glyphs[i].font_rid != RID()) { - uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id()); - hash = hash_murmur3_one_32(glyphs[i].index, hash); - - const GlyphMeshData &gl_data = cache[hash]; + GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index); + _generate_glyph_mesh_data(key, glyphs[i]); + const GlyphMeshData &gl_data = cache[key]; int64_t ts = gl_data.triangles.size(); const Vector2 *ts_ptr = gl_data.triangles.ptr(); diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 38cc7db5fe..a6d8978c2d 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -475,6 +475,7 @@ private: sharp = p_sharp; }; }; + struct ContourInfo { real_t length = 0.0; bool ccw = true; @@ -484,6 +485,27 @@ private: ccw = p_ccw; } }; + + struct GlyphMeshKey { + uint64_t font_id; + uint32_t gl_id; + + bool operator==(const GlyphMeshKey &p_b) const { + return (font_id == p_b.font_id) && (gl_id == p_b.gl_id); + } + + GlyphMeshKey(uint64_t p_font_id, uint32_t p_gl_id) { + font_id = p_font_id; + gl_id = p_gl_id; + } + }; + + struct GlyphMeshKeyHasher { + _FORCE_INLINE_ static uint32_t hash(const GlyphMeshKey &p_a) { + return hash_murmur3_buffer(&p_a, sizeof(GlyphMeshKey)); + } + }; + struct GlyphMeshData { Vector<Vector2> triangles; Vector<Vector<ContourPoint>> contours; @@ -491,7 +513,7 @@ private: Vector2 min_p = Vector2(INFINITY, INFINITY); Vector2 max_p = Vector2(-INFINITY, -INFINITY); }; - mutable HashMap<uint32_t, GlyphMeshData> cache; + mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache; RID text_rid; String text; @@ -517,7 +539,7 @@ private: mutable bool dirty_font = true; mutable bool dirty_cache = true; - void _generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_glyph) const; + void _generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_glyph) const; void _font_changed(); protected: |