From 0e81f89dd3ea7418573075a716dcdd94b73e8621 Mon Sep 17 00:00:00 2001 From: Emmanuel Leblond Date: Sat, 22 Oct 2022 13:46:59 +0200 Subject: [PATCH] Uses `StringName` in GDExtension perf critical instance creation & method/properties setter/getter --- binding_generator.py | 20 ++++++++++++----- godot-headers/godot/gdnative_interface.h | 22 +++++++++---------- include/godot_cpp/classes/wrapped.hpp | 28 ++++++++++++++---------- src/classes/wrapped.cpp | 10 ++++----- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 0bf46ea9..84e82028 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -687,20 +687,24 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl f"\t_method_bindings.destructor = internal::gdn_interface->variant_get_ptr_destructor({enum_type_name});" ) + result.append(f"StringName __name;") + if "methods" in builtin_api: for method in builtin_api["methods"]: # TODO: Add error check for hash mismatch. + result.append(f'\t__name = StringName("{method["name"]}");') result.append( - f'\t_method_bindings.method_{method["name"]} = internal::gdn_interface->variant_get_ptr_builtin_method({enum_type_name}, "{method["name"]}", {method["hash"]});' + f'\t_method_bindings.method_{method["name"]} = internal::gdn_interface->variant_get_ptr_builtin_method({enum_type_name}, (void *)&__name, {method["hash"]});' ) if "members" in builtin_api: for member in builtin_api["members"]: + result.append(f'\t__name = StringName("{member["name"]}");') result.append( - f'\t_method_bindings.member_{member["name"]}_setter = internal::gdn_interface->variant_get_ptr_setter({enum_type_name}, "{member["name"]}");' + f'\t_method_bindings.member_{member["name"]}_setter = internal::gdn_interface->variant_get_ptr_setter({enum_type_name}, (void *)&__name);' ) result.append( - f'\t_method_bindings.member_{member["name"]}_getter = internal::gdn_interface->variant_get_ptr_getter({enum_type_name}, "{member["name"]}");' + f'\t_method_bindings.member_{member["name"]}_getter = internal::gdn_interface->variant_get_ptr_getter({enum_type_name}, (void *)&__name);' ) if "indexing_return_type" in builtin_api: @@ -1292,8 +1296,9 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us if is_singleton: result.append(f"{class_name} *{class_name}::get_singleton() {{") + result.append(f'\tconst StringName __class_name = {class_name}::get_class_static();') result.append( - f'\tstatic GDNativeObjectPtr singleton_obj = internal::gdn_interface->global_get_singleton("{class_name}");' + f"\tstatic GDNativeObjectPtr singleton_obj = internal::gdn_interface->global_get_singleton((void *)&__class_name);" ) result.append("#ifdef DEBUG_ENABLED") result.append("\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);") @@ -1318,8 +1323,10 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us result.append(method_signature + " {") # Method body. + result.append(f'\tconst StringName __class_name = {class_name}::get_class_static();') + result.append(f'\tconst StringName __method_name = "{method["name"]}";') result.append( - f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::gdn_interface->classdb_get_method_bind("{class_name}", "{method["name"]}", {method["hash"]});' + f'\tstatic GDNativeMethodBindPtr ___method_bind = internal::gdn_interface->classdb_get_method_bind((void *)&__class_name, (void *)&__method_name, {method["hash"]});' ) method_call = "\t" has_return = "return_value" in method and method["return_value"]["type"] != "void" @@ -1566,8 +1573,9 @@ def generate_utility_functions(api, output_dir): # Function body. + source.append(f'\tconst StringName __function_name = "{function["name"]}";') source.append( - f'\tstatic GDNativePtrUtilityFunction ___function = internal::gdn_interface->variant_get_ptr_utility_function("{function["name"]}", {function["hash"]});' + f'\tstatic GDNativePtrUtilityFunction ___function = internal::gdn_interface->variant_get_ptr_utility_function((void *)&__function_name, {function["hash"]});' ) has_return = "return_type" in function and function["return_type"] != "void" if has_return: diff --git a/godot-headers/godot/gdnative_interface.h b/godot-headers/godot/gdnative_interface.h index 1ce50bc1..eaad1791 100644 --- a/godot-headers/godot/gdnative_interface.h +++ b/godot-headers/godot/gdnative_interface.h @@ -400,7 +400,7 @@ typedef struct { void (*print_warning)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); void (*print_script_error)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line); - uint64_t (*get_native_struct_size)(const char *p_name); + uint64_t (*get_native_struct_size)(const GDNativeStringNamePtr p_name); /* GODOT VARIANT */ @@ -443,19 +443,19 @@ typedef struct { GDNativeVariantFromTypeConstructorFunc (*get_variant_from_type_constructor)(GDNativeVariantType p_type); GDNativeTypeFromVariantConstructorFunc (*get_variant_to_type_constructor)(GDNativeVariantType p_type); GDNativePtrOperatorEvaluator (*variant_get_ptr_operator_evaluator)(GDNativeVariantOperator p_operator, GDNativeVariantType p_type_a, GDNativeVariantType p_type_b); - GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const char *p_method, GDNativeInt p_hash); + GDNativePtrBuiltInMethod (*variant_get_ptr_builtin_method)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_method, GDNativeInt p_hash); GDNativePtrConstructor (*variant_get_ptr_constructor)(GDNativeVariantType p_type, int32_t p_constructor); GDNativePtrDestructor (*variant_get_ptr_destructor)(GDNativeVariantType p_type); void (*variant_construct)(GDNativeVariantType p_type, GDNativeVariantPtr p_base, const GDNativeVariantPtr *p_args, int32_t p_argument_count, GDNativeCallError *r_error); - GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const char *p_member); - GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const char *p_member); + GDNativePtrSetter (*variant_get_ptr_setter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); + GDNativePtrGetter (*variant_get_ptr_getter)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_member); GDNativePtrIndexedSetter (*variant_get_ptr_indexed_setter)(GDNativeVariantType p_type); GDNativePtrIndexedGetter (*variant_get_ptr_indexed_getter)(GDNativeVariantType p_type); GDNativePtrKeyedSetter (*variant_get_ptr_keyed_setter)(GDNativeVariantType p_type); GDNativePtrKeyedGetter (*variant_get_ptr_keyed_getter)(GDNativeVariantType p_type); GDNativePtrKeyedChecker (*variant_get_ptr_keyed_checker)(GDNativeVariantType p_type); - void (*variant_get_constant_value)(GDNativeVariantType p_type, const char *p_constant, GDNativeVariantPtr r_ret); - GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const char *p_function, GDNativeInt p_hash); + void (*variant_get_constant_value)(GDNativeVariantType p_type, const GDNativeStringNamePtr p_constant, GDNativeVariantPtr r_ret); + GDNativePtrUtilityFunction (*variant_get_ptr_utility_function)(const GDNativeStringNamePtr p_function, GDNativeInt p_hash); /* extra utilities */ @@ -524,12 +524,12 @@ typedef struct { void (*object_method_bind_call)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeVariantPtr *p_args, GDNativeInt p_arg_count, GDNativeVariantPtr r_ret, GDNativeCallError *r_error); void (*object_method_bind_ptrcall)(const GDNativeMethodBindPtr p_method_bind, GDNativeObjectPtr p_instance, const GDNativeTypePtr *p_args, GDNativeTypePtr r_ret); void (*object_destroy)(GDNativeObjectPtr p_o); - GDNativeObjectPtr (*global_get_singleton)(const char *p_name); + GDNativeObjectPtr (*global_get_singleton)(const GDNativeStringNamePtr p_name); void *(*object_get_instance_binding)(GDNativeObjectPtr p_o, void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks); void (*object_set_instance_binding)(GDNativeObjectPtr p_o, void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks); - void (*object_set_instance)(GDNativeObjectPtr p_o, const char *p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ + void (*object_set_instance)(GDNativeObjectPtr p_o, const GDNativeStringNamePtr p_classname, GDExtensionClassInstancePtr p_instance); /* p_classname should be a registered extension class and should extend the p_o object's class. */ GDNativeObjectPtr (*object_cast_to)(const GDNativeObjectPtr p_object, void *p_class_tag); GDNativeObjectPtr (*object_get_instance_from_id)(GDObjectInstanceID p_instance_id); @@ -540,9 +540,9 @@ typedef struct { GDNativeScriptInstancePtr (*script_instance_create)(const GDNativeExtensionScriptInstanceInfo *p_info, GDNativeExtensionScriptInstanceDataPtr p_instance_data); /* CLASSDB */ - GDNativeObjectPtr (*classdb_construct_object)(const char *p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ - GDNativeMethodBindPtr (*classdb_get_method_bind)(const char *p_classname, const char *p_methodname, GDNativeInt p_hash); - void *(*classdb_get_class_tag)(const char *p_classname); + GDNativeObjectPtr (*classdb_construct_object)(const GDNativeStringNamePtr p_classname); /* The passed class must be a built-in godot class, or an already-registered extension class. In both case, object_set_instance should be called to fully initialize the object. */ + GDNativeMethodBindPtr (*classdb_get_method_bind)(const GDNativeStringNamePtr p_classname, const GDNativeStringNamePtr p_methodname, GDNativeInt p_hash); + void *(*classdb_get_class_tag)(const GDNativeStringNamePtr p_classname); /* CLASSDB EXTENSION */ diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index ce1bc51a..128e091f 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -49,7 +49,7 @@ class Wrapped { friend void postinitialize_handler(Wrapped *); protected: - virtual const char *_get_extension_class() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. + virtual const StringName *_get_extension_class() const; // This is needed to retrieve the class name before the godot object has its _extension and _extension_instance members assigned. virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const = 0; void _notification(int p_what){}; @@ -74,12 +74,13 @@ protected: void _postinitialize(); - Wrapped(const char *p_godot_class); + Wrapped(const StringName p_godot_class); Wrapped(GodotObject *p_godot_object); public: - static const char *get_class_static() { - return "Wrapped"; + static StringName get_class_static() { + static StringName string_name = StringName("Wrapped"); + return string_name; } uint64_t get_instance_id() const { @@ -105,8 +106,9 @@ private: friend class ::godot::ClassDB; \ \ protected: \ - virtual const char *_get_extension_class() const override { \ - return get_class_static(); \ + virtual const StringName *_get_extension_class() const override { \ + static StringName string_name = get_class_static(); \ + return &string_name; \ } \ \ virtual const GDNativeInstanceBindingCallbacks *_get_bindings_callbacks() const override { \ @@ -164,11 +166,12 @@ public: initialized = true; \ } \ \ - static const char *get_class_static() { \ - return #m_class; \ + static StringName get_class_static() { \ + static StringName string_name = StringName(#m_class); \ + return string_name; \ } \ \ - static const char *get_parent_class_static() { \ + static StringName *get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ @@ -357,11 +360,12 @@ protected: public: \ static void initialize_class() {} \ \ - static const char *get_class_static() { \ - return #m_class; \ + static StringName get_class_static() { \ + static StringName string_name = StringName(#m_class); \ + return string_name; \ } \ \ - static const char *get_parent_class_static() { \ + static StringName get_parent_class_static() { \ return m_inherits::get_class_static(); \ } \ \ diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index a62edc4d..84ac3a47 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -36,20 +36,20 @@ namespace godot { -const char *Wrapped::_get_extension_class() const { +const StringName *Wrapped::_get_extension_class() const { return nullptr; } void Wrapped::_postinitialize() { - const char *extension_class = _get_extension_class(); + const StringName *extension_class = _get_extension_class(); if (extension_class) { - godot::internal::gdn_interface->object_set_instance(_owner, extension_class, this); + godot::internal::gdn_interface->object_set_instance(_owner, (void *)extension_class, this); } godot::internal::gdn_interface->object_set_instance_binding(_owner, godot::internal::token, this, _get_bindings_callbacks()); } -Wrapped::Wrapped(const char *p_godot_class) { - _owner = godot::internal::gdn_interface->classdb_construct_object(p_godot_class); +Wrapped::Wrapped(const StringName p_godot_class) { + _owner = godot::internal::gdn_interface->classdb_construct_object((void *)&p_godot_class); } Wrapped::Wrapped(GodotObject *p_godot_object) {