2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2007 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup nodes
|
2011-09-05 21:01:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "DNA_node_types.h"
|
|
|
|
|
|
|
|
|
|
#include "BLI_listbase.h"
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2024-02-10 18:25:14 +01:00
|
|
|
#include "BKE_global.hh"
|
2022-11-18 12:46:20 +01:00
|
|
|
#include "BKE_node_runtime.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_node_tree_update.hh"
|
2011-09-05 21:01:50 +00:00
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2023-05-04 00:09:29 +02:00
|
|
|
#include "node_exec.hh"
|
2023-05-03 14:21:14 +02:00
|
|
|
#include "node_util.hh"
|
2011-09-05 21:01:50 +00:00
|
|
|
|
2022-01-26 15:28:05 -05:00
|
|
|
static int node_exec_socket_use_stack(bNodeSocket *sock)
|
2013-03-18 16:34:57 +00:00
|
|
|
{
|
2023-10-05 21:55:10 +02:00
|
|
|
/* NOTE: INT and BOOL supported as FLOAT. Only for EEVEE. */
|
|
|
|
|
return ELEM(sock->type, SOCK_INT, SOCK_BOOLEAN, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
|
|
|
|
|
{
|
2019-04-22 13:31:31 +10:00
|
|
|
if (stack && sock && sock->stack_index >= 0) {
|
2012-06-01 13:42:18 +00:00
|
|
|
return stack + sock->stack_index;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2021-04-01 15:14:53 +02:00
|
|
|
return nullptr;
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
|
|
|
|
|
{
|
|
|
|
|
/* build pointer stack */
|
|
|
|
|
if (in) {
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2011-09-05 21:01:50 +00:00
|
|
|
*(in++) = node_get_socket_stack(stack, sock);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
if (out) {
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2011-09-05 21:01:50 +00:00
|
|
|
*(out++) = node_get_socket_stack(stack, sock);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-24 12:57:48 +00:00
|
|
|
static void node_init_input_index(bNodeSocket *sock, int *index)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2017-06-01 12:18:57 +02:00
|
|
|
/* Only consider existing link if from socket is valid! */
|
2021-03-16 19:11:54 +00:00
|
|
|
if (sock->link && !(sock->link->flag & NODE_LINK_MUTED) && sock->link->fromsock &&
|
|
|
|
|
sock->link->fromsock->stack_index >= 0)
|
|
|
|
|
{
|
2011-09-05 21:01:50 +00:00
|
|
|
sock->stack_index = sock->link->fromsock->stack_index;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2019-04-22 13:31:31 +10:00
|
|
|
if (node_exec_socket_use_stack(sock)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->stack_index = (*index)++;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->stack_index = -1;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-18 13:46:21 +01:00
|
|
|
static void node_init_output_index_muted(bNodeSocket *sock,
|
|
|
|
|
int *index,
|
2023-01-09 23:29:58 -05:00
|
|
|
const blender::MutableSpan<bNodeLink> internal_links)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2023-01-09 23:29:58 -05:00
|
|
|
const bNodeLink *link;
|
2022-11-18 13:46:21 +01:00
|
|
|
/* copy the stack index from internally connected input to skip the node */
|
2023-01-09 23:29:58 -05:00
|
|
|
for (bNodeLink &iter_link : internal_links) {
|
|
|
|
|
if (iter_link.tosock == sock) {
|
|
|
|
|
sock->stack_index = iter_link.fromsock->stack_index;
|
2022-11-18 13:46:21 +01:00
|
|
|
/* set the link pointer to indicate that this socket
|
|
|
|
|
* should not overwrite the stack value!
|
|
|
|
|
*/
|
2023-01-09 23:29:58 -05:00
|
|
|
sock->link = &iter_link;
|
|
|
|
|
link = &iter_link;
|
2022-11-18 13:46:21 +01:00
|
|
|
break;
|
2013-03-18 16:34:57 +00:00
|
|
|
}
|
2012-10-24 12:57:48 +00:00
|
|
|
}
|
2022-11-18 13:46:21 +01:00
|
|
|
/* if not internally connected, assign a new stack index anyway to avoid bad stack access */
|
|
|
|
|
if (!link) {
|
2019-04-22 13:31:31 +10:00
|
|
|
if (node_exec_socket_use_stack(sock)) {
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->stack_index = (*index)++;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2013-03-18 16:34:57 +00:00
|
|
|
sock->stack_index = -1;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2012-10-24 12:57:48 +00:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
2022-11-18 13:46:21 +01:00
|
|
|
static void node_init_output_index(bNodeSocket *sock, int *index)
|
|
|
|
|
{
|
|
|
|
|
if (node_exec_socket_use_stack(sock)) {
|
|
|
|
|
sock->stack_index = (*index)++;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
sock->stack_index = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* basic preparation of socket stacks */
|
2023-06-03 08:36:28 +10:00
|
|
|
static bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
|
|
|
|
bNodeStack *ns = node_get_socket_stack(stack, sock);
|
2019-04-22 13:31:31 +10:00
|
|
|
if (!ns) {
|
2021-04-01 15:14:53 +02:00
|
|
|
return nullptr;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* don't mess with remote socket stacks, these are initialized by other nodes! */
|
2021-03-16 19:11:54 +00:00
|
|
|
if (sock->link && !(sock->link->flag & NODE_LINK_MUTED)) {
|
2011-09-05 21:01:50 +00:00
|
|
|
return ns;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
ns->sockettype = sock->type;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
switch (sock->type) {
|
2011-09-05 21:01:50 +00:00
|
|
|
case SOCK_FLOAT:
|
2013-03-18 16:34:57 +00:00
|
|
|
ns->vec[0] = node_socket_get_float(ntree, node, sock);
|
2011-09-05 21:01:50 +00:00
|
|
|
break;
|
|
|
|
|
case SOCK_VECTOR:
|
2013-03-18 16:34:57 +00:00
|
|
|
node_socket_get_vector(ntree, node, sock, ns->vec);
|
2011-09-05 21:01:50 +00:00
|
|
|
break;
|
|
|
|
|
case SOCK_RGBA:
|
2013-03-18 16:34:57 +00:00
|
|
|
node_socket_get_color(ntree, node, sock, ns->vec);
|
2011-09-05 21:01:50 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
return ns;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
|
|
|
|
|
bNodeTree *ntree,
|
|
|
|
|
bNodeInstanceKey parent_key)
|
2011-09-05 21:01:50 +00:00
|
|
|
{
|
2022-11-21 11:30:49 -06:00
|
|
|
using namespace blender;
|
2011-09-05 21:01:50 +00:00
|
|
|
bNodeTreeExec *exec;
|
|
|
|
|
bNode *node;
|
|
|
|
|
bNodeExec *nodeexec;
|
2013-03-18 16:34:57 +00:00
|
|
|
bNodeInstanceKey nodekey;
|
2011-09-05 21:01:50 +00:00
|
|
|
bNodeStack *ns;
|
2012-10-24 12:57:48 +00:00
|
|
|
int index;
|
2021-04-08 16:20:22 +10:00
|
|
|
/* XXX: texture-nodes have threading issues with muting, have to disable it there. */
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* ensure all sock->link pointers and node levels are correct */
|
2018-06-25 12:02:20 +02:00
|
|
|
/* Using global main here is likely totally wrong, not sure what to do about that one though...
|
2019-04-29 20:12:09 +10:00
|
|
|
* We cannot even check ntree is in global main,
|
|
|
|
|
* since most of the time it won't be (thanks to ntree design)!!! */
|
2025-01-09 17:00:05 +01:00
|
|
|
BKE_ntree_update_after_single_tree_change(*G.main, *ntree);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2022-11-21 11:30:49 -06:00
|
|
|
ntree->ensure_topology_cache();
|
|
|
|
|
const Span<bNode *> nodelist = ntree->toposort_left_to_right();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* XXX could let callbacks do this for specialized data */
|
2025-03-05 16:35:09 +01:00
|
|
|
exec = MEM_callocN<bNodeTreeExec>("node tree execution data");
|
2022-11-01 12:24:06 +11:00
|
|
|
/* Back-pointer to node tree. */
|
2011-09-05 21:01:50 +00:00
|
|
|
exec->nodetree = ntree;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-24 12:57:48 +00:00
|
|
|
/* set stack indices */
|
|
|
|
|
index = 0;
|
2022-11-21 11:30:49 -06:00
|
|
|
for (const int n : nodelist.index_range()) {
|
2011-09-05 21:01:50 +00:00
|
|
|
node = nodelist[n];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* init node socket stack indexes */
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2011-09-05 21:01:50 +00:00
|
|
|
node_init_input_index(sock, &index);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-17 12:17:49 +01:00
|
|
|
if (node->is_muted() || node->is_reroute()) {
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2022-11-18 13:46:21 +01:00
|
|
|
node_init_output_index_muted(sock, &index, node->runtime->internal_links);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2012-10-24 12:57:48 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2022-11-18 13:46:21 +01:00
|
|
|
node_init_output_index(sock, &index);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2012-10-24 12:57:48 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* allocated exec data pointers for nodes */
|
2022-11-21 11:30:49 -06:00
|
|
|
exec->totnodes = nodelist.size();
|
2025-04-12 17:17:24 +02:00
|
|
|
exec->nodeexec = MEM_calloc_arrayN<bNodeExec>(exec->totnodes, "node execution data");
|
2011-09-05 21:01:50 +00:00
|
|
|
/* allocate data pointer for node stack */
|
|
|
|
|
exec->stacksize = index;
|
2025-04-12 17:17:24 +02:00
|
|
|
exec->stack = MEM_calloc_arrayN<bNodeStack>(exec->stacksize, "bNodeStack");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-10-12 12:55:32 +00:00
|
|
|
/* all non-const results are considered inputs */
|
2022-11-21 11:30:49 -06:00
|
|
|
int n;
|
2019-09-08 00:12:26 +10:00
|
|
|
for (n = 0; n < exec->stacksize; n++) {
|
2011-10-12 12:55:32 +00:00
|
|
|
exec->stack[n].hasinput = 1;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
/* prepare all nodes for execution */
|
2022-11-21 11:30:49 -06:00
|
|
|
for (n = 0, nodeexec = exec->nodeexec; n < nodelist.size(); n++, nodeexec++) {
|
2011-09-05 21:01:50 +00:00
|
|
|
node = nodeexec->node = nodelist[n];
|
2021-03-05 17:35:25 +01:00
|
|
|
nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* tag inputs */
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
|
2011-09-05 21:01:50 +00:00
|
|
|
/* disable the node if an input link is invalid */
|
2019-04-22 13:31:31 +10:00
|
|
|
if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) {
|
2022-11-18 12:46:20 +01:00
|
|
|
node->runtime->need_exec = 0;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-18 16:34:57 +00:00
|
|
|
ns = setup_stack(exec->stack, ntree, node, sock);
|
2019-04-22 13:31:31 +10:00
|
|
|
if (ns) {
|
2013-03-18 16:34:57 +00:00
|
|
|
ns->hasoutput = 1;
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
/* tag all outputs */
|
2023-08-04 08:51:13 +10:00
|
|
|
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
|
2013-03-18 16:34:57 +00:00
|
|
|
/* ns = */ setup_stack(exec->stack, ntree, node, sock);
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-08-19 20:27:37 +02:00
|
|
|
nodekey = bke::node_instance_key(parent_key, ntree, node);
|
2021-03-05 17:35:25 +01:00
|
|
|
if (node->typeinfo->init_exec_fn) {
|
|
|
|
|
nodeexec->data.data = node->typeinfo->init_exec_fn(context, node, nodekey);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
return exec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ntree_exec_end(bNodeTreeExec *exec)
|
|
|
|
|
{
|
|
|
|
|
bNodeExec *nodeexec;
|
|
|
|
|
int n;
|
2018-06-08 08:07:48 +02:00
|
|
|
|
2019-04-22 13:31:31 +10:00
|
|
|
if (exec->stack) {
|
2011-09-05 21:01:50 +00:00
|
|
|
MEM_freeN(exec->stack);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2018-06-08 08:07:48 +02:00
|
|
|
|
2019-09-08 00:12:26 +10:00
|
|
|
for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
|
2021-03-05 17:35:25 +01:00
|
|
|
if (nodeexec->free_exec_fn) {
|
|
|
|
|
nodeexec->free_exec_fn(nodeexec->data.data);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2011-09-05 21:01:50 +00:00
|
|
|
}
|
2018-06-08 08:07:48 +02:00
|
|
|
|
2019-04-22 13:31:31 +10:00
|
|
|
if (exec->nodeexec) {
|
2011-09-05 21:01:50 +00:00
|
|
|
MEM_freeN(exec->nodeexec);
|
2019-04-22 13:31:31 +10:00
|
|
|
}
|
2018-06-08 08:07:48 +02:00
|
|
|
|
2011-09-05 21:01:50 +00:00
|
|
|
MEM_freeN(exec);
|
|
|
|
|
}
|