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.
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.
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.
16 * The Original Code is Copyright (C) 2007 Blender Foundation.
17 * All rights reserved.
24 #include "DNA_node_types.h"
26 #include "BLI_listbase.h"
27 #include "BLI_utildefines.h"
29 #include "BKE_global.h"
32 #include "MEM_guardedalloc.h"
34 #include "node_exec.h"
35 #include "node_util.h"
37 /* supported socket types in old nodes */
38 int node_exec_socket_use_stack(bNodeSocket *sock)
40 /* NOTE: INT supported as FLOAT. Only for EEVEE. */
41 return ELEM(sock->type, SOCK_INT, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
44 /* for a given socket, find the actual stack entry */
45 bNodeStack *node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
47 if (stack && sock && sock->stack_index >= 0) {
48 return stack + sock->stack_index;
53 void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
57 /* build pointer stack */
59 for (sock = node->inputs.first; sock; sock = sock->next) {
60 *(in++) = node_get_socket_stack(stack, sock);
65 for (sock = node->outputs.first; sock; sock = sock->next) {
66 *(out++) = node_get_socket_stack(stack, sock);
71 static void node_init_input_index(bNodeSocket *sock, int *index)
73 /* Only consider existing link if from socket is valid! */
74 if (sock->link && sock->link->fromsock && sock->link->fromsock->stack_index >= 0) {
75 sock->stack_index = sock->link->fromsock->stack_index;
78 if (node_exec_socket_use_stack(sock)) {
79 sock->stack_index = (*index)++;
82 sock->stack_index = -1;
87 static void node_init_output_index(bNodeSocket *sock, int *index, ListBase *internal_links)
91 /* copy the stack index from internally connected input to skip the node */
92 for (link = internal_links->first; link; link = link->next) {
93 if (link->tosock == sock) {
94 sock->stack_index = link->fromsock->stack_index;
95 /* set the link pointer to indicate that this socket
96 * should not overwrite the stack value!
102 /* if not internally connected, assign a new stack index anyway to avoid bad stack access */
104 if (node_exec_socket_use_stack(sock)) {
105 sock->stack_index = (*index)++;
108 sock->stack_index = -1;
113 if (node_exec_socket_use_stack(sock)) {
114 sock->stack_index = (*index)++;
117 sock->stack_index = -1;
122 /* basic preparation of socket stacks */
123 static struct bNodeStack *setup_stack(bNodeStack *stack,
128 bNodeStack *ns = node_get_socket_stack(stack, sock);
133 /* don't mess with remote socket stacks, these are initialized by other nodes! */
138 ns->sockettype = sock->type;
140 switch (sock->type) {
142 ns->vec[0] = node_socket_get_float(ntree, node, sock);
145 node_socket_get_vector(ntree, node, sock, ns->vec);
148 node_socket_get_color(ntree, node, sock, ns->vec);
155 bNodeTreeExec *ntree_exec_begin(bNodeExecContext *context,
157 bNodeInstanceKey parent_key)
162 bNodeInstanceKey nodekey;
168 /* XXX texnodes have threading issues with muting, have to disable it there ... */
170 /* ensure all sock->link pointers and node levels are correct */
171 /* Using global main here is likely totally wrong, not sure what to do about that one though...
172 * We cannot even check ntree is in global main,
173 * since most of the time it won't be (thanks to ntree design)!!! */
174 ntreeUpdateTree(G.main, ntree);
176 /* get a dependency-sorted list of nodes */
177 ntreeGetDependencyList(ntree, &nodelist, &totnodes);
179 /* XXX could let callbacks do this for specialized data */
180 exec = MEM_callocN(sizeof(bNodeTreeExec), "node tree execution data");
181 /* backpointer to node tree */
182 exec->nodetree = ntree;
184 /* set stack indices */
186 for (n = 0; n < totnodes; n++) {
189 /* init node socket stack indexes */
190 for (sock = node->inputs.first; sock; sock = sock->next) {
191 node_init_input_index(sock, &index);
194 if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
195 for (sock = node->outputs.first; sock; sock = sock->next) {
196 node_init_output_index(sock, &index, &node->internal_links);
200 for (sock = node->outputs.first; sock; sock = sock->next) {
201 node_init_output_index(sock, &index, NULL);
206 /* allocated exec data pointers for nodes */
207 exec->totnodes = totnodes;
208 exec->nodeexec = MEM_callocN(exec->totnodes * sizeof(bNodeExec), "node execution data");
209 /* allocate data pointer for node stack */
210 exec->stacksize = index;
211 exec->stack = MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
213 /* all non-const results are considered inputs */
214 for (n = 0; n < exec->stacksize; n++) {
215 exec->stack[n].hasinput = 1;
218 /* prepare all nodes for execution */
219 for (n = 0, nodeexec = exec->nodeexec; n < totnodes; n++, nodeexec++) {
220 node = nodeexec->node = nodelist[n];
221 nodeexec->freeexecfunc = node->typeinfo->freeexecfunc;
224 for (sock = node->inputs.first; sock; sock = sock->next) {
225 /* disable the node if an input link is invalid */
226 if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) {
230 ns = setup_stack(exec->stack, ntree, node, sock);
236 /* tag all outputs */
237 for (sock = node->outputs.first; sock; sock = sock->next) {
238 /* ns = */ setup_stack(exec->stack, ntree, node, sock);
241 nodekey = BKE_node_instance_key(parent_key, ntree, node);
242 nodeexec->data.preview = context->previews ?
243 BKE_node_instance_hash_lookup(context->previews, nodekey) :
245 if (node->typeinfo->initexecfunc) {
246 nodeexec->data.data = node->typeinfo->initexecfunc(context, node, nodekey);
257 void ntree_exec_end(bNodeTreeExec *exec)
263 MEM_freeN(exec->stack);
266 for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
267 if (nodeexec->freeexecfunc) {
268 nodeexec->freeexecfunc(nodeexec->data.data);
272 if (exec->nodeexec) {
273 MEM_freeN(exec->nodeexec);
279 /**** Material/Texture trees ****/
281 bNodeThreadStack *ntreeGetThreadStack(bNodeTreeExec *exec, int thread)
283 ListBase *lb = &exec->threadstack[thread];
284 bNodeThreadStack *nts;
286 for (nts = lb->first; nts; nts = nts->next) {
294 nts = MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
295 nts->stack = MEM_dupallocN(exec->stack);
297 BLI_addtail(lb, nts);
303 void ntreeReleaseThreadStack(bNodeThreadStack *nts)
308 bool ntreeExecThreadNodes(bNodeTreeExec *exec, bNodeThreadStack *nts, void *callerdata, int thread)
310 bNodeStack *nsin[MAX_SOCKET] = {NULL}; /* arbitrary... watch this */
311 bNodeStack *nsout[MAX_SOCKET] = {NULL}; /* arbitrary... watch this */
316 /* nodes are presorted, so exec is in order of list */
318 for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
319 node = nodeexec->node;
320 if (node->need_exec) {
321 node_get_stack(node, nts->stack, nsin, nsout);
322 /* Handle muted nodes...
323 * If the mute func is not set, assume the node should never be muted,
324 * and hence execute it!
326 if (node->typeinfo->execfunc && !(node->flag & NODE_MUTED)) {
327 node->typeinfo->execfunc(callerdata, thread, node, &nodeexec->data, nsin, nsout);
332 /* signal to that all went OK, for render */