[Bf-blender-cvs] [f4d5397] depsgraph_refactor: Depsgraph: Add simple relation cycle detector
Sergey Sharybin
noreply at git.blender.org
Wed Feb 4 14:50:43 CET 2015
Commit: f4d5397102cf6b8052e3fc705b0fa662c418edd7
Author: Sergey Sharybin
Date: Wed Feb 4 18:49:09 2015 +0500
Branches: depsgraph_refactor
https://developer.blender.org/rBf4d5397102cf6b8052e3fc705b0fa662c418edd7
Depsgraph: Add simple relation cycle detector
For now it only reports if there are cycles in the graph and prints
nodes identifiers and relation names in the terminal.
TODO:
- Add cycles solver
- Improve reported operations names
===================================================================
M source/blender/depsgraph/intern/depsgraph_build.cpp
===================================================================
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cpp b/source/blender/depsgraph/intern/depsgraph_build.cpp
index 1f710a2..3542955 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_build.cpp
@@ -535,6 +535,98 @@ void DepsgraphIDUsersBuilder::add_relation(const ID *from_id, const ID *to_id,
}
}
+/* *************** */
+/* Cycle detection */
+
+static void deg_graph_detect_cycles(Depsgraph *graph)
+{
+ struct StackEntry {
+ OperationDepsNode *node;
+ StackEntry *from;
+ DepsRelation *via_relation;
+ };
+ /* Not is not visited at all during traversal. */
+ const int NODE_NOT_VISITED = 0;
+ /* Node has been visited during traversal and not in current stack. */
+ const int NODE_VISITED = 1;
+ /* Node has been visited during traversal and is in current stack. */
+ const int NODE_IN_STACK = 2;
+
+ std::stack<StackEntry> traversal_stack;
+ for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
+ it_op != graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ bool has_inlinks = false;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
+ it_rel != node->inlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ has_inlinks = true;
+ }
+ }
+ if (has_inlinks == false) {
+ StackEntry entry;
+ entry.node = node;
+ entry.from = NULL;
+ entry.via_relation = NULL;
+ traversal_stack.push(entry);
+ node->done = NODE_IN_STACK;
+ }
+ else {
+ node->done = NODE_NOT_VISITED;
+ }
+ }
+
+ while (!traversal_stack.empty()) {
+ StackEntry &entry = traversal_stack.top();
+ OperationDepsNode *node = entry.node;;
+ bool all_child_traversed = true;
+ for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
+ it_rel != node->outlinks.end();
+ ++it_rel)
+ {
+ DepsRelation *rel = *it_rel;
+ if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ if (to->done == NODE_IN_STACK) {
+ printf("Dependency cycle detected:\n");
+ printf(" '%s' depends on '%s' through '%s'\n",
+ to->identifier().c_str(),
+ node->identifier().c_str(),
+ rel->name.c_str());
+ StackEntry *current = &entry;
+ while (current->node != to) {
+ BLI_assert(current != NULL);
+ printf(" '%s' depends on '%s' through '%s'\n",
+ current->node->identifier().c_str(),
+ current->from->node->identifier().c_str(),
+ current->via_relation->name.c_str());
+ current = current->from;
+ }
+ }
+ else if (to->done == NODE_NOT_VISITED) {
+ StackEntry new_entry;
+ new_entry.node = to;
+ new_entry.from = &entry;
+ new_entry.via_relation = rel;
+ traversal_stack.push(new_entry);
+ to->done = NODE_IN_STACK;
+ all_child_traversed = false;
+ break;
+ }
+ }
+ }
+ if (all_child_traversed) {
+ node->done = NODE_VISITED;
+ traversal_stack.pop();
+ }
+ }
+}
+
/* ************************************************* */
/* Graph Building API's */
@@ -574,8 +666,10 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
*/
//relation_builder.add_relation(RootKey(), IDKey(scene), DEPSREL_TYPE_ROOT_TO_ACTIVE, "Root to Active Scene");
relation_builder.build_scene(scene);
-
-
+
+ /* Detect and solve cycles. */
+ deg_graph_detect_cycles(graph);
+
/* 4) Simplify the graph by removing redundant relations (to optimise 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) {
More information about the Bf-blender-cvs
mailing list