Blender V4.3
node_tree_field_inferencing.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_node.hh"
6#include "BKE_node_runtime.hh"
7
8#include "NOD_geometry.hh"
10#include "NOD_socket.hh"
11
12#include "BLI_resource_scope.hh"
13#include "BLI_set.hh"
14#include "BLI_stack.hh"
15
17
18using nodes::FieldInferencingInterface;
20using nodes::NodeDeclaration;
21using nodes::OutputFieldDependency;
23using nodes::SocketDeclaration;
24
25static bool is_field_socket_type(const bNodeSocket &socket)
26{
28}
29
31{
32 for (const bNodeSocket *socket : sockets) {
33 if (!socket->owner_node().is_dangling_reroute()) {
34 return false;
35 }
36 }
37 return true;
38}
39
40static InputSocketFieldType get_interface_input_field_type(const bNode &node,
41 const bNodeSocket &socket)
42{
43 if (!is_field_socket_type(socket)) {
44 return InputSocketFieldType::None;
45 }
46 if (node.type == NODE_REROUTE) {
47 return InputSocketFieldType::IsSupported;
48 }
49 if (node.type == NODE_GROUP_OUTPUT) {
50 /* Outputs always support fields when the data type is correct. */
51 return InputSocketFieldType::IsSupported;
52 }
53 if (node.typeinfo == &blender::bke::NodeTypeUndefined) {
54 return InputSocketFieldType::None;
55 }
56 if (node.type == NODE_CUSTOM) {
57 return InputSocketFieldType::None;
58 }
59
60 /* TODO: Ensure declaration exists. */
61 const NodeDeclaration *node_decl = node.declaration();
62
63 /* Node declarations should be implemented for nodes involved here. */
64 BLI_assert(node_decl != nullptr);
65
66 /* Get the field type from the declaration. */
67 const SocketDeclaration &socket_decl = *node_decl->inputs[socket.index()];
68 const InputSocketFieldType field_type = socket_decl.input_field_type;
69 return field_type;
70}
71
72static OutputFieldDependency get_interface_output_field_dependency(const bNode &node,
73 const bNodeSocket &socket)
74{
75 if (!is_field_socket_type(socket)) {
76 /* Non-field sockets always output data. */
77 return OutputFieldDependency::ForDataSource();
78 }
79 if (node.type == NODE_REROUTE) {
80 /* The reroute just forwards what is passed in. */
81 return OutputFieldDependency::ForDependentField();
82 }
83 if (node.type == NODE_GROUP_INPUT) {
84 /* Input nodes get special treatment in #determine_group_input_states. */
85 return OutputFieldDependency::ForDependentField();
86 }
87 if (node.typeinfo == &blender::bke::NodeTypeUndefined) {
88 return OutputFieldDependency::ForDataSource();
89 }
90 if (node.type == NODE_CUSTOM) {
91 return OutputFieldDependency::ForDataSource();
92 }
93
94 const NodeDeclaration *node_decl = node.declaration();
95
96 /* Node declarations should be implemented for nodes involved here. */
97 BLI_assert(node_decl != nullptr);
98
99 /* Use the socket declaration. */
100 const SocketDeclaration &socket_decl = *node_decl->outputs[socket.index()];
101 return socket_decl.output_field_dependency;
102}
103
105 ResourceScope &scope)
106{
107 auto &inferencing_interface = scope.construct<FieldInferencingInterface>();
108 inferencing_interface.inputs.append_n_times(InputSocketFieldType::None,
109 node.input_sockets().size());
110 inferencing_interface.outputs.append_n_times(OutputFieldDependency::ForDataSource(),
111 node.output_sockets().size());
112 return inferencing_interface;
113}
114
121 ResourceScope &scope)
122{
123 /* Node groups already reference all required information, so just return that. */
124 if (node.is_group()) {
125 bNodeTree *group = (bNodeTree *)node.id;
126 if (group == nullptr) {
127 static const FieldInferencingInterface empty_interface;
128 return empty_interface;
129 }
130 if (!bke::node_tree_is_registered(group)) {
131 /* This can happen when there is a linked node group that was not found (see #92799). */
132 return get_dummy_field_inferencing_interface(node, scope);
133 }
134 if (!group->runtime->field_inferencing_interface) {
135 /* This shouldn't happen because referenced node groups should always be updated first. */
137 }
138 return *group->runtime->field_inferencing_interface;
139 }
140
141 auto &inferencing_interface = scope.construct<FieldInferencingInterface>();
142 for (const bNodeSocket *input_socket : node.input_sockets()) {
143 inferencing_interface.inputs.append(get_interface_input_field_type(node, *input_socket));
144 }
145
146 for (const bNodeSocket *output_socket : node.output_sockets()) {
147 inferencing_interface.outputs.append(
148 get_interface_output_field_dependency(node, *output_socket));
149 }
150 return inferencing_interface;
151}
152
158 /* This socket starts a new field. */
159 bool is_field_source = false;
160 /* This socket can never become a field, because the node itself does not support it. */
161 bool is_always_single = false;
162 /* This socket is currently a single value. It could become a field though. */
163 bool is_single = true;
164 /* This socket is required to be a single value. This can be because the node itself only
165 * supports this socket to be a single value, or because a node afterwards requires this to be a
166 * single value. */
167 bool requires_single = false;
168};
169
171 const OutputFieldDependency &field_dependency, const bNode &node)
172{
173 const OutputSocketFieldType type = field_dependency.field_type();
174 Vector<const bNodeSocket *> input_sockets;
175 switch (type) {
176 case OutputSocketFieldType::FieldSource:
177 case OutputSocketFieldType::None: {
178 break;
179 }
180 case OutputSocketFieldType::DependentField: {
181 /* This output depends on all inputs. */
182 input_sockets.extend(node.input_sockets());
183 break;
184 }
185 case OutputSocketFieldType::PartiallyDependent: {
186 /* This output depends only on a few inputs. */
187 for (const int i : field_dependency.linked_input_indices()) {
188 input_sockets.append(&node.input_socket(i));
189 }
190 break;
191 }
192 }
193 return input_sockets;
194}
195
200static OutputFieldDependency find_group_output_dependencies(
201 const bNodeSocket &group_output_socket,
202 const Span<const FieldInferencingInterface *> interface_by_node,
203 const Span<SocketFieldState> field_state_by_socket_id)
204{
205 if (!is_field_socket_type(group_output_socket)) {
206 return OutputFieldDependency::ForDataSource();
207 }
208
209 /* Use a Set here instead of an array indexed by socket id, because we my only need to look at
210 * very few sockets. */
211 Set<const bNodeSocket *> handled_sockets;
212 Stack<const bNodeSocket *> sockets_to_check;
213
214 handled_sockets.add(&group_output_socket);
215 sockets_to_check.push(&group_output_socket);
216
217 /* Keeps track of group input indices that are (indirectly) connected to the output. */
218 Vector<int> linked_input_indices;
219
220 while (!sockets_to_check.is_empty()) {
221 const bNodeSocket *input_socket = sockets_to_check.pop();
222
223 if (!input_socket->is_directly_linked() &&
224 !field_state_by_socket_id[input_socket->index_in_tree()].is_single)
225 {
226 /* This socket uses a field as input by default. */
227 return OutputFieldDependency::ForFieldSource();
228 }
229
230 for (const bNodeSocket *origin_socket : input_socket->directly_linked_sockets()) {
231 const bNode &origin_node = origin_socket->owner_node();
232 const SocketFieldState &origin_state =
233 field_state_by_socket_id[origin_socket->index_in_tree()];
234
235 if (origin_state.is_field_source) {
236 if (origin_node.type == NODE_GROUP_INPUT) {
237 /* Found a group input that the group output depends on. */
238 linked_input_indices.append_non_duplicates(origin_socket->index());
239 }
240 else {
241 /* Found a field source that is not the group input. So the output is always a field. */
242 return OutputFieldDependency::ForFieldSource();
243 }
244 }
245 else if (!origin_state.is_single) {
246 const FieldInferencingInterface &inferencing_interface =
247 *interface_by_node[origin_node.index()];
248 const OutputFieldDependency &field_dependency =
249 inferencing_interface.outputs[origin_socket->index()];
250
251 /* Propagate search further to the left. */
252 for (const bNodeSocket *origin_input_socket :
253 gather_input_socket_dependencies(field_dependency, origin_node))
254 {
255 if (!origin_input_socket->is_available()) {
256 continue;
257 }
258 if (!field_state_by_socket_id[origin_input_socket->index_in_tree()].is_single) {
259 if (handled_sockets.add(origin_input_socket)) {
260 sockets_to_check.push(origin_input_socket);
261 }
262 }
263 }
264 }
265 }
266 }
267 return OutputFieldDependency::ForPartiallyDependentField(std::move(linked_input_indices));
268}
269
271enum class eFieldStateSyncResult : char {
272 /* Nothing changed. */
273 NONE = 0,
274 /* State A has been modified. */
275 CHANGED_A = (1 << 0),
276 /* State B has been modified. */
277 CHANGED_B = (1 << 1),
278};
280
281
287{
288 const bool requires_single = a.requires_single || b.requires_single;
289 const bool is_single = a.is_single && b.is_single;
290
292 if (a.requires_single != requires_single || a.is_single != is_single) {
294 }
295 if (b.requires_single != requires_single || b.is_single != is_single) {
297 }
298
299 a.requires_single = requires_single;
300 b.requires_single = requires_single;
301 a.is_single = is_single;
302 b.is_single = is_single;
303
304 return res;
305}
306
313 const bNode &input_node,
314 const bNode &output_node,
315 const MutableSpan<SocketFieldState> field_state_by_socket_id)
316{
318 for (const int i : output_node.output_sockets().index_range()) {
319 /* First input node output is Delta Time which does not appear in the output node outputs. */
320 const bNodeSocket &input_socket = input_node.output_socket(i + 1);
321 const bNodeSocket &output_socket = output_node.output_socket(i);
322 SocketFieldState &input_state = field_state_by_socket_id[input_socket.index_in_tree()];
323 SocketFieldState &output_state = field_state_by_socket_id[output_socket.index_in_tree()];
324 res |= sync_field_states(input_state, output_state);
325 }
326 return res;
327}
328
330 const bNode &input_node,
331 const bNode &output_node,
332 const MutableSpan<SocketFieldState> field_state_by_socket_id)
333{
335 const NodeGeometryRepeatOutput &storage = *static_cast<const NodeGeometryRepeatOutput *>(
336 output_node.storage);
337 for (const int i : IndexRange(storage.items_num)) {
338 const bNodeSocket &input_socket = input_node.output_socket(i + 1);
339 const bNodeSocket &output_socket = output_node.output_socket(i);
340 SocketFieldState &input_state = field_state_by_socket_id[input_socket.index_in_tree()];
341 SocketFieldState &output_state = field_state_by_socket_id[output_socket.index_in_tree()];
342 res |= sync_field_states(input_state, output_state);
343 }
344 return res;
345}
346
348 const bNodeTree &tree,
349 const bNode &node,
350 const MutableSpan<SocketFieldState> field_state_by_socket_id)
351{
352 tree.ensure_topology_cache();
353
354 bool need_update = false;
355
356 /* Sync field state between zone nodes and schedule another pass if necessary. */
357 switch (node.type) {
359 const NodeGeometrySimulationInput &data = *static_cast<const NodeGeometrySimulationInput *>(
360 node.storage);
361 if (const bNode *output_node = tree.node_by_id(data.output_node_id)) {
363 node, *output_node, field_state_by_socket_id);
364 if (bool(sync_result & eFieldStateSyncResult::CHANGED_B)) {
365 need_update = true;
366 }
367 }
368 break;
369 }
371 for (const bNode *input_node : tree.nodes_by_type("GeometryNodeSimulationInput")) {
372 const NodeGeometrySimulationInput &data =
373 *static_cast<const NodeGeometrySimulationInput *>(input_node->storage);
374 if (node.identifier == data.output_node_id) {
376 *input_node, node, field_state_by_socket_id);
377 if (bool(sync_result & eFieldStateSyncResult::CHANGED_A)) {
378 need_update = true;
379 }
380 }
381 }
382 break;
383 }
385 const NodeGeometryRepeatInput &data = *static_cast<const NodeGeometryRepeatInput *>(
386 node.storage);
387 if (const bNode *output_node = tree.node_by_id(data.output_node_id)) {
389 node, *output_node, field_state_by_socket_id);
390 if (bool(sync_result & eFieldStateSyncResult::CHANGED_B)) {
391 need_update = true;
392 }
393 }
394 break;
395 }
397 for (const bNode *input_node : tree.nodes_by_type("GeometryNodeRepeatInput")) {
398 const NodeGeometryRepeatInput &data = *static_cast<const NodeGeometryRepeatInput *>(
399 input_node->storage);
400 if (node.identifier == data.output_node_id) {
402 *input_node, node, field_state_by_socket_id);
403 if (bool(sync_result & eFieldStateSyncResult::CHANGED_A)) {
404 need_update = true;
405 }
406 }
407 }
408 break;
409 }
410 }
411
412 return need_update;
413}
414
416 const bNodeTree &tree,
417 const Span<const FieldInferencingInterface *> interface_by_node,
418 const MutableSpan<SocketFieldState> field_state_by_socket_id)
419{
420 const Span<const bNode *> toposort_result = tree.toposort_right_to_left();
421
422 while (true) {
423 /* Node updates may require several passes due to cyclic dependencies caused by simulation or
424 * repeat input/output nodes. */
425 bool need_update = false;
426
427 for (const bNode *node : toposort_result) {
428 const FieldInferencingInterface &inferencing_interface = *interface_by_node[node->index()];
429
430 for (const bNodeSocket *output_socket : node->output_sockets()) {
431 SocketFieldState &state = field_state_by_socket_id[output_socket->index_in_tree()];
432
433 const OutputFieldDependency &field_dependency =
434 inferencing_interface.outputs[output_socket->index()];
435
436 if (field_dependency.field_type() == OutputSocketFieldType::FieldSource) {
437 continue;
438 }
439 if (field_dependency.field_type() == OutputSocketFieldType::None) {
440 state.requires_single = true;
441 state.is_always_single = true;
442 continue;
443 }
444
445 /* The output is required to be a single value when it is connected to any input that does
446 * not support fields. */
447 for (const bNodeSocket *target_socket : output_socket->directly_linked_sockets()) {
448 if (target_socket->is_available()) {
449 state.requires_single |=
450 field_state_by_socket_id[target_socket->index_in_tree()].requires_single;
451 }
452 }
453
454 if (state.requires_single) {
455 bool any_input_is_field_implicitly = false;
457 field_dependency, *node);
458 for (const bNodeSocket *input_socket : connected_inputs) {
459 if (!input_socket->is_available()) {
460 continue;
461 }
462 if (inferencing_interface.inputs[input_socket->index()] ==
463 InputSocketFieldType::Implicit)
464 {
465 if (!input_socket->is_logically_linked()) {
466 any_input_is_field_implicitly = true;
467 break;
468 }
469 }
470 }
471 if (any_input_is_field_implicitly) {
472 /* This output isn't a single value actually. */
473 state.requires_single = false;
474 }
475 else {
476 /* If the output is required to be a single value, the connected inputs in the same
477 * node must not be fields as well. */
478 for (const bNodeSocket *input_socket : connected_inputs) {
479 field_state_by_socket_id[input_socket->index_in_tree()].requires_single = true;
480 }
481 }
482 }
483 }
484
485 /* Some inputs do not require fields independent of what the outputs are connected to. */
486 for (const bNodeSocket *input_socket : node->input_sockets()) {
487 SocketFieldState &state = field_state_by_socket_id[input_socket->index_in_tree()];
488 if (inferencing_interface.inputs[input_socket->index()] == InputSocketFieldType::None) {
489 state.requires_single = true;
490 state.is_always_single = true;
491 }
492 }
493
494 /* Find reverse dependencies and resolve conflicts, which may require another pass. */
495 if (propagate_special_data_requirements(tree, *node, field_state_by_socket_id)) {
496 need_update = true;
497 }
498 }
499
500 if (!need_update) {
501 break;
502 }
503 }
504}
505
507 const bNodeTree &tree,
508 FieldInferencingInterface &new_inferencing_interface,
509 const MutableSpan<SocketFieldState> field_state_by_socket_id)
510{
511 {
512 /* Non-field inputs never support fields. */
513 for (const int index : tree.interface_inputs().index_range()) {
514 const bNodeTreeInterfaceSocket *group_input = tree.interface_inputs()[index];
515 const bNodeSocketType *typeinfo = group_input->socket_typeinfo();
516 const eNodeSocketDatatype type = typeinfo ? eNodeSocketDatatype(typeinfo->type) :
519 new_inferencing_interface.inputs[index] = InputSocketFieldType::None;
520 }
521 else if (group_input->default_input != NODE_INPUT_DEFAULT_VALUE) {
522 new_inferencing_interface.inputs[index] = InputSocketFieldType::Implicit;
523 }
524 else if (is_layer_selection_field(*group_input)) {
525 new_inferencing_interface.inputs[index] = InputSocketFieldType::Implicit;
526 }
527 else if (group_input->flag & NODE_INTERFACE_SOCKET_SINGLE_VALUE_ONLY) {
528 new_inferencing_interface.inputs[index] = InputSocketFieldType::None;
529 }
530 }
531 }
532 /* Check if group inputs are required to be single values, because they are (indirectly)
533 * connected to some socket that does not support fields. */
534 for (const bNode *node : tree.group_input_nodes()) {
535 for (const bNodeSocket *output_socket : node->output_sockets().drop_back(1)) {
536 SocketFieldState &state = field_state_by_socket_id[output_socket->index_in_tree()];
537 const int output_index = output_socket->index();
538 if (state.requires_single) {
539 if (new_inferencing_interface.inputs[output_index] == InputSocketFieldType::Implicit) {
540 /* Don't override hard-coded implicit fields. */
541 continue;
542 }
543 new_inferencing_interface.inputs[output_index] = InputSocketFieldType::None;
544 }
545 }
546 }
547 /* If an input does not support fields, this should be reflected in all Group Input nodes. */
548 for (const bNode *node : tree.group_input_nodes()) {
549 for (const bNodeSocket *output_socket : node->output_sockets().drop_back(1)) {
550 SocketFieldState &state = field_state_by_socket_id[output_socket->index_in_tree()];
551 const bool supports_field = new_inferencing_interface.inputs[output_socket->index()] !=
552 InputSocketFieldType::None;
553 if (supports_field) {
554 state.is_single = false;
555 state.is_field_source = true;
556 }
557 else {
558 state.requires_single = true;
559 }
560 }
561 SocketFieldState &dummy_socket_state =
562 field_state_by_socket_id[node->output_sockets().last()->index_in_tree()];
563 dummy_socket_state.requires_single = true;
564 }
565}
566
568 const bNodeTree &tree,
569 const Span<const FieldInferencingInterface *> interface_by_node,
570 const MutableSpan<SocketFieldState> field_state_by_socket_id)
571{
572 const Span<const bNode *> toposort_result = tree.toposort_left_to_right();
573
574 while (true) {
575 /* Node updates may require several passes due to cyclic dependencies. */
576 bool need_update = false;
577
578 for (const bNode *node : toposort_result) {
579 if (node->type == NODE_GROUP_INPUT) {
580 continue;
581 }
582
583 const FieldInferencingInterface &inferencing_interface = *interface_by_node[node->index()];
584
585 /* Update field state of input sockets, also taking into account linked origin sockets. */
586 for (const bNodeSocket *input_socket : node->input_sockets()) {
587 SocketFieldState &state = field_state_by_socket_id[input_socket->index_in_tree()];
588 if (state.is_always_single) {
589 state.is_single = true;
590 continue;
591 }
592 state.is_single = true;
593 if (!input_socket->is_directly_linked() ||
594 all_dangling_reroutes(input_socket->directly_linked_sockets()))
595 {
596 if (inferencing_interface.inputs[input_socket->index()] ==
597 InputSocketFieldType::Implicit)
598 {
599 state.is_single = false;
600 }
601 }
602 else {
603 for (const bNodeSocket *origin_socket : input_socket->directly_linked_sockets()) {
604 if (!field_state_by_socket_id[origin_socket->index_in_tree()].is_single) {
605 state.is_single = false;
606 break;
607 }
608 }
609 }
610 }
611
612 /* Update field state of output sockets, also taking into account input sockets. */
613 for (const bNodeSocket *output_socket : node->output_sockets()) {
614 SocketFieldState &state = field_state_by_socket_id[output_socket->index_in_tree()];
615 const OutputFieldDependency &field_dependency =
616 inferencing_interface.outputs[output_socket->index()];
617
618 switch (field_dependency.field_type()) {
619 case OutputSocketFieldType::None: {
620 state.is_single = true;
621 break;
622 }
623 case OutputSocketFieldType::FieldSource: {
624 state.is_single = false;
625 state.is_field_source = true;
626 break;
627 }
628 case OutputSocketFieldType::PartiallyDependent:
629 case OutputSocketFieldType::DependentField: {
630 for (const bNodeSocket *input_socket :
631 gather_input_socket_dependencies(field_dependency, *node))
632 {
633 if (!input_socket->is_available()) {
634 continue;
635 }
636 if (!field_state_by_socket_id[input_socket->index_in_tree()].is_single) {
637 state.is_single = false;
638 break;
639 }
640 }
641 break;
642 }
643 }
644 }
645
646 /* Find reverse dependencies and resolve conflicts, which may require another pass. */
647 if (propagate_special_data_requirements(tree, *node, field_state_by_socket_id)) {
648 need_update = true;
649 }
650 }
651
652 if (!need_update) {
653 break;
654 }
655 }
656}
657
659 const bNodeTree &tree,
660 FieldInferencingInterface &new_inferencing_interface,
661 const Span<const FieldInferencingInterface *> interface_by_node,
662 const Span<SocketFieldState> field_state_by_socket_id)
663{
664 const bNode *group_output_node = tree.group_output_node();
665 if (!group_output_node) {
666 return;
667 }
668
669 for (const bNodeSocket *group_output_socket : group_output_node->input_sockets().drop_back(1)) {
670 OutputFieldDependency field_dependency = find_group_output_dependencies(
671 *group_output_socket, interface_by_node, field_state_by_socket_id);
672 new_inferencing_interface.outputs[group_output_socket->index()] = std::move(field_dependency);
673 }
674}
675
677 const Span<SocketFieldState> field_state_by_socket_id)
678{
679 auto get_state_to_store = [&](const SocketFieldState &state) {
680 if (state.is_always_single) {
682 }
683 if (!state.is_single) {
685 }
686 if (state.requires_single) {
688 }
690 };
691
692 for (const bNodeSocket *socket : tree.all_sockets()) {
693 const SocketFieldState &state = field_state_by_socket_id[socket->index_in_tree()];
694 const_cast<bNodeSocket *>(socket)->runtime->field_state = get_state_to_store(state);
695 }
696}
697
699 const Span<const bNode *> nodes,
701 ResourceScope &scope)
702{
703 for (const int i : nodes.index_range()) {
704 interface_by_node[i] = &get_node_field_inferencing_interface(*nodes[i], scope);
705 }
706}
707
709{
711 tree.ensure_topology_cache();
712 tree.ensure_interface_cache();
713
714 const Span<const bNode *> nodes = tree.all_nodes();
715 ResourceScope scope;
716 Array<const FieldInferencingInterface *> interface_by_node(nodes.size());
717 prepare_inferencing_interfaces(nodes, interface_by_node, scope);
718
719 /* Create new inferencing interface for this node group. */
720 std::unique_ptr<FieldInferencingInterface> new_inferencing_interface =
721 std::make_unique<FieldInferencingInterface>();
722 new_inferencing_interface->inputs.resize(tree.interface_inputs().size(),
723 InputSocketFieldType::IsSupported);
724 new_inferencing_interface->outputs.resize(tree.interface_outputs().size(),
725 OutputFieldDependency::ForDataSource());
726
727 /* Keep track of the state of all sockets. The index into this array is #SocketRef::id(). */
728 Array<SocketFieldState> field_state_by_socket_id(tree.all_sockets().size());
729
731 tree, interface_by_node, field_state_by_socket_id);
732 determine_group_input_states(tree, *new_inferencing_interface, field_state_by_socket_id);
733 propagate_field_status_from_left_to_right(tree, interface_by_node, field_state_by_socket_id);
735 tree, *new_inferencing_interface, interface_by_node, field_state_by_socket_id);
736 update_socket_states(tree, field_state_by_socket_id);
737
738 /* Update the previous group interface. */
739 const bool group_interface_changed = !tree.runtime->field_inferencing_interface ||
740 *tree.runtime->field_inferencing_interface !=
741 *new_inferencing_interface;
742 tree.runtime->field_inferencing_interface = std::move(new_inferencing_interface);
743
744 return group_interface_changed;
745}
746
747} // namespace blender::bke::node_field_inferencing
#define NODE_REROUTE
Definition BKE_node.hh:804
#define NODE_CUSTOM
Definition BKE_node.hh:799
#define NODE_GROUP_OUTPUT
Definition BKE_node.hh:806
#define GEO_NODE_SIMULATION_OUTPUT
Definition BKE_node.hh:1331
#define GEO_NODE_REPEAT_OUTPUT
Definition BKE_node.hh:1338
#define GEO_NODE_REPEAT_INPUT
Definition BKE_node.hh:1337
#define NODE_GROUP_INPUT
Definition BKE_node.hh:805
#define GEO_NODE_SIMULATION_INPUT
Definition BKE_node.hh:1330
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ENUM_OPERATORS(_type, _max)
@ NODE_INTERFACE_SOCKET_SINGLE_VALUE_ONLY
#define NODE_INPUT_DEFAULT_VALUE
@ NTREE_GEOMETRY
eNodeSocketDatatype
@ SOCK_CUSTOM
T & construct(Args &&...args)
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_stack.hh:308
void push(const T &value)
Definition BLI_stack.hh:213
void append(const T &value)
void extend(Span< T > array)
void append_non_duplicates(const T &value)
void append_n_times(const T &value, const int64_t n)
Vector< SocketDeclaration * > inputs
Vector< SocketDeclaration * > outputs
local_group_size(16, 16) .push_constant(Type b
KDTree_3d * tree
static ulong state[N]
static void determine_group_output_states(const bNodeTree &tree, FieldInferencingInterface &new_inferencing_interface, const Span< const FieldInferencingInterface * > interface_by_node, const Span< SocketFieldState > field_state_by_socket_id)
static void update_socket_states(const bNodeTree &tree, const Span< SocketFieldState > field_state_by_socket_id)
static InputSocketFieldType get_interface_input_field_type(const bNode &node, const bNodeSocket &socket)
static eFieldStateSyncResult sync_field_states(SocketFieldState &a, SocketFieldState &b)
static OutputFieldDependency get_interface_output_field_dependency(const bNode &node, const bNodeSocket &socket)
static bool all_dangling_reroutes(const Span< const bNodeSocket * > sockets)
static const FieldInferencingInterface & get_node_field_inferencing_interface(const bNode &node, ResourceScope &scope)
static bool propagate_special_data_requirements(const bNodeTree &tree, const bNode &node, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static bool is_field_socket_type(const bNodeSocket &socket)
static OutputFieldDependency find_group_output_dependencies(const bNodeSocket &group_output_socket, const Span< const FieldInferencingInterface * > interface_by_node, const Span< SocketFieldState > field_state_by_socket_id)
static void propagate_field_status_from_left_to_right(const bNodeTree &tree, const Span< const FieldInferencingInterface * > interface_by_node, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static void propagate_data_requirements_from_right_to_left(const bNodeTree &tree, const Span< const FieldInferencingInterface * > interface_by_node, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static Vector< const bNodeSocket * > gather_input_socket_dependencies(const OutputFieldDependency &field_dependency, const bNode &node)
static const FieldInferencingInterface & get_dummy_field_inferencing_interface(const bNode &node, ResourceScope &scope)
static void prepare_inferencing_interfaces(const Span< const bNode * > nodes, MutableSpan< const FieldInferencingInterface * > interface_by_node, ResourceScope &scope)
static void determine_group_input_states(const bNodeTree &tree, FieldInferencingInterface &new_inferencing_interface, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static eFieldStateSyncResult repeat_field_state_sync(const bNode &input_node, const bNode &output_node, const MutableSpan< SocketFieldState > field_state_by_socket_id)
static eFieldStateSyncResult simulation_nodes_field_state_sync(const bNode &input_node, const bNode &output_node, const MutableSpan< SocketFieldState > field_state_by_socket_id)
bNodeType NodeTypeUndefined
Definition node.cc:135
bool node_tree_is_registered(const bNodeTree *ntree)
Definition node.cc:1657
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
bool is_layer_selection_field(const bNodeTreeInterfaceSocket &socket)
bNodeSocketTypeHandle * typeinfo
void * storage
int16_t type
Defines a socket type.
Definition BKE_node.hh:151