diff options
12 files changed, 324 insertions, 16 deletions
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index e30b77ea742..aee925ad8f8 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -37,6 +37,7 @@ set(INC_SYS set(SRC intern/builder/deg_builder.cc + intern/builder/deg_builder_cache.cc intern/builder/deg_builder_cycle.cc intern/builder/deg_builder_map.cc intern/builder/deg_builder_nodes.cc @@ -82,6 +83,7 @@ set(SRC DEG_depsgraph_query.h intern/builder/deg_builder.h + intern/builder/deg_builder_cache.h intern/builder/deg_builder_cycle.h intern/builder/deg_builder_map.h intern/builder/deg_builder_nodes.h diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index ef36dec6f34..bcf397da335 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -55,6 +55,11 @@ namespace DEG { * Base class for builders. */ +DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache) + : bmain_(bmain), graph_(graph), cache_(cache) +{ +} + namespace { struct VisibilityCheckData { @@ -108,10 +113,6 @@ bool deg_check_base_available_for_build(const Depsgraph *graph, Base *base) return false; } -DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph) : bmain_(bmain), graph_(graph) -{ -} - bool DepsgraphBuilder::need_pull_base_into_graph(Base *base) { return deg_check_base_available_for_build(graph_, base); diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h index 310944f2f28..88df0e870f3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.h +++ b/source/blender/depsgraph/intern/builder/deg_builder.h @@ -29,17 +29,20 @@ struct Main; namespace DEG { struct Depsgraph; +class DepsgraphBuilderCache; class DepsgraphBuilder { public: bool need_pull_base_into_graph(struct Base *base); protected: - DepsgraphBuilder(Main *bmain, Depsgraph *graph); + /* NOTE: The builder does NOT take ownership over any of those resources. */ + DepsgraphBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache); /* State which never changes, same for the whole builder time. */ Main *bmain_; Depsgraph *graph_; + DepsgraphBuilderCache *cache_; }; bool deg_check_base_available_for_build(const Depsgraph *graph, Base *base); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc new file mode 100644 index 00000000000..3df707e92c1 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -0,0 +1,186 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/builder/deg_builder_cache.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" + +#include "BLI_utildefines.h" + +extern "C" { +#include "BKE_animsys.h" +} + +namespace DEG { + +/* Animated property storage. */ + +AnimatedPropertyID::AnimatedPropertyID() : data(NULL), property_rna(NULL) +{ +} + +AnimatedPropertyID::AnimatedPropertyID(const PointerRNA *pointer_rna, + const PropertyRNA *property_rna) + : AnimatedPropertyID(*pointer_rna, property_rna) +{ +} + +AnimatedPropertyID::AnimatedPropertyID(const PointerRNA &pointer_rna, + const PropertyRNA *property_rna) + : data(pointer_rna.data), property_rna(property_rna) +{ +} + +AnimatedPropertyID::AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name) + : data(id) +{ + property_rna = RNA_struct_type_find_property(type, property_name); +} + +AnimatedPropertyID::AnimatedPropertyID(ID * /*id*/, + StructRNA *type, + void *data, + const char *property_name) + : data(data) +{ + property_rna = RNA_struct_type_find_property(type, property_name); +} + +bool AnimatedPropertyID::operator<(const AnimatedPropertyID &other) const +{ + if (data < other.data) { + return true; + } + else if (data == other.data) { + return property_rna < other.property_rna; + } + return false; +} + +namespace { + +struct AnimatedPropertyCallbackData { + PointerRNA pointer_rna; + AnimatedPropertyStorage *animated_property_storage; + DepsgraphBuilderCache *builder_cache; +}; + +void animated_property_cb(ID * /*id*/, FCurve *fcurve, void *data_v) +{ + if (fcurve->rna_path == NULL || fcurve->rna_path[0] == '\0') { + return; + } + AnimatedPropertyCallbackData *data = static_cast<AnimatedPropertyCallbackData *>(data_v); + /* Resolve property. */ + PointerRNA pointer_rna; + PropertyRNA *property_rna = NULL; + if (!RNA_path_resolve_property( + &data->pointer_rna, fcurve->rna_path, &pointer_rna, &property_rna)) { + return; + } + /* Get storage for the ID. + * This is needed to deal with cases when nested datablock is animated by its parent. */ + AnimatedPropertyStorage *animated_property_storage = data->animated_property_storage; + if (pointer_rna.id.data != data->pointer_rna.id.data) { + animated_property_storage = data->builder_cache->ensureAnimatedPropertyStorage( + reinterpret_cast<ID *>(pointer_rna.id.data)); + } + /* Set the property as animated. */ + animated_property_storage->tagPropertyAsAnimated(&pointer_rna, property_rna); +} + +} // namespace + +AnimatedPropertyStorage::AnimatedPropertyStorage() : is_fully_initialized(false) +{ +} + +void AnimatedPropertyStorage::initializeFromID(DepsgraphBuilderCache *builder_cache, ID *id) +{ + AnimatedPropertyCallbackData data; + RNA_id_pointer_create(id, &data.pointer_rna); + data.animated_property_storage = this; + data.builder_cache = builder_cache; + BKE_fcurves_id_cb(id, animated_property_cb, &data); +} + +void AnimatedPropertyStorage::tagPropertyAsAnimated(const AnimatedPropertyID &property_id) +{ + animated_properties_set.insert(property_id); +} + +void AnimatedPropertyStorage::tagPropertyAsAnimated(const PointerRNA *pointer_rna, + const PropertyRNA *property_rna) +{ + tagPropertyAsAnimated(AnimatedPropertyID(pointer_rna, property_rna)); +} + +bool AnimatedPropertyStorage::isPropertyAnimated(const AnimatedPropertyID &property_id) +{ + return animated_properties_set.find(property_id) != animated_properties_set.end(); +} + +bool AnimatedPropertyStorage::isPropertyAnimated(const PointerRNA *pointer_rna, + const PropertyRNA *property_rna) +{ + return isPropertyAnimated(AnimatedPropertyID(pointer_rna, property_rna)); +} + +/* Builder cache itself. */ + +DepsgraphBuilderCache::DepsgraphBuilderCache() +{ +} + +DepsgraphBuilderCache::~DepsgraphBuilderCache() +{ + for (AnimatedPropertyStorageMap::value_type &iter : animated_property_storage_map_) { + AnimatedPropertyStorage *animated_property_storage = iter.second; + OBJECT_GUARDED_DELETE(animated_property_storage, AnimatedPropertyStorage); + } +} + +AnimatedPropertyStorage *DepsgraphBuilderCache::ensureAnimatedPropertyStorage(ID *id) +{ + AnimatedPropertyStorageMap::iterator it = animated_property_storage_map_.find(id); + if (it != animated_property_storage_map_.end()) { + return it->second; + } + AnimatedPropertyStorage *animated_property_storage = OBJECT_GUARDED_NEW(AnimatedPropertyStorage); + animated_property_storage_map_.insert(make_pair(id, animated_property_storage)); + return animated_property_storage; +} + +AnimatedPropertyStorage *DepsgraphBuilderCache::ensureInitializedAnimatedPropertyStorage(ID *id) +{ + AnimatedPropertyStorage *animated_property_storage = ensureAnimatedPropertyStorage(id); + if (!animated_property_storage->is_fully_initialized) { + animated_property_storage->initializeFromID(this, id); + animated_property_storage->is_fully_initialized = true; + } + return animated_property_storage; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.h b/source/blender/depsgraph/intern/builder/deg_builder_cache.h new file mode 100644 index 00000000000..949020e3a81 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.h @@ -0,0 +1,103 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2018 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/depsgraph_type.h" + +#include "RNA_access.h" + +struct ID; +struct PointerRNA; +struct PropertyRNA; + +namespace DEG { + +class DepsgraphBuilderCache; + +/* Identifier for animated property. */ +class AnimatedPropertyID { + public: + AnimatedPropertyID(); + AnimatedPropertyID(const PointerRNA *pointer_rna, const PropertyRNA *property_rna); + AnimatedPropertyID(const PointerRNA &pointer_rna, const PropertyRNA *property_rna); + AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name); + AnimatedPropertyID(ID *id, StructRNA *type, void *data, const char *property_name); + + bool operator<(const AnimatedPropertyID &other) const; + + /* Corresponds to PointerRNA.data. */ + void *data; + const PropertyRNA *property_rna; +}; + +class AnimatedPropertyStorage { + public: + AnimatedPropertyStorage(); + + void initializeFromID(DepsgraphBuilderCache *builder_cache, ID *id); + + void tagPropertyAsAnimated(const AnimatedPropertyID &property_id); + void tagPropertyAsAnimated(const PointerRNA *pointer_rna, const PropertyRNA *property_rna); + + bool isPropertyAnimated(const AnimatedPropertyID &property_id); + bool isPropertyAnimated(const PointerRNA *pointer_rna, const PropertyRNA *property_rna); + + /* The storage is fully initialized from all F-Curves from corresponding ID. */ + bool is_fully_initialized; + + /* indexed by PointerRNA.data. */ + set<AnimatedPropertyID> animated_properties_set; +}; + +typedef map<ID *, AnimatedPropertyStorage *> AnimatedPropertyStorageMap; + +/* Cached data which can be re-used by multiple builders. */ +class DepsgraphBuilderCache { + public: + DepsgraphBuilderCache(); + ~DepsgraphBuilderCache(); + + /* Makes sure storage for animated properties exists and initialized for the given ID. */ + AnimatedPropertyStorage *ensureAnimatedPropertyStorage(ID *id); + AnimatedPropertyStorage *ensureInitializedAnimatedPropertyStorage(ID *id); + + /* Shortcuts to go through ensureInitializedAnimatedPropertyStorage and its + * isPropertyAnimated. + * + * NOTE: Avoid using for multiple subsequent lookups, query for the storage once, and then query + * the storage. + * + * TODO(sergey): Technically, this makes this class something else than just a cache, but what is + * the better name? */ + template<typename... Args> bool isPropertyAnimated(ID *id, Args... args) + { + AnimatedPropertyStorage *animated_property_storage = ensureInitializedAnimatedPropertyStorage( + id); + return animated_property_storage->isPropertyAnimated(args...); + } + + AnimatedPropertyStorageMap animated_property_storage_map_; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index a4c269886a3..27823bffb87 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -129,8 +129,10 @@ void free_copy_on_write_datablock(void *id_info_v) /* **** General purpose functions **** */ -DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) - : DepsgraphBuilder(bmain, graph), +DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, + Depsgraph *graph, + DepsgraphBuilderCache *cache) + : DepsgraphBuilder(bmain, graph, cache), scene_(NULL), view_layer_(NULL), view_layer_index_(-1), diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index d88f5a792e0..cf7cf1a62d8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -69,6 +69,7 @@ namespace DEG { struct ComponentNode; struct Depsgraph; +class DepsgraphBuilderCache; struct IDNode; struct Node; struct OperationNode; @@ -76,7 +77,7 @@ struct TimeSourceNode; class DepsgraphNodeBuilder : public DepsgraphBuilder { public: - DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph); + DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache); ~DepsgraphNodeBuilder(); /* For given original ID get ID which is created by CoW system. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 9ea41e54a59..36cc105273d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -209,8 +209,10 @@ static bool bone_has_segments(Object *object, const char *bone_name) /* **** General purpose functions **** */ -DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph) - : DepsgraphBuilder(bmain, graph), scene_(NULL), rna_node_query_(graph) +DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, + Depsgraph *graph, + DepsgraphBuilderCache *cache) + : DepsgraphBuilder(bmain, graph, cache), scene_(NULL), rna_node_query_(graph, this) { } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 5b2d34a270c..90bdb9bae65 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -86,6 +86,7 @@ namespace DEG { struct ComponentNode; struct DepsNodeHandle; struct Depsgraph; +class DepsgraphBuilderCache; struct IDNode; struct Node; struct OperationNode; @@ -155,7 +156,7 @@ struct RNAPathKey { class DepsgraphRelationBuilder : public DepsgraphBuilder { public: - DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph); + DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache); void begin_build(); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 27899abc972..ac4e8e84d44 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -45,6 +45,7 @@ extern "C" { #include "RNA_access.h" #include "intern/depsgraph.h" +#include "intern/builder/deg_builder.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_component.h" #include "intern/node/deg_node_id.h" @@ -130,8 +131,10 @@ void ghash_id_data_free_func(void *value) } // namespace -RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph) - : depsgraph_(depsgraph), id_data_map_(BLI_ghash_ptr_new("rna node query id data hash")) +RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder) + : depsgraph_(depsgraph), + builder_(builder), + id_data_map_(BLI_ghash_ptr_new("rna node query id data hash")) { } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h index e8dbd7fb523..26d7963e0a8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -36,6 +36,7 @@ namespace DEG { struct Depsgraph; struct Node; class RNANodeQueryIDData; +class DepsgraphBuilder; /* For queries which gives operation node or key defines whether we are * interested in a result of the given property or whether we are linking some @@ -72,13 +73,14 @@ class RNANodeIdentifier { * dependency graph which satisfies given RNA pointer or RAN path. */ class RNANodeQuery { public: - RNANodeQuery(Depsgraph *depsgraph); + RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder); ~RNANodeQuery(); Node *find_node(const PointerRNA *ptr, const PropertyRNA *prop, RNAPointerSource source); protected: Depsgraph *depsgraph_; + DepsgraphBuilder *builder_; /* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */ GHash *id_data_map_; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index e4c84264960..dd2979160cd 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -46,6 +46,7 @@ extern "C" { #include "DEG_depsgraph_build.h" #include "builder/deg_builder.h" +#include "builder/deg_builder_cache.h" #include "builder/deg_builder_cycle.h" #include "builder/deg_builder_nodes.h" #include "builder/deg_builder_relations.h" @@ -238,14 +239,15 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph, BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1); BLI_assert(deg_graph->scene == scene); BLI_assert(deg_graph->view_layer == view_layer); + DEG::DepsgraphBuilderCache builder_cache; /* Generate all the nodes in the graph first */ - DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph); + DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); node_builder.begin_build(); node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY); node_builder.end_build(); /* Hook up relationships between operations - to determine evaluation * order. */ - DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph); + DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); relation_builder.begin_build(); relation_builder.build_view_layer(scene, view_layer); relation_builder.build_copy_on_write_relations(); |