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:
authorJacques Lucke <jacques@blender.org>2021-12-21 17:18:56 +0300
committerJacques Lucke <jacques@blender.org>2021-12-21 17:18:56 +0300
commit7e712b2d6a0d257d272ed35622b41d06274af8df (patch)
treed33cfb610da7fa43351a282f9c9a9ba25c77d1f8 /source/blender/depsgraph/intern/builder
parent1abf2f3c7c08051502ae0830ab5d4fa8d8d9f13a (diff)
Nodes: refactor node tree update handling
Goals of this refactor: * More unified approach to updating everything that needs to be updated after a change in a node tree. * The updates should happen in the correct order and quadratic or worse algorithms should be avoided. * Improve detection of changes to the output to avoid tagging the depsgraph when it's not necessary. * Move towards a more declarative style of defining nodes by having a more centralized update procedure. The refactor consists of two main parts: * Node tree tagging and update refactor. * Generally, when changes are done to a node tree, it is tagged dirty until a global update function is called that updates everything in the correct order. * The tagging is more fine-grained compared to before, to allow for more precise depsgraph update tagging. * Depsgraph changes. * The shading specific depsgraph node for node trees as been removed. * Instead, there is a new `NTREE_OUTPUT` depsgrap node, which is only tagged when the output of the node tree changed (e.g. the Group Output or Material Output node). * The copy-on-write relation from node trees to the data block they are embedded in is now non-flushing. This avoids e.g. triggering a material update after the shader node tree changed in unrelated ways. Instead the material has a flushing relation to the new `NTREE_OUTPUT` node now. * The depsgraph no longer reports data block changes through to cycles through `Depsgraph.updates` when only the node tree changed in ways that do not affect the output. Avoiding unnecessary updates seems to work well for geometry nodes and cycles. The situation is a bit worse when there are drivers on the node tree, but that could potentially be improved separately in the future. Avoiding updates in eevee and the compositor is more tricky, but also less urgent. * Eevee updates are triggered by calling `DRW_notify_view_update` in `ED_render_view3d_update` indirectly from `DEG_editors_update`. * Compositor updates are triggered by `ED_node_composite_job` in `node_area_refresh`. This is triggered by calling `ED_area_tag_refresh` in `node_area_listener`. Removing updates always has the risk of breaking some dependency that no one was aware of. It's not unlikely that this will happen here as well. Adding back missing updates should be quite a bit easier than getting rid of unnecessary updates though. Differential Revision: https://developer.blender.org/D13246
Diffstat (limited to 'source/blender/depsgraph/intern/builder')
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc73
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc2
4 files changed, 47 insertions, 34 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 51582508b6f..16eacc735d4 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -1710,8 +1710,8 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
build_idproperties(ntree->id.properties);
/* Animation, */
build_animdata(&ntree->id);
- /* Shading update. */
- add_operation_node(&ntree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ /* Output update. */
+ add_operation_node(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
build_idproperties(bnode->prop);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index b195b2d9e11..09263718677 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1770,7 +1770,7 @@ void DepsgraphRelationBuilder::build_world(World *world)
if (world->nodetree != nullptr) {
build_nodetree(world->nodetree);
OperationKey ntree_key(
- &world->nodetree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ &world->nodetree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
add_relation(ntree_key, world_key, "World's NTree");
build_nested_nodetree(&world->id, world->nodetree);
}
@@ -2381,17 +2381,17 @@ void DepsgraphRelationBuilder::build_light(Light *lamp)
ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
+ /* For allowing drivers on lamp properties. */
+ ComponentKey shading_key(&lamp->id, NodeType::SHADING);
+ add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters");
+
/* light's nodetree */
if (lamp->nodetree != nullptr) {
build_nodetree(lamp->nodetree);
- ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING);
- add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters");
+ ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::NTREE_OUTPUT);
+ add_relation(nodetree_key, shading_key, "NTree->Light Parameters");
build_nested_nodetree(&lamp->id, lamp->nodetree);
}
-
- /* For allowing drivers on lamp properties. */
- ComponentKey shading_key(&lamp->id, NodeType::SHADING);
- add_relation(lamp_parameters_key, shading_key, "Light Shading Parameters");
}
void DepsgraphRelationBuilder::build_nodetree_socket(bNodeSocket *socket)
@@ -2441,7 +2441,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_idproperties(ntree->id.properties);
build_animdata(&ntree->id);
build_parameters(&ntree->id);
- ComponentKey shading_key(&ntree->id, NodeType::SHADING);
+ OperationKey ntree_output_key(&ntree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
/* nodetree's nodes... */
LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
build_idproperties(bnode->prop);
@@ -2460,25 +2460,25 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
if (id_type == ID_MA) {
build_material((Material *)bnode->id);
ComponentKey material_key(id, NodeType::SHADING);
- add_relation(material_key, shading_key, "Material -> Node");
+ add_relation(material_key, ntree_output_key, "Material -> Node");
}
else if (id_type == ID_TE) {
build_texture((Tex *)bnode->id);
ComponentKey texture_key(id, NodeType::GENERIC_DATABLOCK);
- add_relation(texture_key, shading_key, "Texture -> Node");
+ add_relation(texture_key, ntree_output_key, "Texture -> Node");
}
else if (id_type == ID_IM) {
build_image((Image *)bnode->id);
ComponentKey image_key(id, NodeType::GENERIC_DATABLOCK);
- add_relation(image_key, shading_key, "Image -> Node");
+ add_relation(image_key, ntree_output_key, "Image -> Node");
}
else if (id_type == ID_OB) {
build_object((Object *)id);
ComponentKey object_transform_key(id, NodeType::TRANSFORM);
- add_relation(object_transform_key, shading_key, "Object Transform -> Node");
+ add_relation(object_transform_key, ntree_output_key, "Object Transform -> Node");
if (object_have_geometry_component(reinterpret_cast<Object *>(id))) {
ComponentKey object_geometry_key(id, NodeType::GEOMETRY);
- add_relation(object_geometry_key, shading_key, "Object Geometry -> Node");
+ add_relation(object_geometry_key, ntree_output_key, "Object Geometry -> Node");
}
}
else if (id_type == ID_SCE) {
@@ -2498,23 +2498,28 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
else if (id_type == ID_MSK) {
build_mask((Mask *)id);
OperationKey mask_key(id, NodeType::PARAMETERS, OperationCode::MASK_EVAL);
- add_relation(mask_key, shading_key, "Mask -> Node");
+ add_relation(mask_key, ntree_output_key, "Mask -> Node");
}
else if (id_type == ID_MC) {
build_movieclip((MovieClip *)id);
OperationKey clip_key(id, NodeType::PARAMETERS, OperationCode::MOVIECLIP_EVAL);
- add_relation(clip_key, shading_key, "Clip -> Node");
+ add_relation(clip_key, ntree_output_key, "Clip -> Node");
}
else if (id_type == ID_VF) {
build_vfont((VFont *)id);
ComponentKey vfont_key(id, NodeType::GENERIC_DATABLOCK);
- add_relation(vfont_key, shading_key, "VFont -> Node");
+ add_relation(vfont_key, ntree_output_key, "VFont -> Node");
}
else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
bNodeTree *group_ntree = (bNodeTree *)id;
build_nodetree(group_ntree);
- ComponentKey group_shading_key(&group_ntree->id, NodeType::SHADING);
- add_relation(group_shading_key, shading_key, "Group Node");
+ ComponentKey group_output_key(&group_ntree->id, NodeType::NTREE_OUTPUT);
+ /* The output of the current tree does not necessarily change when the output of the group
+ * changed. The parent node group is currently explicitly tagged for update in
+ * #ED_node_tree_propagate_change. In the future we could move this relation to the
+ * depsgraph, but then the depsgraph has to do some more static analysis of the node tree to
+ * see which groups the output actually depends on. */
+ add_relation(group_output_key, ntree_output_key, "Group Node", RELATION_FLAG_NO_FLUSH);
}
else {
BLI_assert_msg(0, "Unknown ID type used for node");
@@ -2528,14 +2533,10 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
build_idproperties(socket->prop);
}
- OperationKey shading_update_key(&ntree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
-
if (check_id_has_anim_component(&ntree->id)) {
ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
- add_relation(animation_key, shading_update_key, "NTree Shading Parameters");
+ add_relation(animation_key, ntree_output_key, "NTree Shading Parameters");
}
- ComponentKey parameters_key(&ntree->id, NodeType::PARAMETERS);
- add_relation(parameters_key, shading_update_key, "NTree Shading Parameters");
}
/* Recursively build graph for material */
@@ -2558,7 +2559,7 @@ void DepsgraphRelationBuilder::build_material(Material *material)
if (material->nodetree != nullptr) {
build_nodetree(material->nodetree);
OperationKey ntree_key(
- &material->nodetree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ &material->nodetree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
add_relation(ntree_key, material_key, "Material's NTree");
build_nested_nodetree(&material->id, material->nodetree);
}
@@ -2587,8 +2588,13 @@ void DepsgraphRelationBuilder::build_texture(Tex *texture)
build_parameters(&texture->id);
/* texture's nodetree */
- build_nodetree(texture->nodetree);
- build_nested_nodetree(&texture->id, texture->nodetree);
+ if (texture->nodetree) {
+ build_nodetree(texture->nodetree);
+ OperationKey ntree_key(
+ &texture->nodetree->id, NodeType::NTREE_OUTPUT, OperationCode::NTREE_OUTPUT);
+ add_relation(ntree_key, texture_key, "Texture's NTree");
+ build_nested_nodetree(&texture->id, texture->nodetree);
+ }
/* Special cases for different IDs which texture uses. */
if (texture->type == TEX_IMAGE) {
@@ -2875,12 +2881,16 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations()
*
* This is similar to what happens in ntree_hack_remap_pointers().
*/
-void DepsgraphRelationBuilder::build_nested_datablock(ID *owner, ID *id)
+void DepsgraphRelationBuilder::build_nested_datablock(ID *owner, ID *id, bool flush_cow_changes)
{
+ int relation_flag = 0;
+ if (!flush_cow_changes) {
+ relation_flag |= RELATION_FLAG_NO_FLUSH;
+ }
OperationKey owner_copy_on_write_key(
owner, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
OperationKey id_copy_on_write_key(id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
- add_relation(id_copy_on_write_key, owner_copy_on_write_key, "Eval Order");
+ add_relation(id_copy_on_write_key, owner_copy_on_write_key, "Eval Order", relation_flag);
}
void DepsgraphRelationBuilder::build_nested_nodetree(ID *owner, bNodeTree *ntree)
@@ -2888,7 +2898,10 @@ void DepsgraphRelationBuilder::build_nested_nodetree(ID *owner, bNodeTree *ntree
if (ntree == nullptr) {
return;
}
- build_nested_datablock(owner, &ntree->id);
+ /* Don't flush cow changes, because the node tree may change in ways that do not affect the
+ * owner data block (e.g. when a node is deleted that is not connected to any output).
+ * Data blocks owning node trees should add a relation to the `NTREE_OUTPUT` node instead. */
+ build_nested_datablock(owner, &ntree->id, false);
}
void DepsgraphRelationBuilder::build_nested_shapekey(ID *owner, Key *key)
@@ -2896,7 +2909,7 @@ void DepsgraphRelationBuilder::build_nested_shapekey(ID *owner, Key *key)
if (key == nullptr) {
return;
}
- build_nested_datablock(owner, &key->id);
+ build_nested_datablock(owner, &key->id, true);
}
void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 09003de3ce4..787e3799029 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -299,7 +299,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer);
virtual void build_vfont(VFont *vfont);
- virtual void build_nested_datablock(ID *owner, ID *id);
+ virtual void build_nested_datablock(ID *owner, ID *id, bool flush_cow_changes);
virtual void build_nested_nodetree(ID *owner, bNodeTree *ntree);
virtual void build_nested_shapekey(ID *owner, Key *key);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index 40e59875832..43d24125dc2 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -351,7 +351,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
- node_identifier.type = NodeType::SHADING;
+ node_identifier.type = NodeType::NTREE_OUTPUT;
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {