Merge pull request #106434 from Ivorforce/invert-hashfuncs

Reduce cross project includes by rewriting `HashMapHasherDefault`.
This commit is contained in:
Thaddeus Crews 2025-10-06 09:06:37 -05:00
commit 686b56fae9
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
29 changed files with 253 additions and 222 deletions

View file

@ -32,6 +32,7 @@
#include "core/math/plane.h" #include "core/math/plane.h"
#include "core/math/vector3.h" #include "core/math/vector3.h"
#include "core/templates/hashfuncs.h"
/** /**
* AABB (Axis Aligned Bounding Box) * AABB (Axis Aligned Bounding Box)
@ -131,6 +132,16 @@ struct [[nodiscard]] AABB {
return position + (size * 0.5f); 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; explicit operator String() const;
AABB() = default; AABB() = default;

View file

@ -31,6 +31,7 @@
#pragma once #pragma once
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String; 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_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); } _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() : constexpr Color() :
r(0), g(0), b(0), a(1) {} r(0), g(0), b(0), a(1) {}

View file

@ -33,6 +33,7 @@
#include "core/math/aabb.h" #include "core/math/aabb.h"
#include "core/math/projection.h" #include "core/math/projection.h"
#include "core/math/vector3.h" #include "core/math/vector3.h"
#include "core/math/vector3i.h"
#include "core/templates/a_hash_map.h" #include "core/templates/a_hash_map.h"
#include "core/templates/list.h" #include "core/templates/list.h"
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"

View file

@ -30,8 +30,10 @@
#pragma once #pragma once
#include "core/math/color.h"
#include "core/math/delaunay_3d.h" #include "core/math/delaunay_3d.h"
#include "core/math/face3.h" #include "core/math/face3.h"
#include "core/math/vector2.h"
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"
#include "core/templates/vector.h" #include "core/templates/vector.h"

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/vector2.h" #include "core/math/vector2.h"
#include "core/templates/hashfuncs.h"
class String; class String;
struct Rect2i; struct Rect2i;
@ -361,6 +362,14 @@ struct [[nodiscard]] Rect2 {
explicit operator String() const; explicit operator String() const;
operator Rect2i() 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; Rect2() = default;
constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) : constexpr Rect2(real_t p_x, real_t p_y, real_t p_width, real_t p_height) :
position(Point2(p_x, p_y)), position(Point2(p_x, p_y)),

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/vector2i.h" #include "core/math/vector2i.h"
#include "core/templates/hashfuncs.h"
class String; class String;
struct Rect2; struct Rect2;
@ -226,6 +227,14 @@ struct [[nodiscard]] Rect2i {
explicit operator String() const; explicit operator String() const;
operator Rect2() 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; Rect2i() = default;
constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) : constexpr Rect2i(int p_x, int p_y, int p_width, int p_height) :
position(Point2i(p_x, p_y)), position(Point2i(p_x, p_y)),

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String; class String;
struct Vector2i; struct Vector2i;
@ -190,6 +191,12 @@ struct [[nodiscard]] Vector2 {
explicit operator String() const; explicit operator String() const;
operator Vector2i() 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) // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
constexpr Vector2() : constexpr Vector2() :
x(0), y(0) {} x(0), y(0) {}

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String; class String;
struct Vector2; struct Vector2;
@ -147,6 +148,12 @@ struct [[nodiscard]] Vector2i {
explicit operator String() const; explicit operator String() const;
operator Vector2() 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) // NOLINTBEGIN(cppcoreguidelines-pro-type-member-init)
constexpr Vector2i() : constexpr Vector2i() :
x(0), y(0) {} x(0), y(0) {}

View file

@ -214,6 +214,13 @@ struct [[nodiscard]] Vector3 {
explicit operator String() const; explicit operator String() const;
operator Vector3i() 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() : constexpr Vector3() :
x(0), y(0), z(0) {} x(0), y(0), z(0) {}
constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) : constexpr Vector3(real_t p_x, real_t p_y, real_t p_z) :

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String; class String;
struct Vector3; struct Vector3;
@ -140,6 +141,13 @@ struct [[nodiscard]] Vector3i {
explicit operator String() const; explicit operator String() const;
operator Vector3() 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() : constexpr Vector3i() :
x(0), y(0), z(0) {} x(0), y(0), z(0) {}
constexpr Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) : constexpr Vector3i(int32_t p_x, int32_t p_y, int32_t p_z) :

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/math_defs.h" #include "core/math/math_defs.h"
#include "core/templates/hashfuncs.h"
#include "core/typedefs.h" #include "core/typedefs.h"
class String; class String;
@ -146,6 +147,14 @@ struct [[nodiscard]] Vector4 {
explicit operator String() const; explicit operator String() const;
operator Vector4i() 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() : constexpr Vector4() :
x(0), y(0), z(0), w(0) {} 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) : constexpr Vector4(real_t p_x, real_t p_y, real_t p_z, real_t p_w) :

View file

@ -32,6 +32,7 @@
#include "core/error/error_macros.h" #include "core/error/error_macros.h"
#include "core/math/math_funcs.h" #include "core/math/math_funcs.h"
#include "core/templates/hashfuncs.h"
class String; class String;
struct Vector4; struct Vector4;
@ -135,6 +136,14 @@ struct [[nodiscard]] Vector4i {
explicit operator String() const; explicit operator String() const;
operator Vector4() 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() : constexpr Vector4i() :
x(0), y(0), z(0), w(0) {} x(0), y(0), z(0), w(0) {}
Vector4i(const Vector4 &p_vec4); Vector4i(const Vector4 &p_vec4);

View file

@ -637,7 +637,7 @@ private:
}; };
MethodInfo user; MethodInfo user;
HashMap<Callable, Slot, HashableHasher<Callable>> slot_map; HashMap<Callable, Slot> slot_map;
bool removable = false; bool removable = false;
}; };
friend struct _ObjectSignalLock; friend struct _ObjectSignalLock;

View file

@ -30,6 +30,7 @@
#pragma once #pragma once
#include "core/templates/hashfuncs.h"
#include "core/typedefs.h" #include "core/typedefs.h"
// Class to store an object ID (int64) // 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=(int64_t p_int64) { id = p_int64; }
_ALWAYS_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; } _ALWAYS_INLINE_ void operator=(uint64_t p_uint64) { id = p_uint64; }
uint32_t hash() const { return HashMapHasherDefault::hash(id); }
_ALWAYS_INLINE_ ObjectID() {} _ALWAYS_INLINE_ ObjectID() {}
_ALWAYS_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; } _ALWAYS_INLINE_ explicit ObjectID(const uint64_t p_id) { id = p_id; }
_ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; } _ALWAYS_INLINE_ explicit ObjectID(const int64_t p_id) { id = p_id; }

View file

@ -216,6 +216,8 @@ public:
ref(memnew(T(p_params...))); ref(memnew(T(p_params...)));
} }
uint32_t hash() const { return HashMapHasherDefault::hash(reference); }
Ref() = default; Ref() = default;
~Ref() { ~Ref() {

View file

@ -34,6 +34,7 @@
#include "core/string/char_utils.h" // IWYU pragma: export #include "core/string/char_utils.h" // IWYU pragma: export
#include "core/templates/cowdata.h" #include "core/templates/cowdata.h"
#include "core/templates/hashfuncs.h"
#include "core/templates/vector.h" #include "core/templates/vector.h"
#include "core/typedefs.h" #include "core/typedefs.h"
#include "core/variant/array.h" #include "core/variant/array.h"
@ -232,6 +233,8 @@ public:
return *this; return *this;
} }
uint32_t hash() const { return hash_djb2(get_data()); }
protected: protected:
void copy_from(const T *p_cstr) { void copy_from(const T *p_cstr) {
if (!p_cstr) { if (!p_cstr) {

View file

@ -30,8 +30,12 @@
#pragma once #pragma once
#include "core/string/ustring.h"
#include "core/templates/hash_map.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 * 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 * memory usage. Works like a dynamic array, adding elements to the end of the array, and

View file

@ -30,37 +30,17 @@
#pragma once #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_defs.h"
#include "core/math/math_funcs.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/typedefs.h"
#include "core/variant/callable.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#include <intrin.h> // Needed for `__umulh` below. #include <intrin.h> // Needed for `__umulh` below.
#endif #endif
template <typename F, typename S>
struct Pair;
/** /**
* Hashing functions * Hashing functions
*/ */
@ -315,114 +295,136 @@ static _FORCE_INLINE_ uint64_t hash_make_uint64_t(T p_in) {
return _u._u64; return _u._u64;
} }
template <typename, typename = std::void_t<>>
struct has_hash_method : std::false_type {};
template <typename T> template <typename T>
class Ref; struct has_hash_method<T, std::void_t<std::is_same<decltype(std::declval<const T>().hash()), uint32_t>>> : std::true_type {};
template <typename T>
constexpr bool has_hash_method_v = has_hash_method<T>::value;
template <typename T, typename = void>
struct HashMapHasherDefaultImpl {
};
struct HashMapHasherDefault { struct HashMapHasherDefault {
// Generic hash function for any type.
template <typename T> template <typename T>
static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); } static _FORCE_INLINE_ uint32_t hash(const T &p_type) {
return HashMapHasherDefaultImpl<std::decay_t<T>>::hash(p_type);
template <typename T>
static _FORCE_INLINE_ uint32_t hash(const Ref<T> &p_ref) { return hash_one_uint64((uint64_t)p_ref.operator->()); }
template <typename F, typename S>
static _FORCE_INLINE_ uint32_t hash(const Pair<F, S> &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);
} }
}; };
template <typename T>
struct HashMapHasherDefaultImpl<T, std::enable_if_t<has_hash_method_v<T>>> {
// For self hashing types.
static _FORCE_INLINE_ uint32_t hash(const T &p_value) {
return p_value.hash();
}
};
template <typename T>
struct HashMapHasherDefaultImpl<T *> {
// For pointer types.
static _FORCE_INLINE_ uint32_t hash(const T *p_pointer) { return hash_one_uint64((uint64_t)p_pointer); }
};
template <typename T>
struct HashMapHasherDefaultImpl<T, std::enable_if_t<std::is_enum_v<T>>> {
// For all enums.
static _FORCE_INLINE_ uint32_t hash(T p_value) {
return HashMapHasherDefaultImpl<std::underlying_type_t<T>>::hash(static_cast<std::underlying_type_t<T>>(p_value));
}
};
template <>
struct HashMapHasherDefaultImpl<char *> {
static _FORCE_INLINE_ uint32_t hash(const char *p_cstr) { return hash_djb2(p_cstr); }
};
template <>
struct HashMapHasherDefaultImpl<wchar_t> {
static _FORCE_INLINE_ uint32_t hash(const wchar_t p_wchar) { return hash_fmix32(uint32_t(p_wchar)); }
};
template <>
struct HashMapHasherDefaultImpl<char16_t> {
static _FORCE_INLINE_ uint32_t hash(const char16_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
};
template <>
struct HashMapHasherDefaultImpl<char32_t> {
static _FORCE_INLINE_ uint32_t hash(const char32_t p_uchar) { return hash_fmix32(uint32_t(p_uchar)); }
};
template <>
struct HashMapHasherDefaultImpl<uint64_t> {
static _FORCE_INLINE_ uint32_t hash(const uint64_t p_int) { return hash_one_uint64(p_int); }
};
template <>
struct HashMapHasherDefaultImpl<int64_t> {
static _FORCE_INLINE_ uint32_t hash(const int64_t p_int) { return hash_one_uint64(uint64_t(p_int)); }
};
template <>
struct HashMapHasherDefaultImpl<float> {
static _FORCE_INLINE_ uint32_t hash(const float p_float) { return hash_murmur3_one_float(p_float); }
};
template <>
struct HashMapHasherDefaultImpl<double> {
static _FORCE_INLINE_ uint32_t hash(const double p_double) { return hash_murmur3_one_double(p_double); }
};
template <>
struct HashMapHasherDefaultImpl<uint32_t> {
static _FORCE_INLINE_ uint32_t hash(const uint32_t p_int) { return hash_fmix32(p_int); }
};
template <>
struct HashMapHasherDefaultImpl<int32_t> {
static _FORCE_INLINE_ uint32_t hash(const int32_t p_int) { return hash_fmix32(uint32_t(p_int)); }
};
template <>
struct HashMapHasherDefaultImpl<uint16_t> {
static _FORCE_INLINE_ uint32_t hash(const uint16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
};
template <>
struct HashMapHasherDefaultImpl<int16_t> {
static _FORCE_INLINE_ uint32_t hash(const int16_t p_int) { return hash_fmix32(uint32_t(p_int)); }
};
template <>
struct HashMapHasherDefaultImpl<uint8_t> {
static _FORCE_INLINE_ uint32_t hash(const uint8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
};
template <>
struct HashMapHasherDefaultImpl<int8_t> {
static _FORCE_INLINE_ uint32_t hash(const int8_t p_int) { return hash_fmix32(uint32_t(p_int)); }
};
template <typename F, typename S>
struct HashMapHasherDefaultImpl<Pair<F, S>> {
static _FORCE_INLINE_ uint32_t hash(const Pair<F, S> &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 <typename, typename = std::void_t<>>
struct has_is_same_method : std::false_type {};
template <typename T>
struct has_is_same_method<T, std::void_t<std::is_same<decltype(std::declval<const T>().is_same(std::declval<const T>())), uint32_t>>> : std::true_type {};
template <typename T>
constexpr bool has_is_same_method_v = has_is_same_method<T>::value;
struct HashHasher { struct HashHasher {
static _FORCE_INLINE_ uint32_t hash(const int32_t hash) { return hash; } static _FORCE_INLINE_ uint32_t hash(const int32_t hash) { return hash; }
static _FORCE_INLINE_ uint32_t hash(const uint32_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; } static _FORCE_INLINE_ uint64_t hash(const uint64_t hash) { return hash; }
}; };
// TODO: Fold this into HashMapHasherDefault once C++20 concepts are allowed template <typename T, typename = void>
template <typename T>
struct HashableHasher {
static _FORCE_INLINE_ uint32_t hash(const T &hashable) { return hashable.hash(); }
};
template <typename T>
struct HashMapComparatorDefault { struct HashMapComparatorDefault {
static bool compare(const T &p_lhs, const T &p_rhs) { static bool compare(const T &p_lhs, const T &p_rhs) {
return p_lhs == p_rhs; return p_lhs == p_rhs;
@ -457,86 +453,10 @@ struct HashMapComparatorDefault<double> {
} }
}; };
template <> template <typename T>
struct HashMapComparatorDefault<Color> { struct HashMapComparatorDefault<T, std::enable_if_t<has_is_same_method_v<T>>> {
static bool compare(const Color &p_lhs, const Color &p_rhs) { // For self comparing types.
return p_lhs.is_same(p_rhs); static bool compare(const T &p_lhs, const T &p_rhs) {
}
};
template <>
struct HashMapComparatorDefault<Vector2> {
static bool compare(const Vector2 &p_lhs, const Vector2 &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Vector3> {
static bool compare(const Vector3 &p_lhs, const Vector3 &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Vector4> {
static bool compare(const Vector4 &p_lhs, const Vector4 &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Rect2> {
static bool compare(const Rect2 &p_lhs, const Rect2 &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<AABB> {
static bool compare(const AABB &p_lhs, const AABB &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Plane> {
static bool compare(const Plane &p_lhs, const Plane &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Transform2D> {
static bool compare(const Transform2D &p_lhs, const Transform2D &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Basis> {
static bool compare(const Basis &p_lhs, const Basis &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Transform3D> {
static bool compare(const Transform3D &p_lhs, const Transform3D &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Projection> {
static bool compare(const Projection &p_lhs, const Projection &p_rhs) {
return p_lhs.is_same(p_rhs);
}
};
template <>
struct HashMapComparatorDefault<Quaternion> {
static bool compare(const Quaternion &p_lhs, const Quaternion &p_rhs) {
return p_lhs.is_same(p_rhs); return p_lhs.is_same(p_rhs);
} }
}; };

View file

@ -30,6 +30,7 @@
#pragma once #pragma once
#include "core/templates/hashfuncs.h"
#include "core/typedefs.h" #include "core/typedefs.h"
class RID_AllocBase; class RID_AllocBase;
@ -69,6 +70,8 @@ public:
} }
_ALWAYS_INLINE_ uint64_t get_id() const { return _id; } _ALWAYS_INLINE_ uint64_t get_id() const { return _id; }
uint32_t hash() const { return HashMapHasherDefault::hash(_id); }
_ALWAYS_INLINE_ RID() {} _ALWAYS_INLINE_ RID() {}
}; };

View file

@ -33,6 +33,8 @@
#include "core/templates/hash_map.h" #include "core/templates/hash_map.h"
#include "core/templates/local_vector.h" #include "core/templates/local_vector.h"
#include <iterator>
/// An unordered map that splits elements between a fast-access vector of LinearCount consecutively /// 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. /// indexed elements, and a slower-access map holding sparse indexes larger than LinearCount.
/// ///

View file

@ -196,7 +196,7 @@ public:
class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MDResourceCache { class API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0)) MDResourceCache {
private: private:
typedef HashMap<ClearAttKey, id<MTLRenderPipelineState>, HashableHasher<ClearAttKey>> HashMap; typedef HashMap<ClearAttKey, id<MTLRenderPipelineState>> HashMap;
std::unique_ptr<MDResourceFactory> resource_factory; std::unique_ptr<MDResourceFactory> resource_factory;
HashMap clear_states; HashMap clear_states;

View file

@ -60,6 +60,7 @@ GODOT_CLANG_WARNING_PUSH_AND_IGNORE("-Wdeprecated-declarations")
#include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_device.h"
#import <Metal/Metal.h> #import <Metal/Metal.h>
#include <iterator>
#pragma mark - #pragma mark -
#pragma mark Metal format capabilities #pragma mark Metal format capabilities

View file

@ -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 * 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. * there are no more references to the MDLibrary associated with the cache entry.
*/ */
HashMap<SHA256Digest, ShaderCacheEntry *, HashableHasher<SHA256Digest>> _shader_cache; HashMap<SHA256Digest, ShaderCacheEntry *> _shader_cache;
void shader_cache_free_entry(const SHA256Digest &key); void shader_cache_free_entry(const SHA256Digest &key);
public: public:

View file

@ -70,6 +70,8 @@ class GridMap : public Node3D {
return Vector3i(x, y, z); return Vector3i(x, y, z);
} }
uint32_t hash() const { return operator Vector3i().hash(); }
IndexKey(Vector3i p_vector) { IndexKey(Vector3i p_vector) {
x = (int16_t)p_vector.x; x = (int16_t)p_vector.x;
y = (int16_t)p_vector.y; y = (int16_t)p_vector.y;

View file

@ -109,22 +109,22 @@ Error ImageLoaderSVG::create_image_from_utf8_buffer(Ref<Image> p_image, const ui
tvg::Result res = sw_canvas->target((uint32_t *)buffer.ptrw(), width, width, height, tvg::SwCanvas::ABGR8888S); tvg::Result res = sw_canvas->target((uint32_t *)buffer.ptrw(), width, width, height, tvg::SwCanvas::ABGR8888S);
if (res != tvg::Result::Success) { 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)); res = sw_canvas->push(std::move(picture));
if (res != tvg::Result::Success) { 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(); res = sw_canvas->draw();
if (res != tvg::Result::Success) { 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(); res = sw_canvas->sync();
if (res != tvg::Result::Success) { 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); p_image->set_data(width, height, false, Image::FORMAT_RGBA8, buffer);

View file

@ -43,6 +43,7 @@ using namespace godot;
// Headers for building as built-in module. // Headers for building as built-in module.
#include "core/os/mutex.h" #include "core/os/mutex.h"
#include "core/string/ustring.h"
#include "core/templates/hash_map.h" #include "core/templates/hash_map.h"
#include "core/typedefs.h" #include "core/typedefs.h"

View file

@ -43,6 +43,7 @@ using namespace godot;
// Headers for building as built-in module. // Headers for building as built-in module.
#include "core/os/mutex.h" #include "core/os/mutex.h"
#include "core/string/ustring.h"
#include "core/templates/hash_map.h" #include "core/templates/hash_map.h"
#include "core/typedefs.h" #include "core/typedefs.h"

View file

@ -153,8 +153,9 @@ private:
uint64_t port : 32; uint64_t port : 32;
}; };
uint64_t key = 0; 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<uint64_t>::compare(key, p_key.key); }
}; };
Error _write_node(Type p_type, StringBuilder *p_global_code, StringBuilder *p_global_code_per_node, HashMap<Type, StringBuilder> *p_global_code_per_func, StringBuilder &r_code, Vector<DefaultTextureParam> &r_def_tex_params, const HashMap<ConnectionKey, const List<Connection>::Element *> &p_input_connections, int p_node, HashSet<int> &r_processed, bool p_for_preview, HashSet<StringName> &r_classes) const; Error _write_node(Type p_type, StringBuilder *p_global_code, StringBuilder *p_global_code_per_node, HashMap<Type, StringBuilder> *p_global_code_per_func, StringBuilder &r_code, Vector<DefaultTextureParam> &r_def_tex_params, const HashMap<ConnectionKey, const List<Connection>::Element *> &p_input_connections, int p_node, HashSet<int> &r_processed, bool p_for_preview, HashSet<StringName> &r_classes) const;

View file

@ -487,7 +487,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
static void _uniform_set_invalidation_callback(void *p_userdata); static void _uniform_set_invalidation_callback(void *p_userdata);
static void _canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata); static void _canvas_texture_invalidation_callback(bool p_deleted, void *p_userdata);
typedef LRUCache<RIDSetKey, RID, HashableHasher<RIDSetKey>, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache; typedef LRUCache<RIDSetKey, RID, HashMapHasherDefault, HashMapComparatorDefault<RIDSetKey>, _before_evict> RIDCache;
RIDCache rid_set_to_uniform_set; RIDCache rid_set_to_uniform_set;
/// Maps a CanvasTexture to its associated uniform sets, which must /// Maps a CanvasTexture to its associated uniform sets, which must
/// be invalidated when the CanvasTexture is updated, such as changing the /// be invalidated when the CanvasTexture is updated, such as changing the
@ -526,7 +526,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
uint32_t flags = 0; uint32_t flags = 0;
}; };
HashMap<TextureState, TextureInfo, HashableHasher<TextureState>, HashMapComparatorDefault<TextureState>, PagedAllocator<HashMapElement<TextureState, TextureInfo>>> texture_info_map; HashMap<TextureState, TextureInfo, HashMapHasherDefault, HashMapComparatorDefault<TextureState>, PagedAllocator<HashMapElement<TextureState, TextureInfo>>> texture_info_map;
// per-frame buffers // per-frame buffers
struct DataBuffer { struct DataBuffer {