Blender V4.3
node_exec.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "DNA_node_types.h"
10
11#include "BLI_listbase.h"
12#include "BLI_utildefines.h"
13
14#include "BKE_global.hh"
15#include "BKE_node_runtime.hh"
17
18#include "MEM_guardedalloc.h"
19
20#include "node_exec.hh"
21#include "node_util.hh"
22
24{
25 /* NOTE: INT and BOOL supported as FLOAT. Only for EEVEE. */
27}
28
30{
31 if (stack && sock && sock->stack_index >= 0) {
32 return stack + sock->stack_index;
33 }
34 return nullptr;
35}
36
37void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
38{
39 /* build pointer stack */
40 if (in) {
41 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
42 *(in++) = node_get_socket_stack(stack, sock);
43 }
44 }
45
46 if (out) {
47 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
48 *(out++) = node_get_socket_stack(stack, sock);
49 }
50 }
51}
52
53static void node_init_input_index(bNodeSocket *sock, int *index)
54{
55 /* Only consider existing link if from socket is valid! */
56 if (sock->link && !(sock->link->flag & NODE_LINK_MUTED) && sock->link->fromsock &&
57 sock->link->fromsock->stack_index >= 0)
58 {
59 sock->stack_index = sock->link->fromsock->stack_index;
60 }
61 else {
63 sock->stack_index = (*index)++;
64 }
65 else {
66 sock->stack_index = -1;
67 }
68 }
69}
70
72 int *index,
73 const blender::MutableSpan<bNodeLink> internal_links)
74{
75 const bNodeLink *link;
76 /* copy the stack index from internally connected input to skip the node */
77 for (bNodeLink &iter_link : internal_links) {
78 if (iter_link.tosock == sock) {
79 sock->stack_index = iter_link.fromsock->stack_index;
80 /* set the link pointer to indicate that this socket
81 * should not overwrite the stack value!
82 */
83 sock->link = &iter_link;
84 link = &iter_link;
85 break;
86 }
87 }
88 /* if not internally connected, assign a new stack index anyway to avoid bad stack access */
89 if (!link) {
91 sock->stack_index = (*index)++;
92 }
93 else {
94 sock->stack_index = -1;
95 }
96 }
97}
98
99static void node_init_output_index(bNodeSocket *sock, int *index)
100{
101 if (node_exec_socket_use_stack(sock)) {
102 sock->stack_index = (*index)++;
103 }
104 else {
105 sock->stack_index = -1;
106 }
107}
108
109/* basic preparation of socket stacks */
110static bNodeStack *setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, 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{
143 using namespace blender;
145 bNode *node;
146 bNodeExec *nodeexec;
147 bNodeInstanceKey nodekey;
148 bNodeStack *ns;
149 int index;
150 /* XXX: texture-nodes have threading issues with muting, have to disable it there. */
151
152 /* ensure all sock->link pointers and node levels are correct */
153 /* Using global main here is likely totally wrong, not sure what to do about that one though...
154 * We cannot even check ntree is in global main,
155 * since most of the time it won't be (thanks to ntree design)!!! */
156 BKE_ntree_update_main_tree(G.main, ntree, nullptr);
157
158 ntree->ensure_topology_cache();
159 const Span<bNode *> nodelist = ntree->toposort_left_to_right();
160
161 /* XXX could let callbacks do this for specialized data */
162 exec = MEM_cnew<bNodeTreeExec>("node tree execution data");
163 /* Back-pointer to node tree. */
164 exec->nodetree = ntree;
165
166 /* set stack indices */
167 index = 0;
168 for (const int n : nodelist.index_range()) {
169 node = nodelist[n];
170
171 /* init node socket stack indexes */
172 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
173 node_init_input_index(sock, &index);
174 }
175
176 if (node->flag & NODE_MUTED || node->type == NODE_REROUTE) {
177 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
178 node_init_output_index_muted(sock, &index, node->runtime->internal_links);
179 }
180 }
181 else {
182 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
183 node_init_output_index(sock, &index);
184 }
185 }
186 }
187
188 /* allocated exec data pointers for nodes */
189 exec->totnodes = nodelist.size();
190 exec->nodeexec = (bNodeExec *)MEM_callocN(exec->totnodes * sizeof(bNodeExec),
191 "node execution data");
192 /* allocate data pointer for node stack */
193 exec->stacksize = index;
194 exec->stack = (bNodeStack *)MEM_callocN(exec->stacksize * sizeof(bNodeStack), "bNodeStack");
195
196 /* all non-const results are considered inputs */
197 int n;
198 for (n = 0; n < exec->stacksize; n++) {
199 exec->stack[n].hasinput = 1;
200 }
201
202 /* prepare all nodes for execution */
203 for (n = 0, nodeexec = exec->nodeexec; n < nodelist.size(); n++, nodeexec++) {
204 node = nodeexec->node = nodelist[n];
205 nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
206
207 /* tag inputs */
208 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
209 /* disable the node if an input link is invalid */
210 if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) {
211 node->runtime->need_exec = 0;
212 }
213
214 ns = setup_stack(exec->stack, ntree, node, sock);
215 if (ns) {
216 ns->hasoutput = 1;
217 }
218 }
219
220 /* tag all outputs */
221 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
222 /* ns = */ setup_stack(exec->stack, ntree, node, sock);
223 }
224
225 nodekey = bke::node_instance_key(parent_key, ntree, node);
226 nodeexec->data.preview = context->previews ? (bNodePreview *)bke::node_instance_hash_lookup(
227 context->previews, nodekey) :
228 nullptr;
229 if (node->typeinfo->init_exec_fn) {
230 nodeexec->data.data = node->typeinfo->init_exec_fn(context, node, nodekey);
231 }
232 }
233
234 return exec;
235}
236
238{
239 bNodeExec *nodeexec;
240 int n;
241
242 if (exec->stack) {
243 MEM_freeN(exec->stack);
244 }
245
246 for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
247 if (nodeexec->free_exec_fn) {
248 nodeexec->free_exec_fn(nodeexec->data.data);
249 }
250 }
251
252 if (exec->nodeexec) {
253 MEM_freeN(exec->nodeexec);
254 }
255
257}
#define NODE_REROUTE
Definition BKE_node.hh:804
void BKE_ntree_update_main_tree(Main *bmain, bNodeTree *ntree, NodeTreeUpdateExtraParams *params)
#define LISTBASE_FOREACH(type, var, list)
#define ELEM(...)
@ NODE_MUTED
@ NODE_LINK_MUTED
@ NODE_LINK_VALID
@ SOCK_INT
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_SHADER
@ SOCK_FLOAT
@ SOCK_RGBA
Read Guarded memory(de)allocation.
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
OperationNode * node
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
#define G(x, y, z)
bNodeTreeExec * ntree_exec_begin(bNodeExecContext *context, bNodeTree *ntree, bNodeInstanceKey parent_key)
Definition node_exec.cc:139
void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
Definition node_exec.cc:37
static void node_init_output_index(bNodeSocket *sock, int *index)
Definition node_exec.cc:99
bNodeStack * node_get_socket_stack(bNodeStack *stack, bNodeSocket *sock)
Definition node_exec.cc:29
static void node_init_input_index(bNodeSocket *sock, int *index)
Definition node_exec.cc:53
static bNodeStack * setup_stack(bNodeStack *stack, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
Definition node_exec.cc:110
static void node_init_output_index_muted(bNodeSocket *sock, int *index, const blender::MutableSpan< bNodeLink > internal_links)
Definition node_exec.cc:71
static int node_exec_socket_use_stack(bNodeSocket *sock)
Definition node_exec.cc:23
void ntree_exec_end(bNodeTreeExec *exec)
Definition node_exec.cc:237
static void exec(void *data, int, bNode *node, bNodeExecData *execdata, bNodeStack **in, bNodeStack **out)
void node_socket_get_color(bNodeTree *ntree, bNode *, bNodeSocket *sock, float *value)
Definition node_util.cc:306
float node_socket_get_float(bNodeTree *ntree, bNode *, bNodeSocket *sock)
Definition node_util.cc:294
void node_socket_get_vector(bNodeTree *ntree, bNode *, bNodeSocket *sock, float *value)
Definition node_util.cc:321
bNodePreview * preview
Definition node_util.hh:24
bNodeExecData data
Definition node_exec.hh:29
bNode * node
Definition node_exec.hh:28
blender::bke::NodeFreeExecFunction free_exec_fn
Definition node_exec.hh:32
struct bNodeLink * link
float vec[4]