Blender  V2.93
node_exec.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "DNA_node_types.h"
25 
26 #include "BLI_listbase.h"
27 #include "BLI_utildefines.h"
28 
29 #include "BKE_global.h"
30 #include "BKE_node.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "node_exec.h"
35 #include "node_util.h"
36 
37 /* supported socket types in old nodes */
39 {
40  /* NOTE: INT supported as FLOAT. Only for EEVEE. */
42 }
43 
44 /* for a given socket, find the actual stack entry */
46 {
47  if (stack && sock && sock->stack_index >= 0) {
48  return stack + sock->stack_index;
49  }
50  return nullptr;
51 }
52 
54 {
55  bNodeSocket *sock;
56 
57  /* build pointer stack */
58  if (in) {
59  for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
60  *(in++) = node_get_socket_stack(stack, sock);
61  }
62  }
63 
64  if (out) {
65  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
66  *(out++) = node_get_socket_stack(stack, sock);
67  }
68  }
69 }
70 
71 static void node_init_input_index(bNodeSocket *sock, int *index)
72 {
73  /* Only consider existing link if from socket is valid! */
74  if (sock->link && !(sock->link->flag & NODE_LINK_MUTED) && sock->link->fromsock &&
75  sock->link->fromsock->stack_index >= 0) {
76  sock->stack_index = sock->link->fromsock->stack_index;
77  }
78  else {
79  if (node_exec_socket_use_stack(sock)) {
80  sock->stack_index = (*index)++;
81  }
82  else {
83  sock->stack_index = -1;
84  }
85  }
86 }
87 
88 static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
89 {
90  if (internal_links) {
91  bNodeLink *link;
92  /* copy the stack index from internally connected input to skip the node */
93  for (link = (bNodeLink *)internal_links->first; link; link = link->next) {
94  if (link->tosock == sock) {
95  sock->stack_index = link->fromsock->stack_index;
96  /* set the link pointer to indicate that this socket
97  * should not overwrite the stack value!
98  */
99  sock->link = link;
100  break;
101  }
102  }
103  /* if not internally connected, assign a new stack index anyway to avoid bad stack access */
104  if (!link) {
105  if (node_exec_socket_use_stack(sock)) {
106  sock->stack_index = (*index)++;
107  }
108  else {
109  sock->stack_index = -1;
110  }
111  }
112  }
113  else {
114  if (node_exec_socket_use_stack(sock)) {
115  sock->stack_index = (*index)++;
116  }
117  else {
118  sock->stack_index = -1;
119  }
120  }
121 }
122 
123 /* basic preparation of socket stacks */
124 static struct bNodeStack *setup_stack(bNodeStack *stack,
125  bNodeTree *ntree,
126  bNode *node,
127  bNodeSocket *sock)
128 {
129  bNodeStack *ns = node_get_socket_stack(stack, sock);
130  if (!ns) {
131  return nullptr;
132  }
133 
134  /* don't mess with remote socket stacks, these are initialized by other nodes! */
135  if (sock->link && !(sock->link->flag & NODE_LINK_MUTED)) {
136  return ns;
137  }
138 
139  ns->sockettype = sock->type;
140 
141  switch (sock->type) {
142  case SOCK_FLOAT:
143  ns->vec[0] = node_socket_get_float(ntree, node, sock);
144  break;
145  case SOCK_VECTOR:
146  node_socket_get_vector(ntree, node, sock, ns->vec);
147  break;
148  case SOCK_RGBA:
149  node_socket_get_color(ntree, node, sock, ns->vec);
150  break;
151  }
152 
153  return ns;
154 }
155 
157  bNodeTree *ntree,
158  bNodeInstanceKey parent_key)
159 {
161  bNode *node;
162  bNodeExec *nodeexec;
163  bNodeInstanceKey nodekey;
164  bNodeSocket *sock;
165  bNodeStack *ns;
166  int index;
167  bNode **nodelist;
168  int totnodes, n;
169  /* XXX: texture-nodes have threading issues with muting, have to disable it there. */
170 
171  /* ensure all sock->link pointers and node levels are correct */
172  /* Using global main here is likely totally wrong, not sure what to do about that one though...
173  * We cannot even check ntree is in global main,
174  * since most of the time it won't be (thanks to ntree design)!!! */
175  ntreeUpdateTree(G.main, ntree);
176 
177  /* get a dependency-sorted list of nodes */
178  ntreeGetDependencyList(ntree, &nodelist, &totnodes);
179 
180  /* XXX could let callbacks do this for specialized data */
181  exec = (bNodeTreeExec *)MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
182  /* backpointer to node tree */
183  exec->nodetree = ntree;
184 
185  /* set stack indices */
186  index = 0;
187  for (n = 0; n < totnodes; n++) {
188  node = nodelist[n];
189 
190  /* init node socket stack indexes */
191  for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
192  node_init_input_index(sock, &index);
193  }
194 
195  if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
196  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
197  node_init_output_index(sock, &index, &node->internal_links);
198  }
199  }
200  else {
201  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
202  node_init_output_index(sock, &index, nullptr);
203  }
204  }
205  }
206 
207  /* allocated exec data pointers for nodes */
208  exec->totnodes = totnodes;
209  exec->nodeexec = (bNodeExec *)MEM_callocN(exec->totnodes * sizeof(bNodeExec),
210  "node execution data");
211  /* allocate data pointer for node stack */
212  exec->stacksize = index;
213  exec->stack = (bNodeStack *)MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
214 
215  /* all non-const results are considered inputs */
216  for (n = 0; n < exec->stacksize; n++) {
217  exec->stack[n].hasinput = 1;
218  }
219 
220  /* prepare all nodes for execution */
221  for (n = 0, nodeexec = exec->nodeexec; n < totnodes; n++, nodeexec++) {
222  node = nodeexec->node = nodelist[n];
223  nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
224 
225  /* tag inputs */
226  for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) {
227  /* disable the node if an input link is invalid */
228  if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) {
229  node->need_exec = 0;
230  }
231 
232  ns = setup_stack(exec->stack, ntree, node, sock);
233  if (ns) {
234  ns->hasoutput = 1;
235  }
236  }
237 
238  /* tag all outputs */
239  for (sock = (bNodeSocket *)node->outputs.first; sock; sock = sock->next) {
240  /* ns = */ setup_stack(exec->stack, ntree, node, sock);
241  }
242 
243  nodekey = BKE_node_instance_key(parent_key, ntree, node);
245  context->previews, nodekey) :
246  nullptr;
247  if (node->typeinfo->init_exec_fn) {
248  nodeexec->data.data = node->typeinfo->init_exec_fn(context, node, nodekey);
249  }
250  }
251 
252  if (nodelist) {
253  MEM_freeN(nodelist);
254  }
255 
256  return exec;
257 }
258 
260 {
261  bNodeExec *nodeexec;
262  int n;
263 
264  if (exec->stack) {
265  MEM_freeN(exec->stack);
266  }
267 
268  for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
269  if (nodeexec->free_exec_fn) {
270  nodeexec->free_exec_fn(nodeexec->data.data);
271  }
272  }
273 
274  if (exec->nodeexec) {
275  MEM_freeN(exec->nodeexec);
276  }
277 
278  MEM_freeN(exec);
279 }
280 
281 /**** Material/Texture trees ****/
282 
284 {
285  ListBase *lb = &exec->threadstack[thread];
286  bNodeThreadStack *nts;
287 
288  for (nts = (bNodeThreadStack *)lb->first; nts; nts = nts->next) {
289  if (!nts->used) {
290  nts->used = true;
291  break;
292  }
293  }
294 
295  if (!nts) {
296  nts = (bNodeThreadStack *)MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
297  nts->stack = (bNodeStack *)MEM_dupallocN(exec->stack);
298  nts->used = true;
299  BLI_addtail(lb, nts);
300  }
301 
302  return nts;
303 }
304 
306 {
307  nts->used = false;
308 }
309 
310 bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
311 {
312  bNodeStack *nsin[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */
313  bNodeStack *nsout[MAX_SOCKET] = {nullptr}; /* arbitrary... watch this */
314  bNodeExec *nodeexec;
315  bNode *node;
316  int n;
317 
318  /* nodes are presorted, so exec is in order of list */
319 
320  for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
321  node = nodeexec->node;
322  if (node->need_exec) {
323  node_get_stack(node, nts->stack, nsin, nsout);
324  /* Handle muted nodes...
325  * If the mute func is not set, assume the node should never be muted,
326  * and hence execute it!
327  */
328  if (node->typeinfo->exec_fn && !(node->flag & NODE_MUTED)) {
329  node->typeinfo->exec_fn(callerdata, thread, node, &nodeexec->data, nsin, nsout);
330  }
331  }
332  }
333 
334  /* signal to that all went OK, for render */
335  return true;
336 }
#define NODE_REROUTE
Definition: BKE_node.h:873
void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree)
Definition: node.cc:4262
#define MAX_SOCKET
Definition: BKE_node.h:41
void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist, int *r_deplist_len)
Definition: node.cc:4107
void * BKE_node_instance_hash_lookup(bNodeInstanceHash *hash, bNodeInstanceKey key)
Definition: node.cc:3977
bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, const struct bNodeTree *ntree, const struct bNode *node)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
#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:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
bNodeTreeExec * ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition: node_exec.cc:156
bNodeThreadStack * ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
Definition: node_exec.cc:283
bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
Definition: node_exec.cc:310
static struct bNodeStack * setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
Definition: node_exec.cc:124
void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
Definition: node_exec.cc:53
static void node_init_input_index(bNodeSocket *sock, int *index)
Definition: node_exec.cc:71
static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
Definition: node_exec.cc:88
int node_exec_socket_use_stack(bNodeSocket *sock)
Definition: node_exec.cc:38
void ntree_exec_end(bNodeTreeExec *exec)
Definition: node_exec.cc:259
void ntreeReleaseThreadStack(bNodeThreadStack *nts)
Definition: node_exec.cc:305
bNodeStack * node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
Definition: node_exec.cc:45
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:573
float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock)
Definition: node_util.c:559
void node_socket_get_vector(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, float *value)
Definition: node_util.c:590
struct SELECTID_Context context
Definition: select_engine.c:47
void * first
Definition: DNA_listBase.h:47
void * data
Definition: node_util.h:53
struct bNodePreview * preview
Definition: node_util.h:54
bNodeExecData data
Definition: node_exec.h:48
NodeFreeExecFunction free_exec_fn
Definition: node_exec.h:51
struct bNode * node
Definition: node_exec.h:47
struct bNodeLink * link
struct bNodeSocket * next
short hasoutput
short sockettype
float vec[4]
struct bNodeThreadStack * next
Definition: node_exec.h:69
struct bNodeStack * stack
Definition: node_exec.h:70
#define G(x, y, z)