- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 23.5k
 
Optimize animation performance and improve internals #112308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Optimize animation performance and improve internals #112308
Conversation
a5d9659    to
    ba1f999      
    Compare
  
    | thread_local AnimationNode::ProcessState *AnimationNode::tls_process_state = nullptr; | ||
| thread_local AnimationNodeInstance *AnimationNode::current_instance = nullptr; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the difference from #110474 is that this was added. Are there any other changes? Is a new benchmark comparison possible?
If #110474 (review) issue was due to multiple same AnimationNode resources being instantiated and placed, then the fix to manage each resource's instance makes sense. I confirmed that this no longer causes #110474 (review) issue.
However, since I recall past issues similar to #110506, I'm a bit concerned about whether using thread_local is appropriate. Testing in a project editing scenes containing a large number of AnimationTree instances might be necessary.
Also, I have some concerns regarding code readability. Passing instance pointers as arguments is indeed safe, but since there should be never occur to access different ProcessState and AnimationNodeInstance within a single AnimationNode like:
double length_a = instance_a.get_parameter(current_length);
double length_b = instance_b.get_parameter(current_length);
, so it always p_instance.get_parameter(), it would be ideal if there is a way to omit them, same with old code. This would significantly reduce the number of lines requiring modification. Do you have any ideas @lyuma @SaracenOne?
If there are no other way, I assume it can be accepted depending on the benchmark improvement. In other words, we want a benchmark comparison before and after, focusing solely on changes to the AnimationTree instance, excluding any other changes. This was one reason why I suggested separating the PR.
| 
               | 
          ||
| void get_animation_list(List<StringName> *p_animations) const; | ||
| Ref<Animation> get_animation(const StringName &p_name) const; | ||
| void get_animation_list(LocalVector<StringName> *p_animations, const bool p_sorted = true) const; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| void get_animation_list(LocalVector<StringName> *p_animations, const bool p_sorted = true) const; | |
| void get_animation_list(LocalVector<StringName> *p_animations, bool p_sorted = true) const; | 
No const for simple types
| virtual Variant get_parameter_default_value(const StringName &p_parameter) const override; | ||
| 
               | 
          ||
| virtual NodeTimeInfo get_node_time_info() const override; // Wrapper of get_parameter(). | ||
| virtual NodeTimeInfo get_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state) const override; // Wrapper of get_parameter(). | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| virtual NodeTimeInfo get_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state) const override; // Wrapper of get_parameter(). | |
| virtual NodeTimeInfo get_node_time_info(AnimationNodeInstance &p_instance, ProcessState &p_process_state) const override; // Wrapper for get_parameter(). | 
| void _node_renamed(const String &p_text, Ref<AnimationNode> p_node, StringName p_name); | ||
| void _node_renamed_focus_out(Ref<AnimationNode> p_node, StringName p_name); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| void _node_renamed(const String &p_text, Ref<AnimationNode> p_node, StringName p_name); | |
| void _node_renamed_focus_out(Ref<AnimationNode> p_node, StringName p_name); | |
| void _node_renamed(const String &p_text, Ref<AnimationNode> p_node, const StringName &p_name); | |
| void _node_renamed_focus_out(Ref<AnimationNode> p_node, const StringName &p_name); | 
| void set_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state, const NodeTimeInfo &p_node_time_info); // Wrapper of set_parameter(). | ||
| virtual NodeTimeInfo get_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state) const; // Wrapper of get_parameter(). | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| void set_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state, const NodeTimeInfo &p_node_time_info); // Wrapper of set_parameter(). | |
| virtual NodeTimeInfo get_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state) const; // Wrapper of get_parameter(). | |
| void set_node_time_info(AnimationNodeInstance &p_instance, ProcessState &p_process_state, const NodeTimeInfo &p_node_time_info); // Wrapper for set_parameter(). | |
| virtual NodeTimeInfo get_node_time_info(AnimationNodeInstance &p_instance, ProcessState &p_process_state) const; // Wrapper for get_parameter(). | 
| AnimationNodeInstance *parent = nullptr; | ||
| // TODO: Maybe ptr to parent AnimationNodeInstance for faster access??? | ||
| AnimationNode *parent_node = nullptr; | ||
| // Multiple AnimationNodeInstance's can share the same node btw | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Multiple AnimationNodeInstance's can share the same node btw | |
| // Multiple AnimationNodeInstances can share the same node btw. | 
| ad.name = key; | ||
| ad.last_update = animation_set_update_pass; | ||
| animation_set.insert(ad.name, ad); | ||
| //todo: possible issue here, not using key, but instead ad.name? | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| //todo: possible issue here, not using key, but instead ad.name? | |
| // TODO: possible issue here, not using key, but instead ad.name? | 
| anims.sort(); | ||
| for (const String &E : anims) { | ||
| p_animations->push_back(E); | ||
| void AnimationMixer::get_animation_list(LocalVector<StringName> *p_animations, const bool p_sorted) const { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| void AnimationMixer::get_animation_list(LocalVector<StringName> *p_animations, const bool p_sorted) const { | |
| void AnimationMixer::get_animation_list(LocalVector<StringName> *p_animations, bool p_sorted) const { | 
| } | ||
| 
               | 
          ||
| AnimationNode::NodeTimeInfo AnimationNodeAnimation::get_node_time_info() const { | ||
| AnimationNode::NodeTimeInfo AnimationNodeAnimation::get_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state) const { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| AnimationNode::NodeTimeInfo AnimationNodeAnimation::get_node_time_info(AnimationNodeInstance &instance, ProcessState &p_process_state) const { | |
| AnimationNode::NodeTimeInfo AnimationNodeAnimation::get_node_time_info(AnimationNodeInstance &p_instance, ProcessState &p_process_state) const { | 
| 
               | 
          ||
| return _blend_node(output, "output", this, pi, FILTER_IGNORE, true, p_test_only, nullptr); | ||
| AnimationNodeInstance &output_instance = p_instance.get_child_instance_by_path(SceneStringName(output)); | ||
| return _blend_node(p_process_state, p_instance, output_instance, SNAME("output"), this, pi, FILTER_IGNORE, true, p_test_only, nullptr); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return _blend_node(p_process_state, p_instance, output_instance, SNAME("output"), this, pi, FILTER_IGNORE, true, p_test_only, nullptr); | |
| return _blend_node(p_process_state, p_instance, output_instance, SceneStringName(output), this, pi, FILTER_IGNORE, true, p_test_only, nullptr); | 
| property_map[new_name] = property_map[E.name]; | ||
| property_map.erase(E.name); | ||
| //print_line("Node: " + ObjectDB::get_instance(p_oid)->get_class() + " (" + itos(p_oid) + ") renamed: " + p_old_name + " -> " + p_new_name); | ||
| for (auto &pp : instance_paths[p_oid]) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
Supersedes #110474