From 7f562030be89be6fca9b09b3a403e14667e87806 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Mon, 4 Jul 2022 09:46:38 +0300 Subject: [PATCH] Use custom key struct, instead of raw hashes for the Label3D cache to avoid potential hash collisions. --- scene/3d/label_3d.cpp | 21 +++++++-------------- scene/3d/label_3d.h | 25 ++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 00c95063a99..8791c9b6e57 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -535,15 +535,8 @@ float Label3D::_generate_glyph_surfaces(const Ref &p_font, CharType p_char gl_uv = p_font->get_char_tx_uv_rect(p_char, p_next, p_outline); texs = p_font->get_char_texture_size(p_char, p_next, p_outline); - 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_djb2_one_64(p_priority, mat_hash); - - if (!surfaces.has(mat_hash)) { + SurfaceKey key = SurfaceKey(tex.get_id(), p_priority); + if (!surfaces.has(key)) { SurfaceData surf; surf.material = RID_PRIME(VisualServer::get_singleton()->material_create()); // Set defaults for material, names need to match up those in SpatialMaterial @@ -567,9 +560,9 @@ float Label3D::_generate_glyph_surfaces(const Ref &p_font, CharType p_char surf.z_shift = p_priority; } - 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); @@ -624,7 +617,7 @@ void Label3D::_shape() { // Clear materials. { - const uint64_t *k = nullptr; + const SurfaceKey *k = nullptr; while ((k = surfaces.next(k))) { VS::get_singleton()->free(surfaces[*k].material); } @@ -754,7 +747,7 @@ void Label3D::_shape() { line++; } - const uint64_t *k = nullptr; + const SurfaceKey *k = nullptr; int idx = 0; while ((k = surfaces.next(k))) { const SurfaceData &surf = surfaces[*k]; @@ -1063,7 +1056,7 @@ Label3D::~Label3D() { } VS::get_singleton()->free(mesh); - const uint64_t *k = nullptr; + const SurfaceKey *k = nullptr; while ((k = surfaces.next(k))) { VS::get_singleton()->free(surfaces[*k].material); } diff --git a/scene/3d/label_3d.h b/scene/3d/label_3d.h index ab578a257d0..6bf08a54382 100644 --- a/scene/3d/label_3d.h +++ b/scene/3d/label_3d.h @@ -78,6 +78,7 @@ private: mutable Ref triangle_mesh; RID mesh; + struct SurfaceData { PoolVector3Array mesh_vertices; PoolVector3Array mesh_normals; @@ -89,7 +90,29 @@ private: float z_shift = 0.0; RID material; }; - HashMap surfaces; + + struct SurfaceKey { + uint64_t texture_id; + int32_t priority; + + bool operator==(const SurfaceKey &p_b) const { + return (texture_id == p_b.texture_id) && (priority == p_b.priority); + } + + SurfaceKey(uint64_t p_texture_id, int p_priority) { + texture_id = p_texture_id; + priority = p_priority; + } + }; + + struct SurfaceKeyHasher { + _FORCE_INLINE_ static uint32_t hash(const SurfaceKey &p_a) { + uint32_t hash = hash_djb2_one_32(p_a.texture_id); + return hash_djb2_one_32(p_a.priority, hash); + } + }; + + HashMap surfaces; struct WordCache { enum {