Blender V4.3
node_tree_anonymous_attributes.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
6#include "NOD_socket.hh"
7
8#include "BKE_node_runtime.hh"
12
14#include "BLI_bit_span_ops.hh"
15
16#include "BLI_resource_scope.hh"
17
18#include <iostream>
19#include <sstream>
20
22namespace aal = nodes::aal;
23using nodes::NodeDeclaration;
24
25static bool socket_is_field(const bNodeSocket &socket)
26{
27 return socket.runtime->field_state == FieldSocketState::IsField;
28}
29
30static const aal::RelationsInNode &get_relations_in_node(const bNode &node, ResourceScope &scope)
31{
32 if (node.is_group()) {
33 if (const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node.id)) {
34 /* Undefined tree types have no relations. */
35 if (!bke::node_tree_is_registered(group)) {
36 return scope.construct<aal::RelationsInNode>();
37 }
38 /* It's possible that the inferencing failed on the group. */
39 if (!group->runtime->anonymous_attribute_inferencing) {
40 return scope.construct<aal::RelationsInNode>();
41 }
42 return group->runtime->anonymous_attribute_inferencing->tree_relations;
43 }
44 }
45 if (node.is_reroute()) {
46 const bNodeSocket &socket = node.input_socket(0);
47 if (socket_is_field(socket)) {
48 static const aal::RelationsInNode field_relations = []() {
49 aal::RelationsInNode relations;
50 relations.reference_relations.append({0, 0});
51 return relations;
52 }();
53 return field_relations;
54 }
55 if (socket.type == SOCK_GEOMETRY) {
56 static const aal::RelationsInNode geometry_relations = []() {
57 aal::RelationsInNode relations;
58 relations.propagate_relations.append({0, 0});
59 return relations;
60 }();
61 return geometry_relations;
62 }
63 }
64 if (node.is_muted()) {
65 aal::RelationsInNode &relations = scope.construct<aal::RelationsInNode>();
66 for (const bNodeLink &link : node.internal_links()) {
67 const bNodeSocket &input = *link.fromsock;
68 const bNodeSocket &output = *link.tosock;
69 if (socket_is_field(input) || socket_is_field(output)) {
70 relations.reference_relations.append({input.index(), output.index()});
71 }
72 else if (input.type == SOCK_GEOMETRY) {
73 BLI_assert(input.type == output.type);
74 relations.propagate_relations.append({input.index(), output.index()});
75 }
76 }
77 return relations;
78 }
79 if (ELEM(node.type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_SIMULATION_OUTPUT, GEO_NODE_BAKE)) {
80 aal::RelationsInNode &relations = scope.construct<aal::RelationsInNode>();
81 {
82 /* Add eval relations. */
83 int last_geometry_index = -1;
84 for (const int i : node.input_sockets().index_range()) {
85 const bNodeSocket &socket = node.input_socket(i);
86 if (socket.type == SOCK_GEOMETRY) {
87 last_geometry_index = i;
88 }
89 else if (socket_is_field(socket)) {
90 if (last_geometry_index != -1) {
91 relations.eval_relations.append({i, last_geometry_index});
92 }
93 }
94 }
95 }
96
97 {
98 /* Add available relations. */
99 int last_geometry_index = -1;
100 for (const int i : node.output_sockets().index_range()) {
101 const bNodeSocket &socket = node.output_socket(i);
102 if (socket.type == SOCK_GEOMETRY) {
103 last_geometry_index = i;
104 }
105 else if (socket_is_field(socket)) {
106 if (last_geometry_index == -1) {
107 relations.available_on_none.append(i);
108 }
109 else {
110 relations.available_relations.append({i, last_geometry_index});
111 }
112 }
113 }
114 }
115 return relations;
116 }
117 if (ELEM(node.type, GEO_NODE_REPEAT_INPUT, GEO_NODE_REPEAT_OUTPUT)) {
118 aal::RelationsInNode &relations = scope.construct<aal::RelationsInNode>();
119 /* TODO: Use smaller set of eval and available relations. For now this makes the pessimistic
120 * assumption that every field may belong to any geometry. In many cases it should be possible
121 * to reduce this set a bit with static analysis. */
122 for (const bNodeSocket *socket : node.output_sockets()) {
123 if (socket->type == SOCK_GEOMETRY) {
124 for (const bNodeSocket *other_output : node.output_sockets()) {
125 if (socket_is_field(*other_output)) {
126 relations.available_relations.append({other_output->index(), socket->index()});
127 }
128 }
129 }
130 }
131 for (const bNodeSocket *socket : node.input_sockets()) {
132 if (socket->type == SOCK_GEOMETRY) {
133 for (const bNodeSocket *other_input : node.input_sockets()) {
134 if (socket_is_field(*other_input)) {
135 relations.eval_relations.append({other_input->index(), socket->index()});
136 }
137 }
138 }
139 }
140 const int input_items_start = (node.type == GEO_NODE_REPEAT_INPUT) ? 1 : 0;
141 const int output_items_start = (node.type == GEO_NODE_REPEAT_INPUT) ? 1 : 0;
142 const int items_num = node.output_sockets().size() - 1 - output_items_start;
143 for (const int i : IndexRange(items_num)) {
144 const int input_index = input_items_start + i;
145 const int output_index = output_items_start + i;
146 const bNodeSocket &input_socket = node.input_socket(input_index);
147 if (input_socket.type == SOCK_GEOMETRY) {
148 relations.propagate_relations.append({input_index, output_index});
149 }
150 else if (socket_is_field(input_socket)) {
151 relations.reference_relations.append({input_index, output_index});
152 }
153 }
154 return relations;
155 }
156 if (const NodeDeclaration *node_decl = node.declaration()) {
157 if (const aal::RelationsInNode *relations = node_decl->anonymous_attribute_relations()) {
158 return *relations;
159 }
160 }
161 return scope.construct<aal::RelationsInNode>();
162}
163
165 ResourceScope &scope)
166{
167 const Span<const bNode *> nodes = tree.all_nodes();
168 Array<const aal::RelationsInNode *> relations_by_node(nodes.size());
169 for (const int i : nodes.index_range()) {
170 relations_by_node[i] = &get_relations_in_node(*nodes[i], scope);
171 }
172 return relations_by_node;
173}
174
176 private:
178
179 public:
185
186 std::string socket_name(const bNodeSocket &socket) const override
187 {
188 if (socket.type == SOCK_GEOMETRY) {
189 std::stringstream ss;
190 ss << socket.identifier << " [";
191 bits::foreach_1_index(result_.required_fields_by_geometry_socket[socket.index_in_tree()],
192 [&](const int i) { ss << i << ","; });
193 ss << "] [";
195 result_.propagate_to_output_by_geometry_socket[socket.index_in_tree()],
196 [&](const int i) { ss << result_.propagated_output_geometry_indices[i] << ","; });
197 ss << "]";
198 return ss.str();
199 }
201 std::stringstream ss;
202 ss << socket.identifier << " [";
203 bits::foreach_1_index(result_.propagated_fields_by_socket[socket.index_in_tree()],
204 [&](const int i) { ss << i << ","; });
205 ss << "]";
206 return ss.str();
207 }
208 return socket.identifier;
209 }
210};
211
214 const BoundedBitSpan mask)
215{
216 if (bits::spans_equal_masked(a, b, mask)) {
217 return false;
218 }
219 bits::inplace_or_masked(a, mask, b);
220 bits::inplace_or_masked(b, mask, a);
221 return true;
222}
223
225{
226 if (bits::spans_equal(a, b)) {
227 return false;
228 }
229 a |= b;
230 b |= a;
231 return true;
232}
233
235 const int64_t a,
236 const int64_t b,
237 const BoundedBitSpan mask)
238{
239 return or_into_each_other_masked(vec[a], vec[b], mask);
240}
241
242static bool or_into_each_other(BitGroupVector<> &vec, const int64_t a, const int64_t b)
243{
244 return or_into_each_other(vec[a], vec[b]);
245}
246
248 const bNodeTree &tree)
249{
250 BLI_assert(!tree.has_available_link_cycle());
251 tree.ensure_interface_cache();
252
253 ResourceScope scope;
254 const Array<const aal::RelationsInNode *> relations_by_node = get_relations_by_node(tree, scope);
255
256 /* Repeat zones need some special behavior because they can propagate anonymous attributes from
257 * right to left (from the repeat output to the repeat input node). */
258 const bNodeTreeZones *zones = tree.zones();
259 Vector<const bNodeTreeZone *> repeat_zones_to_consider;
260 if (zones) {
261 for (const std::unique_ptr<bNodeTreeZone> &zone : zones->zones) {
262 if (ELEM(nullptr, zone->input_node, zone->output_node)) {
263 continue;
264 }
265 if (zone->output_node->type != GEO_NODE_REPEAT_OUTPUT) {
266 continue;
267 }
268 repeat_zones_to_consider.append(zone.get());
269 }
270 }
271
272 Vector<FieldSource> all_field_sources;
273 Vector<GeometrySource> all_geometry_sources;
274
275 /* Find input field and geometry sources. */
276 for (const int i : tree.interface_inputs().index_range()) {
277 const bNodeTreeInterfaceSocket &interface_socket = *tree.interface_inputs()[i];
278 const bNodeSocketType *typeinfo = bke::node_socket_type_find(interface_socket.socket_type);
279 const eNodeSocketDatatype type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM;
280 if (type == SOCK_GEOMETRY) {
281 all_geometry_sources.append_and_get_index({InputGeometrySource{i}});
282 }
283 else if (nodes::socket_type_supports_fields(type)) {
284 all_field_sources.append_and_get_index({InputFieldSource{i}});
285 }
286 }
287 for (const int geometry_source_index : all_geometry_sources.index_range()) {
288 for (const int field_source_index : all_field_sources.index_range()) {
289 all_geometry_sources[geometry_source_index].field_sources.append(field_source_index);
290 all_field_sources[field_source_index].geometry_sources.append(geometry_source_index);
291 }
292 }
293
294 /* Find socket field and geometry sources. */
295 Map<const bNodeSocket *, int> field_source_by_socket;
296 Map<const bNodeSocket *, int> geometry_source_by_socket;
297 for (const bNode *node : tree.all_nodes()) {
298 const aal::RelationsInNode &relations = *relations_by_node[node->index()];
299 for (const aal::AvailableRelation &relation : relations.available_relations) {
300 const bNodeSocket &geometry_socket = node->output_socket(relation.geometry_output);
301 const bNodeSocket &field_socket = node->output_socket(relation.field_output);
302 if (!field_socket.is_available()) {
303 continue;
304 }
305 if (!field_socket.is_directly_linked()) {
306 continue;
307 }
308
309 const int field_source_index = field_source_by_socket.lookup_or_add_cb(&field_socket, [&]() {
310 return all_field_sources.append_and_get_index({SocketFieldSource{&field_socket}});
311 });
312 const int geometry_source_index = geometry_source_by_socket.lookup_or_add_cb(
313 &geometry_socket, [&]() {
314 return all_geometry_sources.append_and_get_index(
315 {SocketGeometrySource{&geometry_socket}});
316 });
317
318 all_field_sources[field_source_index].geometry_sources.append(geometry_source_index);
319 all_geometry_sources[geometry_source_index].field_sources.append(field_source_index);
320 }
321 }
322
323 const int sockets_num = tree.all_sockets().size();
324 BitGroupVector<> propagated_fields_by_socket(sockets_num, all_field_sources.size(), false);
325 BitGroupVector<> propagated_geometries_by_socket(
326 sockets_num, all_geometry_sources.size(), false);
327 BitGroupVector<> available_fields_by_geometry_socket(
328 sockets_num, all_field_sources.size(), false);
329
330 /* Insert field and geometry sources into the maps for the first inferencing pass. */
331 for (const int field_source_index : all_field_sources.index_range()) {
332 const FieldSource &field_source = all_field_sources[field_source_index];
333 if (const auto *input_field = std::get_if<InputFieldSource>(&field_source.data)) {
334 for (const bNode *node : tree.group_input_nodes()) {
335 const bNodeSocket &socket = node->output_socket(input_field->input_index);
336 propagated_fields_by_socket[socket.index_in_tree()][field_source_index].set();
337 }
338 }
339 else {
340 const auto &socket_field = std::get<SocketFieldSource>(field_source.data);
341 propagated_fields_by_socket[socket_field.socket->index_in_tree()][field_source_index].set();
342 }
343 }
344 for (const int geometry_source_index : all_geometry_sources.index_range()) {
345 const GeometrySource &geometry_source = all_geometry_sources[geometry_source_index];
346 if (const auto *input_geometry = std::get_if<InputGeometrySource>(&geometry_source.data)) {
347 for (const bNode *node : tree.group_input_nodes()) {
348 const bNodeSocket &socket = node->output_socket(input_geometry->input_index);
349 const int socket_i = socket.index_in_tree();
350 propagated_geometries_by_socket[socket_i][geometry_source_index].set();
351 for (const int field_source_index : geometry_source.field_sources) {
352 available_fields_by_geometry_socket[socket_i][field_source_index].set();
353 }
354 }
355 }
356 else {
357 const auto &socket_geometry = std::get<SocketGeometrySource>(geometry_source.data);
358 const int socket_i = socket_geometry.socket->index_in_tree();
359 propagated_geometries_by_socket[socket_i][geometry_source_index].set();
360 for (const int field_source_index : geometry_source.field_sources) {
361 available_fields_by_geometry_socket[socket_i][field_source_index].set();
362 }
363 }
364 }
365
366 /* Inferencing pass from left to right to figure out where fields and geometries may be
367 * propagated to. */
368 auto pass_left_to_right = [&]() {
369 for (const bNode *node : tree.toposort_left_to_right()) {
370 for (const bNodeSocket *socket : node->input_sockets()) {
371 if (!socket->is_available()) {
372 continue;
373 }
374 const int dst_index = socket->index_in_tree();
375 for (const bNodeLink *link : socket->directly_linked_links()) {
376 if (link->is_used()) {
377 const int src_index = link->fromsock->index_in_tree();
378 propagated_fields_by_socket[dst_index] |= propagated_fields_by_socket[src_index];
379 propagated_geometries_by_socket[dst_index] |=
380 propagated_geometries_by_socket[src_index];
381 available_fields_by_geometry_socket[dst_index] |=
382 available_fields_by_geometry_socket[src_index];
383 }
384 }
385 }
386 switch (node->type) {
387 default: {
388 const aal::RelationsInNode &relations = *relations_by_node[node->index()];
389 for (const aal::ReferenceRelation &relation : relations.reference_relations) {
390 const bNodeSocket &from_socket = node->input_socket(relation.from_field_input);
391 const bNodeSocket &to_socket = node->output_socket(relation.to_field_output);
392 if (!from_socket.is_available() || !to_socket.is_available()) {
393 continue;
394 }
395 const int src_index = from_socket.index_in_tree();
396 const int dst_index = to_socket.index_in_tree();
397 propagated_fields_by_socket[dst_index] |= propagated_fields_by_socket[src_index];
398 }
399 for (const aal::PropagateRelation &relation : relations.propagate_relations) {
400 const bNodeSocket &from_socket = node->input_socket(relation.from_geometry_input);
401 const bNodeSocket &to_socket = node->output_socket(relation.to_geometry_output);
402 if (!from_socket.is_available() || !to_socket.is_available()) {
403 continue;
404 }
405 const int src_index = from_socket.index_in_tree();
406 const int dst_index = to_socket.index_in_tree();
407 propagated_geometries_by_socket[dst_index] |=
408 propagated_geometries_by_socket[src_index];
409 available_fields_by_geometry_socket[dst_index] |=
410 available_fields_by_geometry_socket[src_index];
411 }
412 /* This zone needs additional special handling because attributes from the input geometry
413 * are propagated to the output node. */
414 if (node->type == GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT) {
415 if (zones == nullptr) {
416 break;
417 }
418 const bNodeTreeZone *zone = zones->get_zone_by_node(node->identifier);
419 if (!zone->input_node) {
420 break;
421 }
422 const bNode *input_node = zone->input_node;
423 const bNode *output_node = node;
424 const int src_index = input_node->input_socket(0).index_in_tree();
425 for (const bNodeSocket *output_socket : output_node->output_sockets()) {
426 if (output_socket->type == SOCK_GEOMETRY) {
427 const int dst_index = output_socket->index_in_tree();
428 propagated_geometries_by_socket[dst_index] |=
429 propagated_geometries_by_socket[src_index];
430 available_fields_by_geometry_socket[dst_index] |=
431 available_fields_by_geometry_socket[src_index];
432 }
433 }
434 }
435 break;
436 }
437 /* The repeat output node needs special handling for two reasons:
438 * - It propagates data directly from the zone input in case the iteration count is zero.
439 * - Fields coming out of the repeat zone are wrapped by a new #FieldSource, because the
440 * intermediate fields from within the zone are not available afterwards. */
442 if (zones == nullptr) {
443 break;
444 }
445 /* If the amount of iterations is zero, the data is directly forwarded from the Repeat
446 * Input to the Repeat Output node. Therefor, all anonymous attributes may be propagated
447 * as well. */
448 const bNodeTreeZone *zone = zones->get_zone_by_node(node->identifier);
449 const int items_num = node->output_sockets().size() - 1;
450 if (const bNode *input_node = zone->input_node) {
451 for (const int i : IndexRange(items_num)) {
452 const int src_index = input_node->input_socket(i + 1).index_in_tree();
453 const int dst_index = node->output_socket(i).index_in_tree();
454 propagated_fields_by_socket[dst_index] |= propagated_fields_by_socket[src_index];
455 propagated_geometries_by_socket[dst_index] |=
456 propagated_geometries_by_socket[src_index];
457 available_fields_by_geometry_socket[dst_index] |=
458 available_fields_by_geometry_socket[src_index];
459 }
460 }
461
462 auto can_propagate_field_source_out_of_zone = [&](const int field_source_index) {
463 const FieldSource &field_source = all_field_sources[field_source_index];
464 if (const auto *socket_field_source = std::get_if<SocketFieldSource>(
465 &field_source.data))
466 {
467 const bNode &field_source_node = socket_field_source->socket->owner_node();
468 if (zone->contains_node_recursively(field_source_node)) {
469 return false;
470 }
471 }
472 return true;
473 };
474 auto can_propagated_geometry_source_out_of_zone = [&](const int geometry_source_index) {
475 const GeometrySource &geometry_source = all_geometry_sources[geometry_source_index];
476 if (const auto *socket_geometry_source = std::get_if<SocketGeometrySource>(
477 &geometry_source.data))
478 {
479 const bNode &geometry_source_node = socket_geometry_source->socket->owner_node();
480 if (zone->contains_node_recursively(geometry_source_node)) {
481 return false;
482 }
483 }
484 return true;
485 };
486
487 /* Propagate fields that have not been created inside of the repeat zones. Field sources
488 * from inside the repeat zone become new field sources on the outside. */
489 for (const int i : IndexRange(items_num)) {
490 const int src_index = node->input_socket(i).index_in_tree();
491 const int dst_index = node->output_socket(i).index_in_tree();
493 propagated_fields_by_socket[src_index], [&](const int field_source_index) {
494 if (can_propagate_field_source_out_of_zone(field_source_index)) {
495 propagated_fields_by_socket[dst_index][field_source_index].set();
496 }
497 });
499 available_fields_by_geometry_socket[src_index], [&](const int field_source_index) {
500 if (can_propagate_field_source_out_of_zone(field_source_index)) {
501 available_fields_by_geometry_socket[dst_index][field_source_index].set();
502 }
503 });
505 propagated_geometries_by_socket[src_index], [&](const int geometry_source_index) {
506 if (can_propagated_geometry_source_out_of_zone(geometry_source_index)) {
507 propagated_geometries_by_socket[dst_index][geometry_source_index].set();
508 }
509 });
510 }
511 break;
512 }
513 }
514 }
515 };
516
517 while (true) {
518 pass_left_to_right();
519
520 /* Repeat zones may need multiple inference passes. That's because anonymous attributes
521 * propagated to a repeat output node also come out of the corresponding repeat input node. */
522 bool changed = false;
523 for (const bNodeTreeZone *zone : repeat_zones_to_consider) {
524 const auto &storage = *static_cast<const NodeGeometryRepeatOutput *>(
525 zone->output_node->storage);
526 /* Only field and geometry sources that come before the repeat zone, can be propagated from
527 * the repeat output to the repeat input node. Otherwise, a socket can depend on the field
528 * source that only comes later in the tree, which leads to a cyclic dependency. */
529 BitVector<> input_propagated_fields(all_field_sources.size(), false);
530 BitVector<> input_propagated_geometries(all_geometry_sources.size(), false);
531 for (const bNodeSocket *socket : zone->input_node->input_sockets()) {
532 const int src = socket->index_in_tree();
533 input_propagated_fields |= propagated_fields_by_socket[src];
534 input_propagated_geometries |= propagated_geometries_by_socket[src];
535 }
536 for (const bNodeLink *link : zone->border_links) {
537 const int src = link->fromsock->index_in_tree();
538 input_propagated_fields |= propagated_fields_by_socket[src];
539 input_propagated_geometries |= propagated_geometries_by_socket[src];
540 }
541 for (const int i : IndexRange(storage.items_num)) {
542 const bNodeSocket &body_input_socket = zone->input_node->output_socket(i + 1);
543 const bNodeSocket &body_output_socket = zone->output_node->input_socket(i);
544 const int in_index = body_input_socket.index_in_tree();
545 const int out_index = body_output_socket.index_in_tree();
546
547 changed |= or_into_each_other_masked(
548 propagated_fields_by_socket, in_index, out_index, input_propagated_fields);
549 changed |= or_into_each_other_masked(
550 propagated_geometries_by_socket, in_index, out_index, input_propagated_geometries);
551 changed |= or_into_each_other_masked(
552 available_fields_by_geometry_socket, in_index, out_index, input_propagated_fields);
553 }
554 }
555 if (!changed) {
556 break;
557 }
558 }
559
560 BitGroupVector<> required_fields_by_geometry_socket(
561 sockets_num, all_field_sources.size(), false);
562 VectorSet<int> propagated_output_geometry_indices;
563 aal::RelationsInNode tree_relations;
564
565 /* Create #PropagateRelation, #AvailableRelation and #ReferenceRelation for the tree based on
566 * the propagated data from above. */
567 if (const bNode *group_output_node = tree.group_output_node()) {
568 for (const bNodeSocket *socket : group_output_node->input_sockets().drop_back(1)) {
569 if (socket->type == SOCK_GEOMETRY) {
570 const BoundedBitSpan propagated_geometries =
571 propagated_geometries_by_socket[socket->index_in_tree()];
572 bits::foreach_1_index(propagated_geometries, [&](const int geometry_source_index) {
573 const GeometrySource &geometry_source = all_geometry_sources[geometry_source_index];
574 if (const auto *input_geometry = std::get_if<InputGeometrySource>(&geometry_source.data))
575 {
576 tree_relations.propagate_relations.append(
577 aal::PropagateRelation{input_geometry->input_index, socket->index()});
578 propagated_output_geometry_indices.add(socket->index());
579 }
580 else {
581 [[maybe_unused]] const auto &socket_geometry = std::get<SocketGeometrySource>(
582 geometry_source.data);
583 for (const int field_source_index : geometry_source.field_sources) {
584 for (const bNodeSocket *other_socket :
585 group_output_node->input_sockets().drop_back(1))
586 {
588 continue;
589 }
590 if (propagated_fields_by_socket[other_socket->index_in_tree()][field_source_index]
591 .test())
592 {
593 tree_relations.available_relations.append(
594 aal::AvailableRelation{other_socket->index(), socket->index()});
595 required_fields_by_geometry_socket[socket->index_in_tree()][field_source_index]
596 .set();
597 }
598 }
599 }
600 }
601 });
602 }
604 const BoundedBitSpan propagated_fields =
605 propagated_fields_by_socket[socket->index_in_tree()];
606 bits::foreach_1_index(propagated_fields, [&](const int field_source_index) {
607 const FieldSource &field_source = all_field_sources[field_source_index];
608 if (const auto *input_field = std::get_if<InputFieldSource>(&field_source.data)) {
609 tree_relations.reference_relations.append(
610 aal::ReferenceRelation{input_field->input_index, socket->index()});
611 }
612 });
613 }
614 }
615 }
616
617 /* Initialize map for second inferencing pass. */
618 BitGroupVector<> propagate_to_output_by_geometry_socket(
619 sockets_num, propagated_output_geometry_indices.size(), false);
620 for (const aal::PropagateRelation &relation : tree_relations.propagate_relations) {
621 const bNodeSocket &socket = tree.group_output_node()->input_socket(
622 relation.to_geometry_output);
623 propagate_to_output_by_geometry_socket[socket.index_in_tree()]
624 [propagated_output_geometry_indices.index_of(
625 relation.to_geometry_output)]
626 .set();
627 }
628
629 /* Inferencing pass from right to left to determine which anonymous attributes have to be
630 * propagated to which geometry sockets. */
631 auto pass_right_to_left = [&]() {
632 for (const bNode *node : tree.toposort_right_to_left()) {
633 for (const bNodeSocket *socket : node->output_sockets()) {
634 if (!socket->is_available()) {
635 continue;
636 }
637 const int dst_index = socket->index_in_tree();
638 for (const bNodeLink *link : socket->directly_linked_links()) {
639 if (link->is_used()) {
640 const int src_index = link->tosock->index_in_tree();
641 required_fields_by_geometry_socket[dst_index] |=
642 required_fields_by_geometry_socket[src_index];
643 propagate_to_output_by_geometry_socket[dst_index] |=
644 propagate_to_output_by_geometry_socket[src_index];
645 }
646 }
647 }
648 const aal::RelationsInNode &relations = *relations_by_node[node->index()];
649 for (const aal::PropagateRelation &relation : relations.propagate_relations) {
650 const bNodeSocket &output_socket = node->output_socket(relation.to_geometry_output);
651 const bNodeSocket &input_socket = node->input_socket(relation.from_geometry_input);
652 const int src_index = output_socket.index_in_tree();
653 const int dst_index = input_socket.index_in_tree();
654 required_fields_by_geometry_socket[dst_index] |=
655 required_fields_by_geometry_socket[src_index];
656 propagate_to_output_by_geometry_socket[dst_index] |=
657 propagate_to_output_by_geometry_socket[src_index];
658 }
659 for (const aal::EvalRelation &relation : relations.eval_relations) {
660 const bNodeSocket &geometry_socket = node->input_socket(relation.geometry_input);
661 const bNodeSocket &field_socket = node->input_socket(relation.field_input);
662 required_fields_by_geometry_socket[geometry_socket.index_in_tree()] |=
663 propagated_fields_by_socket[field_socket.index_in_tree()];
664 }
665
666 switch (node->type) {
668 if (!zones) {
669 break;
670 }
671 /* Propagate from the geometry outputs to the geometry input. */
672 const bNodeTreeZone *zone = zones->get_zone_by_node(node->identifier);
673 if (!zone) {
674 break;
675 }
676 const bNode *input_node = node;
677 const bNode *output_node = zone->output_node;
678 const int dst_index = input_node->input_socket(0).index_in_tree();
679 for (const bNodeSocket *output_socket : output_node->output_sockets()) {
680 if (output_socket->type == SOCK_GEOMETRY) {
681 const int src_index = output_socket->index_in_tree();
682 required_fields_by_geometry_socket[dst_index] |=
683 required_fields_by_geometry_socket[src_index];
684 propagate_to_output_by_geometry_socket[dst_index] |=
685 propagate_to_output_by_geometry_socket[src_index];
686 }
687 }
688 break;
689 }
690 }
691 }
692 };
693
694 while (true) {
695 pass_right_to_left();
696
697 /* Data required by a repeat input node will also be required by the repeat output node,
698 * because that's where the data comes from after the first iteration. */
699 bool changed = false;
700 for (const bNodeTreeZone *zone : repeat_zones_to_consider) {
701 const auto &storage = *static_cast<const NodeGeometryRepeatOutput *>(
702 zone->output_node->storage);
703 for (const int i : IndexRange(storage.items_num)) {
704 const bNodeSocket &body_input_socket = zone->input_node->output_socket(i + 1);
705 const bNodeSocket &body_output_socket = zone->output_node->input_socket(i);
706 const int in_index = body_input_socket.index_in_tree();
707 const int out_index = body_output_socket.index_in_tree();
708
709 changed |= or_into_each_other(required_fields_by_geometry_socket, in_index, out_index);
710 changed |= or_into_each_other(propagate_to_output_by_geometry_socket, in_index, out_index);
711 }
712 }
713 if (!changed) {
714 break;
715 }
716 }
717
718 /* Make sure that only available fields are also required. */
719 required_fields_by_geometry_socket.all_bits() &= available_fields_by_geometry_socket.all_bits();
720
721 /* Create #EvalRelation for the tree. */
722 tree.ensure_topology_cache();
723
724 for (const int interface_i : tree.interface_inputs().index_range()) {
725 const bNodeTreeInterfaceSocket &interface_socket = *tree.interface_inputs()[interface_i];
726 const bNodeSocketType *typeinfo = interface_socket.socket_typeinfo();
727 eNodeSocketDatatype socket_type = typeinfo ? eNodeSocketDatatype(typeinfo->type) : SOCK_CUSTOM;
728 if (socket_type != SOCK_GEOMETRY) {
729 continue;
730 }
731 BitVector<> required_fields(all_field_sources.size(), false);
732 for (const bNode *node : tree.group_input_nodes()) {
733 const bNodeSocket &geometry_socket = node->output_socket(interface_i);
734 required_fields |= required_fields_by_geometry_socket[geometry_socket.index_in_tree()];
735 }
736 bits::foreach_1_index(required_fields, [&](const int field_source_index) {
737 const FieldSource &field_source = all_field_sources[field_source_index];
738 if (const auto *input_field = std::get_if<InputFieldSource>(&field_source.data)) {
739 tree_relations.eval_relations.append(
740 aal::EvalRelation{input_field->input_index, interface_i});
741 }
742 });
743 }
744
745 AnonymousAttributeInferencingResult result{std::move(all_field_sources),
746 std::move(all_geometry_sources),
747 std::move(propagated_fields_by_socket),
748 std::move(propagated_geometries_by_socket),
749 std::move(available_fields_by_geometry_socket),
750 std::move(required_fields_by_geometry_socket),
751 std::move(propagated_output_geometry_indices),
752 std::move(propagate_to_output_by_geometry_socket),
753 std::move(tree_relations)};
754
755/* Print analysis result for debugging purposes. */
756#if 0
757 bNodeTreeToDotOptionsForAnonymousAttributeInferencing options{result};
758 std::cout << "\n\n" << node_tree_to_dot(tree, options) << "\n\n";
759#endif
760 return result;
761}
762
764{
765 tree.ensure_topology_cache();
766
767 if (tree.has_available_link_cycle()) {
768 const bool changed = bool(tree.runtime->anonymous_attribute_inferencing);
769 tree.runtime->anonymous_attribute_inferencing.reset();
770 return changed;
771 }
772
774
775 const bool group_interface_changed =
776 !tree.runtime->anonymous_attribute_inferencing ||
777 tree.runtime->anonymous_attribute_inferencing->tree_relations != result.tree_relations;
778
779 tree.runtime->anonymous_attribute_inferencing =
780 std::make_unique<AnonymousAttributeInferencingResult>(std::move(result));
781
782 return group_interface_changed;
783}
784
785} // namespace blender::bke::anonymous_attribute_inferencing
#define GEO_NODE_FOREACH_GEOMETRY_ELEMENT_INPUT
Definition BKE_node.hh:1378
#define GEO_NODE_REPEAT_OUTPUT
Definition BKE_node.hh:1338
#define GEO_NODE_REPEAT_INPUT
Definition BKE_node.hh:1337
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
eNodeSocketDatatype
@ SOCK_CUSTOM
@ SOCK_GEOMETRY
Value & lookup_or_add_cb(const Key &key, const CreateValueF &create_value)
Definition BLI_map.hh:582
T & construct(Args &&...args)
bool add(const Key &key)
int64_t size() const
int64_t append_and_get_index(const T &value)
void append(const T &value)
IndexRange index_range() const
const bNodeTreeZone * get_zone_by_node(const int32_t node_id) const
Vector< std::unique_ptr< bNodeTreeZone > > zones
local_group_size(16, 16) .push_constant(Type b
CCL_NAMESPACE_BEGIN struct Options options
OperationNode * node
KDTree_3d * tree
void inplace_or_masked(FirstBitSpanT &first_arg, const MaskBitSpanT &mask, const BitSpanT &...args)
void foreach_1_index(const BitSpanT &data, Fn &&fn)
bool spans_equal(const BitSpanT1 &a, const BitSpanT2 &b)
bool spans_equal_masked(const BitSpanT1 &a, const BitSpanT2 &b, const BitSpanT3 &mask)
Array< const nodes::aal::RelationsInNode * > get_relations_by_node(const bNodeTree &tree, ResourceScope &scope)
static const aal::RelationsInNode & get_relations_in_node(const bNode &node, ResourceScope &scope)
static bool or_into_each_other(MutableBoundedBitSpan a, MutableBoundedBitSpan b)
static AnonymousAttributeInferencingResult analyze_anonymous_attribute_usages(const bNodeTree &tree)
static bool or_into_each_other_masked(MutableBoundedBitSpan a, MutableBoundedBitSpan b, const BoundedBitSpan mask)
bNodeSocketType * node_socket_type_find(const char *idname)
Definition node.cc:1763
std::string node_tree_to_dot(const bNodeTree &tree, const bNodeTreeToDotOptions &options=bNodeTreeToDotOptions())
bool node_tree_is_registered(const bNodeTree *ntree)
Definition node.cc:1657
bool socket_type_supports_fields(const eNodeSocketDatatype socket_type)
__int64 int64_t
Definition stdint.h:89
bNodeSocketRuntimeHandle * runtime
char identifier[64]
std::variant< InputGeometrySource, SocketGeometrySource > data
Defines a socket type.
Definition BKE_node.hh:151