Blender V4.5
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
8
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
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)!!! */
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_callocN<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->is_muted() || node->is_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 = MEM_calloc_arrayN<bNodeExec>(exec->totnodes, "node execution data");
191 /* allocate data pointer for node stack */
192 exec->stacksize = index;
193 exec->stack = MEM_calloc_arrayN<bNodeStack>(exec->stacksize, "bNodeStack");
194
195 /* all non-const results are considered inputs */
196 int n;
197 for (n = 0; n < exec->stacksize; n++) {
198 exec->stack[n].hasinput = 1;
199 }
200
201 /* prepare all nodes for execution */
202 for (n = 0, nodeexec = exec->nodeexec; n < nodelist.size(); n++, nodeexec++) {
203 node = nodeexec->node = nodelist[n];
204 nodeexec->free_exec_fn = node->typeinfo->free_exec_fn;
205
206 /* tag inputs */
207 LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
208 /* disable the node if an input link is invalid */
209 if (sock->link && !(sock->link->flag & NODE_LINK_VALID)) {
210 node->runtime->need_exec = 0;
211 }
212
213 ns = setup_stack(exec->stack, ntree, node, sock);
214 if (ns) {
215 ns->hasoutput = 1;
216 }
217 }
218
219 /* tag all outputs */
220 LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
221 /* ns = */ setup_stack(exec->stack, ntree, node, sock);
222 }
223
224 nodekey = bke::node_instance_key(parent_key, ntree, node);
225 if (node->typeinfo->init_exec_fn) {
226 nodeexec->data.data = node->typeinfo->init_exec_fn(context, node, nodekey);
227 }
228 }
229
230 return exec;
231}
232
234{
235 bNodeExec *nodeexec;
236 int n;
237
238 if (exec->stack) {
239 MEM_freeN(exec->stack);
240 }
241
242 for (n = 0, nodeexec = exec->nodeexec; n < exec->totnodes; n++, nodeexec++) {
243 if (nodeexec->free_exec_fn) {
244 nodeexec->free_exec_fn(nodeexec->data.data);
245 }
246 }
247
248 if (exec->nodeexec) {
249 MEM_freeN(exec->nodeexec);
250 }
251
253}
void BKE_ntree_update_after_single_tree_change(Main &bmain, bNodeTree &modified_tree, const NodeTreeUpdateExtraParams &params={})
#define LISTBASE_FOREACH(type, var, list)
#define ELEM(...)
@ 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:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
#define in
#define out
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
bNodeInstanceKey node_instance_key(bNodeInstanceKey parent_key, const bNodeTree *ntree, const bNode *node)
Definition node.cc:5139
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:233
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:304
float node_socket_get_float(bNodeTree *ntree, bNode *, bNodeSocket *sock)
Definition node_util.cc:292
void node_socket_get_vector(bNodeTree *ntree, bNode *, bNodeSocket *sock, float *value)
Definition node_util.cc:319
bNodeExecData data
Definition node_exec.hh:25
bNode * node
Definition node_exec.hh:24
blender::bke::NodeFreeExecFunction free_exec_fn
Definition node_exec.hh:28
struct bNodeLink * link
float vec[4]
bNodeTypeHandle * typeinfo
ListBase inputs
bNodeRuntimeHandle * runtime
ListBase outputs