Depsgraph: Add query methods to identify all the ID's that a given datablock depends on

This commit adds a new method, DEG_foreach_ancestor_ID()
to accompany the existing DEG_foreach_descendent_ID().

It can be used to help print/collect all the ID's that
a given ID block depends on (i.e. all the datablocks that
need to be evaluated before the datablock of interest can
be evaluated)
This commit is contained in:
Joshua Leung 2018-08-21 16:20:54 +12:00
parent 351d13194d
commit 2a5f319465
2 changed files with 77 additions and 0 deletions

View File

@ -197,6 +197,9 @@ typedef void (*DEGForeachIDCallback)(ID *id, void *user_data);
/* NOTE: Modifies runtime flags in depsgraph nodes, so can not be used in
* parallel. Keep an eye on that!
*/
void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph,
const ID *id,
DEGForeachIDCallback callback, void *user_data);
void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
const ID *id,
DEGForeachIDCallback callback, void *user_data);

View File

@ -136,6 +136,71 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph,
}
}
static void deg_foreach_ancestor_ID(const Depsgraph *graph,
const ID *id,
DEGForeachIDCallback callback,
void *user_data)
{
/* Start with getting ID node from the graph. */
IDDepsNode *target_id_node = graph->find_id_node(id);
if (target_id_node == NULL) {
/* TODO(sergey): Shall we inform or assert here about attempt to start
* iterating over non-existing ID?
*/
return;
}
/* Make sure all runtime flags are ready and clear. */
deg_foreach_clear_flags(graph);
/* Start with scheduling all operations from ID node. */
TraversalQueue queue;
GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, target_id_node->components)
{
foreach (OperationDepsNode *op_node, comp_node->operations) {
queue.push_back(op_node);
op_node->scheduled = true;
}
}
GHASH_FOREACH_END();
target_id_node->done = true;
/* Process the queue. */
while (!queue.empty()) {
/* get next operation node to process. */
OperationDepsNode *op_node = queue.front();
queue.pop_front();
for (;;) {
/* Check whether we need to inform callee about corresponding ID node. */
ComponentDepsNode *comp_node = op_node->owner;
IDDepsNode *id_node = comp_node->owner;
if (!id_node->done) {
/* TODO(sergey): Is it orig or CoW? */
callback(id_node->id_orig, user_data);
id_node->done = true;
}
/* Schedule incoming operation nodes. */
if (op_node->inlinks.size() == 1) {
OperationDepsNode *from_node = (OperationDepsNode *)op_node->inlinks[0]->from;
if (from_node->scheduled == false) {
from_node->scheduled = true;
op_node = from_node;
}
else {
break;
}
}
else {
foreach (DepsRelation *rel, op_node->inlinks) {
OperationDepsNode *from_node = (OperationDepsNode *)rel->from;
if (from_node->scheduled == false) {
queue.push_front(from_node);
from_node->scheduled = true;
}
}
break;
}
}
}
}
static void deg_foreach_id(const Depsgraph *depsgraph,
DEGForeachIDCallback callback, void *user_data)
{
@ -155,6 +220,15 @@ void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
callback, user_data);
}
void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph,
const ID *id,
DEGForeachIDCallback callback, void *user_data)
{
DEG::deg_foreach_ancestor_ID((const DEG::Depsgraph *)depsgraph,
id,
callback, user_data);
}
void DEG_foreach_ID(const Depsgraph *depsgraph,
DEGForeachIDCallback callback, void *user_data)
{