From 65779b022dc14e4dff107e925817968fc93570f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 3 Dec 2018 17:19:04 +0100 Subject: Fix T58280: Blender 2.8 hangs when the LookDev mode is enabled The hang was due to the nodes being "evaluated" for every incomming link. Solution: only evaluate once per nodetree. Also merge the tagging of SSS and SSR into one traversal only. --- source/blender/makesdna/DNA_node_types.h | 2 +- source/blender/nodes/shader/node_shader_tree.c | 87 +++++++++++--------------- 2 files changed, 39 insertions(+), 50 deletions(-) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index a776fbbc3a6..fe921cf96ac 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -221,7 +221,7 @@ typedef struct bNode { * and replacing all uses with per-instance data. */ short preview_xsize, preview_ysize; /* reserved size of the preview rect */ - short pad2[2]; + short tmp_flag, pad2; /* Used at runtime when going through the tree. Initialize before use. */ struct uiBlock *block; /* runtime during drawing */ float ssr_id; /* XXX: eevee only, id of screen space reflection layer, needs to be a float to feed GPU_uniform. */ diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 7fe5b7df37d..6a8fce76fa7 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -66,8 +66,11 @@ #include "node_shader_util.h" -static void ntree_shader_tag_ssr_node(bNodeTree *ntree, bNode *output_node); -static void ntree_shader_tag_sss_node(bNodeTree *ntree, bNode *output_node); +typedef struct nTreeTags { + float ssr_id, sss_id; +} nTreeTags; + +static void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags); static bool shader_tree_poll(const bContext *C, bNodeTreeType *UNUSED(treetype)) { @@ -633,27 +636,42 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod ntreeUpdateTree(G.main, ntree); } -static bool ntree_tag_ssr_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed)) +static bool ntree_tag_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed)) { + /* Don't evaluate nodes more than once. */ + if (fromnode->tmp_flag) { + return true; + } + fromnode->tmp_flag = 1; + switch (fromnode->type) { case NODE_GROUP: /* Recursive */ if (fromnode->id != NULL) { bNodeTree *ntree = (bNodeTree *)fromnode->id; bNode *group_output = ntree_group_output_node(ntree); - ntree_shader_tag_ssr_node(ntree, group_output); + ntree_shader_tag_nodes(ntree, group_output, (nTreeTags *)userdata); } break; case SH_NODE_BSDF_ANISOTROPIC: case SH_NODE_EEVEE_SPECULAR: - case SH_NODE_BSDF_PRINCIPLED: case SH_NODE_BSDF_GLOSSY: case SH_NODE_BSDF_GLASS: - fromnode->ssr_id = (*(float *)userdata); - (*(float *)userdata) += 1; + fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; + ((nTreeTags *)userdata)->ssr_id += 1; + break; + case SH_NODE_SUBSURFACE_SCATTERING: + fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; + ((nTreeTags *)userdata)->sss_id += 1; + break; + case SH_NODE_BSDF_PRINCIPLED: + fromnode->ssr_id = ((nTreeTags *)userdata)->ssr_id; + fromnode->sss_id = ((nTreeTags *)userdata)->sss_id; + ((nTreeTags *)userdata)->sss_id += 1; + ((nTreeTags *)userdata)->ssr_id += 1; break; default: - /* We could return false here but since we (will) + /* We could return false here but since we * allow the use of Closure as RGBA, we can have * Bsdf nodes linked to other Bsdf nodes. */ break; @@ -663,9 +681,9 @@ static bool ntree_tag_ssr_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void * } /* EEVEE: Scan the ntree to set the Screen Space Reflection - * layer id of every specular node. + * layer id of every specular node AND the Subsurface Scattering id of every SSS node. */ -void ntree_shader_tag_ssr_node(bNodeTree *ntree, bNode *output_node) +void ntree_shader_tag_nodes(bNodeTree *ntree, bNode *output_node, nTreeTags *tags) { if (output_node == NULL) { return; @@ -673,45 +691,12 @@ void ntree_shader_tag_ssr_node(bNodeTree *ntree, bNode *output_node) /* Make sure sockets links pointers are correct. */ ntreeUpdateTree(G.main, ntree); - float lobe_id = 1; - nodeChainIter(ntree, output_node, ntree_tag_ssr_bsdf_cb, &lobe_id, true); -} - -static bool ntree_tag_sss_bsdf_cb(bNode *fromnode, bNode *UNUSED(tonode), void *userdata, const bool UNUSED(reversed)) -{ - switch (fromnode->type) { - case NODE_GROUP: - /* Recursive */ - if (fromnode->id != NULL) { - bNodeTree *ntree = (bNodeTree *)fromnode->id; - bNode *group_output = ntree_group_output_node(ntree); - ntree_shader_tag_sss_node(ntree, group_output); - } - break; - case SH_NODE_BSDF_PRINCIPLED: - case SH_NODE_SUBSURFACE_SCATTERING: - fromnode->sss_id = (*(float *)userdata); - (*(float *)userdata) += 1; - break; - default: - break; - } - - return true; -} - -/* EEVEE: Scan the ntree to set the Subsurface Scattering id of every SSS node. - */ -void ntree_shader_tag_sss_node(bNodeTree *ntree, bNode *output_node) -{ - if (output_node == NULL) { - return; + /* Reset visit flag. */ + for (bNode *node = ntree->nodes.first; node; node = node->next) { + node->tmp_flag = 0; } - /* Make sure sockets links pointers are correct. */ - ntreeUpdateTree(G.main, ntree); - float sss_id = 1; - nodeChainIter(ntree, output_node, ntree_tag_sss_bsdf_cb, &sss_id, true); + nodeChainIter(ntree, output_node, ntree_tag_bsdf_cb, tags, true); } /* This one needs to work on a local tree. */ @@ -727,8 +712,12 @@ void ntreeGPUMaterialNodes(bNodeTree *localtree, GPUMaterial *mat, bool *has_sur */ ntree_shader_relink_displacement(localtree, output); - ntree_shader_tag_ssr_node(localtree, output); - ntree_shader_tag_sss_node(localtree, output); + /* TODO(fclem): consider moving this to the gpu shader tree evaluation. */ + nTreeTags tags = { + .ssr_id = 1.0, + .sss_id = 1.0 + }; + ntree_shader_tag_nodes(localtree, output, &tags); exec = ntreeShaderBeginExecTree(localtree); ntreeExecGPUNodes(exec, mat, 1); -- cgit v1.2.3