Fix #890 differs crash

This commit is contained in:
Cory Petkovsek 2025-12-09 01:21:32 +07:00
parent d3972276d3
commit 96feda6c4a
3 changed files with 19 additions and 29 deletions

View File

@ -754,14 +754,14 @@ void Terrain3DMaterial::set_shader_override_enabled(const bool p_enabled) {
}
void Terrain3DMaterial::set_shader_override(const Ref<Shader> &p_shader) {
LOG(INFO, "Setting override shader");
SET_IF_DIFF(_shader_override, p_shader);
LOG(INFO, "Setting override shader");
_update_shader();
}
void Terrain3DMaterial::set_buffer_shader_override_enabled(const bool p_enabled) {
SET_IF_DIFF(_buffer_shader_override_enabled, p_enabled);
LOG(INFO, "Enable shader override: ", p_enabled);
_buffer_shader_override_enabled = p_enabled;
if (_buffer_shader_override_enabled && _buffer_shader_override.is_null()) {
LOG(DEBUG, "Instantiating new _shader_override");
_buffer_shader_override.instantiate();
@ -770,8 +770,8 @@ void Terrain3DMaterial::set_buffer_shader_override_enabled(const bool p_enabled)
}
void Terrain3DMaterial::set_buffer_shader_override(const Ref<Shader> &p_shader) {
SET_IF_DIFF(_buffer_shader_override, p_shader);
LOG(INFO, "Setting override shader");
_buffer_shader_override = p_shader;
_update_shader();
}

View File

@ -283,24 +283,8 @@ _FORCE_INLINE_ String ptr_to_str(const void *p_ptr) {
return "0x" + String::num_uint64(uint64_t(p_ptr), 16, true);
}
// Trait to detect types with _native_ptr(): Dictionary, Array, String, etc
template <typename T, typename = void>
struct has_native_ptr : std::false_type {};
template <typename T>
struct has_native_ptr<T, std::void_t<decltype(std::declval<T>()._native_ptr())>>
: std::true_type {};
using GDPtr = void **;
template <typename T>
_FORCE_INLINE_ constexpr const void *get_gd_ptr(const T &obj) {
static_assert(has_native_ptr<T>::value, "Type must have _native_ptr()");
return *(GDPtr)obj._native_ptr();
}
// Returns if A is shallow different from B
// O(1) size and pointer compare for Array/Dictionary/String
// O(1) size and pointer compare for Array/Dictionary/String/StringName/NodePath
// Operator==() otherwise
// Two arrays/dicts with different pointers could have the same value, this will return true
// Two strings or ints with different pointers but the same value will return false
@ -308,21 +292,25 @@ _FORCE_INLINE_ constexpr const void *get_gd_ptr(const T &obj) {
template <typename T>
_FORCE_INLINE_ bool differs(const T &a, const T &b) {
if constexpr (std::is_base_of_v<String, T>) {
if (a.length() != b.length()) { // Common path predictable early exit
if (a.length() != b.length()) {
return true;
}
const void *ptr_a = get_gd_ptr(a);
const void *ptr_b = get_gd_ptr(b);
bool ptr_diff = (*(GDPtr)(static_cast<const uint8_t *>(ptr_a) + 8) !=
*(GDPtr)(static_cast<const uint8_t *>(ptr_b) + 8));
return ptr_diff ? !(a == b) : false;
if (a.is_empty()) { // Both empty
return false;
}
// Both non-empty, but same length
if (a.ptr() == b.ptr()) { // Same COW buffer
return false;
}
return a != b; // Full comparison
} else if constexpr (std::is_base_of_v<Array, T> || std::is_base_of_v<Dictionary, T>) {
if (a.size() != b.size()) { // Redundant but common path predictable
return true;
}
return get_gd_ptr(a) != get_gd_ptr(b);
// These store a real GDExtensionTypePtr (void**) at offset 0
return *(const void **)a._native_ptr() != *(const void **)b._native_ptr();
} else {
return !(a == b);
return a != b;
}
}

View File

@ -61,7 +61,9 @@ void test_differs() {
String s2 = s1; // Shared (COW)
String s3("test"); // Separate alloc, same value
String s4 = "diff";
log_differs(s1, s2, "String shared", false); // Same ptr
log_differs(String(), String(), "String() vs String()", false);
log_differs(String(), String("a"), "String() vs String('a')", true);
log_differs(s1, s2, "String shared", false);
log_differs(s1, s3, "String same value diff ptr", false); // Length match + == true
log_differs(s1, s4, "String diff value", true); // Length may match, but == false
}