Merge pull request #62175 from bruvzg/custom_keys
This commit is contained in:
commit
c32646c1c3
5 changed files with 65 additions and 31 deletions
|
@ -35,7 +35,7 @@
|
||||||
#include "hash_map.h"
|
#include "hash_map.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
template <class TKey, class TData>
|
template <class TKey, class TData, class Hasher = HashMapHasherDefault, class Comparator = HashMapComparatorDefault<TKey>>
|
||||||
class LRUCache {
|
class LRUCache {
|
||||||
private:
|
private:
|
||||||
struct Pair {
|
struct Pair {
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
typedef typename List<Pair>::Element *Element;
|
typedef typename List<Pair>::Element *Element;
|
||||||
|
|
||||||
List<Pair> _list;
|
List<Pair> _list;
|
||||||
HashMap<TKey, Element> _map;
|
HashMap<TKey, Element, Hasher, Comparator> _map;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -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);
|
bool msdf = TS->font_is_multichannel_signed_distance_field(p_glyph.font_rid);
|
||||||
|
|
||||||
uint64_t mat_hash;
|
SurfaceKey key = SurfaceKey(tex.get_id(), p_priority, p_outline_size);
|
||||||
if (tex != RID()) {
|
if (!surfaces.has(key)) {
|
||||||
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)) {
|
|
||||||
SurfaceData surf;
|
SurfaceData surf;
|
||||||
surf.material = RenderingServer::get_singleton()->material_create();
|
surf.material = RenderingServer::get_singleton()->material_create();
|
||||||
// Set defaults for material, names need to match up those in StandardMaterial3D
|
// 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;
|
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_vertices.resize((s.offset + 1) * 4);
|
||||||
s.mesh_normals.resize((s.offset + 1) * 4);
|
s.mesh_normals.resize((s.offset + 1) * 4);
|
||||||
|
@ -464,7 +457,7 @@ void Label3D::_shape() {
|
||||||
aabb = AABB();
|
aabb = AABB();
|
||||||
|
|
||||||
// Clear materials.
|
// Clear materials.
|
||||||
for (const KeyValue<uint64_t, SurfaceData> &E : surfaces) {
|
for (const KeyValue<SurfaceKey, SurfaceData> &E : surfaces) {
|
||||||
RenderingServer::get_singleton()->free(E.value.material);
|
RenderingServer::get_singleton()->free(E.value.material);
|
||||||
}
|
}
|
||||||
surfaces.clear();
|
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;
|
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;
|
Array mesh_array;
|
||||||
mesh_array.resize(RS::ARRAY_MAX);
|
mesh_array.resize(RS::ARRAY_MAX);
|
||||||
mesh_array[RS::ARRAY_VERTEX] = E.value.mesh_vertices;
|
mesh_array[RS::ARRAY_VERTEX] = E.value.mesh_vertices;
|
||||||
|
@ -1018,7 +1011,7 @@ Label3D::~Label3D() {
|
||||||
TS->free_rid(text_rid);
|
TS->free_rid(text_rid);
|
||||||
|
|
||||||
RenderingServer::get_singleton()->free(mesh);
|
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);
|
RenderingServer::get_singleton()->free(E.value.material);
|
||||||
}
|
}
|
||||||
surfaces.clear();
|
surfaces.clear();
|
||||||
|
|
|
@ -76,7 +76,29 @@ private:
|
||||||
RID material;
|
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;
|
HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;
|
||||||
VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;
|
VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;
|
||||||
|
|
|
@ -2190,12 +2190,12 @@ RibbonTrailMesh::RibbonTrailMesh() {
|
||||||
/* TextMesh */
|
/* TextMesh */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
void TextMesh::_generate_glyph_mesh_data(uint32_t p_hash, const Glyph &p_gl) const {
|
void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_gl) const {
|
||||||
if (cache.has(p_hash)) {
|
if (cache.has(p_key)) {
|
||||||
return;
|
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);
|
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;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (glyphs[i].font_rid != RID()) {
|
if (glyphs[i].font_rid != RID()) {
|
||||||
uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id());
|
GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index);
|
||||||
hash = hash_murmur3_one_32(glyphs[i].index, hash);
|
_generate_glyph_mesh_data(key, glyphs[i]);
|
||||||
|
GlyphMeshData &gl_data = cache[key];
|
||||||
_generate_glyph_mesh_data(hash, glyphs[i]);
|
|
||||||
GlyphMeshData &gl_data = cache[hash];
|
|
||||||
|
|
||||||
p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1);
|
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);
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (glyphs[i].font_rid != RID()) {
|
if (glyphs[i].font_rid != RID()) {
|
||||||
uint32_t hash = hash_one_uint64(glyphs[i].font_rid.get_id());
|
GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index);
|
||||||
hash = hash_murmur3_one_32(glyphs[i].index, hash);
|
_generate_glyph_mesh_data(key, glyphs[i]);
|
||||||
|
const GlyphMeshData &gl_data = cache[key];
|
||||||
const GlyphMeshData &gl_data = cache[hash];
|
|
||||||
|
|
||||||
int64_t ts = gl_data.triangles.size();
|
int64_t ts = gl_data.triangles.size();
|
||||||
const Vector2 *ts_ptr = gl_data.triangles.ptr();
|
const Vector2 *ts_ptr = gl_data.triangles.ptr();
|
||||||
|
|
|
@ -475,6 +475,7 @@ private:
|
||||||
sharp = p_sharp;
|
sharp = p_sharp;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContourInfo {
|
struct ContourInfo {
|
||||||
real_t length = 0.0;
|
real_t length = 0.0;
|
||||||
bool ccw = true;
|
bool ccw = true;
|
||||||
|
@ -484,6 +485,27 @@ private:
|
||||||
ccw = p_ccw;
|
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 {
|
struct GlyphMeshData {
|
||||||
Vector<Vector2> triangles;
|
Vector<Vector2> triangles;
|
||||||
Vector<Vector<ContourPoint>> contours;
|
Vector<Vector<ContourPoint>> contours;
|
||||||
|
@ -491,7 +513,7 @@ private:
|
||||||
Vector2 min_p = Vector2(INFINITY, INFINITY);
|
Vector2 min_p = Vector2(INFINITY, INFINITY);
|
||||||
Vector2 max_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;
|
RID text_rid;
|
||||||
String text;
|
String text;
|
||||||
|
@ -517,7 +539,7 @@ private:
|
||||||
mutable bool dirty_font = true;
|
mutable bool dirty_font = true;
|
||||||
mutable bool dirty_cache = 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();
|
void _font_changed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in a new issue