Depsgraph: Replace LIB_TAG_DOIT with hash lookup

This allows us to:

- Not mock around with tags stored in a global space,
    and not to iterate over all datablocks in the database
    to clear the tags.

- Properly deal with datablocks which might not be in main database.

    While it sounds crazy, it might be handy when dealing with preview,
    or some partial scene updates, such as motion paths.

- Avoids majority of places where depsgraph construction needed bmain.

    This is something what could help in blender2.8 branch.

From tests with production file here did not see any measurable slowdown.

Hopefully, there is no functional changes :)
This commit is contained in:
Sergey Sharybin 2018-02-22 11:03:39 +01:00
parent 76953a6ebd
commit 93072e44d1
6 changed files with 85 additions and 169 deletions

View File

@ -279,32 +279,13 @@ OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
/* **** Build functions for entity nodes **** */
void DepsgraphNodeBuilder::begin_build() {
/* LIB_TAG_DOIT is used to indicate whether node for given ID was already
* created or not. This flag is being set in add_id_node(), so functions
* shouldn't bother with setting it, they only might query this flag when
* needed.
*/
BKE_main_id_tag_all(bmain_, LIB_TAG_DOIT, false);
/* XXX nested node trees are not included in tag-clearing above,
* so we need to do this manually.
*/
FOREACH_NODETREE(bmain_, nodetree, id)
{
if (id != (ID *)nodetree) {
nodetree->id.tag &= ~LIB_TAG_DOIT;
}
}
FOREACH_NODETREE_END;
}
void DepsgraphNodeBuilder::build_group(Base *base, Group *group)
{
ID *group_id = &group->id;
if (group_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(group)) {
return;
}
group_id->tag |= LIB_TAG_DOIT;
LISTBASE_FOREACH (GroupObject *, go, &group->gobject) {
build_object(base, go->ob);
}
@ -312,7 +293,7 @@ void DepsgraphNodeBuilder::build_group(Base *base, Group *group)
void DepsgraphNodeBuilder::build_object(Base *base, Object *object)
{
const bool has_object = (object->id.tag & LIB_TAG_DOIT);
const bool has_object = built_map_.checkIsBuiltAndTag(object);
IDDepsNode *id_node = (has_object)
? graph_->find_id_node(&object->id)
: add_id_node(&object->id);
@ -334,7 +315,6 @@ void DepsgraphNodeBuilder::build_object(Base *base, Object *object)
if (has_object) {
return;
}
object->id.tag |= LIB_TAG_DOIT;
object->customdata_mask = 0;
/* Transform. */
build_object_transform(object);
@ -424,7 +404,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
default:
{
ID *obdata = (ID *)object->data;
if ((obdata->tag & LIB_TAG_DOIT) == 0) {
if (built_map_.checkIsBuilt(obdata) == 0) {
build_animdata(obdata);
}
break;
@ -565,22 +545,18 @@ OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu)
/* Recursively build graph for world */
void DepsgraphNodeBuilder::build_world(World *world)
{
ID *world_id = &world->id;
if (world_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(world)) {
return;
}
ID *world_id = &world->id;
build_animdata(world_id);
/* world itself */
add_operation_node(world_id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
/* textures */
build_texture_stack(world->mtex);
/* world's nodetree */
if (world->nodetree) {
build_nodetree(world->nodetree);
@ -785,7 +761,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
// add geometry collider relations
}
if (obdata->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(obdata)) {
return;
}
@ -905,20 +881,16 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
void DepsgraphNodeBuilder::build_camera(Object *object)
{
/* TODO: Link scene-camera links in somehow... */
Camera *cam = (Camera *)object->data;
ID *camera_id = &cam->id;
if (camera_id->tag & LIB_TAG_DOIT) {
Camera *camera = (Camera *)object->data;
if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
build_animdata(&cam->id);
add_operation_node(camera_id,
build_animdata(&camera->id);
add_operation_node(&camera->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
if (cam->dof_ob != NULL) {
if (camera->dof_ob != NULL) {
/* TODO(sergey): For now parametrs are on object level. */
add_operation_node(&object->id, DEG_NODE_TYPE_PARAMETERS, NULL,
DEG_OPCODE_PLACEHOLDER, "Camera DOF");
@ -928,47 +900,40 @@ void DepsgraphNodeBuilder::build_camera(Object *object)
/* Lamps */
void DepsgraphNodeBuilder::build_lamp(Object *object)
{
Lamp *la = (Lamp *)object->data;
ID *lamp_id = &la->id;
if (lamp_id->tag & LIB_TAG_DOIT) {
Lamp *lamp = (Lamp *)object->data;
if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
build_animdata(&la->id);
build_animdata(&lamp->id);
/* TODO(sergey): Is it really how we're supposed to work with drivers? */
add_operation_node(lamp_id,
add_operation_node(&lamp->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
/* lamp's nodetree */
if (la->nodetree) {
build_nodetree(la->nodetree);
}
build_nodetree(lamp->nodetree);
/* textures */
build_texture_stack(la->mtex);
build_texture_stack(lamp->mtex);
}
void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
{
if (!ntree)
if (ntree == NULL) {
return;
}
if (built_map_.checkIsBuiltAndTag(ntree)) {
return;
}
/* nodetree itself */
ID *ntree_id = &ntree->id;
OperationDepsNode *op_node;
build_animdata(ntree_id);
build_animdata(&ntree->id);
/* Parameters for drivers. */
op_node = add_operation_node(ntree_id,
op_node = add_operation_node(&ntree->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PARAMETERS_EVAL);
op_node->set_as_exit();
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
@ -998,9 +963,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
}
else if (bnode->type == NODE_GROUP) {
bNodeTree *group_ntree = (bNodeTree *)id;
if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
build_nodetree(group_ntree);
}
build_nodetree(group_ntree);
}
else {
BLI_assert(!"Unknown ID type used for node");
@ -1011,24 +974,20 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
}
/* Recursively build graph for material */
void DepsgraphNodeBuilder::build_material(Material *ma)
void DepsgraphNodeBuilder::build_material(Material *material)
{
ID *ma_id = &ma->id;
if (ma_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(material)) {
return;
}
add_operation_node(ma_id, DEG_NODE_TYPE_SHADING, NULL,
add_operation_node(&material->id, DEG_NODE_TYPE_SHADING, NULL,
DEG_OPCODE_PLACEHOLDER, "Material Update");
/* material animation */
build_animdata(ma_id);
build_animdata(&material->id);
/* textures */
build_texture_stack(ma->mtex);
build_texture_stack(material->mtex);
/* material's nodetree */
build_nodetree(ma->nodetree);
build_nodetree(material->nodetree);
}
/* Texture-stack attached to some shading datablock */
@ -1045,33 +1004,29 @@ void DepsgraphNodeBuilder::build_texture_stack(MTex **texture_stack)
}
/* Recursively build graph for texture */
void DepsgraphNodeBuilder::build_texture(Tex *tex)
void DepsgraphNodeBuilder::build_texture(Tex *texture)
{
ID *tex_id = &tex->id;
if (tex_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(texture)) {
return;
}
tex_id->tag |= LIB_TAG_DOIT;
/* Texture itself. */
build_animdata(tex_id);
build_animdata(&texture->id);
/* Texture's nodetree. */
build_nodetree(tex->nodetree);
build_nodetree(texture->nodetree);
/* Special cases for different IDs which texture uses. */
if (tex->type == TEX_IMAGE) {
if (tex->ima != NULL) {
build_image(tex->ima);
if (texture->type == TEX_IMAGE) {
if (texture->ima != NULL) {
build_image(texture->ima);
}
}
}
void DepsgraphNodeBuilder::build_image(Image *image) {
ID *image_id = &image->id;
if (image_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(image)) {
return;
}
image_id->tag |= LIB_TAG_DOIT;
/* Placeholder so we can add relations and tag ID node for update. */
add_operation_node(image_id,
add_operation_node(&image->id,
DEG_NODE_TYPE_PARAMETERS,
NULL,
DEG_OPCODE_PLACEHOLDER,

View File

@ -30,6 +30,7 @@
#pragma once
#include "intern/builder/deg_builder_map.h"
#include "intern/depsgraph_types.h"
struct Base;
@ -161,6 +162,8 @@ protected:
/* State which demotes currently built entities. */
Scene *scene_;
BuilderMap built_map_;
};
} // namespace DEG

View File

@ -123,9 +123,8 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
* Eventually, we need some type of proxy/isolation mechanism in-between here
* to ensure that we can use same rig multiple times in same scene...
*/
if ((arm->id.tag & LIB_TAG_DOIT) == 0) {
if (built_map_.checkIsBuilt(arm)) {
build_animdata(&arm->id);
/* Make sure pose is up-to-date with armature updates. */
add_operation_node(&arm->id,
DEG_NODE_TYPE_PARAMETERS,

View File

@ -406,26 +406,11 @@ Depsgraph *DepsgraphRelationBuilder::getGraph()
void DepsgraphRelationBuilder::begin_build()
{
/* LIB_TAG_DOIT is used to indicate whether node for given ID was already
* created or not.
*/
BKE_main_id_tag_all(bmain_, LIB_TAG_DOIT, false);
/* XXX nested node trees are notr included in tag-clearing above,
* so we need to do this manually.
*/
FOREACH_NODETREE(bmain_, nodetree, id)
{
if (id != (ID *)nodetree) {
nodetree->id.tag &= ~LIB_TAG_DOIT;
}
}
FOREACH_NODETREE_END;
}
void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
{
ID *group_id = &group->id;
bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0;
const bool group_done = built_map_.checkIsBuiltAndTag(group);
OperationKey object_local_transform_key(object != NULL ? &object->id : NULL,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_LOCAL);
@ -438,15 +423,13 @@ void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
}
}
group_id->tag |= LIB_TAG_DOIT;
}
void DepsgraphRelationBuilder::build_object(Object *object)
{
if (object->id.tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(object)) {
return;
}
object->id.tag |= LIB_TAG_DOIT;
/* Object Transforms */
eDepsOperation_Code base_op = (object->parent) ? DEG_OPCODE_TRANSFORM_PARENT
: DEG_OPCODE_TRANSFORM_LOCAL;
@ -1233,24 +1216,18 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
void DepsgraphRelationBuilder::build_world(World *world)
{
ID *world_id = &world->id;
if (world_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(world)) {
return;
}
world_id->tag |= LIB_TAG_DOIT;
build_animdata(world_id);
build_animdata(&world->id);
/* TODO: other settings? */
/* textures */
build_texture_stack(world->mtex);
/* world's nodetree */
if (world->nodetree != NULL) {
build_nodetree(world->nodetree);
ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS);
ComponentKey world_key(&world->id, DEG_NODE_TYPE_PARAMETERS);
add_relation(ntree_key, world_key, "NTree->World Parameters");
}
}
@ -1609,10 +1586,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
}
if (obdata->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(obdata)) {
return;
}
obdata->tag |= LIB_TAG_DOIT;
/* Link object data evaluation node to exit operation. */
OperationKey obdata_geom_eval_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval");
@ -1708,16 +1684,14 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
// TODO: Link scene-camera links in somehow...
void DepsgraphRelationBuilder::build_camera(Object *object)
{
Camera *cam = (Camera *)object->data;
ID *camera_id = &cam->id;
if (camera_id->tag & LIB_TAG_DOIT) {
Camera *camera = (Camera *)object->data;
if (built_map_.checkIsBuiltAndTag(camera)) {
return;
}
camera_id->tag |= LIB_TAG_DOIT;
/* DOF */
if (cam->dof_ob) {
if (camera->dof_ob) {
ComponentKey ob_param_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
ComponentKey dof_ob_key(&camera->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
add_relation(dof_ob_key, ob_param_key, "Camera DOF");
}
}
@ -1725,36 +1699,33 @@ void DepsgraphRelationBuilder::build_camera(Object *object)
/* Lamps */
void DepsgraphRelationBuilder::build_lamp(Object *object)
{
Lamp *la = (Lamp *)object->data;
ID *lamp_id = &la->id;
if (lamp_id->tag & LIB_TAG_DOIT) {
Lamp *lamp = (Lamp *)object->data;
if (built_map_.checkIsBuiltAndTag(lamp)) {
return;
}
lamp_id->tag |= LIB_TAG_DOIT;
/* lamp's nodetree */
if (la->nodetree != NULL) {
build_nodetree(la->nodetree);
ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
if (lamp->nodetree != NULL) {
build_nodetree(lamp->nodetree);
ComponentKey parameters_key(&lamp->id, DEG_NODE_TYPE_PARAMETERS);
ComponentKey nodetree_key(&lamp->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters");
}
/* textures */
build_texture_stack(la->mtex);
build_texture_stack(lamp->mtex);
}
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
{
if (!ntree)
if (ntree == NULL) {
return;
ID *ntree_id = &ntree->id;
build_animdata(ntree_id);
OperationKey parameters_key(ntree_id,
}
if (built_map_.checkIsBuiltAndTag(ntree)) {
return;
}
build_animdata(&ntree->id);
OperationKey parameters_key(&ntree->id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PARAMETERS_EVAL);
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
ID *id = bnode->id;
@ -1784,10 +1755,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
}
else if (bnode->type == NODE_GROUP) {
bNodeTree *group_ntree = (bNodeTree *)id;
if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
build_nodetree(group_ntree);
group_ntree->id.tag |= LIB_TAG_DOIT;
}
build_nodetree(group_ntree);
OperationKey group_parameters_key(&group_ntree->id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PARAMETERS_EVAL);
@ -1800,27 +1768,22 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
}
/* Recursively build graph for material */
void DepsgraphRelationBuilder::build_material(Material *ma)
void DepsgraphRelationBuilder::build_material(Material *material)
{
ID *ma_id = &ma->id;
if (ma_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(material)) {
return;
}
ma_id->tag |= LIB_TAG_DOIT;
/* animation */
build_animdata(ma_id);
build_animdata(&material->id);
/* textures */
build_texture_stack(ma->mtex);
build_texture_stack(material->mtex);
/* material's nodetree */
if (ma->nodetree != NULL) {
build_nodetree(ma->nodetree);
OperationKey ntree_key(&ma->nodetree->id,
if (material->nodetree != NULL) {
build_nodetree(material->nodetree);
OperationKey ntree_key(&material->nodetree->id,
DEG_NODE_TYPE_PARAMETERS,
DEG_OPCODE_PARAMETERS_EVAL);
OperationKey material_key(&ma->id,
OperationKey material_key(&material->id,
DEG_NODE_TYPE_SHADING,
DEG_OPCODE_PLACEHOLDER,
"Material Update");
@ -1829,28 +1792,22 @@ void DepsgraphRelationBuilder::build_material(Material *ma)
}
/* Recursively build graph for texture */
void DepsgraphRelationBuilder::build_texture(Tex *tex)
void DepsgraphRelationBuilder::build_texture(Tex *texture)
{
ID *tex_id = &tex->id;
if (tex_id->tag & LIB_TAG_DOIT) {
if (built_map_.checkIsBuiltAndTag(texture)) {
return;
}
tex_id->tag |= LIB_TAG_DOIT;
/* texture itself */
build_animdata(tex_id);
build_animdata(&texture->id);
/* texture's nodetree */
build_nodetree(tex->nodetree);
build_nodetree(texture->nodetree);
}
/* Texture-stack attached to some shading datablock */
void DepsgraphRelationBuilder::build_texture_stack(MTex **texture_stack)
{
int i;
/* for now assume that all texture-stacks have same number of max items */
for (i = 0; i < MAX_MTEX; i++) {
for (int i = 0; i < MAX_MTEX; i++) {
MTex *mtex = texture_stack[i];
if (mtex && mtex->tex)
build_texture(mtex->tex);

View File

@ -43,6 +43,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "intern/builder/deg_builder_map.h"
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@ -318,6 +319,8 @@ private:
/* State which demotes currently built entities. */
Scene *scene_;
BuilderMap built_map_;
};
struct DepsNodeHandle

View File

@ -290,7 +290,6 @@ IDDepsNode *Depsgraph::add_id_node(ID *id, const char *name)
if (!id_node) {
DepsNodeFactory *factory = deg_type_get_factory(DEG_NODE_TYPE_ID_REF);
id_node = (IDDepsNode *)factory->create_node(id, "", name);
id->tag |= LIB_TAG_DOIT;
/* register */
BLI_ghash_insert(id_hash, id, id_node);
id_nodes.push_back(id_node);