From ad600125df2ce267e48fb1588d688b858647321c Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Thu, 15 May 2025 11:50:46 +0200 Subject: [PATCH] Rewrite `HashMapHasherDefault` based on type traits - it is now possible to declare a default hashing function for any type. Remove cross-project includes from `hashfuncs.h`. Improve hashing function for `Color` (based on values instead of `String`). Move `Variant` comparison from `hash_map.h` to `dictionary.cpp` (`VariantComparatorDictionary`), where it's used. Remove now unnecessary `HashableHasher`. --- core/math/aabb.h | 11 + core/math/color.h | 9 + core/math/delaunay_3d.h | 1 + core/math/geometry_3d.h | 2 + core/math/rect2.h | 9 + core/math/rect2i.h | 9 + core/math/vector2.h | 7 + core/math/vector2i.h | 7 + core/math/vector3.h | 7 + core/math/vector3i.h | 8 + core/math/vector4.h | 9 + core/math/vector4i.h | 9 + core/object/object.h | 2 +- core/object/object_id.h | 3 + core/object/ref_counted.h | 2 + core/string/ustring.h | 3 + core/templates/a_hash_map.h | 4 + core/templates/hashfuncs.h | 342 +++++++----------- core/templates/rid.h | 3 + drivers/metal/inflection_map.h | 2 + drivers/metal/metal_objects.h | 2 +- drivers/metal/pixel_formats.h | 1 + drivers/metal/rendering_device_driver_metal.h | 2 +- modules/gridmap/grid_map.h | 2 + modules/svg/image_loader_svg.cpp | 8 +- modules/text_server_adv/thorvg_svg_in_ot.h | 1 + modules/text_server_fb/thorvg_svg_in_ot.h | 1 + scene/resources/visual_shader.h | 5 +- .../renderer_rd/renderer_canvas_render_rd.h | 4 +- 29 files changed, 253 insertions(+), 222 deletions(-) diff --git a/core/math/aabb.h b/core/math/aabb.h index 9880e2791e3..5f0ba8a0b6a 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -32,6 +32,7 @@ #include "core/math/plane.h" #include "core/math/vector3.h" +#include "core/templates/hashfuncs.h" /** * AABB (Axis Aligned Bounding Box) @@ -131,6 +132,16 @@ struct [[nodiscard]] AABB { return position + (size * 0.5f); } + uint32_t hash() const { + uint32_t h = hash_murmur3_one_real(position.x); + h = hash_murmur3_one_real(position.y, h); + h = hash_murmur3_one_real(position.z, h); + h = hash_murmur3_one_real(size.x, h); + h = hash_murmur3_one_real(size.y, h); + h = hash_murmur3_one_real(size.z, h); + return hash_fmix32(h); + } + explicit operator String() const; AABB() = default; diff --git a/core/math/color.h b/core/math/color.h index f24e24f22d2..5b5fd495752 100644 --- a/core/math/color.h +++ b/core/math/color.h @@ -31,6 +31,7 @@ #pragma once #include "core/math/math_funcs.h" +#include "core/templates/hashfuncs.h" class String; @@ -239,6 +240,14 @@ struct [[nodiscard]] Color { _FORCE_INLINE_ void set_ok_hsl_s(float p_s) { set_ok_hsl(get_ok_hsl_h(), p_s, get_ok_hsl_l(), a); } _FORCE_INLINE_ void set_ok_hsl_l(float p_l) { set_ok_hsl(get_ok_hsl_h(), get_ok_hsl_s(), p_l, a); } + uint32_t hash() const { + uint32_t h = hash_murmur3_one_float(r); + h = hash_murmur3_one_float(r, h); + h = hash_murmur3_one_float(b, h); + h = hash_murmur3_one_float(a, h); + return hash_fmix32(h); + } + constexpr Color() : r(0), g(0), b(0), a(1) {} diff --git a/core/math/delaunay_3d.h b/core/math/delaunay_3d.h index a4b274ddf19..7acf8cbcce2 100644 --- a/core/math/delaunay_3d.h +++ b/core/math/delaunay_3d.h @@ -33,6 +33,7 @@ #include "core/math/aabb.h" #include "core/math/projection.h" #include "core/math/vector3.h" +#include "core/math/vector3i.h" #include "core/templates/a_hash_map.h" #include "core/templates/list.h" #include "core/templates/local_vector.h" diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h index fd945c17f89..6af902b28b8 100644 --- a/core/math/geometry_3d.h +++ b/core/math/geometry_3d.h @@ -30,8 +30,10 @@ #pragma once +#include "core/math/color.h" #include "core/math/delaunay_3d.h" #include "core/math/face3.h" +#include "core/math/vector2.h" #include "core/templates/local_vector.h" #include "core/templates/vector.h" diff --git a/core/math/rect2.h b/core/math/rect2.h index 4b51fee10d1..2ba59fde352 100644 --- a/core/math/rect2.h +++ b/core/math/rect2.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/vector2.h" +#include "core/templates/hashfuncs.h" class String; struct Rect2i; @@ -361,6 +362,14 @@ struct [[nodiscard]] Rect2 { explicit operator String() const; operator Rect2i() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_real(position.x); + h = hash_murmur3_one_real(position.y, h); + h = hash_murmur3_one_real(size.x, h); + h = hash_murmur3_one_real(size.y, h); + return hash_fmix32(h); + } + Rect2() = default; constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) : position(Point2(p_x, p_y)), diff --git a/core/math/rect2i.h b/core/math/rect2i.h index 2b51f3e133e..05cd9f5eae9 100644 --- a/core/math/rect2i.h +++ b/core/math/rect2i.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/vector2i.h" +#include "core/templates/hashfuncs.h" class String; struct Rect2; @@ -226,6 +227,14 @@ struct [[nodiscard]] Rect2i { explicit operator String() const; operator Rect2() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_32(uint32_t(position.x)); + h = hash_murmur3_one_32(uint32_t(position.y), h); + h = hash_murmur3_one_32(uint32_t(size.x), h); + h = hash_murmur3_one_32(uint32_t(size.y), h); + return hash_fmix32(h); + } + Rect2i() = default; constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) : position(Point2i(p_x, p_y)), diff --git a/core/math/vector2.h b/core/math/vector2.h index b347bd05122..98207474a3b 100644 --- a/core/math/vector2.h +++ b/core/math/vector2.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/math_funcs.h" +#include "core/templates/hashfuncs.h" class String; struct Vector2i; @@ -190,6 +191,12 @@ struct [[nodiscard]] Vector2 { explicit operator String() const; operator Vector2i() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_real(x); + h = hash_murmur3_one_real(y, h); + return hash_fmix32(h); + } + // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) constexpr Vector2() : x(0), y(0) {} diff --git a/core/math/vector2i.h b/core/math/vector2i.h index aae35f78871..5f2dc161a60 100644 --- a/core/math/vector2i.h +++ b/core/math/vector2i.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/math_funcs.h" +#include "core/templates/hashfuncs.h" class String; struct Vector2; @@ -147,6 +148,12 @@ struct [[nodiscard]] Vector2i { explicit operator String() const; operator Vector2() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_32(uint32_t(x)); + h = hash_murmur3_one_32(uint32_t(y), h); + return hash_fmix32(h); + } + // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init) constexpr Vector2i() : x(0), y(0) {} diff --git a/core/math/vector3.h b/core/math/vector3.h index 0ebab7a3a90..b0f29e0d566 100644 --- a/core/math/vector3.h +++ b/core/math/vector3.h @@ -214,6 +214,13 @@ struct [[nodiscard]] Vector3 { explicit operator String() const; operator Vector3i() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_real(x); + h = hash_murmur3_one_real(y, h); + h = hash_murmur3_one_real(z, h); + return hash_fmix32(h); + } + constexpr Vector3() : x(0), y(0), z(0) {} constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) : diff --git a/core/math/vector3i.h b/core/math/vector3i.h index bef53a96449..d13f08df39d 100644 --- a/core/math/vector3i.h +++ b/core/math/vector3i.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/math_funcs.h" +#include "core/templates/hashfuncs.h" class String; struct Vector3; @@ -140,6 +141,13 @@ struct [[nodiscard]] Vector3i { explicit operator String() const; operator Vector3() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_32(uint32_t(x)); + h = hash_murmur3_one_32(uint32_t(y), h); + h = hash_murmur3_one_32(uint32_t(z), h); + return hash_fmix32(h); + } + constexpr Vector3i() : x(0), y(0), z(0) {} constexpr Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) : diff --git a/core/math/vector4.h b/core/math/vector4.h index d1839de4c12..e05968eae1f 100644 --- a/core/math/vector4.h +++ b/core/math/vector4.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/math_defs.h" +#include "core/templates/hashfuncs.h" #include "core/typedefs.h" class String; @@ -146,6 +147,14 @@ struct [[nodiscard]] Vector4 { explicit operator String() const; operator Vector4i() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_real(x); + h = hash_murmur3_one_real(y, h); + h = hash_murmur3_one_real(z, h); + h = hash_murmur3_one_real(w, h); + return hash_fmix32(h); + } + constexpr Vector4() : x(0), y(0), z(0), w(0) {} constexpr Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) : diff --git a/core/math/vector4i.h b/core/math/vector4i.h index 8234ab81ebc..d67cbed05d6 100644 --- a/core/math/vector4i.h +++ b/core/math/vector4i.h @@ -32,6 +32,7 @@ #include "core/error/error_macros.h" #include "core/math/math_funcs.h" +#include "core/templates/hashfuncs.h" class String; struct Vector4; @@ -135,6 +136,14 @@ struct [[nodiscard]] Vector4i { explicit operator String() const; operator Vector4() const; + uint32_t hash() const { + uint32_t h = hash_murmur3_one_32(uint32_t(x)); + h = hash_murmur3_one_32(uint32_t(y), h); + h = hash_murmur3_one_32(uint32_t(z), h); + h = hash_murmur3_one_32(uint32_t(w), h); + return hash_fmix32(h); + } + constexpr Vector4i() : x(0), y(0), z(0), w(0) {} Vector4i(const Vector4 &p_vec4); diff --git a/core/object/object.h b/core/object/object.h index c2cbad425ac..331fdb315c5 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -641,7 +641,7 @@ private: }; MethodInfo user; - HashMap> slot_map; + HashMap slot_map; bool removable = false; }; friend struct _ObjectSignalLock; diff --git a/core/object/object_id.h b/core/object/object_id.h index 2fc66beb387..97d75d8aeeb 100644 --- a/core/object/object_id.h +++ b/core/object/object_id.h @@ -30,6 +30,7 @@ #pragma once +#include "core/templates/hashfuncs.h" #include "core/typedefs.h" // Class to store an object ID (int64) @@ -54,6 +55,8 @@ public: _ALWAYS_INLINE_ void operator=(int64_t p_int64) { id = p_int64; } _ALWAYS_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; } + uint32_t hash() const { return HashMapHasherDefault::hash(id); } + _ALWAYS_INLINE_ ObjectID() {} _ALWAYS_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; } _ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; } diff --git a/core/object/ref_counted.h b/core/object/ref_counted.h index 9fca55dd225..9b6c3c7a85b 100644 --- a/core/object/ref_counted.h +++ b/core/object/ref_counted.h @@ -216,6 +216,8 @@ public: ref(memnew(T(p_params...))); } + uint32_t hash() const { return HashMapHasherDefault::hash(reference); } + Ref() = default; ~Ref() { diff --git a/core/string/ustring.h b/core/string/ustring.h index 4f28d2db2ea..ea16792ace0 100644 --- a/core/string/ustring.h +++ b/core/string/ustring.h @@ -34,6 +34,7 @@ #include "core/string/char_utils.h" // IWYU pragma: export #include "core/templates/cowdata.h" +#include "core/templates/hashfuncs.h" #include "core/templates/vector.h" #include "core/typedefs.h" #include "core/variant/array.h" @@ -232,6 +233,8 @@ public: return *this; } + uint32_t hash() const { return hash_djb2(get_data()); } + protected: void copy_from(const T *p_cstr) { if (!p_cstr) { diff --git a/core/templates/a_hash_map.h b/core/templates/a_hash_map.h index 9db2775149a..ac48c0c4ef2 100644 --- a/core/templates/a_hash_map.h +++ b/core/templates/a_hash_map.h @@ -30,8 +30,12 @@ #pragma once +#include "core/string/ustring.h" #include "core/templates/hash_map.h" +class StringName; +class Variant; + /** * An array-based implementation of a hash map. It is very efficient in terms of performance and * memory usage. Works like a dynamic array, adding elements to the end of the array, and diff --git a/core/templates/hashfuncs.h b/core/templates/hashfuncs.h index 6a228b0cde4..9b3a4638aea 100644 --- a/core/templates/hashfuncs.h +++ b/core/templates/hashfuncs.h @@ -30,37 +30,17 @@ #pragma once -#include "core/math/aabb.h" -#include "core/math/basis.h" -#include "core/math/color.h" #include "core/math/math_defs.h" #include "core/math/math_funcs.h" -#include "core/math/plane.h" -#include "core/math/projection.h" -#include "core/math/quaternion.h" -#include "core/math/rect2.h" -#include "core/math/rect2i.h" -#include "core/math/transform_2d.h" -#include "core/math/transform_3d.h" -#include "core/math/vector2.h" -#include "core/math/vector2i.h" -#include "core/math/vector3.h" -#include "core/math/vector3i.h" -#include "core/math/vector4.h" -#include "core/math/vector4i.h" -#include "core/object/object_id.h" -#include "core/string/node_path.h" -#include "core/string/string_name.h" -#include "core/string/ustring.h" -#include "core/templates/pair.h" -#include "core/templates/rid.h" #include "core/typedefs.h" -#include "core/variant/callable.h" #ifdef _MSC_VER #include // Needed for `__umulh` below. #endif +template +struct Pair; + /** * Hashing functions */ @@ -315,114 +295,136 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) { return _u._u64; } +template > +struct has_hash_method : std::false_type {}; + template -class Ref; +struct has_hash_method().hash()), uint32_t>>> : std::true_type {}; + +template +constexpr bool has_hash_method_v = has_hash_method::value; + +template +struct HashMapHasherDefaultImpl { +}; struct HashMapHasherDefault { - // Generic hash function for any type. template - static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); } - - template - static _FORCE_INLINE_ uint32_t hash(const Ref &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); } - - template - static _FORCE_INLINE_ uint32_t hash(const Pair &p_pair) { - uint64_t h1 = hash(p_pair.first); - uint64_t h2 = hash(p_pair.second); - return hash_one_uint64((h1 << 32) | h2); - } - - static _FORCE_INLINE_ uint32_t hash(const String &p_string) { return p_string.hash(); } - static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } - static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); } - static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); } - static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); } - static _FORCE_INLINE_ uint32_t hash(const RID &p_rid) { return hash_one_uint64(p_rid.get_id()); } - static _FORCE_INLINE_ uint32_t hash(const CharString &p_char_string) { return hash_djb2(p_char_string.get_data()); } - static _FORCE_INLINE_ uint32_t hash(const StringName &p_string_name) { return p_string_name.hash(); } - static _FORCE_INLINE_ uint32_t hash(const NodePath &p_path) { return p_path.hash(); } - static _FORCE_INLINE_ uint32_t hash(const ObjectID &p_id) { return hash_one_uint64(p_id); } - static _FORCE_INLINE_ uint32_t hash(const Callable &p_callable) { return p_callable.hash(); } - - static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } - static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); } - static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); } - static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); } - static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); } - static _FORCE_INLINE_ uint32_t hash(const Vector2i &p_vec) { - uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x)); - h = hash_murmur3_one_32(uint32_t(p_vec.y), h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector3i &p_vec) { - uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x)); - h = hash_murmur3_one_32(uint32_t(p_vec.y), h); - h = hash_murmur3_one_32(uint32_t(p_vec.z), h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector4i &p_vec) { - uint32_t h = hash_murmur3_one_32(uint32_t(p_vec.x)); - h = hash_murmur3_one_32(uint32_t(p_vec.y), h); - h = hash_murmur3_one_32(uint32_t(p_vec.z), h); - h = hash_murmur3_one_32(uint32_t(p_vec.w), h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector2 &p_vec) { - uint32_t h = hash_murmur3_one_real(p_vec.x); - h = hash_murmur3_one_real(p_vec.y, h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector3 &p_vec) { - uint32_t h = hash_murmur3_one_real(p_vec.x); - h = hash_murmur3_one_real(p_vec.y, h); - h = hash_murmur3_one_real(p_vec.z, h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Vector4 &p_vec) { - uint32_t h = hash_murmur3_one_real(p_vec.x); - h = hash_murmur3_one_real(p_vec.y, h); - h = hash_murmur3_one_real(p_vec.z, h); - h = hash_murmur3_one_real(p_vec.w, h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Color &p_vec) { - uint32_t h = hash_murmur3_one_float(p_vec.r); - h = hash_murmur3_one_float(p_vec.g, h); - h = hash_murmur3_one_float(p_vec.b, h); - h = hash_murmur3_one_float(p_vec.a, h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Rect2i &p_rect) { - uint32_t h = hash_murmur3_one_32(uint32_t(p_rect.position.x)); - h = hash_murmur3_one_32(uint32_t(p_rect.position.y), h); - h = hash_murmur3_one_32(uint32_t(p_rect.size.x), h); - h = hash_murmur3_one_32(uint32_t(p_rect.size.y), h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const Rect2 &p_rect) { - uint32_t h = hash_murmur3_one_real(p_rect.position.x); - h = hash_murmur3_one_real(p_rect.position.y, h); - h = hash_murmur3_one_real(p_rect.size.x, h); - h = hash_murmur3_one_real(p_rect.size.y, h); - return hash_fmix32(h); - } - static _FORCE_INLINE_ uint32_t hash(const AABB &p_aabb) { - uint32_t h = hash_murmur3_one_real(p_aabb.position.x); - h = hash_murmur3_one_real(p_aabb.position.y, h); - h = hash_murmur3_one_real(p_aabb.position.z, h); - h = hash_murmur3_one_real(p_aabb.size.x, h); - h = hash_murmur3_one_real(p_aabb.size.y, h); - h = hash_murmur3_one_real(p_aabb.size.z, h); - return hash_fmix32(h); + static _FORCE_INLINE_ uint32_t hash(const T &p_type) { + return HashMapHasherDefaultImpl>::hash(p_type); } }; +template +struct HashMapHasherDefaultImpl>> { + // For self hashing types. + static _FORCE_INLINE_ uint32_t hash(const T &p_value) { + return p_value.hash(); + } +}; + +template +struct HashMapHasherDefaultImpl { + // For pointer types. + static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); } +}; + +template +struct HashMapHasherDefaultImpl>> { + // For all enums. + static _FORCE_INLINE_ uint32_t hash(T p_value) { + return HashMapHasherDefaultImpl>::hash(static_cast>(p_value)); + } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); } +}; + +template <> +struct HashMapHasherDefaultImpl { + static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); } +}; + +template +struct HashMapHasherDefaultImpl> { + static _FORCE_INLINE_ uint32_t hash(const Pair &p_pair) { + uint64_t h1 = HashMapHasherDefault::hash(p_pair.first); + uint64_t h2 = HashMapHasherDefault::hash(p_pair.second); + return hash_one_uint64((h1 << 32) | h2); + } +}; + +template > +struct has_is_same_method : std::false_type {}; + +template +struct has_is_same_method().is_same(std::declval())), uint32_t>>> : std::true_type {}; + +template +constexpr bool has_is_same_method_v = has_is_same_method::value; + struct HashHasher { static _FORCE_INLINE_ uint32_t hash(const int32_t hash) { return hash; } static _FORCE_INLINE_ uint32_t hash(const uint32_t hash) { return hash; } @@ -430,13 +432,7 @@ struct HashHasher { static _FORCE_INLINE_ uint64_t hash(const uint64_t hash) { return hash; } }; -// TODO: Fold this into HashMapHasherDefault once C++20 concepts are allowed -template -struct HashableHasher { - static _FORCE_INLINE_ uint32_t hash(const T &hashable) { return hashable.hash(); } -}; - -template +template struct HashMapComparatorDefault { static bool compare(const T &p_lhs, const T &p_rhs) { return p_lhs == p_rhs; @@ -457,86 +453,10 @@ struct HashMapComparatorDefault { } }; -template <> -struct HashMapComparatorDefault { - static bool compare(const Color &p_lhs, const Color &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Vector2 &p_lhs, const Vector2 &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Vector3 &p_lhs, const Vector3 &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Vector4 &p_lhs, const Vector4 &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Rect2 &p_lhs, const Rect2 &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const AABB &p_lhs, const AABB &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Plane &p_lhs, const Plane &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Transform2D &p_lhs, const Transform2D &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Basis &p_lhs, const Basis &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Transform3D &p_lhs, const Transform3D &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Projection &p_lhs, const Projection &p_rhs) { - return p_lhs.is_same(p_rhs); - } -}; - -template <> -struct HashMapComparatorDefault { - static bool compare(const Quaternion &p_lhs, const Quaternion &p_rhs) { +template +struct HashMapComparatorDefault>> { + // For self comparing types. + static bool compare(const T &p_lhs, const T &p_rhs) { return p_lhs.is_same(p_rhs); } }; diff --git a/core/templates/rid.h b/core/templates/rid.h index a8b86c1e535..b5d81d61ac0 100644 --- a/core/templates/rid.h +++ b/core/templates/rid.h @@ -30,6 +30,7 @@ #pragma once +#include "core/templates/hashfuncs.h" #include "core/typedefs.h" class RID_AllocBase; @@ -69,6 +70,8 @@ public: } _ALWAYS_INLINE_ uint64_t get_id() const { return _id; } + uint32_t hash() const { return HashMapHasherDefault::hash(_id); } + _ALWAYS_INLINE_ RID() {} }; diff --git a/drivers/metal/inflection_map.h b/drivers/metal/inflection_map.h index ee426194700..7377c04da3b 100644 --- a/drivers/metal/inflection_map.h +++ b/drivers/metal/inflection_map.h @@ -33,6 +33,8 @@ #include "core/templates/hash_map.h" #include "core/templates/local_vector.h" +#include + /// An unordered map that splits elements between a fast-access vector of LinearCount consecutively /// indexed elements, and a slower-access map holding sparse indexes larger than LinearCount. /// diff --git a/drivers/metal/metal_objects.h b/drivers/metal/metal_objects.h index 4826ded95d6..d019c08d489 100644 --- a/drivers/metal/metal_objects.h +++ b/drivers/metal/metal_objects.h @@ -196,7 +196,7 @@ public: class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MDResourceCache { private: - typedef HashMap, HashableHasher> HashMap; + typedef HashMap> HashMap; std::unique_ptr resource_factory; HashMap clear_states; diff --git a/drivers/metal/pixel_formats.h b/drivers/metal/pixel_formats.h index 2db9be25577..04f1d9350db 100644 --- a/drivers/metal/pixel_formats.h +++ b/drivers/metal/pixel_formats.h @@ -60,6 +60,7 @@ GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations") #include "servers/rendering/rendering_device.h" #import +#include #pragma mark - #pragma mark Metal format capabilities diff --git a/drivers/metal/rendering_device_driver_metal.h b/drivers/metal/rendering_device_driver_metal.h index 09a3742925f..43d7fb0f5c9 100644 --- a/drivers/metal/rendering_device_driver_metal.h +++ b/drivers/metal/rendering_device_driver_metal.h @@ -90,7 +90,7 @@ class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) RenderingDeviceDriverMet * To prevent unbounded growth of the cache, cache entries are automatically freed when * there are no more references to the MDLibrary associated with the cache entry. */ - HashMap> _shader_cache; + HashMap _shader_cache; void shader_cache_free_entry(const SHA256Digest &key); public: diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index c5730a5e1cd..fdbef70c247 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -70,6 +70,8 @@ class GridMap : public Node3D { return Vector3i(x, y, z); } + uint32_t hash() const { return operator Vector3i().hash(); } + IndexKey(Vector3i p_vector) { x = (int16_t)p_vector.x; y = (int16_t)p_vector.y; diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index d0e2b1728c6..ca4c02e8b24 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -109,22 +109,22 @@ Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref p_image, const ui tvg::Result res = sw_canvas->target((uint32_t *)buffer.ptrw(), width, width, height, tvg::SwCanvas::ABGR8888S); if (res != tvg::Result::Success) { - ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't set target on ThorVG canvas."); + ERR_FAIL_V_MSG(FAILED, vformat("ImageLoaderSVG: Couldn't set target on ThorVG canvas, error code %d.", res)); } res = sw_canvas->push(std::move(picture)); if (res != tvg::Result::Success) { - ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't insert ThorVG picture on canvas."); + ERR_FAIL_V_MSG(FAILED, vformat("ImageLoaderSVG: Couldn't insert ThorVG picture on canvas, error code %d.", res)); } res = sw_canvas->draw(); if (res != tvg::Result::Success) { - ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't draw ThorVG pictures on canvas."); + ERR_FAIL_V_MSG(FAILED, vformat("ImageLoaderSVG: Couldn't draw ThorVG pictures on canvas, error code %d.", res)); } res = sw_canvas->sync(); if (res != tvg::Result::Success) { - ERR_FAIL_V_MSG(FAILED, "ImageLoaderSVG: Couldn't sync ThorVG canvas."); + ERR_FAIL_V_MSG(FAILED, vformat("ImageLoaderSVG: Couldn't sync ThorVG canvas, error code %d.", res)); } p_image->set_data(width, height, false, Image::FORMAT_RGBA8, buffer); diff --git a/modules/text_server_adv/thorvg_svg_in_ot.h b/modules/text_server_adv/thorvg_svg_in_ot.h index 39c66eb194c..ebb0f8fb6fa 100644 --- a/modules/text_server_adv/thorvg_svg_in_ot.h +++ b/modules/text_server_adv/thorvg_svg_in_ot.h @@ -43,6 +43,7 @@ using namespace godot; // Headers for building as built-in module. #include "core/os/mutex.h" +#include "core/string/ustring.h" #include "core/templates/hash_map.h" #include "core/typedefs.h" diff --git a/modules/text_server_fb/thorvg_svg_in_ot.h b/modules/text_server_fb/thorvg_svg_in_ot.h index 39c66eb194c..ebb0f8fb6fa 100644 --- a/modules/text_server_fb/thorvg_svg_in_ot.h +++ b/modules/text_server_fb/thorvg_svg_in_ot.h @@ -43,6 +43,7 @@ using namespace godot; // Headers for building as built-in module. #include "core/os/mutex.h" +#include "core/string/ustring.h" #include "core/templates/hash_map.h" #include "core/typedefs.h" diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index a526af03e43..916fc5d07a3 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -153,8 +153,9 @@ private: uint64_t port : 32; }; uint64_t key = 0; - // This is used to apply default equal and hash methods for uint64_t to ConnectionKey. - operator uint64_t() const { return key; } + + uint32_t hash() const { return HashMapHasherDefault::hash(key); } + bool is_same(const ConnectionKey &p_key) const { return HashMapComparatorDefault::compare(key, p_key.key); } }; Error _write_node(Type p_type, StringBuilder *p_global_code, StringBuilder *p_global_code_per_node, HashMap *p_global_code_per_func, StringBuilder &r_code, Vector &r_def_tex_params, const HashMap::Element *> &p_input_connections, int p_node, HashSet &r_processed, bool p_for_preview, HashSet &r_classes) const; diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index a927834820a..6245072bd4d 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -487,7 +487,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { static void _uniform_set_invalidation_callback(void *p_userdata); static void _canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata); - typedef LRUCache, HashMapComparatorDefault, _before_evict> RIDCache; + typedef LRUCache, _before_evict> RIDCache; RIDCache rid_set_to_uniform_set; /// Maps a CanvasTexture to its associated uniform sets, which must /// be invalidated when the CanvasTexture is updated, such as changing the @@ -526,7 +526,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { uint32_t flags = 0; }; - HashMap, HashMapComparatorDefault, PagedAllocator>> texture_info_map; + HashMap, PagedAllocator>> texture_info_map; // per-frame buffers struct DataBuffer {