diff options
Diffstat (limited to 'source/blender/depsgraph')
46 files changed, 1502 insertions, 689 deletions
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 355d2536e1a..417aaa2c4c0 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -46,6 +46,7 @@ set(SRC intern/builder/deg_builder_nodes_view_layer.cc intern/builder/deg_builder_pchanmap.cc intern/builder/deg_builder_relations.cc + intern/builder/deg_builder_relations_drivers.cc intern/builder/deg_builder_relations_keys.cc intern/builder/deg_builder_relations_rig.cc intern/builder/deg_builder_relations_scene.cc @@ -53,6 +54,11 @@ set(SRC intern/builder/deg_builder_remove_noop.cc intern/builder/deg_builder_rna.cc intern/builder/deg_builder_transitive.cc + intern/builder/pipeline.cc + intern/builder/pipeline_compositor.cc + intern/builder/pipeline_from_ids.cc + intern/builder/pipeline_render.cc + intern/builder/pipeline_view_layer.cc intern/debug/deg_debug.cc intern/debug/deg_debug_relations_graphviz.cc intern/debug/deg_debug_stats_gnuplot.cc @@ -100,6 +106,7 @@ set(SRC intern/builder/deg_builder.h intern/builder/deg_builder_cache.h intern/builder/deg_builder_cycle.h + intern/builder/deg_builder_relations_drivers.h intern/builder/deg_builder_map.h intern/builder/deg_builder_nodes.h intern/builder/deg_builder_pchanmap.h @@ -108,6 +115,11 @@ set(SRC intern/builder/deg_builder_remove_noop.h intern/builder/deg_builder_rna.h intern/builder/deg_builder_transitive.h + intern/builder/pipeline.h + intern/builder/pipeline_compositor.h + intern/builder/pipeline_from_ids.h + intern/builder/pipeline_render.h + intern/builder/pipeline_view_layer.h intern/debug/deg_debug.h intern/debug/deg_time_average.h intern/eval/deg_eval.h @@ -145,3 +157,14 @@ set(LIB ) blender_add_lib(bf_depsgraph "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") + +if(WITH_GTESTS) + set(TEST_SRC + intern/builder/deg_builder_rna_test.cc + ) + set(TEST_LIB + bf_depsgraph + ) + include(GTestTesting) + blender_add_test_lib(bf_depsgraph_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB}") +endif() diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index d735d3b89bc..b3636743101 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -43,8 +43,7 @@ * - These are used in all depsgraph code and by all callers of Depsgraph API... */ -#ifndef __DEG_DEPSGRAPH_H__ -#define __DEG_DEPSGRAPH_H__ +#pragma once #include "DNA_ID.h" @@ -233,5 +232,3 @@ void DEG_debug_print_eval_time(struct Depsgraph *depsgraph, #ifdef __cplusplus } /* extern "C" */ #endif - -#endif /* __DEG_DEPSGRAPH_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index 81157102bb1..50f22b00028 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -23,8 +23,7 @@ * Public API for Depsgraph */ -#ifndef __DEG_DEPSGRAPH_BUILD_H__ -#define __DEG_DEPSGRAPH_BUILD_H__ +#pragma once /* ************************************************* */ @@ -201,5 +200,3 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle); #ifdef __cplusplus } /* extern "C" */ #endif - -#endif /* __DEG_DEPSGRAPH_BUILD_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h index 73e03523003..e261ff67a20 100644 --- a/source/blender/depsgraph/DEG_depsgraph_debug.h +++ b/source/blender/depsgraph/DEG_depsgraph_debug.h @@ -23,8 +23,7 @@ * Public API for Querying and Filtering Depsgraph */ -#ifndef __DEG_DEPSGRAPH_DEBUG_H__ -#define __DEG_DEPSGRAPH_DEBUG_H__ +#pragma once #include <stdio.h> @@ -80,5 +79,3 @@ bool DEG_debug_consistency_check(struct Depsgraph *graph); #ifdef __cplusplus } /* extern "C" */ #endif - -#endif /* __DEG_DEPSGRAPH_DEBUG_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_physics.h b/source/blender/depsgraph/DEG_depsgraph_physics.h index 7eae6b4eec4..7bd2994b426 100644 --- a/source/blender/depsgraph/DEG_depsgraph_physics.h +++ b/source/blender/depsgraph/DEG_depsgraph_physics.h @@ -23,8 +23,7 @@ * Physics utilities for effectors and collision. */ -#ifndef __DEG_DEPSGRAPH_PHYSICS_H__ -#define __DEG_DEPSGRAPH_PHYSICS_H__ +#pragma once #include "DEG_depsgraph.h" @@ -74,5 +73,3 @@ void DEG_add_forcefield_relations(struct DepsNodeHandle *handle, #ifdef __cplusplus } /* extern "C" */ #endif - -#endif /* __DEG_DEPSGRAPH_PHYSICS_H__ */ diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 3d570536223..e0166a13d69 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -23,8 +23,7 @@ * Public API for Querying Depsgraph. */ -#ifndef __DEG_DEPSGRAPH_QUERY_H__ -#define __DEG_DEPSGRAPH_QUERY_H__ +#pragma once #include "BLI_iterator.h" @@ -261,5 +260,3 @@ void DEG_foreach_ID(const Depsgraph *depsgraph, DEGForeachIDCallback callback, v #ifdef __cplusplus } /* extern "C" */ #endif - -#endif /* __DEG_DEPSGRAPH_QUERY_H__ */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index 1095905c570..750bccf0e52 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -72,11 +72,11 @@ bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b) return a.data == b.data && a.property_rna == b.property_rna; } -uint32_t AnimatedPropertyID::hash() const +uint64_t AnimatedPropertyID::hash() const { uintptr_t ptr1 = (uintptr_t)data; uintptr_t ptr2 = (uintptr_t)property_rna; - return (uint32_t)(((ptr1 >> 4) * 33) ^ (ptr2 >> 4)); + return (uint64_t)(((ptr1 >> 4) * 33) ^ (ptr2 >> 4)); } namespace { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.h b/source/blender/depsgraph/intern/builder/deg_builder_cache.h index 43348e3bf23..e04ae3a3727 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.h @@ -47,7 +47,7 @@ class AnimatedPropertyID { AnimatedPropertyID(ID *id, StructRNA *type, const char *property_name); AnimatedPropertyID(ID *id, StructRNA *type, void *data, const char *property_name); - uint32_t hash() const; + uint64_t hash() const; friend bool operator==(const AnimatedPropertyID &a, const AnimatedPropertyID &b); /* Corresponds to PointerRNA.data. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h index 5dfc3297b3e..8b23d3d0d3b 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_map.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h @@ -40,7 +40,7 @@ class BuilderMap { TAG_SCENE_COMPOSITOR = (1 << 4), TAG_SCENE_SEQUENCER = (1 << 5), - TAG_SCENE_AUDIO = (1 << 5), + TAG_SCENE_AUDIO = (1 << 6), /* All ID components has been built. */ TAG_COMPLETE = (TAG_ANIMATION | TAG_PARAMETERS | TAG_TRANSFORM | TAG_GEOMETRY | diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index f5cc5963253..e262c880421 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1126,6 +1126,12 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) if (object->type != OB_MESH) { continue; } + if (object->rigidbody_object == nullptr) { + continue; + } + if (object->rigidbody_object->type == RBO_TYPE_PASSIVE) { + continue; + } /* Create operation for flushing results. */ /* Object's transform component - where the rigidbody operation * lives. */ @@ -1466,6 +1472,18 @@ void DepsgraphNodeBuilder::build_light(Light *lamp) function_bind(BKE_light_eval, _1, lamp_cow)); } +void DepsgraphNodeBuilder::build_nodetree_socket(bNodeSocket *socket) +{ + build_idproperties(socket->prop); + + if (socket->type == SOCK_OBJECT) { + build_id((ID *)((bNodeSocketValueObject *)socket->default_value)->value); + } + else if (socket->type == SOCK_IMAGE) { + build_id((ID *)((bNodeSocketValueImage *)socket->default_value)->value); + } +} + void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) { if (ntree == nullptr) { @@ -1494,10 +1512,10 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->inputs) { - build_idproperties(socket->prop); + build_nodetree_socket(socket); } LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->outputs) { - build_idproperties(socket->prop); + build_nodetree_socket(socket); } ID *id = bnode->id; @@ -1780,8 +1798,10 @@ void DepsgraphNodeBuilder::build_simulation(Simulation *simulation) return; } add_id_node(&simulation->id); + build_idproperties(simulation->id.properties); build_animdata(&simulation->id); build_parameters(&simulation->id); + build_nodetree(simulation->nodetree); Simulation *simulation_cow = get_cow_datablock(simulation); Scene *scene_cow = get_cow_datablock(scene_); @@ -1797,6 +1817,9 @@ void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) if (scene->ed == nullptr) { return; } + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_SEQUENCER)) { + return; + } build_scene_audio(scene); Scene *scene_cow = get_cow_datablock(scene); add_operation_node(&scene->id, @@ -1831,6 +1854,10 @@ void DepsgraphNodeBuilder::build_scene_audio(Scene *scene) return; } + OperationNode *audio_entry_node = add_operation_node( + &scene->id, NodeType::AUDIO, OperationCode::AUDIO_ENTRY); + audio_entry_node->set_as_entry(); + add_operation_node(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL); Scene *scene_cow = get_cow_datablock(scene); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 256fa3450a6..40f42705a52 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -31,6 +31,7 @@ #include "DEG_depsgraph.h" +struct bNodeSocket; struct CacheFile; struct Camera; struct Collection; @@ -211,6 +212,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { virtual void build_camera(Camera *camera); virtual void build_light(Light *lamp); virtual void build_nodetree(bNodeTree *ntree); + virtual void build_nodetree_socket(bNodeSocket *socket); virtual void build_material(Material *ma); virtual void build_materials(Material **materials, int num_materials); virtual void build_freestyle_lineset(FreestyleLineSet *fls); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 50c52a519b4..5ae71dd1792 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -104,6 +104,7 @@ #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_pchanmap.h" +#include "intern/builder/deg_builder_relations_drivers.h" #include "intern/debug/deg_debug.h" #include "intern/depsgraph_physics.h" #include "intern/depsgraph_tag.h" @@ -1697,6 +1698,22 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) if (object->type != OB_MESH) { continue; } + if (object->rigidbody_object == nullptr) { + continue; + } + if (object->rigidbody_object->type == RBO_TYPE_PASSIVE) { + continue; + } + + if (object->parent != nullptr && object->parent->rigidbody_object != nullptr && + object->parent->rigidbody_object->shape == RB_SHAPE_COMPOUND) { + /* If we are a child of a compound shape object, the transforms and sim evaluation will be + * handled by the parent compound shape object. Do not add any evaluation triggers + * for the child objects. + */ + continue; + } + OperationKey rb_transform_copy_key( &object->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY); /* Rigid body synchronization depends on the actual simulation. */ @@ -1746,13 +1763,18 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* final result of the constraint object's transform controls how * the constraint affects the physics sim for these objects. */ ComponentKey trans_key(&object->id, NodeType::TRANSFORM); - OperationKey ob1_key( - &rbc->ob1->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY); - OperationKey ob2_key( - &rbc->ob2->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY); - /* Constrained-objects sync depends on the constraint-holder. */ - add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1"); - add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2"); + if (rbc->ob1->rigidbody_object->type == RBO_TYPE_ACTIVE) { + OperationKey ob1_key( + &rbc->ob1->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY); + /* Constrained-objects sync depends on the constraint-holder. */ + add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1"); + } + if (rbc->ob2->rigidbody_object->type == RBO_TYPE_ACTIVE) { + OperationKey ob2_key( + &rbc->ob2->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY); + /* Constrained-objects sync depends on the constraint-holder. */ + add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2"); + } /* Ensure that sim depends on this constraint's transform. */ add_relation(trans_key, rb_simulate_key, "RigidBodyConstraint Transform -> RB Simulation"); } @@ -2275,6 +2297,24 @@ void DepsgraphRelationBuilder::build_light(Light *lamp) add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters"); } +void DepsgraphRelationBuilder::build_nodetree_socket(bNodeSocket *socket) +{ + build_idproperties(socket->prop); + + if (socket->type == SOCK_OBJECT) { + Object *object = ((bNodeSocketValueObject *)socket->default_value)->value; + if (object != nullptr) { + build_object(object); + } + } + else if (socket->type == SOCK_IMAGE) { + Image *image = ((bNodeSocketValueImage *)socket->default_value)->value; + if (image != nullptr) { + build_image(image); + } + } +} + void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) { if (ntree == nullptr) { @@ -2291,10 +2331,10 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->inputs) { - build_idproperties(socket->prop); + build_nodetree_socket(socket); } LISTBASE_FOREACH (bNodeSocket *, socket, &bnode->outputs) { - build_idproperties(socket->prop); + build_nodetree_socket(socket); } ID *id = bnode->id; @@ -2601,13 +2641,39 @@ void DepsgraphRelationBuilder::build_simulation(Simulation *simulation) if (built_map_.checkIsBuiltAndTag(simulation)) { return; } + build_idproperties(simulation->id.properties); build_animdata(&simulation->id); build_parameters(&simulation->id); - OperationKey simulation_update_key( + build_nodetree(simulation->nodetree); + build_nested_nodetree(&simulation->id, simulation->nodetree); + + OperationKey simulation_eval_key( &simulation->id, NodeType::SIMULATION, OperationCode::SIMULATION_EVAL); TimeSourceKey time_src_key; - add_relation(time_src_key, simulation_update_key, "TimeSrc -> Simulation"); + add_relation(time_src_key, simulation_eval_key, "TimeSrc -> Simulation"); + + OperationKey nodetree_key( + &simulation->nodetree->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT); + add_relation(nodetree_key, simulation_eval_key, "NodeTree -> Simulation", 0); + + LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) { + if (dependency->id == nullptr) { + continue; + } + build_id(dependency->id); + if (GS(dependency->id->name) == ID_OB) { + Object *object = (Object *)dependency->id; + if (dependency->flag & SIM_DEPENDS_ON_TRANSFORM) { + ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM); + add_relation(object_transform_key, simulation_eval_key, "Object Transform -> Simulation"); + } + if (dependency->flag & SIM_DEPENDS_ON_GEOMETRY) { + ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY); + add_relation(object_geometry_key, simulation_eval_key, "Object Geometry -> Simulation"); + } + } + } } void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) @@ -2655,8 +2721,10 @@ void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) void DepsgraphRelationBuilder::build_scene_audio(Scene *scene) { + OperationKey scene_audio_entry_key(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_ENTRY); OperationKey scene_audio_volume_key(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_VOLUME); OperationKey scene_sound_eval_key(&scene->id, NodeType::AUDIO, OperationCode::SOUND_EVAL); + add_relation(scene_audio_entry_key, scene_audio_volume_key, "Audio Entry -> Volume"); add_relation(scene_audio_volume_key, scene_sound_eval_key, "Audio Volume -> Sound"); if (scene->audio.flag & AUDIO_VOLUME_ANIMATED) { @@ -2841,121 +2909,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) #endif } -static bool is_reachable(const Node *const from, const Node *const to) -{ - if (from == to) { - return true; - } - - // Perform a graph walk from 'to' towards its incoming connections. - // Walking from 'from' towards its outgoing connections is 10x slower on the Spring rig. - deque<const Node *> queue; - Set<const Node *> seen; - queue.push_back(to); - while (!queue.empty()) { - // Visit the next node to inspect. - const Node *visit = queue.back(); - queue.pop_back(); - - if (visit == from) { - return true; - } - - // Queue all incoming relations that we haven't seen before. - for (Relation *relation : visit->inlinks) { - const Node *prev_node = relation->from; - if (seen.add(prev_node)) { - queue.push_back(prev_node); - } - } - } - return false; -} - -void DepsgraphRelationBuilder::build_driver_relations() -{ - for (IDNode *id_node : graph_->id_nodes) { - build_driver_relations(id_node); - } -} - -void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node) -{ - /* Add relations between drivers that write to the same datablock. - * - * This prevents threading issues when two separate RNA properties write to - * the same memory address. For example: - * - Drivers on individual array elements, as the animation system will write - * the whole array back to RNA even when changing individual array value. - * - Drivers on RNA properties that map to a single bit flag. Changing the RNA - * value will write the entire int containing the bit, in a non-thread-safe - * way. - */ - ID *id_orig = id_node->id_orig; - AnimData *adt = BKE_animdata_from_id(id_orig); - if (adt == nullptr) { - return; - } - - // Mapping from RNA prefix -> set of driver evaluation nodes: - Map<string, Vector<Node *>> driver_groups; - - LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { - if (fcu->rna_path == nullptr) { - continue; - } - // Get the RNA path except the part after the last dot. - char *last_dot = strrchr(fcu->rna_path, '.'); - StringRef rna_prefix; - if (last_dot != nullptr) { - rna_prefix = StringRef(fcu->rna_path, last_dot); - } - - // Insert this driver node into the group belonging to the RNA prefix. - OperationKey driver_key( - id_orig, NodeType::PARAMETERS, OperationCode::DRIVER, fcu->rna_path, fcu->array_index); - Node *node_driver = get_node(driver_key); - driver_groups.lookup_or_add_default_as(rna_prefix).append(node_driver); - } - - for (Span<Node *> prefix_group : driver_groups.values()) { - // For each node in the driver group, try to connect it to another node - // in the same group without creating any cycles. - int num_drivers = prefix_group.size(); - if (num_drivers < 2) { - // A relation requires two drivers. - continue; - } - for (int from_index = 0; from_index < num_drivers; ++from_index) { - Node *op_from = prefix_group[from_index]; - - // Start by trying the next node in the group. - for (int to_offset = 1; to_offset < num_drivers; ++to_offset) { - int to_index = (from_index + to_offset) % num_drivers; - Node *op_to = prefix_group[to_index]; - - // Investigate whether this relation would create a dependency cycle. - // Example graph: - // A -> B -> C - // and investigating a potential connection C->A. Because A->C is an - // existing transitive connection, adding C->A would create a cycle. - if (is_reachable(op_to, op_from)) { - continue; - } - - // No need to directly connect this node if there is already a transitive connection. - if (is_reachable(op_from, op_to)) { - break; - } - - add_operation_relation( - op_from->get_exit_operation(), op_to->get_entry_operation(), "Driver Serialisation"); - break; - } - } - } -} // namespace DEG - /* **** ID traversal callbacks functions **** */ void DepsgraphRelationBuilder::modifier_walk(void *user_data, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index b4b0dc71f85..04f2a3f911d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -46,6 +46,7 @@ #include "intern/node/deg_node_operation.h" struct Base; +struct bNodeSocket; struct CacheFile; struct Camera; struct Collection; @@ -275,6 +276,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { virtual void build_camera(Camera *camera); virtual void build_light(Light *lamp); virtual void build_nodetree(bNodeTree *ntree); + virtual void build_nodetree_socket(bNodeSocket *socket); virtual void build_material(Material *ma); virtual void build_materials(Material **materials, int num_materials); virtual void build_freestyle_lineset(FreestyleLineSet *fls); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc new file mode 100644 index 00000000000..717c8300f9b --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc @@ -0,0 +1,258 @@ +/* + * 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) 2013 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + * + * Methods for constructing depsgraph relations for drivers. + */ + +#include "intern/builder/deg_builder_relations_drivers.h" + +#include <cstring> + +#include "DNA_anim_types.h" + +#include "BKE_anim_data.h" + +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph_relation.h" +#include "intern/node/deg_node.h" + +namespace blender { +namespace deg { + +DriverDescriptor::DriverDescriptor(PointerRNA *id_ptr, FCurve *fcu) + : rna_prefix(), + rna_suffix(), + id_ptr_(id_ptr), + fcu_(fcu), + driver_relations_needed_(false), + pointer_rna_(), + property_rna_(nullptr), + is_array_(false) +{ + driver_relations_needed_ = determine_relations_needed(); + split_rna_path(); +} + +bool DriverDescriptor::determine_relations_needed() +{ + if (fcu_->array_index > 0) { + /* Drivers on array elements always need relations. */ + is_array_ = true; + return true; + } + + if (!resolve_rna()) { + /* Properties that don't exist can't cause threading issues either. */ + return false; + } + + if (RNA_property_array_check(property_rna_)) { + /* Drivers on array elements always need relations. */ + is_array_ = true; + return true; + } + + /* Drivers on Booleans and Enums (when used as bitflags) can write to the same memory location, + * so they need relations between each other. */ + return ELEM(RNA_property_type(property_rna_), PROP_BOOLEAN, PROP_ENUM); +} + +bool DriverDescriptor::driver_relations_needed() const +{ + return driver_relations_needed_; +} + +bool DriverDescriptor::is_array() const +{ + return is_array_; +} + +/* Assumes that 'other' comes from the same RNA group, that is, has the same RNA path prefix. */ +bool DriverDescriptor::is_same_array_as(const DriverDescriptor &other) const +{ + if (!is_array_ || !other.is_array_) { + return false; + } + return rna_suffix == other.rna_suffix; +} + +OperationKey DriverDescriptor::depsgraph_key() const +{ + return OperationKey(id_ptr_->owner_id, + NodeType::PARAMETERS, + OperationCode::DRIVER, + fcu_->rna_path, + fcu_->array_index); +} + +void DriverDescriptor::split_rna_path() +{ + const char *last_dot = strrchr(fcu_->rna_path, '.'); + if (last_dot == nullptr || last_dot[1] == '\0') { + rna_prefix = StringRef(); + rna_suffix = StringRef(fcu_->rna_path); + return; + } + + rna_prefix = StringRef(fcu_->rna_path, last_dot); + rna_suffix = StringRef(last_dot + 1); +} + +bool DriverDescriptor::resolve_rna() +{ + return RNA_path_resolve_property(id_ptr_, fcu_->rna_path, &pointer_rna_, &property_rna_); +} + +static bool is_reachable(const Node *const from, const Node *const to) +{ + if (from == to) { + return true; + } + + // Perform a graph walk from 'to' towards its incoming connections. + // Walking from 'from' towards its outgoing connections is 10x slower on the Spring rig. + deque<const Node *> queue; + Set<const Node *> seen; + queue.push_back(to); + while (!queue.empty()) { + // Visit the next node to inspect. + const Node *visit = queue.back(); + queue.pop_back(); + + if (visit == from) { + return true; + } + + // Queue all incoming relations that we haven't seen before. + for (Relation *relation : visit->inlinks) { + const Node *prev_node = relation->from; + if (seen.add(prev_node)) { + queue.push_back(prev_node); + } + } + } + return false; +} + +/* **** DepsgraphRelationBuilder functions **** */ + +void DepsgraphRelationBuilder::build_driver_relations() +{ + for (IDNode *id_node : graph_->id_nodes) { + build_driver_relations(id_node); + } +} + +void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node) +{ + /* Add relations between drivers that write to the same datablock. + * + * This prevents threading issues when two separate RNA properties write to + * the same memory address. For example: + * - Drivers on individual array elements, as the animation system will write + * the whole array back to RNA even when changing individual array value. + * - Drivers on RNA properties that map to a single bit flag. Changing the RNA + * value will write the entire int containing the bit, in a non-thread-safe + * way. + */ + ID *id_orig = id_node->id_orig; + AnimData *adt = BKE_animdata_from_id(id_orig); + if (adt == nullptr) { + return; + } + + // Mapping from RNA prefix -> set of driver descriptors: + Map<string, Vector<DriverDescriptor>> driver_groups; + + PointerRNA id_ptr; + RNA_id_pointer_create(id_orig, &id_ptr); + + LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { + if (fcu->rna_path == nullptr) { + continue; + } + + DriverDescriptor driver_desc(&id_ptr, fcu); + if (!driver_desc.driver_relations_needed()) { + continue; + } + + driver_groups.lookup_or_add_default_as(driver_desc.rna_prefix).append(driver_desc); + } + + for (Span<DriverDescriptor> prefix_group : driver_groups.values()) { + // For each node in the driver group, try to connect it to another node + // in the same group without creating any cycles. + int num_drivers = prefix_group.size(); + if (num_drivers < 2) { + // A relation requires two drivers. + continue; + } + for (int from_index = 0; from_index < num_drivers; ++from_index) { + const DriverDescriptor &driver_from = prefix_group[from_index]; + Node *op_from = get_node(driver_from.depsgraph_key()); + + // Start by trying the next node in the group. + for (int to_offset = 1; to_offset < num_drivers; ++to_offset) { + const int to_index = (from_index + to_offset) % num_drivers; + const DriverDescriptor &driver_to = prefix_group[to_index]; + Node *op_to = get_node(driver_to.depsgraph_key()); + + // Duplicate drivers can exist (see T78615), but cannot be distinguished by OperationKey + // and thus have the same depsgraph node. Relations between those drivers should not be + // created. This not something that is expected to happen (both the UI and the Python API + // prevent duplicate drivers), it did happen in a file and it is easy to deal with here. + if (op_from == op_to) { + continue; + } + + if (from_index < to_index && driver_from.is_same_array_as(driver_to)) { + // This is for adding a relation like `color[0]` -> `color[1]`. + // When the search for another driver wraps around, we cannot blindly add relations any + // more. + } + else { + // Investigate whether this relation would create a dependency cycle. + // Example graph: + // A -> B -> C + // and investigating a potential connection C->A. Because A->C is an + // existing transitive connection, adding C->A would create a cycle. + if (is_reachable(op_to, op_from)) { + continue; + } + + // No need to directly connect this node if there is already a transitive connection. + if (is_reachable(op_from, op_to)) { + break; + } + } + + add_operation_relation( + op_from->get_exit_operation(), op_to->get_entry_operation(), "Driver Serialization"); + break; + } + } + } +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h new file mode 100644 index 00000000000..c80c69be9e2 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h @@ -0,0 +1,76 @@ +/* + * 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) 2013 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "BLI_string_ref.hh" + +#include "RNA_types.h" + +#include "intern/builder/deg_builder_relations.h" + +struct FCurve; + +namespace blender { +namespace deg { + +/* Helper class for determining which relations are needed between driver evaluation nodes. */ +class DriverDescriptor { + public: + /* Drivers are grouped by their RNA prefix. The prefix is the part of the RNA + * path up to the last dot, the suffix is the remainder of the RNA path: + * + * fcu->rna_path rna_prefix rna_suffix + * ------------------------------- ---------------------- ---------- + * 'color' '' 'color' + * 'rigidbody_world.time_scale' 'rigidbody_world' 'time_scale' + * 'pose.bones["master"].location' 'pose.bones["master"]' 'location' + */ + StringRef rna_prefix; + StringRef rna_suffix; + + public: + DriverDescriptor(PointerRNA *id_ptr, FCurve *fcu); + + bool driver_relations_needed() const; + bool is_array() const; + /* Assumes that 'other' comes from the same RNA group, that is, has the same RNA path prefix. */ + bool is_same_array_as(const DriverDescriptor &other) const; + OperationKey depsgraph_key() const; + + private: + PointerRNA *id_ptr_; + FCurve *fcu_; + bool driver_relations_needed_; + + PointerRNA pointer_rna_; + PropertyRNA *property_rna_; + bool is_array_; + + bool determine_relations_needed(); + void split_rna_path(); + bool resolve_rna(); +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 98ae653d294..e3b667427a2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -149,6 +149,25 @@ Node *RNANodeQuery::find_node(const PointerRNA *ptr, node_identifier.operation_name_tag); } +bool RNANodeQuery::contains(const char *prop_identifier, const char *rna_path_component) +{ + const char *substr = strstr(prop_identifier, rna_path_component); + if (substr == nullptr) { + return false; + } + + // If substr != prop_identifier, it means that the substring is found further in prop_identifier, + // and that thus index -1 is a valid memory location. + const bool start_ok = substr == prop_identifier || substr[-1] == '.'; + if (!start_ok) { + return false; + } + + const size_t component_len = strlen(rna_path_component); + const bool end_ok = ELEM(substr[component_len], '\0', '.', '['); + return end_ok; +} + RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, const PropertyRNA *prop, RNAPointerSource source) @@ -283,12 +302,20 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, if (prop != nullptr) { const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); /* TODO(sergey): How to optimize this? */ - if (strstr(prop_identifier, "location") || strstr(prop_identifier, "rotation") || - strstr(prop_identifier, "scale") || strstr(prop_identifier, "matrix_")) { + if (contains(prop_identifier, "location") || contains(prop_identifier, "matrix_basis") || + contains(prop_identifier, "matrix_channel") || + contains(prop_identifier, "matrix_inverse") || + contains(prop_identifier, "matrix_local") || + contains(prop_identifier, "matrix_parent_inverse") || + contains(prop_identifier, "matrix_world") || + contains(prop_identifier, "rotation_axis_angle") || + contains(prop_identifier, "rotation_euler") || + contains(prop_identifier, "rotation_mode") || + contains(prop_identifier, "rotation_quaternion") || contains(prop_identifier, "scale")) { node_identifier.type = NodeType::TRANSFORM; return node_identifier; } - else if (strstr(prop_identifier, "data")) { + else if (contains(prop_identifier, "data")) { /* We access object.data, most likely a geometry. * Might be a bone tho. */ node_identifier.type = NodeType::GEOMETRY; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h index 52d0e5f6b12..d03903d508c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -93,6 +93,19 @@ class RNANodeQuery { /* Make sure ID data exists for the given ID, and returns it. */ RNANodeQueryIDData *ensure_id_data(const ID *id); + + /* Check whether prop_identifier contains rna_path_component. + * + * This checks more than a sub-string: + * + * prop_identifier contains(prop_identifier, "location") + * ------------------------ ------------------------------------- + * location true + * ["test_location"] false + * pose["bone"].location true + * pose["bone"].location.x true + */ + static bool contains(const char *prop_identifier, const char *rna_path_component); }; } // namespace deg diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna_test.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna_test.cc new file mode 100644 index 00000000000..c91dda87190 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna_test.cc @@ -0,0 +1,60 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/builder/deg_builder_rna.h" + +#include "testing/testing.h" + +namespace blender { +namespace deg { +namespace tests { + +class TestableRNANodeQuery : public RNANodeQuery { + public: + static bool contains(const char *prop_identifier, const char *rna_path_component) + { + return RNANodeQuery::contains(prop_identifier, rna_path_component); + } +}; + +TEST(deg_builder_rna, contains) +{ + EXPECT_TRUE(TestableRNANodeQuery::contains("location", "location")); + EXPECT_TRUE(TestableRNANodeQuery::contains("location.x", "location")); + EXPECT_TRUE(TestableRNANodeQuery::contains("pose.bone[\"blork\"].location", "location")); + EXPECT_TRUE(TestableRNANodeQuery::contains("pose.bone[\"blork\"].location.x", "location")); + EXPECT_TRUE(TestableRNANodeQuery::contains("pose.bone[\"blork\"].location[0]", "location")); + + EXPECT_FALSE(TestableRNANodeQuery::contains("", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("locatio", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("locationnn", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("test_location", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("location_test", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("test_location_test", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("pose.bone[\"location\"].scale", "location")); + EXPECT_FALSE(TestableRNANodeQuery::contains("pose.bone[\"location\"].scale[0]", "location")); +} + +} // namespace tests +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline.cc b/source/blender/depsgraph/intern/builder/pipeline.cc new file mode 100644 index 00000000000..d6893ba11d8 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline.cc @@ -0,0 +1,132 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline.h" + +#include "PIL_time.h" + +#include "BKE_global.h" + +#include "DNA_scene_types.h" + +#include "deg_builder_cycle.h" +#include "deg_builder_nodes.h" +#include "deg_builder_relations.h" +#include "deg_builder_transitive.h" + +namespace blender { +namespace deg { + +AbstractBuilderPipeline::AbstractBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) + : deg_graph_(reinterpret_cast<Depsgraph *>(graph)), + bmain_(bmain), + scene_(scene), + view_layer_(view_layer), + builder_cache_() +{ +} + +AbstractBuilderPipeline::~AbstractBuilderPipeline() +{ +} + +void AbstractBuilderPipeline::build() +{ + double start_time = 0.0; + if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { + start_time = PIL_check_seconds_timer(); + } + + build_step_sanity_check(); + build_step_nodes(); + build_step_relations(); + build_step_finalize(); + + if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { + printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); + } +} + +void AbstractBuilderPipeline::build_step_sanity_check() +{ + BLI_assert(BLI_findindex(&scene_->view_layers, view_layer_) != -1); + BLI_assert(deg_graph_->scene == scene_); + BLI_assert(deg_graph_->view_layer == view_layer_); +} + +void AbstractBuilderPipeline::build_step_nodes() +{ + /* Generate all the nodes in the graph first */ + unique_ptr<DepsgraphNodeBuilder> node_builder = construct_node_builder(); + node_builder->begin_build(); + build_nodes(*node_builder); + node_builder->end_build(); +} + +void AbstractBuilderPipeline::build_step_relations() +{ + /* Hook up relationships between operations - to determine evaluation order. */ + unique_ptr<DepsgraphRelationBuilder> relation_builder = construct_relation_builder(); + relation_builder->begin_build(); + build_relations(*relation_builder); + relation_builder->build_copy_on_write_relations(); + relation_builder->build_driver_relations(); +} + +void AbstractBuilderPipeline::build_step_finalize() +{ + /* Detect and solve cycles. */ + deg_graph_detect_cycles(deg_graph_); + /* Simplify the graph by removing redundant relations (to optimize + * traversal later). */ + /* TODO: it would be useful to have an option to disable this in cases where + * it is causing trouble. */ + if (G.debug_value == 799) { + deg_graph_transitive_reduction(deg_graph_); + } + /* Store pointers to commonly used valuated datablocks. */ + deg_graph_->scene_cow = (Scene *)deg_graph_->get_cow_id(°_graph_->scene->id); + /* Flush visibility layer and re-schedule nodes for update. */ + deg_graph_build_finalize(bmain_, deg_graph_); + DEG_graph_on_visible_update(bmain_, reinterpret_cast<::Depsgraph *>(deg_graph_), false); +#if 0 + if (!DEG_debug_consistency_check(deg_graph_)) { + printf("Consistency validation failed, ABORTING!\n"); + abort(); + } +#endif + /* Relations are up to date. */ + deg_graph_->need_update = false; +} + +unique_ptr<DepsgraphNodeBuilder> AbstractBuilderPipeline::construct_node_builder() +{ + return std::make_unique<DepsgraphNodeBuilder>(bmain_, deg_graph_, &builder_cache_); +} + +unique_ptr<DepsgraphRelationBuilder> AbstractBuilderPipeline::construct_relation_builder() +{ + return std::make_unique<DepsgraphRelationBuilder>(bmain_, deg_graph_, &builder_cache_); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline.h b/source/blender/depsgraph/intern/builder/pipeline.h new file mode 100644 index 00000000000..2c9c78bb2cb --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline.h @@ -0,0 +1,77 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "deg_builder_cache.h" + +#include "intern/depsgraph_type.h" + +struct Main; +struct Scene; +struct ViewLayer; +struct Depsgraph; + +namespace blender { +namespace deg { + +struct Depsgraph; +class DepsgraphNodeBuilder; +class DepsgraphRelationBuilder; + +/* Base class for Depsgraph Builder pipelines. + * + * Basically it runs through the following steps: + * - sanity check + * - build nodes + * - build relations + * - finalize + */ +class AbstractBuilderPipeline { + public: + AbstractBuilderPipeline(::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer); + virtual ~AbstractBuilderPipeline(); + + void build(); + + protected: + Depsgraph *deg_graph_; + Main *bmain_; + Scene *scene_; + ViewLayer *view_layer_; + DepsgraphBuilderCache builder_cache_; + + virtual unique_ptr<DepsgraphNodeBuilder> construct_node_builder(); + virtual unique_ptr<DepsgraphRelationBuilder> construct_relation_builder(); + + virtual void build_step_sanity_check(); + void build_step_nodes(); + void build_step_relations(); + void build_step_finalize(); + + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) = 0; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) = 0; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_compositor.cc b/source/blender/depsgraph/intern/builder/pipeline_compositor.cc new file mode 100644 index 00000000000..3e56f17fc7e --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_compositor.cc @@ -0,0 +1,49 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_compositor.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +CompositorBuilderPipeline::CompositorBuilderPipeline( + ::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer, bNodeTree *nodetree) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer), nodetree_(nodetree) +{ + deg_graph_->is_render_pipeline_depsgraph = true; +} + +void CompositorBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_scene_render(scene_, view_layer_); + node_builder.build_nodetree(nodetree_); +} + +void CompositorBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_scene_render(scene_, view_layer_); + relation_builder.build_nodetree(nodetree_); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_compositor.h b/source/blender/depsgraph/intern/builder/pipeline_compositor.h new file mode 100644 index 00000000000..892ece7c2a4 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_compositor.h @@ -0,0 +1,47 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +struct bNodeTree; + +namespace blender { +namespace deg { + +class CompositorBuilderPipeline : public AbstractBuilderPipeline { + public: + CompositorBuilderPipeline( + ::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer, bNodeTree *nodetree); + + protected: + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; + + private: + bNodeTree *nodetree_; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc new file mode 100644 index 00000000000..e44f554f197 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc @@ -0,0 +1,154 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_from_ids.h" + +#include "DNA_layer_types.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +namespace { + +class DepsgraphFromIDsFilter { + public: + DepsgraphFromIDsFilter(ID **ids, const int num_ids) + { + for (int i = 0; i < num_ids; ++i) { + ids_.add(ids[i]); + } + } + + bool contains(ID *id) + { + return ids_.contains(id); + } + + protected: + Set<ID *> ids_; +}; + +class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { + public: + DepsgraphFromIDsNodeBuilder( + Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) + : DepsgraphNodeBuilder(bmain, graph, cache), filter_(ids, num_ids) + { + } + + virtual bool need_pull_base_into_graph(Base *base) override + { + if (!filter_.contains(&base->object->id)) { + return false; + } + return DepsgraphNodeBuilder::need_pull_base_into_graph(base); + } + + virtual void build_object_proxy_group(Object *object, bool is_visible) override + { + if (object->proxy_group == nullptr) { + return; + } + if (!filter_.contains(&object->proxy_group->id)) { + return; + } + DepsgraphNodeBuilder::build_object_proxy_group(object, is_visible); + } + + protected: + DepsgraphFromIDsFilter filter_; +}; + +class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { + public: + DepsgraphFromIDsRelationBuilder( + Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) + : DepsgraphRelationBuilder(bmain, graph, cache), filter_(ids, num_ids) + { + } + + virtual bool need_pull_base_into_graph(Base *base) override + { + if (!filter_.contains(&base->object->id)) { + return false; + } + return DepsgraphRelationBuilder::need_pull_base_into_graph(base); + } + + virtual void build_object_proxy_group(Object *object) override + { + if (object->proxy_group == nullptr) { + return; + } + if (!filter_.contains(&object->proxy_group->id)) { + return; + } + DepsgraphRelationBuilder::build_object_proxy_group(object); + } + + protected: + DepsgraphFromIDsFilter filter_; +}; + +} // namespace + +FromIDsBuilderPipeline::FromIDsBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer, + ID **ids, + const int num_ids) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer), ids_(ids), num_ids_(num_ids) +{ +} + +unique_ptr<DepsgraphNodeBuilder> FromIDsBuilderPipeline::construct_node_builder() +{ + return std::make_unique<DepsgraphFromIDsNodeBuilder>( + bmain_, deg_graph_, &builder_cache_, ids_, num_ids_); +} + +unique_ptr<DepsgraphRelationBuilder> FromIDsBuilderPipeline::construct_relation_builder() +{ + return std::make_unique<DepsgraphFromIDsRelationBuilder>( + bmain_, deg_graph_, &builder_cache_, ids_, num_ids_); +} + +void FromIDsBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); + for (int i = 0; i < num_ids_; ++i) { + node_builder.build_id(ids_[i]); + } +} + +void FromIDsBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); + for (int i = 0; i < num_ids_; ++i) { + relation_builder.build_id(ids_[i]); + } +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.h b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h new file mode 100644 index 00000000000..4a507f2c728 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h @@ -0,0 +1,62 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +namespace blender { +namespace deg { + +/* Optimized builders for dependency graph built from a given set of IDs. + * + * General notes: + * + * - We pull in all bases if their objects are in the set of IDs. This allows to have proper + * visibility and other flags assigned to the objects. + * All other bases (the ones which points to object which is outside of the set of IDs) are + * completely ignored. + * + * - Proxy groups pointing to objects which are outside of the IDs set are also ignored. + * This way we avoid high-poly character body pulled into the dependency graph when it's coming + * from a library into an animation file and the dependency graph constructed for a proxy rig. */ + +class FromIDsBuilderPipeline : public AbstractBuilderPipeline { + public: + FromIDsBuilderPipeline( + ::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer, ID **ids, int num_ids); + + protected: + virtual unique_ptr<DepsgraphNodeBuilder> construct_node_builder() override; + virtual unique_ptr<DepsgraphRelationBuilder> construct_relation_builder() override; + + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; + + private: + ID **ids_; + const int num_ids_; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_render.cc b/source/blender/depsgraph/intern/builder/pipeline_render.cc new file mode 100644 index 00000000000..50a37d0d3e4 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_render.cc @@ -0,0 +1,49 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_render.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +RenderBuilderPipeline::RenderBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer) +{ + deg_graph_->is_render_pipeline_depsgraph = true; +} + +void RenderBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_scene_render(scene_, view_layer_); +} + +void RenderBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_scene_render(scene_, view_layer_); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_render.h b/source/blender/depsgraph/intern/builder/pipeline_render.h new file mode 100644 index 00000000000..df7f9e0de68 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_render.h @@ -0,0 +1,41 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +namespace blender { +namespace deg { + +class RenderBuilderPipeline : public AbstractBuilderPipeline { + public: + RenderBuilderPipeline(::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer); + + protected: + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_view_layer.cc b/source/blender/depsgraph/intern/builder/pipeline_view_layer.cc new file mode 100644 index 00000000000..3223f17f349 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_view_layer.cc @@ -0,0 +1,48 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_view_layer.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +ViewLayerBuilderPipeline::ViewLayerBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer) +{ +} + +void ViewLayerBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); +} + +void ViewLayerBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_view_layer.h b/source/blender/depsgraph/intern/builder/pipeline_view_layer.h new file mode 100644 index 00000000000..fbd7b98acad --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_view_layer.h @@ -0,0 +1,41 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +namespace blender { +namespace deg { + +class ViewLayerBuilderPipeline : public AbstractBuilderPipeline { + public: + ViewLayerBuilderPipeline(::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer); + + protected: + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index 458baf4fb1e..d0356f44022 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -25,6 +25,7 @@ #include <cstdarg> +#include "BLI_dot_export.hh" #include "BLI_utildefines.h" #include "DNA_listBase.h" @@ -41,6 +42,7 @@ #include "intern/node/deg_node_time.h" namespace deg = blender::deg; +namespace dot = blender::dot; /* ****************** */ /* Graphviz Debugging */ @@ -48,8 +50,6 @@ namespace deg = blender::deg; namespace blender { namespace deg { -#define NL "\r\n" - /* Only one should be enabled, defines whether graphviz nodes * get colored by individual types or classes. */ @@ -158,47 +158,43 @@ static int deg_debug_node_color_index(const Node *node) #endif } -struct DebugContext { - FILE *file; +struct DotExportContext { bool show_tags; + dot::DirectedGraph &digraph; + Map<const Node *, dot::Node *> nodes_map; + Map<const Node *, dot::Cluster *> clusters_map; }; -static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) - ATTR_PRINTF_FORMAT(2, 3); -static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) +static void deg_debug_graphviz_legend_color(const char *name, + const char *color, + std::stringstream &ss) { - va_list args; - va_start(args, fmt); - vfprintf(ctx.file, fmt, args); - va_end(args); -} -static void deg_debug_graphviz_legend_color(const DebugContext &ctx, - const char *name, - const char *color) -{ - deg_debug_fprintf(ctx, "<TR>"); - deg_debug_fprintf(ctx, "<TD>%s</TD>", name); - deg_debug_fprintf(ctx, "<TD BGCOLOR=\"%s\"></TD>", color); - deg_debug_fprintf(ctx, "</TR>" NL); + ss << "<TR>"; + ss << "<TD>" << name << "</TD>"; + ss << "<TD BGCOLOR=\"" << color << "\"></TD>"; + ss << "</TR>"; } -static void deg_debug_graphviz_legend(const DebugContext &ctx) +static void deg_debug_graphviz_legend(DotExportContext &ctx) { - deg_debug_fprintf(ctx, "{" NL); - deg_debug_fprintf(ctx, "rank = sink;" NL); - deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL); - deg_debug_fprintf( - ctx, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">" NL); - deg_debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>" NL); + dot::Node &legend_node = ctx.digraph.new_node(""); + legend_node.attributes.set("rank", "sink"); + legend_node.attributes.set("shape", "none"); + legend_node.attributes.set("margin", 0); + + std::stringstream ss; + ss << "<"; + ss << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">"; + ss << "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>"; #ifdef COLOR_SCHEME_NODE_CLASS const char **colors = deg_debug_colors_light; - deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]); - deg_debug_graphviz_legend_color(ctx, "Component", colors[1]); - deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]); - deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]); - deg_debug_graphviz_legend_color(ctx, "Pinned OP", colors[7]); + deg_debug_graphviz_legend_color("Operation", colors[4], ss); + deg_debug_graphviz_legend_color("Component", colors[1], ss); + deg_debug_graphviz_legend_color("ID Node", colors[5], ss); + deg_debug_graphviz_legend_color("NOOP", colors[8], ss); + deg_debug_graphviz_legend_color("Pinned OP", colors[7], ss); #endif #ifdef COLOR_SCHEME_NODE_TYPE @@ -206,18 +202,19 @@ static void deg_debug_graphviz_legend(const DebugContext &ctx) for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; pair++) { DepsNodeFactory *nti = type_get_factory((NodeType)(*pair)[0]); deg_debug_graphviz_legend_color( - ctx, nti->tname().c_str(), deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]); + ctx, nti->tname().c_str(), deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors], ss); } #endif - deg_debug_fprintf(ctx, "</TABLE>" NL); - deg_debug_fprintf(ctx, ">" NL); - deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname); - deg_debug_fprintf(ctx, "];" NL); - deg_debug_fprintf(ctx, "}" NL); + ss << "</TABLE>"; + ss << ">"; + legend_node.attributes.set("label", ss.str()); + legend_node.attributes.set("fontname", deg_debug_graphviz_fontname); } -static void deg_debug_graphviz_node_color(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node_color(DotExportContext &ctx, + const Node *node, + dot::Attributes &dot_attributes) { const char *color_default = "black"; const char *color_modified = "orangered4"; @@ -234,10 +231,12 @@ static void deg_debug_graphviz_node_color(const DebugContext &ctx, const Node *n } } } - deg_debug_fprintf(ctx, "\"%s\"", color); + dot_attributes.set("color", color); } -static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node_penwidth(DotExportContext &ctx, + const Node *node, + dot::Attributes &dot_attributes) { float penwidth_default = 1.0f; float penwidth_modified = 4.0f; @@ -254,20 +253,20 @@ static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx, const Node } } } - deg_debug_fprintf(ctx, "\"%f\"", penwidth); + dot_attributes.set("penwidth", penwidth); } -static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node_fillcolor(const Node *node, dot::Attributes &dot_attributes) { const char *defaultcolor = "gainsboro"; int color_index = deg_debug_node_color_index(node); const char *fillcolor = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors]; - deg_debug_fprintf(ctx, "\"%s\"", fillcolor); + dot_attributes.set("fillcolor", fillcolor); } -static void deg_debug_graphviz_relation_color(const DebugContext &ctx, const Relation *rel) +static void deg_debug_graphviz_relation_color(const Relation *rel, dot::DirectedEdge &edge) { const char *color_default = "black"; const char *color_cyclic = "red4"; /* The color of crime scene. */ @@ -279,10 +278,10 @@ static void deg_debug_graphviz_relation_color(const DebugContext &ctx, const Rel else if (rel->flag & RELATION_FLAG_GODMODE) { color = color_godmode; } - deg_debug_fprintf(ctx, "%s", color); + edge.attributes.set("color", color); } -static void deg_debug_graphviz_relation_style(const DebugContext &ctx, const Relation *rel) +static void deg_debug_graphviz_relation_style(const Relation *rel, dot::DirectedEdge &edge) { const char *style_default = "solid"; const char *style_no_flush = "dashed"; @@ -294,10 +293,10 @@ static void deg_debug_graphviz_relation_style(const DebugContext &ctx, const Rel if (rel->flag & RELATION_FLAG_FLUSH_USER_EDIT_ONLY) { style = style_flush_user_only; } - deg_debug_fprintf(ctx, "%s", style); + edge.attributes.set("style", style); } -static void deg_debug_graphviz_relation_arrowhead(const DebugContext &ctx, const Relation *rel) +static void deg_debug_graphviz_relation_arrowhead(const Relation *rel, dot::DirectedEdge &edge) { const char *shape_default = "normal"; const char *shape_no_cow = "box"; @@ -311,12 +310,14 @@ static void deg_debug_graphviz_relation_arrowhead(const DebugContext &ctx, const shape = shape_no_cow; } } - deg_debug_fprintf(ctx, "%s", shape); + edge.attributes.set("arrowhead", shape); } -static void deg_debug_graphviz_node_style(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node_style(DotExportContext &ctx, + const Node *node, + dot::Attributes &dot_attributes) { - const char *base_style = "filled"; /* default style */ + StringRef base_style = "filled"; /* default style */ if (ctx.show_tags) { if (node->get_class() == NodeClass::OPERATION) { OperationNode *op_node = (OperationNode *)node; @@ -327,95 +328,78 @@ static void deg_debug_graphviz_node_style(const DebugContext &ctx, const Node *n } switch (node->get_class()) { case NodeClass::GENERIC: - deg_debug_fprintf(ctx, "\"%s\"", base_style); + dot_attributes.set("style", base_style); break; case NodeClass::COMPONENT: - deg_debug_fprintf(ctx, "\"%s\"", base_style); + dot_attributes.set("style", base_style); break; case NodeClass::OPERATION: - deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style); + dot_attributes.set("style", base_style + ",rounded"); break; } } -static void deg_debug_graphviz_node_single(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node_single(DotExportContext &ctx, + const Node *node, + dot::Cluster *parent_cluster) { - const char *shape = "box"; string name = node->identifier(); - deg_debug_fprintf(ctx, "// %s\n", name.c_str()); - deg_debug_fprintf(ctx, "\"node_%p\"", node); - deg_debug_fprintf(ctx, "["); - // deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name); - deg_debug_fprintf(ctx, "label=<%s>", name.c_str()); - deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname); - deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size); - deg_debug_fprintf(ctx, ",shape=%s", shape); - deg_debug_fprintf(ctx, ",style="); - deg_debug_graphviz_node_style(ctx, node); - deg_debug_fprintf(ctx, ",color="); - deg_debug_graphviz_node_color(ctx, node); - deg_debug_fprintf(ctx, ",fillcolor="); - deg_debug_graphviz_node_fillcolor(ctx, node); - deg_debug_fprintf(ctx, ",penwidth="); - deg_debug_graphviz_node_penwidth(ctx, node); - deg_debug_fprintf(ctx, "];" NL); - deg_debug_fprintf(ctx, NL); + + dot::Node &dot_node = ctx.digraph.new_node(name); + ctx.nodes_map.add_new(node, &dot_node); + dot_node.set_parent_cluster(parent_cluster); + dot_node.attributes.set("fontname", deg_debug_graphviz_fontname); + dot_node.attributes.set("frontsize", deg_debug_graphviz_node_label_size); + dot_node.attributes.set("shape", "box"); + + deg_debug_graphviz_node_style(ctx, node, dot_node.attributes); + deg_debug_graphviz_node_color(ctx, node, dot_node.attributes); + deg_debug_graphviz_node_fillcolor(node, dot_node.attributes); + deg_debug_graphviz_node_penwidth(ctx, node, dot_node.attributes); } -static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx, const Node *node) +static dot::Cluster °_debug_graphviz_node_cluster_create(DotExportContext &ctx, + const Node *node, + dot::Cluster *parent_cluster) { string name = node->identifier(); - deg_debug_fprintf(ctx, "// %s\n", name.c_str()); - deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node); - // deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name); - deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str()); - deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname); - deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size); - deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16); - deg_debug_fprintf(ctx, "style="); - deg_debug_graphviz_node_style(ctx, node); - deg_debug_fprintf(ctx, ";" NL); - deg_debug_fprintf(ctx, "color="); - deg_debug_graphviz_node_color(ctx, node); - deg_debug_fprintf(ctx, ";" NL); - deg_debug_fprintf(ctx, "fillcolor="); - deg_debug_graphviz_node_fillcolor(ctx, node); - deg_debug_fprintf(ctx, ";" NL); - deg_debug_fprintf(ctx, "penwidth="); - deg_debug_graphviz_node_penwidth(ctx, node); - deg_debug_fprintf(ctx, ";" NL); + dot::Cluster &cluster = ctx.digraph.new_cluster(name); + cluster.set_parent_cluster(parent_cluster); + cluster.attributes.set("fontname", deg_debug_graphviz_fontname); + cluster.attributes.set("fontsize", deg_debug_graphviz_node_label_size); + cluster.attributes.set("margin", 16); + deg_debug_graphviz_node_style(ctx, node, cluster.attributes); + deg_debug_graphviz_node_color(ctx, node, cluster.attributes); + deg_debug_graphviz_node_fillcolor(node, cluster.attributes); + deg_debug_graphviz_node_penwidth(ctx, node, cluster.attributes); /* dummy node, so we can add edges between clusters */ - deg_debug_fprintf(ctx, "\"node_%p\"", node); - deg_debug_fprintf(ctx, "["); - deg_debug_fprintf(ctx, "shape=%s", "point"); - deg_debug_fprintf(ctx, ",style=%s", "invis"); - deg_debug_fprintf(ctx, "];" NL); - deg_debug_fprintf(ctx, NL); + dot::Node &dot_node = ctx.digraph.new_node(""); + dot_node.attributes.set("shape", "point"); + dot_node.attributes.set("style", "invis"); + dot_node.set_parent_cluster(&cluster); + ctx.nodes_map.add_new(node, &dot_node); + ctx.clusters_map.add_new(node, &cluster); + return cluster; } -static void deg_debug_graphviz_node_cluster_end(const DebugContext &ctx) -{ - deg_debug_fprintf(ctx, "}" NL); - deg_debug_fprintf(ctx, NL); -} +static void deg_debug_graphviz_graph_nodes(DotExportContext &ctx, const Depsgraph *graph); +static void deg_debug_graphviz_graph_relations(DotExportContext &ctx, const Depsgraph *graph); -static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgraph *graph); -static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, const Depsgraph *graph); - -static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node(DotExportContext &ctx, + const Node *node, + dot::Cluster *parent_cluster) { switch (node->type) { case NodeType::ID_REF: { const IDNode *id_node = (const IDNode *)node; if (id_node->components.is_empty()) { - deg_debug_graphviz_node_single(ctx, node); + deg_debug_graphviz_node_single(ctx, node, parent_cluster); } else { - deg_debug_graphviz_node_cluster_begin(ctx, node); + dot::Cluster &cluster = deg_debug_graphviz_node_cluster_create(ctx, node, parent_cluster); for (const ComponentNode *comp : id_node->components.values()) { - deg_debug_graphviz_node(ctx, comp); + deg_debug_graphviz_node(ctx, comp, &cluster); } - deg_debug_graphviz_node_cluster_end(ctx); } break; } @@ -445,127 +429,72 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node) case NodeType::GENERIC_DATABLOCK: case NodeType::SIMULATION: { ComponentNode *comp_node = (ComponentNode *)node; - if (!comp_node->operations.is_empty()) { - deg_debug_graphviz_node_cluster_begin(ctx, node); - for (Node *op_node : comp_node->operations) { - deg_debug_graphviz_node(ctx, op_node); - } - deg_debug_graphviz_node_cluster_end(ctx); + if (comp_node->operations.is_empty()) { + deg_debug_graphviz_node_single(ctx, node, parent_cluster); } else { - deg_debug_graphviz_node_single(ctx, node); + dot::Cluster &cluster = deg_debug_graphviz_node_cluster_create(ctx, node, parent_cluster); + for (Node *op_node : comp_node->operations) { + deg_debug_graphviz_node(ctx, op_node, &cluster); + } } break; } case NodeType::UNDEFINED: case NodeType::TIMESOURCE: case NodeType::OPERATION: - deg_debug_graphviz_node_single(ctx, node); + deg_debug_graphviz_node_single(ctx, node, parent_cluster); break; case NodeType::NUM_TYPES: break; } } -static bool deg_debug_graphviz_is_cluster(const Node *node) -{ - switch (node->type) { - case NodeType::ID_REF: { - const IDNode *id_node = (const IDNode *)node; - return !id_node->components.is_empty(); - } - case NodeType::PARAMETERS: - case NodeType::ANIMATION: - case NodeType::TRANSFORM: - case NodeType::PROXY: - case NodeType::GEOMETRY: - case NodeType::SEQUENCER: - case NodeType::EVAL_POSE: - case NodeType::BONE: { - ComponentNode *comp_node = (ComponentNode *)node; - return !comp_node->operations.is_empty(); - } - default: - return false; - } -} - -static bool deg_debug_graphviz_is_owner(const Node *node, const Node *other) -{ - switch (node->get_class()) { - case NodeClass::COMPONENT: { - ComponentNode *comp_node = (ComponentNode *)node; - if (comp_node->owner == other) { - return true; - } - break; - } - case NodeClass::OPERATION: { - OperationNode *op_node = (OperationNode *)node; - if (op_node->owner == other) { - return true; - } - else if (op_node->owner->owner == other) { - return true; - } - break; - } - default: - break; - } - return false; -} - -static void deg_debug_graphviz_node_relations(const DebugContext &ctx, const Node *node) +static void deg_debug_graphviz_node_relations(DotExportContext &ctx, const Node *node) { for (Relation *rel : node->inlinks) { float penwidth = 2.0f; - const Node *tail = rel->to; /* same as node */ - const Node *head = rel->from; - deg_debug_fprintf( - ctx, "// %s -> %s\n", head->identifier().c_str(), tail->identifier().c_str()); - deg_debug_fprintf(ctx, "\"node_%p\"", head); - deg_debug_fprintf(ctx, " -> "); - deg_debug_fprintf(ctx, "\"node_%p\"", tail); + const Node *head = rel->to; /* same as node */ + const Node *tail = rel->from; + dot::Node &dot_tail = *ctx.nodes_map.lookup(tail); + dot::Node &dot_head = *ctx.nodes_map.lookup(head); + + dot::DirectedEdge &edge = ctx.digraph.new_edge(dot_tail, dot_head); - deg_debug_fprintf(ctx, "["); /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */ - deg_debug_fprintf(ctx, "id=\"%s\"", rel->name); - // deg_debug_fprintf(ctx, "label=\"%s\"", rel->name); - deg_debug_fprintf(ctx, ",color="); - deg_debug_graphviz_relation_color(ctx, rel); - deg_debug_fprintf(ctx, ",style="); - deg_debug_graphviz_relation_style(ctx, rel); - deg_debug_fprintf(ctx, ",arrowhead="); - deg_debug_graphviz_relation_arrowhead(ctx, rel); - deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth); + edge.attributes.set("id", rel->name); + deg_debug_graphviz_relation_color(rel, edge); + deg_debug_graphviz_relation_style(rel, edge); + deg_debug_graphviz_relation_arrowhead(rel, edge); + edge.attributes.set("penwidth", penwidth); + /* NOTE: edge from node to own cluster is not possible and gives graphviz * warning, avoid this here by just linking directly to the invisible * placeholder node. */ - if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) { - deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail); + dot::Cluster *tail_cluster = ctx.clusters_map.lookup_default(tail, nullptr); + if (tail_cluster != nullptr && tail_cluster->contains(dot_head)) { + edge.attributes.set("ltail", tail_cluster->name()); } - if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) { - deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head); + dot::Cluster *head_cluster = ctx.clusters_map.lookup_default(head, nullptr); + if (head_cluster != nullptr && head_cluster->contains(dot_tail)) { + edge.attributes.set("lhead", head_cluster->name()); } - deg_debug_fprintf(ctx, "];" NL); - deg_debug_fprintf(ctx, NL); } } -static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgraph *graph) +static void deg_debug_graphviz_graph_nodes(DotExportContext &ctx, const Depsgraph *graph) { for (Node *node : graph->id_nodes) { - deg_debug_graphviz_node(ctx, node); + deg_debug_graphviz_node(ctx, node, nullptr); } TimeSourceNode *time_source = graph->find_time_source(); if (time_source != nullptr) { - deg_debug_graphviz_node(ctx, time_source); + deg_debug_graphviz_node(ctx, time_source, nullptr); } } -static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, const Depsgraph *graph) +static void deg_debug_graphviz_graph_relations(DotExportContext &ctx, const Depsgraph *graph) { for (IDNode *id_node : graph->id_nodes) { for (ComponentNode *comp_node : id_node->components.values()) { @@ -592,27 +521,23 @@ void DEG_debug_relations_graphviz(const Depsgraph *graph, FILE *f, const char *l const deg::Depsgraph *deg_graph = reinterpret_cast<const deg::Depsgraph *>(graph); - deg::DebugContext ctx; - ctx.file = f; - - deg::deg_debug_fprintf(ctx, "digraph depgraph {" NL); - deg::deg_debug_fprintf(ctx, "rankdir=LR;" NL); - deg::deg_debug_fprintf(ctx, "graph ["); - deg::deg_debug_fprintf(ctx, "compound=true"); - deg::deg_debug_fprintf(ctx, ",labelloc=\"t\""); - deg::deg_debug_fprintf(ctx, ",fontsize=%f", deg::deg_debug_graphviz_graph_label_size); - deg::deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg::deg_debug_graphviz_fontname); - deg::deg_debug_fprintf(ctx, ",label=\"%s\"", label); - deg::deg_debug_fprintf(ctx, ",splines=ortho"); - deg::deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato - deg::deg_debug_fprintf(ctx, "];" NL); + dot::DirectedGraph digraph; + deg::DotExportContext ctx{false, digraph}; + + digraph.set_rankdir(dot::Attr_rankdir::LeftToRight); + digraph.attributes.set("compound", "true"); + digraph.attributes.set("labelloc", "t"); + digraph.attributes.set("fontsize", deg::deg_debug_graphviz_graph_label_size); + digraph.attributes.set("fontname", deg::deg_debug_graphviz_fontname); + digraph.attributes.set("label", label); + digraph.attributes.set("splines", "ortho"); + digraph.attributes.set("overlap", "scalexy"); deg::deg_debug_graphviz_graph_nodes(ctx, deg_graph); deg::deg_debug_graphviz_graph_relations(ctx, deg_graph); deg::deg_debug_graphviz_legend(ctx); - deg::deg_debug_fprintf(ctx, "}" NL); + std::string dot_string = digraph.to_dot_string(); + fprintf(f, "%s", dot_string.c_str()); } - -#undef NL diff --git a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc index 515b53297b9..16bdc2d6115 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc @@ -83,7 +83,7 @@ string gnuplotify_id_code(const string &name) string gnuplotify_name(const string &name) { - string result = ""; + string result; const int length = name.length(); for (int i = 0; i < length; i++) { const char ch = name[i]; diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index c11d051e663..fb933cb38f3 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -43,12 +43,11 @@ #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_debug.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" -#include "builder/deg_builder_transitive.h" +#include "builder/pipeline_compositor.h" +#include "builder/pipeline_from_ids.h" +#include "builder/pipeline_render.h" +#include "builder/pipeline_view_layer.h" #include "intern/debug/deg_debug.h" @@ -209,65 +208,14 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle) /* ******************** */ /* Graph Building API's */ -static void graph_build_finalize_common(deg::Depsgraph *deg_graph, Main *bmain) -{ - /* Detect and solve cycles. */ - deg::deg_graph_detect_cycles(deg_graph); - /* Simplify the graph by removing redundant relations (to optimize - * traversal later). */ - /* TODO: it would be useful to have an option to disable this in cases where - * it is causing trouble. */ - if (G.debug_value == 799) { - deg::deg_graph_transitive_reduction(deg_graph); - } - /* Store pointers to commonly used valuated datablocks. */ - deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(°_graph->scene->id); - /* Flush visibility layer and re-schedule nodes for update. */ - deg::deg_graph_build_finalize(bmain, deg_graph); - DEG_graph_on_visible_update(bmain, reinterpret_cast<::Depsgraph *>(deg_graph), false); -#if 0 - if (!DEG_debug_consistency_check(deg_graph)) { - printf("Consistency validation failed, ABORTING!\n"); - abort(); - } -#endif - /* Relations are up to date. */ - deg_graph->need_update = false; -} - /* Build depsgraph for the given scene layer, and dump results in given graph container. */ void DEG_graph_build_from_view_layer(Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - 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, &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, &builder_cache); - relation_builder.begin_build(); - relation_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::ViewLayerBuilderPipeline builder(graph, bmain, scene, view_layer); + builder.build(); } void DEG_graph_build_for_render_pipeline(Depsgraph *graph, @@ -275,170 +223,17 @@ void DEG_graph_build_for_render_pipeline(Depsgraph *graph, Scene *scene, ViewLayer *view_layer) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - BLI_assert(deg_graph->scene == scene); - deg_graph->is_render_pipeline_depsgraph = true; - deg::DepsgraphBuilderCache builder_cache; - /* Generate all the nodes in the graph first */ - deg::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); - node_builder.begin_build(); - node_builder.build_scene_render(scene, view_layer); - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation - * order. */ - deg::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); - relation_builder.begin_build(); - relation_builder.build_scene_render(scene, view_layer); - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::RenderBuilderPipeline builder(graph, bmain, scene, view_layer); + builder.build(); } void DEG_graph_build_for_compositor_preview( Depsgraph *graph, Main *bmain, Scene *scene, struct ViewLayer *view_layer, bNodeTree *nodetree) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - BLI_assert(deg_graph->scene == scene); - deg_graph->is_render_pipeline_depsgraph = true; - deg::DepsgraphBuilderCache builder_cache; - /* Generate all the nodes in the graph first */ - deg::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); - node_builder.begin_build(); - node_builder.build_scene_render(scene, view_layer); - node_builder.build_nodetree(nodetree); - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation - * order. */ - deg::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); - relation_builder.begin_build(); - relation_builder.build_scene_render(scene, view_layer); - relation_builder.build_nodetree(nodetree); - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::CompositorBuilderPipeline builder(graph, bmain, scene, view_layer, nodetree); + builder.build(); } -/* Optimized builders for dependency graph built from a given set of IDs. - * - * General notes: - * - * - We pull in all bases if their objects are in the set of IDs. This allows to have proper - * visibility and other flags assigned to the objects. - * All other bases (the ones which points to object which is outside of the set of IDs) are - * completely ignored. - * - * - Proxy groups pointing to objects which are outside of the IDs set are also ignored. - * This way we avoid high-poly character body pulled into the dependency graph when it's coming - * from a library into an animation file and the dependency graph constructed for a proxy rig. */ - -namespace blender { -namespace deg { -namespace { - -class DepsgraphFromIDsFilter { - public: - DepsgraphFromIDsFilter(ID **ids, const int num_ids) - { - for (int i = 0; i < num_ids; ++i) { - ids_.add(ids[i]); - } - } - - bool contains(ID *id) - { - return ids_.contains(id); - } - - protected: - Set<ID *> ids_; -}; - -class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { - public: - DepsgraphFromIDsNodeBuilder( - Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) - : DepsgraphNodeBuilder(bmain, graph, cache), filter_(ids, num_ids) - { - } - - virtual bool need_pull_base_into_graph(Base *base) override - { - if (!filter_.contains(&base->object->id)) { - return false; - } - return DepsgraphNodeBuilder::need_pull_base_into_graph(base); - } - - virtual void build_object_proxy_group(Object *object, bool is_visible) override - { - if (object->proxy_group == nullptr) { - return; - } - if (!filter_.contains(&object->proxy_group->id)) { - return; - } - DepsgraphNodeBuilder::build_object_proxy_group(object, is_visible); - } - - protected: - DepsgraphFromIDsFilter filter_; -}; - -class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { - public: - DepsgraphFromIDsRelationBuilder( - Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) - : DepsgraphRelationBuilder(bmain, graph, cache), filter_(ids, num_ids) - { - } - - virtual bool need_pull_base_into_graph(Base *base) override - { - if (!filter_.contains(&base->object->id)) { - return false; - } - return DepsgraphRelationBuilder::need_pull_base_into_graph(base); - } - - virtual void build_object_proxy_group(Object *object) override - { - if (object->proxy_group == nullptr) { - return; - } - if (!filter_.contains(&object->proxy_group->id)) { - return; - } - DepsgraphRelationBuilder::build_object_proxy_group(object); - } - - protected: - DepsgraphFromIDsFilter filter_; -}; - -} // namespace -} // namespace deg -} // namespace blender - void DEG_graph_build_from_ids(Depsgraph *graph, Main *bmain, Scene *scene, @@ -446,40 +241,8 @@ void DEG_graph_build_from_ids(Depsgraph *graph, ID **ids, const int num_ids) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - 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::DepsgraphFromIDsNodeBuilder node_builder(bmain, deg_graph, &builder_cache, ids, num_ids); - node_builder.begin_build(); - node_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - for (int i = 0; i < num_ids; ++i) { - node_builder.build_id(ids[i]); - } - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation order. */ - deg::DepsgraphFromIDsRelationBuilder relation_builder( - bmain, deg_graph, &builder_cache, ids, num_ids); - relation_builder.begin_build(); - relation_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - for (int i = 0; i < num_ids; ++i) { - relation_builder.build_id(ids[i]); - } - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::FromIDsBuilderPipeline builder(graph, bmain, scene, view_layer, ids, num_ids); + builder.build(); } /* Tag graph relations for update. */ diff --git a/source/blender/depsgraph/intern/depsgraph_registry.cc b/source/blender/depsgraph/intern/depsgraph_registry.cc index 6bfd2e881cc..623702ee3ae 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.cc +++ b/source/blender/depsgraph/intern/depsgraph_registry.cc @@ -30,29 +30,35 @@ namespace blender { namespace deg { -static Map<Main *, VectorSet<Depsgraph *>> g_graph_registry; +using GraphRegistry = Map<Main *, VectorSet<Depsgraph *>>; +static GraphRegistry &get_graph_registry() +{ + static GraphRegistry graph_registry; + return graph_registry; +} void register_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - g_graph_registry.lookup_or_add_default(bmain).add_new(depsgraph); + get_graph_registry().lookup_or_add_default(bmain).add_new(depsgraph); } void unregister_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - VectorSet<Depsgraph *> &graphs = g_graph_registry.lookup(bmain); + GraphRegistry &graph_registry = get_graph_registry(); + VectorSet<Depsgraph *> &graphs = graph_registry.lookup(bmain); graphs.remove(depsgraph); // If this was the last depsgraph associated with the main, remove the main entry as well. if (graphs.is_empty()) { - g_graph_registry.remove(bmain); + graph_registry.remove(bmain); } } Span<Depsgraph *> get_all_registered_graphs(Main *bmain) { - VectorSet<Depsgraph *> *graphs = g_graph_registry.lookup_ptr(bmain); + VectorSet<Depsgraph *> *graphs = get_graph_registry().lookup_ptr(bmain); if (graphs != nullptr) { return *graphs; } diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 848275eb899..7c201de66f2 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -48,11 +48,8 @@ #include "BKE_idtype.h" #include "BKE_node.h" #include "BKE_scene.h" -#include "BKE_workspace.h" - -#define new new_ #include "BKE_screen.h" -#undef new +#include "BKE_workspace.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -432,7 +429,7 @@ string stringify_update_bitfield(int flag) if (flag == 0) { return "LEGACY_0"; } - string result = ""; + string result; int current_flag = flag; /* Special cases to avoid ALL flags form being split into * individual bits. */ @@ -786,6 +783,7 @@ void DEG_graph_id_type_tag(Depsgraph *depsgraph, short id_type) DEG_graph_id_type_tag(depsgraph, ID_LA); DEG_graph_id_type_tag(depsgraph, ID_WO); DEG_graph_id_type_tag(depsgraph, ID_SCE); + DEG_graph_id_type_tag(depsgraph, ID_SIM); } const int id_type_index = BKE_idtype_idcode_to_index(id_type); deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(depsgraph); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 38350d50da6..89df41944e5 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -120,6 +120,7 @@ union NestedIDHackTempStorage { Scene scene; Tex tex; World world; + Simulation simulation; }; /* Set nested owned ID pointers to nullptr. */ @@ -137,6 +138,7 @@ void nested_id_hack_discard_pointers(ID *id_cow) SPECIAL_CASE(ID_MA, Material, nodetree) SPECIAL_CASE(ID_TE, Tex, nodetree) SPECIAL_CASE(ID_WO, World, nodetree) + SPECIAL_CASE(ID_SIM, Simulation, nodetree) SPECIAL_CASE(ID_CU, Curve, key) SPECIAL_CASE(ID_LT, Lattice, key) @@ -185,6 +187,7 @@ const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage SPECIAL_CASE(ID_MA, Material, nodetree, material) SPECIAL_CASE(ID_TE, Tex, nodetree, tex) SPECIAL_CASE(ID_WO, World, nodetree, world) + SPECIAL_CASE(ID_SIM, Simulation, nodetree, simulation) SPECIAL_CASE(ID_CU, Curve, key, curve) SPECIAL_CASE(ID_LT, Lattice, key, lattice) @@ -224,6 +227,7 @@ void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id) SPECIAL_CASE(ID_SCE, Scene, nodetree) SPECIAL_CASE(ID_TE, Tex, nodetree) SPECIAL_CASE(ID_WO, World, nodetree) + SPECIAL_CASE(ID_SIM, Simulation, nodetree) SPECIAL_CASE(ID_CU, Curve, key) SPECIAL_CASE(ID_LT, Lattice, key) @@ -261,6 +265,7 @@ void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow) SPECIAL_CASE(ID_SCE, Scene, nodetree, bNodeTree) SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree) SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree) + SPECIAL_CASE(ID_SIM, Simulation, nodetree, bNodeTree) SPECIAL_CASE(ID_CU, Curve, key, Key) SPECIAL_CASE(ID_LT, Lattice, key, Key) @@ -283,6 +288,14 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) { const ID *id_for_copy = id; + if (G.debug & G_DEBUG_DEPSGRAPH_UUID) { + const ID_Type id_type = GS(id_for_copy->name); + if (id_type == ID_OB) { + const Object *object = reinterpret_cast<const Object *>(id_for_copy); + BKE_pose_check_uuids_unique_and_report(object->pose); + } + } + #ifdef NESTED_ID_NASTY_WORKAROUND NestedIDHackTempStorage id_hack_storage; id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id); @@ -306,6 +319,10 @@ bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene) { const ID *id_for_copy = &scene->id; + if (G.debug & G_DEBUG_DEPSGRAPH_UUID) { + BKE_sequencer_check_uuids_unique_and_report(scene); + } + #ifdef NESTED_ID_NASTY_WORKAROUND NestedIDHackTempStorage id_hack_storage; id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id); @@ -476,25 +493,6 @@ void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph, * Still not an excuse to have those. */ } -void update_sequence_orig_pointers(const ListBase *sequences_orig, ListBase *sequences_cow) -{ - Sequence *sequence_orig = reinterpret_cast<Sequence *>(sequences_orig->first); - Sequence *sequence_cow = reinterpret_cast<Sequence *>(sequences_cow->first); - while (sequence_orig != nullptr) { - update_sequence_orig_pointers(&sequence_orig->seqbase, &sequence_cow->seqbase); - sequence_cow->orig_sequence = sequence_orig; - sequence_cow = sequence_cow->next; - sequence_orig = sequence_orig->next; - } -} - -void update_scene_orig_pointers(const Scene *scene_orig, Scene *scene_cow) -{ - if (scene_orig->ed != nullptr) { - update_sequence_orig_pointers(&scene_orig->ed->seqbase, &scene_cow->ed->seqbase); - } -} - /* Check whether given ID is expanded or still a shallow copy. */ inline bool check_datablock_expanded(const ID *id_cow) { @@ -711,13 +709,6 @@ void update_modifiers_orig_pointers(const Object *object_orig, Object *object_co &object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data); } -void update_simulation_states_orig_pointers(const Simulation *simulation_orig, - Simulation *simulation_cow) -{ - update_list_orig_pointers( - &simulation_orig->states, &simulation_cow->states, &SimulationState::orig_state); -} - void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow) { NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first); @@ -814,13 +805,6 @@ void update_id_after_copy(const Depsgraph *depsgraph, scene_cow->toolsettings = scene_orig->toolsettings; scene_cow->eevee.light_cache_data = scene_orig->eevee.light_cache_data; scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow)); - update_scene_orig_pointers(scene_orig, scene_cow); - break; - } - case ID_SIM: { - Simulation *simulation_cow = (Simulation *)id_cow; - const Simulation *simulation_orig = (const Simulation *)id_orig; - update_simulation_states_orig_pointers(simulation_orig, simulation_cow); break; } default: diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc index f2d9a87ca9d..934403674a9 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc @@ -41,7 +41,7 @@ bool operator==(const ModifierDataBackupID &a, const ModifierDataBackupID &b) return a.modifier_data == b.modifier_data && a.type == b.type; } -uint32_t ModifierDataBackupID::hash() const +uint64_t ModifierDataBackupID::hash() const { uintptr_t ptr = (uintptr_t)modifier_data; return (ptr >> 4) ^ (uintptr_t)type; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h index dc16bdcc1b8..a5bdf2359ee 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -49,7 +49,7 @@ class ModifierDataBackupID { friend bool operator==(const ModifierDataBackupID &a, const ModifierDataBackupID &b); - uint32_t hash() const; + uint64_t hash() const; ModifierData *modifier_data; ModifierType type; diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index e0957a10cb1..88334e41192 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -85,11 +85,11 @@ void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) { if (object->pose != nullptr) { LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is nullptr in Edit mode. */ - if (pchan->orig_pchan != nullptr) { - pose_channel_runtime_data.add(pchan->orig_pchan, pchan->runtime); - BKE_pose_channel_runtime_reset(&pchan->runtime); - } + const SessionUUID &session_uuid = pchan->runtime.session_uuid; + BLI_assert(BLI_session_uuid_is_generated(&session_uuid)); + + pose_channel_runtime_data.add(session_uuid, pchan->runtime); + BKE_pose_channel_runtime_reset(&pchan->runtime); } } } @@ -171,13 +171,10 @@ void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) { if (object->pose != nullptr) { LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is nullptr in Edit mode. */ - if (pchan->orig_pchan != nullptr) { - optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try( - pchan->orig_pchan); - if (runtime.has_value()) { - pchan->runtime = *runtime; - } + const SessionUUID &session_uuid = pchan->runtime.session_uuid; + optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(session_uuid); + if (runtime.has_value()) { + pchan->runtime = *runtime; } } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h index 04d7fb1bc22..a10f15634ce 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -24,6 +24,9 @@ #pragma once #include "DNA_object_types.h" +#include "DNA_session_uuid_types.h" + +#include "BLI_session_uuid.h" #include "intern/eval/deg_eval_runtime_backup_modifier.h" #include "intern/eval/deg_eval_runtime_backup_pose.h" @@ -54,7 +57,7 @@ class ObjectRuntimeBackup { short base_flag; unsigned short base_local_view_bits; ModifierRuntimeDataBackup modifier_runtime_data; - Map<bPoseChannel *, bPoseChannel_Runtime> pose_channel_runtime_data; + Map<SessionUUID, bPoseChannel_Runtime> pose_channel_runtime_data; }; } // namespace deg diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc index 2780938fe05..ba7d20c0ba8 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc @@ -26,6 +26,8 @@ #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "BLI_assert.h" + #include "BKE_sequencer.h" #include "BKE_sound.h" @@ -43,7 +45,9 @@ void SequencerBackup::init_from_scene(Scene *scene) SequenceBackup sequence_backup(depsgraph); sequence_backup.init_from_sequence(sequence); if (!sequence_backup.isEmpty()) { - sequences_backup.add(sequence->orig_sequence, sequence_backup); + const SessionUUID &session_uuid = sequence->runtime.session_uuid; + BLI_assert(BLI_session_uuid_is_generated(&session_uuid)); + sequences_backup.add(session_uuid, sequence_backup); } } SEQ_END; @@ -53,7 +57,9 @@ void SequencerBackup::restore_to_scene(Scene *scene) { Sequence *sequence; SEQ_BEGIN (scene->ed, sequence) { - SequenceBackup *sequence_backup = sequences_backup.lookup_ptr(sequence->orig_sequence); + const SessionUUID &session_uuid = sequence->runtime.session_uuid; + BLI_assert(BLI_session_uuid_is_generated(&session_uuid)); + SequenceBackup *sequence_backup = sequences_backup.lookup_ptr(session_uuid); if (sequence_backup != nullptr) { sequence_backup->restore_to_sequence(sequence); } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h index 9fe38ec270c..4419238da32 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h @@ -23,6 +23,10 @@ #pragma once +#include "DNA_session_uuid_types.h" + +#include "BLI_session_uuid.h" + #include "intern/depsgraph_type.h" #include "intern/eval/deg_eval_runtime_backup_sequence.h" @@ -43,7 +47,7 @@ class SequencerBackup { const Depsgraph *depsgraph; - Map<Sequence *, SequenceBackup> sequences_backup; + Map<SessionUUID, SequenceBackup> sequences_backup; }; } // namespace deg diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index 490598af8f9..cd82b7be050 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -72,7 +72,7 @@ bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) cons return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag); } -uint32_t ComponentNode::OperationIDKey::hash() const +uint64_t ComponentNode::OperationIDKey::hash() const { const int opcode_as_int = static_cast<int>(opcode); return BLI_ghashutil_combine_hash( @@ -98,9 +98,7 @@ void ComponentNode::init(const ID * /*id*/, const char * /*subdata*/) ComponentNode::~ComponentNode() { clear_operations(); - if (operations_map != nullptr) { - delete operations_map; - } + delete operations_map; } string ComponentNode::identifier() const diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index 3757a1dea5b..06582c88d8b 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -54,7 +54,7 @@ struct ComponentNode : public Node { string identifier() const; bool operator==(const OperationIDKey &other) const; - uint32_t hash() const; + uint64_t hash() const; }; /* Typedef for container of operations */ diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index d0c23f326ce..8d19949adc8 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -67,7 +67,7 @@ bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const return type == other.type && STREQ(name, other.name); } -uint32_t IDNode::ComponentIDKey::hash() const +uint64_t IDNode::ComponentIDKey::hash() const { const int type_as_int = static_cast<int>(type); return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index 9bd6130bbdc..04a9006ac10 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -51,7 +51,7 @@ const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state); struct IDNode : public Node { struct ComponentIDKey { ComponentIDKey(NodeType type, const char *name = ""); - uint32_t hash() const; + uint64_t hash() const; bool operator==(const ComponentIDKey &other) const; NodeType type; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 680e7757ebb..a32a43e2905 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -61,6 +61,8 @@ const char *operationCodeAsString(OperationCode opcode) /* Scene related. */ case OperationCode::SCENE_EVAL: return "SCENE_EVAL"; + case OperationCode::AUDIO_ENTRY: + return "AUDIO_ENTRY"; case OperationCode::AUDIO_VOLUME: return "AUDIO_VOLUME"; /* Object related. */ diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index 87168fc3659..52b6c9a753b 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -61,6 +61,7 @@ enum class OperationCode { /* Scene related. ------------------------------------------------------- */ SCENE_EVAL, + AUDIO_ENTRY, AUDIO_VOLUME, /* Object related. ------------------------------------------------------ */ |