Nodes: Resolve performance bottleneck with mix node updates

Improve animation playback performance in EEVEE for materials using Mix
nodes. Socket availability was being set and reset on every evaluation
of Mix nodes, during animation playback, this was causing the graph to
be marked dirty, and the whole graph being re-evaluated on every frame,
causing performance issues during playback.

Additionally, do a bit of cleanup, traversing the node sockets with
the next link to improve clarity and reduce errors. Also refactoring
`nodeSetSocketAvailability` to early out and increase clarity on no-op.

Differential Revision: https://developer.blender.org/D16929
This commit is contained in:
Indy Ray 2023-01-06 08:30:55 -05:00 committed by Hans Goudey
parent e0d70e6a9d
commit a3a60e9647
2 changed files with 14 additions and 13 deletions

View File

@ -3561,16 +3561,16 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
void nodeSetSocketAvailability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
{
const bool was_available = (sock->flag & SOCK_UNAVAIL) == 0;
if (is_available != was_available) {
BKE_ntree_update_tag_socket_availability(ntree, sock);
if (is_available == was_available) {
return;
}
if (is_available) {
sock->flag &= ~SOCK_UNAVAIL;
}
else {
sock->flag |= SOCK_UNAVAIL;
}
BKE_ntree_update_tag_socket_availability(ntree, sock);
}
int nodeSocketLinkLimit(const bNodeSocket *sock)

View File

@ -108,22 +108,23 @@ static void sh_node_mix_update(bNodeTree *ntree, bNode *node)
const NodeShaderMix &storage = node_storage(*node);
const eNodeSocketDatatype data_type = static_cast<eNodeSocketDatatype>(storage.data_type);
LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) {
bNodeSocket *sock_factor = static_cast<bNodeSocket *>(node->inputs.first);
bNodeSocket *sock_factor_vec = static_cast<bNodeSocket *>(sock_factor->next);
bool use_vector_factor = data_type == SOCK_VECTOR &&
storage.factor_mode != NODE_MIX_MODE_UNIFORM;
nodeSetSocketAvailability(ntree, sock_factor, !use_vector_factor);
nodeSetSocketAvailability(ntree, sock_factor_vec, use_vector_factor);
for (bNodeSocket *socket = sock_factor_vec->next; socket != nullptr; socket = socket->next) {
nodeSetSocketAvailability(ntree, socket, socket->type == data_type);
}
LISTBASE_FOREACH (bNodeSocket *, socket, &node->outputs) {
nodeSetSocketAvailability(ntree, socket, socket->type == data_type);
}
bool use_vector_factor = data_type == SOCK_VECTOR &&
storage.factor_mode != NODE_MIX_MODE_UNIFORM;
bNodeSocket *sock_factor = (bNodeSocket *)BLI_findlink(&node->inputs, 0);
nodeSetSocketAvailability(ntree, sock_factor, !use_vector_factor);
bNodeSocket *sock_factor_vec = (bNodeSocket *)BLI_findlink(&node->inputs, 1);
nodeSetSocketAvailability(ntree, sock_factor_vec, use_vector_factor);
}
class SocketSearchOp {