Depsgraph: Initial implementation of more granular tagging

This commit makes it so that only ID components which correspond to the tag
flag are tagged for update (previously the whole ID would have been updated
in the most of cases).

This allows us to have more granular tag flags and prevent tagging of things
we don't want to be tagged.
This commit is contained in:
Sergey Sharybin 2017-07-18 15:42:53 +02:00
parent 50f5f0957c
commit 414cc821d8
4 changed files with 152 additions and 84 deletions

View File

@ -136,11 +136,6 @@ void DEG_graph_on_visible_update(struct Main *bmain, struct Scene *scene);
/* Update all dependency graphs when visible scenes/layers changes. */
void DEG_on_visible_update(struct Main *bmain, const bool do_time);
/* Tag node(s) associated with changed data for later updates */
void DEG_graph_id_tag_update(struct Main *bmain,
Depsgraph *graph,
struct ID *id);
/* Tag given ID for an update in all the dependency graphs. */
enum {
/* Object transformation changed, corresponds to OB_RECALC_OB. */

View File

@ -118,11 +118,18 @@ void deg_editors_scene_update(struct Main *bmain, struct Scene *scene, bool upda
void lib_id_recalc_tag(struct Main *bmain, struct ID *id);
void lib_id_recalc_data_tag(struct Main *bmain, struct ID *id);
#define DEG_DEBUG_PRINTF(...) \
do { \
if (G.debug & G_DEBUG_DEPSGRAPH) { \
fprintf(stderr, __VA_ARGS__); \
} \
#define DEG_DEBUG_PRINTF(...) \
do { \
if (G.debug & G_DEBUG_DEPSGRAPH) { \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
} \
} while (0)
#define DEG_ERROR_PRINTF(...) \
do { \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
} while (0)
} // namespace DEG

View File

@ -90,67 +90,168 @@ namespace {
void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
{
/* This bit of code ensures legacy object->recalc flags are still filled in
* the same way as it was expected with the old dependency graph.
*
* This is because some areas like motion paths and likely some other
* physics baking process are doing manual scene update on all the frames,
* trying to minimize number of updates.
*
* But this flag will also let us to re-construct entry nodes for update
* after relations update and after layer visibility changes.
*/
if (flag) {
/* This bit of code ensures legacy object->recalc flags
* are still filled in the same way as it was expected
* with the old dependency graph.
*
* This is because some areas like motion paths and likely
* some other physics baking process are doing manual scene
* update on all the frames, trying to minimize number of
* updates.
*
* But this flag will also let us to re-construct entry
* nodes for update after relations update and after layer
* visibility changes.
*/
short idtype = GS(id->name);
if (idtype == ID_OB) {
Object *object = (Object *)id;
object->recalc |= (flag & OB_RECALC_ALL);
}
if (flag & OB_RECALC_OB)
if (flag & OB_RECALC_OB) {
lib_id_recalc_tag(bmain, id);
if (flag & (OB_RECALC_DATA | PSYS_RECALC))
}
if (flag & (OB_RECALC_DATA | PSYS_RECALC)) {
lib_id_recalc_data_tag(bmain, id);
}
}
else {
lib_id_recalc_tag(bmain, id);
}
}
#ifdef WITH_COPY_ON_WRITE
void id_tag_copy_on_write_update(Main *bmain, Depsgraph *graph, ID *id)
/* Special tagging */
void id_tag_update_special_zero_flag(Depsgraph *graph, IDDepsNode *id_node)
{
/* NOTE: Full ID node update for now, need to minimize that i9n the future. */
id_node->tag_update(graph);
}
/* Tag corresponding to OB_RECALC_OB. */
void id_tag_update_object_transform(Depsgraph *graph, IDDepsNode *id_node)
{
ComponentDepsNode *transform_comp =
id_node->find_component(DEG_NODE_TYPE_TRANSFORM);
if (transform_comp == NULL) {
DEG_ERROR_PRINTF("ERROR: Unable to find transform component for %s\n",
id_node->id_orig->name);
BLI_assert(!"This is not supposed to happen!");
return;
}
transform_comp->tag_update(graph);
}
/* Tag corresponding to OB_RECALC_DATA. */
void id_tag_update_object_data(Depsgraph *graph, IDDepsNode *id_node)
{
const short idtype = GS(id_node->id_orig->name);
ComponentDepsNode *data_comp = NULL;
switch (idtype) {
case ID_OB:
{
const Object *object = (Object *)id_node->id_orig;
switch (object->type) {
case OB_MESH:
case OB_CURVE:
case OB_SURF:
case OB_FONT:
data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
break;
case OB_ARMATURE:
data_comp = id_node->find_component(DEG_NODE_TYPE_EVAL_POSE);
break;
/* TODO(sergey): More cases here? */
}
break;
}
case ID_ME:
data_comp = id_node->find_component(DEG_NODE_TYPE_GEOMETRY);
break;
}
if (data_comp == NULL) {
DEG_ERROR_PRINTF("ERROR: Unable to find data component for %s\n",
id_node->id_orig->name);
BLI_assert(!"This is not supposed to happen!");
return;
}
data_comp->tag_update(graph);
}
/* Tag corresponding to OB_RECALC_TIME. */
void id_tag_update_object_time(Depsgraph *graph, IDDepsNode *id_node)
{
ComponentDepsNode *animation_comp =
id_node->find_component(DEG_NODE_TYPE_ANIMATION);
if (animation_comp == NULL) {
/* It's not necessarily we've got animation component in cases when
* we are tagging for time updates.
*/
return;
}
animation_comp->tag_update(graph);
/* TODO(sergey): More components to tag here? */
}
#ifdef WITH_COPY_ON_WRITE
/* Tag corresponding to DEG_TAG_COPY_ON_WRITE. */
void id_tag_update_copy_on_write(Depsgraph *graph, IDDepsNode *id_node)
{
lib_id_recalc_tag(bmain, id);
Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
IDDepsNode *id_node = deg_graph->find_id_node(id);
ComponentDepsNode *cow_comp =
id_node->find_component(DEG::DEG_NODE_TYPE_COPY_ON_WRITE);
id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
OperationDepsNode *cow_node = cow_comp->get_entry_operation();
cow_node->tag_update(deg_graph);
cow_node->tag_update(graph);
cow_node->flag |= DEPSOP_FLAG_SKIP_FLUSH;
}
#endif
void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
{
Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
IDDepsNode *id_node = deg_graph->find_id_node(id);
/* Make sure legacy flags are all nicely update. */
lib_id_recalc_tag_flag(bmain, id, flag);
if (id_node == NULL) {
/* Shouldn't happen, but better be sure here. */
return;
}
/* Tag components based on flags. */
if (flag == 0) {
id_tag_update_special_zero_flag(graph, id_node);
return;
}
if (flag & OB_RECALC_OB) {
id_tag_update_object_transform(graph, id_node);
}
if (flag & OB_RECALC_DATA) {
id_tag_update_object_data(graph, id_node);
}
if (flag & OB_RECALC_TIME) {
id_tag_update_object_time(graph, id_node);
}
#ifdef WITH_COPY_ON_WRITE
if (flag & DEG_TAG_COPY_ON_WRITE) {
id_tag_update_copy_on_write(graph, id_node);
}
#endif
// node->tag_update(deg_graph);
}
void deg_id_tag_update(Main *bmain, ID *id, int flag)
{
lib_id_recalc_tag_flag(bmain, id, flag);
for (Scene *scene = (Scene *)bmain->scene.first;
scene != NULL;
scene = (Scene *)scene->id.next)
{
if (scene->depsgraph_legacy != NULL) {
Depsgraph *graph = (Depsgraph *)scene->depsgraph_legacy;
deg_graph_id_tag_update(bmain, graph, id, flag);
}
}
}
} /* namespace */
} // namespace DEG
/* Tag all nodes in ID-block for update.
* This is a crude measure, but is most convenient for old code.
*/
void DEG_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id)
{
DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
DEG::IDDepsNode *node = deg_graph->find_id_node(id);
DEG::lib_id_recalc_tag(bmain, id);
if (node != NULL) {
node->tag_update(deg_graph);
}
}
/* Tag given ID for an update in all the dependency graphs. */
void DEG_id_tag_update(ID *id, int flag)
{
@ -164,42 +265,7 @@ void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
return;
}
DEG_DEBUG_PRINTF("%s: id=%s flag=%d\n", __func__, id->name, flag);
DEG::lib_id_recalc_tag_flag(bmain, id, flag);
for (Scene *scene = (Scene *)bmain->scene.first;
scene != NULL;
scene = (Scene *)scene->id.next)
{
if (scene->depsgraph_legacy) {
Depsgraph *graph = scene->depsgraph_legacy;
if (flag == 0) {
/* TODO(sergey): Currently blender is still tagging IDs
* for recalc just using flag=0. This isn't totally correct
* but we'd better deal with such cases and don't fail.
*/
DEG_graph_id_tag_update(bmain, graph, id);
continue;
}
if (flag & OB_RECALC_DATA && GS(id->name) == ID_OB) {
Object *object = (Object *)id;
if (object->data != NULL) {
DEG_graph_id_tag_update(bmain,
graph,
(ID *)object->data);
}
}
if (flag & (OB_RECALC_OB | OB_RECALC_DATA)) {
DEG_graph_id_tag_update(bmain, graph, id);
}
else if (flag & OB_RECALC_TIME) {
DEG_graph_id_tag_update(bmain, graph, id);
}
else if (flag & DEG_TAG_COPY_ON_WRITE) {
#ifdef WITH_COPY_ON_WRITE
id_tag_copy_on_write_update(bmain, graph, id);
#endif
}
}
}
DEG::deg_id_tag_update(bmain, id, flag);
}
/* Tag given ID type for update. */

View File

@ -128,8 +128,8 @@ IDDepsNode::ComponentIDKey::ComponentIDKey(eDepsNode_Type type,
bool IDDepsNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
{
return type == other.type &&
STREQ(name, other.name);
return type == other.type &&
STREQ(name, other.name);
}
static unsigned int id_deps_node_hash_key(const void *key_v)