Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/depsgraph')
-rw-r--r--source/blender/depsgraph/CMakeLists.txt23
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h5
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h5
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_debug.h5
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_physics.h5
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h5
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cache.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cache.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc31
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc205
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.cc258
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_drivers.h76
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc33
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.h13
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna_test.cc60
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline.cc132
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline.h77
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_compositor.cc49
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_compositor.h47
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_from_ids.cc154
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_from_ids.h62
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_render.cc49
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_render.h41
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_view_layer.cc48
-rw-r--r--source/blender/depsgraph/intern/builder/pipeline_view_layer.h41
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc357
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc261
-rw-r--r--source/blender/depsgraph/intern/depsgraph_registry.cc16
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc8
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc50
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h2
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc21
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h5
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc10
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h6
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc6
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.h2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h1
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(&deg_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 &deg_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(&deg_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. ------------------------------------------------------ */