Nodes: avoid slow and unecessary node group updates on file read
On file read we need to update group nodes in case the group they refer to has changed its inputs and outputs. This had O(n^2) time complexity and was updating all datablocks even if they did not change.
This commit is contained in:
@@ -35,11 +35,11 @@ void register_node_type_group_output(void);
|
||||
/* internal functions for editor */
|
||||
struct bNodeSocket *node_group_find_input_socket(struct bNode *groupnode, const char *identifier);
|
||||
struct bNodeSocket *node_group_find_output_socket(struct bNode *groupnode, const char *identifier);
|
||||
void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
|
||||
void node_group_update(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
||||
struct bNodeSocket *node_group_input_find_socket(struct bNode *node, const char *identifier);
|
||||
struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char *identifier);
|
||||
void node_group_input_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
|
||||
void node_group_output_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id);
|
||||
void node_group_input_update(struct bNodeTree *ntree, struct bNode *node);
|
||||
void node_group_output_update(struct bNodeTree *ntree, struct bNode *node);
|
||||
|
||||
#endif /* __NOD_COMMON_H__ */
|
||||
|
||||
@@ -53,7 +53,7 @@ void register_node_type_cmp_group(void)
|
||||
node_type_socket_templates(&ntype, NULL, NULL);
|
||||
node_type_size(&ntype, 140, 60, 400);
|
||||
node_type_label(&ntype, node_group_label);
|
||||
node_type_update(&ntype, NULL, node_group_verify);
|
||||
node_type_group_update(&ntype, node_group_update);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ void register_node_type_cmp_image(void)
|
||||
cmp_node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW);
|
||||
node_type_init(&ntype, node_composit_init_image);
|
||||
node_type_storage(&ntype, "ImageUser", node_composit_free_image, node_composit_copy_image);
|
||||
node_type_update(&ntype, cmp_node_image_update, NULL);
|
||||
node_type_update(&ntype, cmp_node_image_update);
|
||||
node_type_label(&ntype, node_image_label);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
@@ -580,7 +580,7 @@ void register_node_type_cmp_rlayers(void)
|
||||
ntype.initfunc_api = node_composit_init_rlayers;
|
||||
ntype.poll = node_composit_poll_rlayers;
|
||||
node_type_storage(&ntype, NULL, node_composit_free_rlayers, node_composit_copy_rlayers);
|
||||
node_type_update(&ntype, cmp_node_rlayers_update, NULL);
|
||||
node_type_update(&ntype, cmp_node_rlayers_update);
|
||||
node_type_init(&ntype, node_cmp_rlayers_outputs);
|
||||
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
|
||||
|
||||
|
||||
@@ -281,7 +281,7 @@ void register_node_type_cmp_output_file(void)
|
||||
node_type_socket_templates(&ntype, NULL, NULL);
|
||||
ntype.initfunc_api = init_output_file;
|
||||
node_type_storage(&ntype, "NodeImageMultiFile", free_output_file, copy_output_file);
|
||||
node_type_update(&ntype, update_output_file, NULL);
|
||||
node_type_update(&ntype, update_output_file);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ void register_node_type_cmp_scale(void)
|
||||
|
||||
cmp_node_type_base(&ntype, CMP_NODE_SCALE, "Scale", NODE_CLASS_DISTORT, 0);
|
||||
node_type_socket_templates(&ntype, cmp_node_scale_in, cmp_node_scale_out);
|
||||
node_type_update(&ntype, node_composite_update_scale, NULL);
|
||||
node_type_update(&ntype, node_composite_update_scale);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ void register_node_type_cmp_switch_view(void)
|
||||
|
||||
ntype.initfunc_api = init_switch_view;
|
||||
|
||||
node_type_update(&ntype, cmp_node_switch_view_update, NULL);
|
||||
node_type_update(&ntype, cmp_node_switch_view_update);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -179,18 +179,16 @@ static void group_verify_socket_list(
|
||||
}
|
||||
|
||||
/* make sure all group node in ntree, which use ngroup, are sync'd */
|
||||
void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id)
|
||||
void node_group_update(struct bNodeTree *ntree, struct bNode *node)
|
||||
{
|
||||
/* check inputs and outputs, and remove or insert them */
|
||||
if (id == node->id) {
|
||||
if (id == NULL) {
|
||||
nodeRemoveAllSockets(ntree, node);
|
||||
}
|
||||
else {
|
||||
bNodeTree *ngroup = (bNodeTree *)node->id;
|
||||
group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN);
|
||||
group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT);
|
||||
}
|
||||
if (node->id == NULL) {
|
||||
nodeRemoveAllSockets(ntree, node);
|
||||
}
|
||||
else {
|
||||
bNodeTree *ngroup = (bNodeTree *)node->id;
|
||||
group_verify_socket_list(ntree, node, &ngroup->inputs, &node->inputs, SOCK_IN);
|
||||
group_verify_socket_list(ntree, node, &ngroup->outputs, &node->outputs, SOCK_OUT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +406,7 @@ void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree)
|
||||
|
||||
static void node_group_input_init(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
node_group_input_verify(ntree, node, (ID *)ntree);
|
||||
node_group_input_update(ntree, node);
|
||||
}
|
||||
|
||||
bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
|
||||
@@ -422,19 +420,7 @@ bNodeSocket *node_group_input_find_socket(bNode *node, const char *identifier)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void node_group_input_verify(bNodeTree *ntree, bNode *node, ID *id)
|
||||
{
|
||||
/* check inputs and outputs, and remove or insert them */
|
||||
if (id == (ID *)ntree) {
|
||||
/* value_in_out inverted for interface nodes to get correct socket value_property */
|
||||
group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT);
|
||||
|
||||
/* add virtual extension socket */
|
||||
nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", "");
|
||||
}
|
||||
}
|
||||
|
||||
static void node_group_input_update(bNodeTree *ntree, bNode *node)
|
||||
void node_group_input_update(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
bNodeSocket *extsock = node->outputs.last;
|
||||
bNodeLink *link, *linknext, *exposelink;
|
||||
@@ -480,7 +466,7 @@ static void node_group_input_update(bNodeTree *ntree, bNode *node)
|
||||
|
||||
gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->tonode, exposelink->tosock);
|
||||
|
||||
node_group_input_verify(ntree, node, (ID *)ntree);
|
||||
node_group_input_update(ntree, node);
|
||||
newsock = node_group_input_find_socket(node, gsock->identifier);
|
||||
|
||||
/* redirect links from the extension socket */
|
||||
@@ -490,6 +476,15 @@ static void node_group_input_update(bNodeTree *ntree, bNode *node)
|
||||
}
|
||||
|
||||
BLI_freelistN(&tmplinks);
|
||||
|
||||
/* check inputs and outputs, and remove or insert them */
|
||||
{
|
||||
/* value_in_out inverted for interface nodes to get correct socket value_property */
|
||||
group_verify_socket_list(ntree, node, &ntree->inputs, &node->outputs, SOCK_OUT);
|
||||
|
||||
/* add virtual extension socket */
|
||||
nodeAddSocket(ntree, node, SOCK_OUT, "NodeSocketVirtual", "__extend__", "");
|
||||
}
|
||||
}
|
||||
|
||||
void register_node_type_group_input(void)
|
||||
@@ -500,7 +495,7 @@ void register_node_type_group_input(void)
|
||||
node_type_base(ntype, NODE_GROUP_INPUT, "Group Input", NODE_CLASS_INTERFACE, 0);
|
||||
node_type_size(ntype, 140, 80, 400);
|
||||
node_type_init(ntype, node_group_input_init);
|
||||
node_type_update(ntype, node_group_input_update, node_group_input_verify);
|
||||
node_type_update(ntype, node_group_input_update);
|
||||
|
||||
ntype->needs_free = 1;
|
||||
nodeRegisterType(ntype);
|
||||
@@ -508,7 +503,7 @@ void register_node_type_group_input(void)
|
||||
|
||||
static void node_group_output_init(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
node_group_output_verify(ntree, node, (ID *)ntree);
|
||||
node_group_output_update(ntree, node);
|
||||
}
|
||||
|
||||
bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
|
||||
@@ -522,19 +517,7 @@ bNodeSocket *node_group_output_find_socket(bNode *node, const char *identifier)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void node_group_output_verify(bNodeTree *ntree, bNode *node, ID *id)
|
||||
{
|
||||
/* check inputs and outputs, and remove or insert them */
|
||||
if (id == (ID *)ntree) {
|
||||
/* value_in_out inverted for interface nodes to get correct socket value_property */
|
||||
group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN);
|
||||
|
||||
/* add virtual extension socket */
|
||||
nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", "");
|
||||
}
|
||||
}
|
||||
|
||||
static void node_group_output_update(bNodeTree *ntree, bNode *node)
|
||||
void node_group_output_update(bNodeTree *ntree, bNode *node)
|
||||
{
|
||||
bNodeSocket *extsock = node->inputs.last;
|
||||
bNodeLink *link, *linknext, *exposelink;
|
||||
@@ -581,7 +564,7 @@ static void node_group_output_update(bNodeTree *ntree, bNode *node)
|
||||
/* XXX what if connecting virtual to virtual socket?? */
|
||||
gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock);
|
||||
|
||||
node_group_output_verify(ntree, node, (ID *)ntree);
|
||||
node_group_output_update(ntree, node);
|
||||
newsock = node_group_output_find_socket(node, gsock->identifier);
|
||||
|
||||
/* redirect links to the extension socket */
|
||||
@@ -591,6 +574,15 @@ static void node_group_output_update(bNodeTree *ntree, bNode *node)
|
||||
}
|
||||
|
||||
BLI_freelistN(&tmplinks);
|
||||
|
||||
/* check inputs and outputs, and remove or insert them */
|
||||
{
|
||||
/* value_in_out inverted for interface nodes to get correct socket value_property */
|
||||
group_verify_socket_list(ntree, node, &ntree->outputs, &node->inputs, SOCK_IN);
|
||||
|
||||
/* add virtual extension socket */
|
||||
nodeAddSocket(ntree, node, SOCK_IN, "NodeSocketVirtual", "__extend__", "");
|
||||
}
|
||||
}
|
||||
|
||||
void register_node_type_group_output(void)
|
||||
@@ -601,7 +593,7 @@ void register_node_type_group_output(void)
|
||||
node_type_base(ntype, NODE_GROUP_OUTPUT, "Group Output", NODE_CLASS_INTERFACE, 0);
|
||||
node_type_size(ntype, 140, 80, 400);
|
||||
node_type_init(ntype, node_group_output_init);
|
||||
node_type_update(ntype, node_group_output_update, node_group_output_verify);
|
||||
node_type_update(ntype, node_group_output_update);
|
||||
|
||||
ntype->needs_free = 1;
|
||||
nodeRegisterType(ntype);
|
||||
|
||||
@@ -235,8 +235,8 @@ static bNode *ntree_shader_relink_output_from_group(bNodeTree *ntree,
|
||||
}
|
||||
|
||||
/* Need to update tree so all node instances nodes gets proper sockets. */
|
||||
node_group_verify(ntree, group_node, &group_ntree->id);
|
||||
node_group_output_verify(group_ntree, group_output_node, &group_ntree->id);
|
||||
node_group_update(ntree, group_node);
|
||||
node_group_output_update(group_ntree, group_output_node);
|
||||
ntreeUpdateTree(G.main, group_ntree);
|
||||
|
||||
/* Remove other shader output nodes so that only the new one can be selected as active. */
|
||||
@@ -576,9 +576,9 @@ static void ntree_shader_link_builtin_group_normal(bNodeTree *ntree,
|
||||
group_ntree, SOCK_IN, "NodeSocketVector", "Normal");
|
||||
/* Need to update tree so all node instances nodes gets proper sockets. */
|
||||
bNode *group_input_node = ntreeFindType(group_ntree, NODE_GROUP_INPUT);
|
||||
node_group_verify(ntree, group_node, &group_ntree->id);
|
||||
node_group_update(ntree, group_node);
|
||||
if (group_input_node) {
|
||||
node_group_input_verify(group_ntree, group_input_node, &group_ntree->id);
|
||||
node_group_input_update(group_ntree, group_input_node);
|
||||
}
|
||||
ntreeUpdateTree(G.main, group_ntree);
|
||||
/* Assumes sockets are always added at the end. */
|
||||
|
||||
@@ -129,7 +129,7 @@ void register_node_type_sh_bsdf_hair_principled(void)
|
||||
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
|
||||
node_type_init(&ntype, node_shader_init_hair_principled);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_update(&ntype, node_shader_update_hair_principled, NULL);
|
||||
node_type_update(&ntype, node_shader_update_hair_principled);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ void register_node_type_sh_bsdf_principled(void)
|
||||
node_type_init(&ntype, node_shader_init_principled);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_bsdf_principled);
|
||||
node_type_update(&ntype, node_shader_update_principled, NULL);
|
||||
node_type_update(&ntype, node_shader_update_principled);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ void register_node_type_sh_group(void)
|
||||
node_type_socket_templates(&ntype, NULL, NULL);
|
||||
node_type_size(&ntype, 140, 60, 400);
|
||||
node_type_label(&ntype, node_group_label);
|
||||
node_type_update(&ntype, NULL, node_group_verify);
|
||||
node_type_group_update(&ntype, node_group_update);
|
||||
node_type_exec(&ntype, group_initexec, group_freeexec, group_execute);
|
||||
node_type_gpu(&ntype, gpu_group_execute);
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ void register_node_type_sh_subsurface_scattering(void)
|
||||
node_type_init(&ntype, node_shader_init_subsurface_scattering);
|
||||
node_type_storage(&ntype, "", NULL, NULL);
|
||||
node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering);
|
||||
node_type_update(&ntype, node_shader_update_subsurface_scattering, NULL);
|
||||
node_type_update(&ntype, node_shader_update_subsurface_scattering);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ void register_node_type_sh_tex_voronoi(void)
|
||||
node_type_storage(
|
||||
&ntype, "NodeTexVoronoi", node_free_standard_storage, node_copy_standard_storage);
|
||||
node_type_gpu(&ntype, node_shader_gpu_tex_voronoi);
|
||||
node_type_update(&ntype, node_shader_update_tex_voronoi, NULL);
|
||||
node_type_update(&ntype, node_shader_update_tex_voronoi);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ void register_node_type_tex_group(void)
|
||||
node_type_socket_templates(&ntype, NULL, NULL);
|
||||
node_type_size(&ntype, 140, 60, 400);
|
||||
node_type_label(&ntype, node_group_label);
|
||||
node_type_update(&ntype, NULL, node_group_verify);
|
||||
node_type_group_update(&ntype, node_group_update);
|
||||
node_type_exec(&ntype, group_initexec, group_freeexec, group_execute);
|
||||
|
||||
nodeRegisterType(&ntype);
|
||||
|
||||
Reference in New Issue
Block a user