Blender  V3.3
node_exec.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. All rights reserved. */
3 
8 #include "DNA_node_types.h"
9 
10 #include "BLI_listbase.h"
11 #include "BLI_utildefines.h"
12 
13 #include "BKE_global.h"
14 #include "BKE_node.h"
15 #include "BKE_node_tree_update.h"
16 
17 #include "MEM_guardedalloc.h"
18 
19 #include "node_exec.h"
20 #include "node_util.h"
21 
23 {
24  /* NOTE: INT supported as FLOAT. Only for EEVEE. */
26 }
27 
29 {
30  if (stack && sock && sock->stack_index >= 0) {
31  return stack + sock->stack_index;
32  }
33  return nullptr;
34 }
35 
37 {
38  bNodeSocket *sock;
39 
40  /* build pointer stack */
41  if (in) {
42  for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
43  *(in++) = node_get_socket_stack(stack, sock);
44  }
45  }
46 
47  if (out) {
48  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
49  *(out++) = node_get_socket_stack(stack, sock);
50  }
51  }
52 }
53 
54 static void node_init_input_index(bNodeSocket *sock, int *index)
55 {
56  /* Only consider existing link if from socket is valid! */
57  if (sock->link && !(sock->link->flag & NODE_LINK_MUTED) && sock->link->fromsock &&
58  sock->link->fromsock->stack_index >= 0) {
59  sock->stack_index = sock->link->fromsock->stack_index;
60  }
61  else {
62  if (node_exec_socket_use_stack(sock)) {
63  sock->stack_index = (*index)++;
64  }
65  else {
66  sock->stack_index = -1;
67  }
68  }
69 }
70 
71 static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
72 {
73  if (internal_links) {
74  bNodeLink *link;
75  /* copy the stack index from internally connected input to skip the node */
76  for (link = (bNodeLink *)internal_links->first; link; link = link->next) {
77  if (link->tosock == sock) {
78  sock->stack_index = link->fromsock->stack_index;
79  /* set the link pointer to indicate that this socket
80  * should not overwrite the stack value!
81  */
82  sock->link = link;
83  break;
84  }
85  }
86  /* if not internally connected, assign a new stack index anyway to avoid bad stack access */
87  if (!link) {
88  if (node_exec_socket_use_stack(sock)) {
89  sock->stack_index = (*index)++;
90  }
91  else {
92  sock->stack_index = -1;
93  }
94  }
95  }
96  else {
97  if (node_exec_socket_use_stack(sock)) {
98  sock->stack_index = (*index)++;
99  }
100  else {
101  sock->stack_index = -1;
102  }
103  }
104 }
105 
106 /* basic preparation of socket stacks */
107 static struct bNodeStack *setup_stack(bNodeStack *stack,
108  bNodeTree *ntree,
109  bNode *node,
110  bNodeSocket *sock)
111 {
112  bNodeStack *ns = node_get_socket_stack(stack, sock);
113  if (!ns) {
114  return nullptr;
115  }
116 
117  /* don't mess with remote socket stacks, these are initialized by other nodes! */
118  if (sock->link && !(sock->link->flag & NODE_LINK_MUTED)) {
119  return ns;
120  }
121 
122  ns->sockettype = sock->type;
123 
124  switch (sock->type) {
125  case SOCK_FLOAT:
126  ns->vec[0] = node_socket_get_float(ntree, node, sock);
127  break;
128  case SOCK_VECTOR:
129  node_socket_get_vector(ntree, node, sock, ns->vec);
130  break;
131  case SOCK_RGBA:
132  node_socket_get_color(ntree, node, sock, ns->vec);
133  break;
134  }
135 
136  return ns;
137 }
138 
140  bNodeTree *ntree,
141  bNodeInstanceKey parent_key)
142 {
144  bNode *node;
145  bNodeExec *nodeexec;
146  bNodeInstanceKey nodekey;
147  bNodeSocket *sock;
148  bNodeStack *ns;
149  int index;
150  bNode **nodelist;
151  int totnodes, n;
152  /* XXX: texture-nodes have threading issues with muting, have to disable it there. */
153 
154  /* ensure all sock->link pointers and node levels are correct */
155  /* Using global main here is likely totally wrong, not sure what to do about that one though...
156  * We cannot even check ntree is in global main,
157  * since most of the time it won't be (thanks to ntree design)!!! */
158  BKE_ntree_update_main_tree(G.main, ntree, nullptr);
159 
160  /* get a dependency-sorted list of nodes */
161  ntreeGetDependencyList(ntree, &nodelist, &totnodes);
162 
163  /* XXX could let callbacks do this for specialized data */
164  exec = MEM_cnew<bNodeTreeExec>("node tree execution data");
165  /* backpointer to node tree */
166  exec->nodetree = ntree;
167 
168  /* set stack indices */
169  index = 0;
170  for (n = 0; n < totnodes; n++) {
171  node = nodelist[n];
172 
173  /* init node socket stack indexes */
174  for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
175  node_init_input_index(sock, &index);
176  }
177 
178  if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
179  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
180  node_init_output_index(sock, &index, &node->internal_links);
181  }
182  }
183  else {
184  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
185  node_init_output_index(sock, &index, nullptr);
186  }
187  }
188  }
189 
190  /* allocated exec data pointers for nodes */
191  exec->totnodes = totnodes;
192  exec->nodeexec = (bNodeExec *)MEM_callocN(exec->totnodes * sizeof(bNodeExec),
193  "node execution data");
194  /* allocate data pointer for node stack */
195  exec->stacksize = index;
196  exec->stack = (bNodeStack *)MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
197 
198  /* all non-const results are considered inputs */
199  for (n = 0; n < exec->stacksize; n++) {
200  exec->stack[n].hasinput = 1;
201  }
202 
203  /* prepare all nodes for execution */
204  for (n = 0, nodeexec = exec->nodeexec; n < totnodes; n++, nodeexec++) {
205  node = nodeexec->node = nodelist[n];
206  nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
207 
208  /* tag inputs */
209  for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
210  /* disable the node if an input link is invalid */
211  if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) {
212  node->need_exec = 0;
213  }
214 
215  ns = setup_stack(exec->stack, ntree, node, sock);
216  if (ns) {
217  ns->hasoutput = 1;
218  }
219  }
220 
221  /* tag all outputs */
222  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
223  /* ns = */ setup_stack(exec->stack, ntree, node, sock);
224  }
225 
226  nodekey = BKE_node_instance_key(parent_key, ntree, node);
228  context->previews, nodekey) :
229  nullptr;
230  if (node->typeinfo->init_exec_fn) {
231  nodeexec->data.data = node->typeinfo->init_exec_fn(context, node, nodekey);
232  }
233  }
234 
235  if (nodelist) {
236  MEM_freeN(nodelist);
237  }
238 
239  return exec;
240 }
241 
243 {
244  bNodeExec *nodeexec;
245  int n;
246 
247  if (exec->stack) {
248  MEM_freeN(exec->stack);
249  }
250 
251  for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
252  if (nodeexec->free_exec_fn) {
253  nodeexec->free_exec_fn(nodeexec->data.data);
254  }
255  }
256 
257  if (exec->nodeexec) {
258  MEM_freeN(exec->nodeexec);
259  }
260 
261  MEM_freeN(exec);
262 }
#define NODE_REROUTE
Definition: BKE_node.h:986
void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist, int *r_deplist_len)
Definition: node.cc:4095
void * BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition: node.cc:3965
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, const struct bNodeTree *ntree, const struct bNode *node)
void BKE_ntree_update_main_tree(struct Main *bmain, struct bNodeTree *ntree, struct NodeTreeUpdateExtraParams *params)
#define ELEM(...)
#define NODE_LINK_VALID
#define NODE_MUTED
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
#define NODE_LINK_MUTED
Read Guarded memory(de)allocation.
OperationNode * node
bNodeTree * ntree
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define G(x, y, z)
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
bNodeTreeExec * ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition: node_exec.cc:139
static struct bNodeStack * setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
Definition: node_exec.cc:107
void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
Definition: node_exec.cc:36
static void node_init_input_index(bNodeSocket *sock, int *index)
Definition: node_exec.cc:54
static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
Definition: node_exec.cc:71
static int node_exec_socket_use_stack(bNodeSocket *sock)
Definition: node_exec.cc:22
void ntree_exec_end(bNodeTreeExec *exec)
Definition: node_exec.cc:242
bNodeStack * node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
Definition: node_exec.cc:28
static void exec(void *data, int UNUSED(thread), bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
void node_socket_get_color(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
Definition: node_util.c:379
float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
Definition: node_util.c:365
void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
Definition: node_util.c:396
void * first
Definition: DNA_listBase.h:31
bNodeExecData data
Definition: node_exec.h:32
NodeFreeExecFunction free_exec_fn
Definition: node_exec.h:35
struct bNode * node
Definition: node_exec.h:31
struct bNodeLink * link
struct bNodeSocket * next
short hasoutput
short sockettype
float vec[4]