Blender  V3.3
MOD_nodes_evaluator.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "MOD_nodes_evaluator.hh"
4 
6 
7 #include "NOD_geometry_exec.hh"
9 
10 #include "DEG_depsgraph_query.h"
11 
12 #include "FN_field.hh"
13 #include "FN_field_cpp_type.hh"
14 #include "FN_multi_function.hh"
15 
16 #include "BLT_translation.h"
17 
19 #include "BLI_generic_value_map.hh"
20 #include "BLI_stack.hh"
21 #include "BLI_task.h"
22 #include "BLI_task.hh"
23 #include "BLI_vector_set.hh"
24 
25 #include <chrono>
26 
28 
29 using fn::Field;
30 using fn::GField;
31 using fn::ValueOrField;
34 using namespace fn::multi_function_types;
35 
36 enum class ValueUsage : uint8_t {
37  /* The value is definitely used. */
38  Required,
39  /* The value may be used. */
40  Maybe,
41  /* The value will definitely not be used. */
42  Unused,
43 };
44 
49  void *value = nullptr;
50 };
51 
67  int provided_value_count = 0;
68 
69  bool all_values_available() const
70  {
71  return this->missing_values() == 0;
72  }
73 
74  int missing_values() const
75  {
76  return this->values.size() - this->provided_value_count;
77  }
78 
79  void add_value(const DSocket origin, void *value)
80  {
81  const int index = this->find_available_index(origin);
82  this->values[index] = value;
83  this->provided_value_count++;
84  }
85 
86  private:
87  int find_available_index(DSocket origin) const
88  {
89  for (const int i : origins.index_range()) {
90  if (values[i] != nullptr) {
91  continue;
92  }
93  if (origins[i] != origin) {
94  continue;
95  }
96  return i;
97  }
99  return -1;
100  }
101 };
102 
103 struct InputState {
104 
108  const CPPType *type = nullptr;
109 
117  union {
120  } value;
121 
129 
140  bool was_ready_for_execution = false;
141 
146  bool force_compute = false;
147 };
148 
149 struct OutputState {
154  bool has_been_computed = false;
155 
162 
171  ValueUsage output_usage_for_execution = ValueUsage::Maybe;
172 
177  int potential_users = 0;
178 };
179 
180 enum class NodeScheduleState {
184  NotScheduled,
188  Scheduled,
192  Running,
200 };
201 
202 struct NodeState {
208 
219 
224  bool non_lazy_inputs_handled = false;
225 
229  bool has_been_executed = false;
230 
236  bool node_has_finished = false;
237 
243  int missing_required_inputs = 0;
244 
250 };
251 
262  /* Store a pointer instead of `NodeState` directly to keep it small and movable. */
263  NodeState *state = nullptr;
264 
265  friend bool operator==(const NodeWithState &a, const NodeWithState &b)
266  {
267  return a.node == b.node;
268  }
269 
270  friend bool operator==(const NodeWithState &a, const DNode &b)
271  {
272  return a.node == b;
273  }
274 
275  friend bool operator==(const DNode &a, const NodeWithState &b)
276  {
277  return a == b.node;
278  }
279 
280  uint64_t hash() const
281  {
282  return node.hash();
283  }
284 
285  static uint64_t hash_as(const DNode &node)
286  {
287  return node.hash();
288  }
289 };
290 
291 class GeometryNodesEvaluator;
292 
298  public:
302  const DNode node;
304 
316 
317  LockedNode(const DNode node, NodeState &node_state) : node(node), node_state(node_state)
318  {
319  }
320 };
321 
322 static const CPPType *get_socket_cpp_type(const SocketRef &socket)
323 {
324  const bNodeSocketType *typeinfo = socket.typeinfo();
325  if (typeinfo->geometry_nodes_cpp_type == nullptr) {
326  return nullptr;
327  }
328  const CPPType *type = typeinfo->geometry_nodes_cpp_type;
329  if (type == nullptr) {
330  return nullptr;
331  }
332  /* The evaluator only supports types that have special member functions. */
333  if (!type->has_special_member_functions()) {
334  return nullptr;
335  }
336  return type;
337 }
338 
339 static const CPPType *get_socket_cpp_type(const DSocket socket)
340 {
341  return get_socket_cpp_type(*socket.socket_ref());
342 }
343 
348 static bool get_implicit_socket_input(const SocketRef &socket, void *r_value)
349 {
350  const NodeRef &node = socket.node();
351  const nodes::NodeDeclaration *node_declaration = node.declaration();
352  if (node_declaration == nullptr) {
353  return false;
354  }
355  const nodes::SocketDeclaration &socket_declaration = *node_declaration->inputs()[socket.index()];
356  if (socket_declaration.input_field_type() == nodes::InputSocketFieldType::Implicit) {
357  const bNode &bnode = *socket.bnode();
358  if (socket.typeinfo()->type == SOCK_VECTOR) {
359  if (bnode.type == GEO_NODE_SET_CURVE_HANDLES) {
360  StringRef side = ((NodeGeometrySetCurveHandlePositions *)bnode.storage)->mode ==
362  "handle_left" :
363  "handle_right";
364  new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>(side));
365  return true;
366  }
367  if (bnode.type == GEO_NODE_EXTRUDE_MESH) {
368  new (r_value)
369  ValueOrField<float3>(Field<float3>(std::make_shared<bke::NormalFieldInput>()));
370  return true;
371  }
372  new (r_value) ValueOrField<float3>(bke::AttributeFieldInput::Create<float3>("position"));
373  return true;
374  }
375  if (socket.typeinfo()->type == SOCK_INT) {
377  new (r_value)
378  ValueOrField<int>(Field<int>(std::make_shared<bke::IDAttributeFieldInput>()));
379  return true;
380  }
381  new (r_value) ValueOrField<int>(Field<int>(std::make_shared<fn::IndexFieldInput>()));
382  return true;
383  }
384  }
385  return false;
386 }
387 
388 static void get_socket_value(const SocketRef &socket, void *r_value)
389 {
390  if (get_implicit_socket_input(socket, r_value)) {
391  return;
392  }
393 
394  const bNodeSocketType *typeinfo = socket.typeinfo();
395  typeinfo->get_geometry_nodes_cpp_value(*socket.bsocket(), r_value);
396 }
397 
399 {
400  return node->typeinfo()->geometry_node_execute_supports_laziness;
401 }
402 
406 };
407 
410  private:
411  GeometryNodesEvaluator &evaluator_;
412  NodeState &node_state_;
413  NodeTaskRunState *run_state_;
414 
415  public:
417  DNode dnode,
418  NodeState &node_state,
419  NodeTaskRunState *run_state);
420 
421  bool can_get_input(StringRef identifier) const override;
422  bool can_set_output(StringRef identifier) const override;
423  GMutablePointer extract_input(StringRef identifier) override;
424  Vector<GMutablePointer> extract_multi_input(StringRef identifier) override;
425  GPointer get_input(StringRef identifier) const override;
426  GMutablePointer alloc_output_value(const CPPType &type) override;
427  void set_output(StringRef identifier, GMutablePointer value) override;
428  void set_input_unused(StringRef identifier) override;
429  bool output_is_required(StringRef identifier) const override;
430 
431  bool lazy_require_input(StringRef identifier) override;
432  bool lazy_output_is_required(StringRef identifier) const override;
433 
434  void set_default_remaining_outputs() override;
435 };
436 
438  private:
443  LinearAllocator<> &outer_allocator_;
453 
458  VectorSet<NodeWithState> node_states_;
459 
463  TaskPool *task_pool_ = nullptr;
464 
466  const blender::bke::DataTypeConversions &conversions_;
467 
468  friend NodeParamsProvider;
469 
470  public:
472  : outer_allocator_(params.allocator),
473  params_(params),
474  conversions_(blender::bke::get_implicit_type_conversions())
475  {
476  }
477 
478  void execute()
479  {
480  task_pool_ = BLI_task_pool_create(this, TASK_PRIORITY_HIGH);
481 
482  this->create_states_for_reachable_nodes();
483  this->forward_group_inputs();
484  this->schedule_initial_nodes();
485 
486  /* This runs until all initially requested inputs have been computed. */
487  BLI_task_pool_work_and_wait(task_pool_);
488  BLI_task_pool_free(task_pool_);
489 
490  this->extract_group_outputs();
491  this->destruct_node_states();
492  }
493 
495  {
496  /* This does a depth first search for all the nodes that are reachable from the group
497  * outputs. This finds all nodes that are relevant. */
498  Stack<DNode> nodes_to_check;
499  /* Start at the output sockets. */
500  for (const DInputSocket &socket : params_.output_sockets) {
501  nodes_to_check.push(socket.node());
502  }
503  for (const DSocket &socket : params_.force_compute_sockets) {
504  nodes_to_check.push(socket.node());
505  }
506  /* Use the local allocator because the states do not need to outlive the evaluator. */
507  LinearAllocator<> &allocator = local_allocators_.local();
508  while (!nodes_to_check.is_empty()) {
509  const DNode node = nodes_to_check.pop();
510  if (node_states_.contains_as(node)) {
511  /* This node has been handled already. */
512  continue;
513  }
514  /* Create a new state for the node. */
515  NodeState &node_state = *allocator.construct<NodeState>().release();
516  node_states_.add_new({node, &node_state});
517 
518  /* Push all linked origins on the stack. */
519  for (const InputSocketRef *input_ref : node->inputs()) {
520  const DInputSocket input{node.context(), input_ref};
521  input.foreach_origin_socket(
522  [&](const DSocket origin) { nodes_to_check.push(origin.node()); });
523  }
524  }
525 
526  /* Initialize the more complex parts of the node states in parallel. At this point no new
527  * node states are added anymore, so it is safe to lookup states from `node_states_` from
528  * multiple threads. */
530  IndexRange(node_states_.size()), 50, [&, this](const IndexRange range) {
531  LinearAllocator<> &allocator = this->local_allocators_.local();
532  for (const NodeWithState &item : node_states_.as_span().slice(range)) {
533  this->initialize_node_state(item.node, *item.state, allocator);
534  }
535  });
536 
537  /* Mark input sockets that have to be computed. */
538  for (const DSocket &socket : params_.force_compute_sockets) {
539  NodeState &node_state = *node_states_.lookup_key_as(socket.node()).state;
540  if (socket->is_input()) {
541  node_state.inputs[socket->index()].force_compute = true;
542  }
543  }
544  }
545 
546  void initialize_node_state(const DNode node, NodeState &node_state, LinearAllocator<> &allocator)
547  {
548  /* Construct arrays of the correct size. */
549  node_state.inputs = allocator.construct_array<InputState>(node->inputs().size());
550  node_state.outputs = allocator.construct_array<OutputState>(node->outputs().size());
551 
552  /* Initialize input states. */
553  for (const int i : node->inputs().index_range()) {
554  InputState &input_state = node_state.inputs[i];
555  const DInputSocket socket = node.input(i);
556  if (!socket->is_available()) {
557  /* Unavailable sockets should never be used. */
558  input_state.type = nullptr;
559  input_state.usage = ValueUsage::Unused;
560  continue;
561  }
562  const CPPType *type = get_socket_cpp_type(socket);
563  input_state.type = type;
564  if (type == nullptr) {
565  /* This is not a known data socket, it shouldn't be used. */
566  input_state.usage = ValueUsage::Unused;
567  continue;
568  }
569  /* Construct the correct struct that can hold the input(s). */
570  if (socket->is_multi_input_socket()) {
571  input_state.value.multi = allocator.construct<MultiInputValue>().release();
572  MultiInputValue &multi_value = *input_state.value.multi;
573  /* Count how many values should be added until the socket is complete. */
574  socket.foreach_origin_socket([&](DSocket origin) { multi_value.origins.append(origin); });
575  /* If no links are connected, we do read the value from socket itself. */
576  if (multi_value.origins.is_empty()) {
577  multi_value.origins.append(socket);
578  }
579  multi_value.values.resize(multi_value.origins.size(), nullptr);
580  }
581  else {
582  input_state.value.single = allocator.construct<SingleInputValue>().release();
583  }
584  }
585  /* Initialize output states. */
586  for (const int i : node->outputs().index_range()) {
587  OutputState &output_state = node_state.outputs[i];
588  const DOutputSocket socket = node.output(i);
589  if (!socket->is_available()) {
590  /* Unavailable outputs should never be used. */
591  output_state.output_usage = ValueUsage::Unused;
592  continue;
593  }
594  const CPPType *type = get_socket_cpp_type(socket);
595  if (type == nullptr) {
596  /* Non data sockets should never be used. */
597  output_state.output_usage = ValueUsage::Unused;
598  continue;
599  }
600  /* Count the number of potential users for this socket. */
601  socket.foreach_target_socket(
602  [&, this](const DInputSocket target_socket,
603  const DOutputSocket::TargetSocketPathInfo &UNUSED(path_info)) {
604  const DNode target_node = target_socket.node();
605  if (!this->node_states_.contains_as(target_node)) {
606  /* The target node is not computed because it is not computed to the output. */
607  return;
608  }
609  output_state.potential_users += 1;
610  });
611  if (output_state.potential_users == 0) {
612  /* If it does not have any potential users, it is unused. It might become required again in
613  * `schedule_initial_nodes`. */
614  output_state.output_usage = ValueUsage::Unused;
615  }
616  }
617  }
618 
620  {
622  IndexRange(node_states_.size()), 50, [&, this](const IndexRange range) {
623  for (const NodeWithState &item : node_states_.as_span().slice(range)) {
624  this->destruct_node_state(item.node, *item.state);
625  }
626  });
627  }
628 
629  void destruct_node_state(const DNode node, NodeState &node_state)
630  {
631  /* Need to destruct stuff manually, because it's allocated by a custom allocator. */
632  for (const int i : node->inputs().index_range()) {
633  InputState &input_state = node_state.inputs[i];
634  if (input_state.type == nullptr) {
635  continue;
636  }
637  const InputSocketRef &socket_ref = node->input(i);
638  if (socket_ref.is_multi_input_socket()) {
639  MultiInputValue &multi_value = *input_state.value.multi;
640  for (void *value : multi_value.values) {
641  if (value != nullptr) {
642  input_state.type->destruct(value);
643  }
644  }
645  multi_value.~MultiInputValue();
646  }
647  else {
648  SingleInputValue &single_value = *input_state.value.single;
649  void *value = single_value.value;
650  if (value != nullptr) {
651  input_state.type->destruct(value);
652  }
653  single_value.~SingleInputValue();
654  }
655  }
656 
657  destruct_n(node_state.inputs.data(), node_state.inputs.size());
658  destruct_n(node_state.outputs.data(), node_state.outputs.size());
659 
660  node_state.~NodeState();
661  }
662 
664  {
665  for (auto &&item : params_.input_values.items()) {
666  const DOutputSocket socket = item.key;
667  GMutablePointer value = item.value;
668 
669  const DNode node = socket.node();
670  if (!node_states_.contains_as(node)) {
671  /* The socket is not connected to any output. */
672  this->log_socket_value({socket}, value);
673  value.destruct();
674  continue;
675  }
676  this->forward_output(socket, value, nullptr);
677  }
678  }
679 
681  {
682  for (const DInputSocket &socket : params_.output_sockets) {
683  const DNode node = socket.node();
684  NodeState &node_state = this->get_node_state(node);
685  this->with_locked_node(node, node_state, nullptr, [&](LockedNode &locked_node) {
686  /* Setting an input as required will schedule any linked node. */
687  this->set_input_required(locked_node, socket);
688  });
689  }
690  for (const DSocket socket : params_.force_compute_sockets) {
691  const DNode node = socket.node();
692  NodeState &node_state = this->get_node_state(node);
693  this->with_locked_node(node, node_state, nullptr, [&](LockedNode &locked_node) {
694  if (socket->is_input()) {
695  this->set_input_required(locked_node, DInputSocket(socket));
696  }
697  else {
698  OutputState &output_state = node_state.outputs[socket->index()];
699  output_state.output_usage = ValueUsage::Required;
700  this->schedule_node(locked_node);
701  }
702  });
703  }
704  }
705 
706  void schedule_node(LockedNode &locked_node)
707  {
708  switch (locked_node.node_state.schedule_state) {
710  /* The node will be scheduled once it is not locked anymore. We could schedule the node
711  * right here, but that would result in a deadlock if the task pool decides to run the task
712  * immediately (this only happens when Blender is started with a single thread). */
714  locked_node.delayed_scheduled_nodes.append(locked_node.node);
715  break;
716  }
718  /* Scheduled already, nothing to do. */
719  break;
720  }
722  /* Reschedule node while it is running.
723  * The node will reschedule itself when it is done. */
725  break;
726  }
728  /* Scheduled already, nothing to do. */
729  break;
730  }
731  }
732  }
733 
734  static void run_node_from_task_pool(TaskPool *task_pool, void *task_data)
735  {
738  const NodeWithState *root_node_with_state = (const NodeWithState *)task_data;
739 
740  /* First, the node provided by the task pool is executed. During the execution other nodes
741  * might be scheduled. One of those nodes is not added to the task pool but is executed in the
742  * loop below directly. This has two main benefits:
743  * - Fewer round trips through the task pool which add threading overhead.
744  * - Helps with cpu cache efficiency, because a thread is more likely to process data that it
745  * has processed shortly before.
746  */
747  DNode next_node_to_run = root_node_with_state->node;
748  while (next_node_to_run) {
749  NodeTaskRunState run_state;
750  evaluator.node_task_run(next_node_to_run, &run_state);
751  next_node_to_run = run_state.next_node_to_run;
752  }
753  }
754 
755  void node_task_run(const DNode node, NodeTaskRunState *run_state)
756  {
757  /* These nodes are sometimes scheduled. We could also check for them in other places, but
758  * it's the easiest to do it here. */
759  if (node->is_group_input_node() || node->is_group_output_node()) {
760  return;
761  }
762 
763  NodeState &node_state = *node_states_.lookup_key_as(node).state;
764 
765  const bool do_execute_node = this->node_task_preprocessing(node, node_state, run_state);
766 
767  /* Only execute the node if all prerequisites are met. There has to be an output that is
768  * required and all required inputs have to be provided already. */
769  if (do_execute_node) {
770  this->execute_node(node, node_state, run_state);
771  }
772 
773  this->node_task_postprocessing(node, node_state, do_execute_node, run_state);
774  }
775 
777  NodeState &node_state,
778  NodeTaskRunState *run_state)
779  {
780  bool do_execute_node = false;
781  this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) {
784 
785  /* Early return if the node has finished already. */
786  if (locked_node.node_state.node_has_finished) {
787  return;
788  }
789  /* Prepare outputs and check if actually any new outputs have to be computed. */
790  if (!this->prepare_node_outputs_for_execution(locked_node)) {
791  return;
792  }
793  /* Initialize inputs that don't support laziness. This is done after at least one output is
794  * required and before we check that all required inputs are provided. This reduces the
795  * number of "round-trips" through the task pool by one for most nodes. */
796  if (!node_state.non_lazy_inputs_handled) {
797  this->require_non_lazy_inputs(locked_node);
798  node_state.non_lazy_inputs_handled = true;
799  }
800  /* Prepare inputs and check if all required inputs are provided. */
801  if (!this->prepare_node_inputs_for_execution(locked_node)) {
802  return;
803  }
804  do_execute_node = true;
805  });
806  return do_execute_node;
807  }
808 
809  /* A node is finished when it has computed all outputs that may be used have been computed and
810  * when no input is still forced to be computed. */
812  {
813  if (locked_node.node_state.node_has_finished) {
814  /* Early return in case this node is known to have finished already. */
815  return true;
816  }
817 
818  /* Check if there is any output that might be used but has not been computed yet. */
819  for (OutputState &output_state : locked_node.node_state.outputs) {
820  if (output_state.has_been_computed) {
821  continue;
822  }
823  if (output_state.output_usage != ValueUsage::Unused) {
824  return false;
825  }
826  }
827 
828  /* Check if there is an input that still has to be computed. */
829  for (InputState &input_state : locked_node.node_state.inputs) {
830  if (input_state.force_compute) {
831  if (!input_state.was_ready_for_execution) {
832  return false;
833  }
834  }
835  }
836 
837  /* If there are no remaining outputs, all the inputs can be destructed and/or can become
838  * unused. This can also trigger a chain reaction where nodes to the left become finished
839  * too. */
840  for (const int i : locked_node.node->inputs().index_range()) {
841  const DInputSocket socket = locked_node.node.input(i);
842  InputState &input_state = locked_node.node_state.inputs[i];
843  if (input_state.usage == ValueUsage::Maybe) {
844  this->set_input_unused(locked_node, socket);
845  }
846  else if (input_state.usage == ValueUsage::Required) {
847  /* The value was required, so it cannot become unused. However, we can destruct the
848  * value. */
849  this->destruct_input_value_if_exists(locked_node, socket);
850  }
851  }
852  locked_node.node_state.node_has_finished = true;
853  return true;
854  }
855 
857  {
858  bool execution_is_necessary = false;
859  for (OutputState &output_state : locked_node.node_state.outputs) {
860  /* Update the output usage for execution to the latest value. */
861  output_state.output_usage_for_execution = output_state.output_usage;
862  if (!output_state.has_been_computed) {
863  if (output_state.output_usage == ValueUsage::Required) {
864  /* Only evaluate when there is an output that is required but has not been computed. */
865  execution_is_necessary = true;
866  }
867  }
868  }
869  return execution_is_necessary;
870  }
871 
873  {
874  this->foreach_non_lazy_input(locked_node, [&](const DInputSocket socket) {
875  this->set_input_required(locked_node, socket);
876  });
877  }
878 
879  void foreach_non_lazy_input(LockedNode &locked_node, FunctionRef<void(DInputSocket socket)> fn)
880  {
881  if (node_supports_laziness(locked_node.node)) {
882  /* In the future only some of the inputs may support laziness. */
883  return;
884  }
885  /* Nodes that don't support laziness require all inputs. */
886  for (const int i : locked_node.node->inputs().index_range()) {
887  InputState &input_state = locked_node.node_state.inputs[i];
888  if (input_state.type == nullptr) {
889  /* Ignore unavailable/non-data sockets. */
890  continue;
891  }
892  fn(locked_node.node.input(i));
893  }
894  }
895 
903  {
904  for (const int i : locked_node.node_state.inputs.index_range()) {
905  InputState &input_state = locked_node.node_state.inputs[i];
906  if (input_state.type == nullptr) {
907  /* Ignore unavailable and non-data sockets. */
908  continue;
909  }
910  const DInputSocket socket = locked_node.node.input(i);
911  const bool is_required = input_state.usage == ValueUsage::Required;
912 
913  /* No need to check this socket again. */
914  if (input_state.was_ready_for_execution) {
915  continue;
916  }
917 
918  if (socket->is_multi_input_socket()) {
919  MultiInputValue &multi_value = *input_state.value.multi;
920  /* Checks if all the linked sockets have been provided already. */
921  if (multi_value.all_values_available()) {
922  input_state.was_ready_for_execution = true;
923  }
924  else if (is_required) {
925  /* The input is required but is not fully provided yet. Therefore the node cannot be
926  * executed yet. */
927  return false;
928  }
929  }
930  else {
931  SingleInputValue &single_value = *input_state.value.single;
932  if (single_value.value != nullptr) {
933  input_state.was_ready_for_execution = true;
934  }
935  else if (is_required) {
936  /* The input is required but has not been provided yet. Therefore the node cannot be
937  * executed yet. */
938  return false;
939  }
940  }
941  }
942  /* All required inputs have been provided. */
943  return true;
944  }
945 
950  void execute_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
951  {
952  const bNode &bnode = *node->bnode();
953 
954  if (node_state.has_been_executed) {
956  /* Nodes that don't support laziness must not be executed more than once. */
958  }
959  }
960  node_state.has_been_executed = true;
961 
962  /* Use the geometry node execute callback if it exists. */
963  if (bnode.typeinfo->geometry_node_execute != nullptr) {
964  this->execute_geometry_node(node, node_state, run_state);
965  return;
966  }
967 
968  /* Use the multi-function implementation if it exists. */
969  const nodes::NodeMultiFunctions::Item &fn_item = params_.mf_by_node->try_get(node);
970  if (fn_item.fn != nullptr) {
971  this->execute_multi_function_node(node, fn_item, node_state, run_state);
972  return;
973  }
974 
975  this->execute_unknown_node(node, node_state, run_state);
976  }
977 
978  void execute_geometry_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
979  {
980  using Clock = std::chrono::steady_clock;
981  const bNode &bnode = *node->bnode();
982 
983  NodeParamsProvider params_provider{*this, node, node_state, run_state};
984  GeoNodeExecParams params{params_provider};
985  Clock::time_point begin = Clock::now();
987  Clock::time_point end = Clock::now();
988  const std::chrono::microseconds duration =
989  std::chrono::duration_cast<std::chrono::microseconds>(end - begin);
990  if (params_.geo_logger != nullptr) {
991  params_.geo_logger->local().log_execution_time(node, duration);
992  }
993  }
994 
996  const nodes::NodeMultiFunctions::Item &fn_item,
997  NodeState &node_state,
998  NodeTaskRunState *run_state)
999  {
1000  LinearAllocator<> &allocator = local_allocators_.local();
1001 
1002  bool any_input_is_field = false;
1003  Vector<const void *, 16> input_values;
1005  for (const int i : node->inputs().index_range()) {
1006  const InputSocketRef &socket_ref = node->input(i);
1007  if (!socket_ref.is_available()) {
1008  continue;
1009  }
1010  BLI_assert(!socket_ref.is_multi_input_socket());
1011  InputState &input_state = node_state.inputs[i];
1012  BLI_assert(input_state.was_ready_for_execution);
1013  SingleInputValue &single_value = *input_state.value.single;
1014  BLI_assert(single_value.value != nullptr);
1015  const ValueOrFieldCPPType &field_cpp_type = static_cast<const ValueOrFieldCPPType &>(
1016  *input_state.type);
1017  input_values.append(single_value.value);
1018  input_types.append(&field_cpp_type);
1019  if (field_cpp_type.is_field(single_value.value)) {
1020  any_input_is_field = true;
1021  }
1022  }
1023 
1024  if (any_input_is_field) {
1025  this->execute_multi_function_node__field(
1026  node, fn_item, node_state, allocator, input_values, input_types, run_state);
1027  }
1028  else {
1029  this->execute_multi_function_node__value(
1030  node, *fn_item.fn, node_state, allocator, input_values, input_types, run_state);
1031  }
1032  }
1033 
1035  const nodes::NodeMultiFunctions::Item &fn_item,
1036  NodeState &node_state,
1037  LinearAllocator<> &allocator,
1038  Span<const void *> input_values,
1040  NodeTaskRunState *run_state)
1041  {
1042  Vector<GField> input_fields;
1043  for (const int i : input_values.index_range()) {
1044  const void *input_value_or_field = input_values[i];
1045  const ValueOrFieldCPPType &field_cpp_type = *input_types[i];
1046  input_fields.append(field_cpp_type.as_field(input_value_or_field));
1047  }
1048 
1049  std::shared_ptr<fn::FieldOperation> operation;
1050  if (fn_item.owned_fn) {
1051  operation = std::make_shared<fn::FieldOperation>(fn_item.owned_fn, std::move(input_fields));
1052  }
1053  else {
1054  operation = std::make_shared<fn::FieldOperation>(*fn_item.fn, std::move(input_fields));
1055  }
1056 
1057  int output_index = 0;
1058  for (const int i : node->outputs().index_range()) {
1059  const OutputSocketRef &socket_ref = node->output(i);
1060  if (!socket_ref.is_available()) {
1061  continue;
1062  }
1063  OutputState &output_state = node_state.outputs[i];
1064  const DOutputSocket socket{node.context(), &socket_ref};
1065  const ValueOrFieldCPPType *cpp_type = static_cast<const ValueOrFieldCPPType *>(
1066  get_socket_cpp_type(socket_ref));
1067  GField new_field{operation, output_index};
1068  void *buffer = allocator.allocate(cpp_type->size(), cpp_type->alignment());
1069  cpp_type->construct_from_field(buffer, std::move(new_field));
1070  this->forward_output(socket, {cpp_type, buffer}, run_state);
1071  output_state.has_been_computed = true;
1072  output_index++;
1073  }
1074  }
1075 
1077  const MultiFunction &fn,
1078  NodeState &node_state,
1079  LinearAllocator<> &allocator,
1080  Span<const void *> input_values,
1082  NodeTaskRunState *run_state)
1083  {
1084  MFParamsBuilder params{fn, 1};
1085  for (const int i : input_values.index_range()) {
1086  const void *input_value_or_field = input_values[i];
1087  const ValueOrFieldCPPType &field_cpp_type = *input_types[i];
1088  const CPPType &base_type = field_cpp_type.base_type();
1089  const void *input_value = field_cpp_type.get_value_ptr(input_value_or_field);
1090  params.add_readonly_single_input(GVArray::ForSingleRef(base_type, 1, input_value));
1091  }
1092 
1093  Vector<GMutablePointer, 16> output_buffers;
1094  for (const int i : node->outputs().index_range()) {
1095  const DOutputSocket socket = node.output(i);
1096  if (!socket->is_available()) {
1097  output_buffers.append({});
1098  continue;
1099  }
1100  const ValueOrFieldCPPType *value_or_field_type = static_cast<const ValueOrFieldCPPType *>(
1101  get_socket_cpp_type(socket));
1102  const CPPType &base_type = value_or_field_type->base_type();
1103  void *value_or_field_buffer = allocator.allocate(value_or_field_type->size(),
1104  value_or_field_type->alignment());
1105  value_or_field_type->default_construct(value_or_field_buffer);
1106  void *value_buffer = value_or_field_type->get_value_ptr(value_or_field_buffer);
1107  base_type.destruct(value_buffer);
1108  params.add_uninitialized_single_output(GMutableSpan{base_type, value_buffer, 1});
1109  output_buffers.append({value_or_field_type, value_or_field_buffer});
1110  }
1111 
1113  fn.call(IndexRange(1), params, context);
1114 
1115  for (const int i : output_buffers.index_range()) {
1116  GMutablePointer buffer = output_buffers[i];
1117  if (buffer.get() == nullptr) {
1118  continue;
1119  }
1120  const DOutputSocket socket = node.output(i);
1121  this->forward_output(socket, buffer, run_state);
1122 
1123  OutputState &output_state = node_state.outputs[i];
1124  output_state.has_been_computed = true;
1125  }
1126  }
1127 
1128  void execute_unknown_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
1129  {
1130  LinearAllocator<> &allocator = local_allocators_.local();
1131  for (const OutputSocketRef *socket : node->outputs()) {
1132  if (!socket->is_available()) {
1133  continue;
1134  }
1135  const CPPType *type = get_socket_cpp_type(*socket);
1136  if (type == nullptr) {
1137  continue;
1138  }
1139  /* Just forward the default value of the type as a fallback. That's typically better than
1140  * crashing or doing nothing. */
1141  OutputState &output_state = node_state.outputs[socket->index()];
1142  output_state.has_been_computed = true;
1143  void *buffer = allocator.allocate(type->size(), type->alignment());
1144  this->construct_default_value(*type, buffer);
1145  this->forward_output({node.context(), socket}, {*type, buffer}, run_state);
1146  }
1147  }
1148 
1150  NodeState &node_state,
1151  bool was_executed,
1152  NodeTaskRunState *run_state)
1153  {
1154  this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) {
1155  const bool node_has_finished = this->finish_node_if_possible(locked_node);
1156  const bool reschedule_requested = node_state.schedule_state ==
1159  if (reschedule_requested && !node_has_finished) {
1160  /* Either the node rescheduled itself or another node tried to schedule it while it ran. */
1161  this->schedule_node(locked_node);
1162  }
1163  if (was_executed) {
1164  this->assert_expected_outputs_have_been_computed(locked_node);
1165  }
1166  });
1167  }
1168 
1170  {
1171 #ifdef DEBUG
1172  /* Outputs can only be computed when all required inputs have been provided. */
1173  if (locked_node.node_state.missing_required_inputs > 0) {
1174  return;
1175  }
1176  /* If the node is still scheduled, it is not necessary that all its expected outputs are
1177  * computed yet. */
1179  return;
1180  }
1181 
1182  const bool supports_laziness = node_supports_laziness(locked_node.node);
1183  /* Iterating over sockets instead of the states directly, because that makes it easier to
1184  * figure out which socket is missing when one of the asserts is hit. */
1185  for (const OutputSocketRef *socket_ref : locked_node.node->outputs()) {
1186  OutputState &output_state = locked_node.node_state.outputs[socket_ref->index()];
1187  if (supports_laziness) {
1188  /* Expected that at least all required sockets have been computed. If more outputs become
1189  * required later, the node will be executed again. */
1190  if (output_state.output_usage_for_execution == ValueUsage::Required) {
1191  BLI_assert(output_state.has_been_computed);
1192  }
1193  }
1194  else {
1195  /* Expect that all outputs that may be used have been computed, because the node cannot
1196  * be executed again. */
1197  if (output_state.output_usage_for_execution != ValueUsage::Unused) {
1198  BLI_assert(output_state.has_been_computed);
1199  }
1200  }
1201  }
1202 #else
1203  UNUSED_VARS(locked_node);
1204 #endif
1205  }
1206 
1208  {
1209  for (const DInputSocket &socket : params_.output_sockets) {
1210  BLI_assert(socket->is_available());
1211  BLI_assert(!socket->is_multi_input_socket());
1212 
1213  const DNode node = socket.node();
1214  NodeState &node_state = this->get_node_state(node);
1215  InputState &input_state = node_state.inputs[socket->index()];
1216 
1217  SingleInputValue &single_value = *input_state.value.single;
1218  void *value = single_value.value;
1219 
1220  /* The value should have been computed by now. If this assert is hit, it means that there
1221  * was some scheduling issue before. */
1222  BLI_assert(value != nullptr);
1223 
1224  /* Move value into memory owned by the outer allocator. */
1225  const CPPType &type = *input_state.type;
1226  void *buffer = outer_allocator_.allocate(type.size(), type.alignment());
1227  type.move_construct(value, buffer);
1228 
1229  params_.r_output_values.append({type, buffer});
1230  }
1231  }
1232 
1237  bool set_input_required(LockedNode &locked_node, const DInputSocket input_socket)
1238  {
1239  BLI_assert(locked_node.node == input_socket.node());
1240  InputState &input_state = locked_node.node_state.inputs[input_socket->index()];
1241 
1242  /* Value set as unused cannot become used again. */
1243  BLI_assert(input_state.usage != ValueUsage::Unused);
1244 
1245  if (input_state.was_ready_for_execution) {
1246  return false;
1247  }
1248 
1249  if (input_state.usage == ValueUsage::Required) {
1250  /* If the input was not ready for execution but is required, the node will be triggered again
1251  * once the input has been computed. */
1252  return true;
1253  }
1254  input_state.usage = ValueUsage::Required;
1255 
1256  /* Count how many values still have to be added to this input until it is "complete". */
1257  int missing_values = 0;
1258  if (input_socket->is_multi_input_socket()) {
1259  MultiInputValue &multi_value = *input_state.value.multi;
1260  missing_values = multi_value.missing_values();
1261  }
1262  else {
1263  SingleInputValue &single_value = *input_state.value.single;
1264  if (single_value.value == nullptr) {
1265  missing_values = 1;
1266  }
1267  }
1268  if (missing_values == 0) {
1269  return false;
1270  }
1271  /* Increase the total number of missing required inputs. This ensures that the node will be
1272  * scheduled correctly when all inputs have been provided. */
1273  locked_node.node_state.missing_required_inputs += missing_values;
1274 
1275  /* Get all origin sockets, because we have to tag those as required as well. */
1276  Vector<DSocket> origin_sockets;
1277  input_socket.foreach_origin_socket(
1278  [&](const DSocket origin_socket) { origin_sockets.append(origin_socket); });
1279 
1280  if (origin_sockets.is_empty()) {
1281  /* If there are no origin sockets, just load the value from the socket directly. */
1282  this->load_unlinked_input_value(locked_node, input_socket, input_state, input_socket);
1283  locked_node.node_state.missing_required_inputs -= 1;
1284  return false;
1285  }
1286  bool requested_from_other_node = false;
1287  for (const DSocket &origin_socket : origin_sockets) {
1288  if (origin_socket->is_input()) {
1289  /* Load the value directly from the origin socket. In most cases this is an unlinked
1290  * group input. */
1291  this->load_unlinked_input_value(locked_node, input_socket, input_state, origin_socket);
1292  locked_node.node_state.missing_required_inputs -= 1;
1293  }
1294  else {
1295  /* The value has not been computed yet, so when it will be forwarded by another node, this
1296  * node will be triggered. */
1297  requested_from_other_node = true;
1298  locked_node.delayed_required_outputs.append(DOutputSocket(origin_socket));
1299  }
1300  }
1301  /* If this node will be triggered by another node, we don't have to schedule it now. */
1302  if (requested_from_other_node) {
1303  return true;
1304  }
1305  return false;
1306  }
1307 
1308  void set_input_unused(LockedNode &locked_node, const DInputSocket socket)
1309  {
1310  InputState &input_state = locked_node.node_state.inputs[socket->index()];
1311 
1312  /* A required socket cannot become unused. */
1313  BLI_assert(input_state.usage != ValueUsage::Required);
1314 
1315  if (input_state.usage == ValueUsage::Unused) {
1316  /* Nothing to do in this case. */
1317  return;
1318  }
1319  input_state.usage = ValueUsage::Unused;
1320 
1321  /* If the input is unused, its value can be destructed now. */
1322  this->destruct_input_value_if_exists(locked_node, socket);
1323 
1324  if (input_state.was_ready_for_execution) {
1325  /* If the value was already computed, we don't need to notify origin nodes. */
1326  return;
1327  }
1328 
1329  /* Notify origin nodes that might want to set its inputs as unused as well. */
1330  socket.foreach_origin_socket([&](const DSocket origin_socket) {
1331  if (origin_socket->is_input()) {
1332  /* Values from these sockets are loaded directly from the sockets, so there is no node to
1333  * notify. */
1334  return;
1335  }
1336  /* Delay notification of the other node until this node is not locked anymore. */
1337  locked_node.delayed_unused_outputs.append(DOutputSocket(origin_socket));
1338  });
1339  }
1340 
1342  {
1343  const DNode node = socket.node();
1344  NodeState &node_state = this->get_node_state(node);
1345  OutputState &output_state = node_state.outputs[socket->index()];
1346 
1347  this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) {
1348  if (output_state.output_usage == ValueUsage::Required) {
1349  /* Output is marked as required already. So the node is scheduled already. */
1350  return;
1351  }
1352  /* The origin node needs to be scheduled so that it provides the requested input
1353  * eventually. */
1354  output_state.output_usage = ValueUsage::Required;
1355  this->schedule_node(locked_node);
1356  });
1357  }
1358 
1360  {
1361  const DNode node = socket.node();
1362  NodeState &node_state = this->get_node_state(node);
1363  OutputState &output_state = node_state.outputs[socket->index()];
1364 
1365  this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) {
1366  output_state.potential_users -= 1;
1367  if (output_state.potential_users == 0) {
1368  /* The socket might be required even though the output is not used by other sockets. That
1369  * can happen when the socket is forced to be computed. */
1370  if (output_state.output_usage != ValueUsage::Required) {
1371  /* The output socket has no users anymore. */
1372  output_state.output_usage = ValueUsage::Unused;
1373  /* Schedule the origin node in case it wants to set its inputs as unused as well. */
1374  this->schedule_node(locked_node);
1375  }
1376  }
1377  });
1378  }
1379 
1381  {
1382  /* Push the task to the pool while it is not locked to avoid a deadlock in case when the task
1383  * is executed immediately. */
1384  const NodeWithState *node_with_state = node_states_.lookup_key_ptr_as(node);
1386  task_pool_, run_node_from_task_pool, (void *)node_with_state, false, nullptr);
1387  }
1388 
1393  void forward_output(const DOutputSocket from_socket,
1394  GMutablePointer value_to_forward,
1395  NodeTaskRunState *run_state)
1396  {
1397  BLI_assert(value_to_forward.get() != nullptr);
1398 
1399  LinearAllocator<> &allocator = local_allocators_.local();
1400 
1401  Vector<DSocket> log_original_value_sockets;
1402  Vector<DInputSocket> forward_original_value_sockets;
1403  log_original_value_sockets.append(from_socket);
1404 
1405  from_socket.foreach_target_socket(
1406  [&](const DInputSocket to_socket, const DOutputSocket::TargetSocketPathInfo &path_info) {
1407  if (!this->should_forward_to_socket(to_socket)) {
1408  return;
1409  }
1410  BLI_assert(to_socket == path_info.sockets.last());
1411  GMutablePointer current_value = value_to_forward;
1412  for (const DSocket &next_socket : path_info.sockets) {
1413  const DNode next_node = next_socket.node();
1414  const bool is_last_socket = to_socket == next_socket;
1415  const bool do_conversion_if_necessary = is_last_socket ||
1416  next_node->is_group_output_node() ||
1417  (next_node->is_group_node() &&
1418  !next_node->is_muted());
1419  if (do_conversion_if_necessary) {
1420  const CPPType &next_type = *get_socket_cpp_type(next_socket);
1421  if (*current_value.type() != next_type) {
1422  void *buffer = allocator.allocate(next_type.size(), next_type.alignment());
1423  this->convert_value(*current_value.type(), next_type, current_value.get(), buffer);
1424  if (current_value.get() != value_to_forward.get()) {
1425  current_value.destruct();
1426  }
1427  current_value = {next_type, buffer};
1428  }
1429  }
1430  if (current_value.get() == value_to_forward.get()) {
1431  /* Log the original value at the current socket. */
1432  log_original_value_sockets.append(next_socket);
1433  }
1434  else {
1435  /* Multi-input sockets are logged when all values are available. */
1436  if (!(next_socket->is_input() && next_socket->as_input().is_multi_input_socket())) {
1437  /* Log the converted value at the socket. */
1438  this->log_socket_value({next_socket}, current_value);
1439  }
1440  }
1441  }
1442  if (current_value.get() == value_to_forward.get()) {
1443  /* The value has not been converted, so forward the original value. */
1444  forward_original_value_sockets.append(to_socket);
1445  }
1446  else {
1447  /* The value has been converted. */
1448  this->add_value_to_input_socket(to_socket, from_socket, current_value, run_state);
1449  }
1450  });
1451  this->log_socket_value(log_original_value_sockets, value_to_forward);
1452  this->forward_to_sockets_with_same_type(
1453  allocator, forward_original_value_sockets, value_to_forward, from_socket, run_state);
1454  }
1455 
1457  {
1458  const DNode to_node = socket.node();
1459  const NodeWithState *target_node_with_state = node_states_.lookup_key_ptr_as(to_node);
1460  if (target_node_with_state == nullptr) {
1461  /* If the socket belongs to a node that has no state, the entire node is not used. */
1462  return false;
1463  }
1464  NodeState &target_node_state = *target_node_with_state->state;
1465  InputState &target_input_state = target_node_state.inputs[socket->index()];
1466 
1467  std::lock_guard lock{target_node_state.mutex};
1468  /* Do not forward to an input socket whose value won't be used. */
1469  return target_input_state.usage != ValueUsage::Unused;
1470  }
1471 
1473  Span<DInputSocket> to_sockets,
1474  GMutablePointer value_to_forward,
1475  const DOutputSocket from_socket,
1476  NodeTaskRunState *run_state)
1477  {
1478  if (to_sockets.is_empty()) {
1479  /* Value is not used anymore, so it can be destructed. */
1480  value_to_forward.destruct();
1481  }
1482  else if (to_sockets.size() == 1) {
1483  /* Value is only used by one input socket, no need to copy it. */
1484  const DInputSocket to_socket = to_sockets[0];
1485  this->add_value_to_input_socket(to_socket, from_socket, value_to_forward, run_state);
1486  }
1487  else {
1488  /* Multiple inputs use the value, make a copy for every input except for one. */
1489  /* First make the copies, so that the next node does not start modifying the value while we
1490  * are still making copies. */
1491  const CPPType &type = *value_to_forward.type();
1492  for (const DInputSocket &to_socket : to_sockets.drop_front(1)) {
1493  void *buffer = allocator.allocate(type.size(), type.alignment());
1494  type.copy_construct(value_to_forward.get(), buffer);
1495  this->add_value_to_input_socket(to_socket, from_socket, {type, buffer}, run_state);
1496  }
1497  /* Forward the original value to one of the targets. */
1498  const DInputSocket to_socket = to_sockets[0];
1499  this->add_value_to_input_socket(to_socket, from_socket, value_to_forward, run_state);
1500  }
1501  }
1502 
1504  const DOutputSocket origin,
1505  GMutablePointer value,
1506  NodeTaskRunState *run_state)
1507  {
1508  BLI_assert(socket->is_available());
1509 
1510  const DNode node = socket.node();
1511  NodeState &node_state = this->get_node_state(node);
1512  InputState &input_state = node_state.inputs[socket->index()];
1513 
1514  this->with_locked_node(node, node_state, run_state, [&](LockedNode &locked_node) {
1515  if (socket->is_multi_input_socket()) {
1516  /* Add a new value to the multi-input. */
1517  MultiInputValue &multi_value = *input_state.value.multi;
1518  multi_value.add_value(origin, value.get());
1519 
1520  if (multi_value.all_values_available()) {
1521  this->log_socket_value({socket}, input_state, multi_value.values);
1522  }
1523  }
1524  else {
1525  /* Assign the value to the input. */
1526  SingleInputValue &single_value = *input_state.value.single;
1527  BLI_assert(single_value.value == nullptr);
1528  single_value.value = value.get();
1529  }
1530 
1531  if (input_state.usage == ValueUsage::Required) {
1532  node_state.missing_required_inputs--;
1533  if (node_state.missing_required_inputs == 0) {
1534  /* Schedule node if all the required inputs have been provided. */
1535  this->schedule_node(locked_node);
1536  }
1537  }
1538  });
1539  }
1540 
1550  const DInputSocket input_socket,
1551  InputState &input_state,
1552  const DSocket origin_socket)
1553  {
1554  /* Only takes locked node as parameter, because the node needs to be locked. */
1555  UNUSED_VARS(locked_node);
1556 
1557  GMutablePointer value = this->get_value_from_socket(origin_socket, *input_state.type);
1558  if (input_socket->is_multi_input_socket()) {
1559  MultiInputValue &multi_value = *input_state.value.multi;
1560  multi_value.add_value(origin_socket, value.get());
1561  if (multi_value.all_values_available()) {
1562  this->log_socket_value({input_socket}, input_state, multi_value.values);
1563  }
1564  }
1565  else {
1566  SingleInputValue &single_value = *input_state.value.single;
1567  single_value.value = value.get();
1568  Vector<DSocket> sockets_to_log_to = {input_socket};
1569  if (origin_socket != input_socket) {
1570  /* This might log the socket value for the #origin_socket more than once, but this is
1571  * handled by the logging system gracefully. */
1572  sockets_to_log_to.append(origin_socket);
1573  }
1574  /* TODO: Log to the intermediate sockets between the group input and where the value is
1575  * actually used as well. */
1576  this->log_socket_value(sockets_to_log_to, value);
1577  }
1578  }
1579 
1580  void destruct_input_value_if_exists(LockedNode &locked_node, const DInputSocket socket)
1581  {
1582  InputState &input_state = locked_node.node_state.inputs[socket->index()];
1583  if (socket->is_multi_input_socket()) {
1584  MultiInputValue &multi_value = *input_state.value.multi;
1585  for (void *&value : multi_value.values) {
1586  if (value != nullptr) {
1587  input_state.type->destruct(value);
1588  value = nullptr;
1589  }
1590  }
1591  multi_value.provided_value_count = 0;
1592  }
1593  else {
1594  SingleInputValue &single_value = *input_state.value.single;
1595  if (single_value.value != nullptr) {
1596  input_state.type->destruct(single_value.value);
1597  single_value.value = nullptr;
1598  }
1599  }
1600  }
1601 
1602  GMutablePointer get_value_from_socket(const DSocket socket, const CPPType &required_type)
1603  {
1604  LinearAllocator<> &allocator = local_allocators_.local();
1605 
1606  const CPPType &type = *get_socket_cpp_type(socket);
1607  void *buffer = allocator.allocate(type.size(), type.alignment());
1608  get_socket_value(*socket.socket_ref(), buffer);
1609 
1610  if (type == required_type) {
1611  return {type, buffer};
1612  }
1613  void *converted_buffer = allocator.allocate(required_type.size(), required_type.alignment());
1614  this->convert_value(type, required_type, buffer, converted_buffer);
1615  type.destruct(buffer);
1616  return {required_type, converted_buffer};
1617  }
1618 
1619  void convert_value(const CPPType &from_type,
1620  const CPPType &to_type,
1621  const void *from_value,
1622  void *to_value)
1623  {
1624  if (from_type == to_type) {
1625  from_type.copy_construct(from_value, to_value);
1626  return;
1627  }
1628  const ValueOrFieldCPPType *from_field_type = dynamic_cast<const ValueOrFieldCPPType *>(
1629  &from_type);
1630  const ValueOrFieldCPPType *to_field_type = dynamic_cast<const ValueOrFieldCPPType *>(&to_type);
1631 
1632  if (from_field_type != nullptr && to_field_type != nullptr) {
1633  const CPPType &from_base_type = from_field_type->base_type();
1634  const CPPType &to_base_type = to_field_type->base_type();
1635  if (conversions_.is_convertible(from_base_type, to_base_type)) {
1636  if (from_field_type->is_field(from_value)) {
1637  const GField &from_field = *from_field_type->get_field_ptr(from_value);
1638  to_field_type->construct_from_field(to_value,
1639  conversions_.try_convert(from_field, to_base_type));
1640  }
1641  else {
1642  to_field_type->default_construct(to_value);
1643  const void *from_value_ptr = from_field_type->get_value_ptr(from_value);
1644  void *to_value_ptr = to_field_type->get_value_ptr(to_value);
1645  conversions_.get_conversion_functions(from_base_type, to_base_type)
1646  ->convert_single_to_initialized(from_value_ptr, to_value_ptr);
1647  }
1648  return;
1649  }
1650  }
1651  if (conversions_.is_convertible(from_type, to_type)) {
1652  /* Do the conversion if possible. */
1653  conversions_.convert_to_uninitialized(from_type, to_type, from_value, to_value);
1654  }
1655  else {
1656  /* Cannot convert, use default value instead. */
1657  this->construct_default_value(to_type, to_value);
1658  }
1659  }
1660 
1661  void construct_default_value(const CPPType &type, void *r_value)
1662  {
1663  type.value_initialize(r_value);
1664  }
1665 
1667  {
1668  return *node_states_.lookup_key_as(node).state;
1669  }
1670 
1671  void log_socket_value(DSocket socket, InputState &input_state, Span<void *> values)
1672  {
1673  if (params_.geo_logger == nullptr) {
1674  return;
1675  }
1676 
1677  Vector<GPointer, 16> value_pointers;
1678  value_pointers.reserve(values.size());
1679  const CPPType &type = *input_state.type;
1680  for (const void *value : values) {
1681  value_pointers.append({type, value});
1682  }
1683  params_.geo_logger->local().log_multi_value_socket(socket, value_pointers);
1684  }
1685 
1687  {
1688  if (params_.geo_logger == nullptr) {
1689  return;
1690  }
1691  params_.geo_logger->local().log_value_for_sockets(sockets, value);
1692  }
1693 
1694  void log_debug_message(DNode node, std::string message)
1695  {
1696  if (params_.geo_logger == nullptr) {
1697  return;
1698  }
1699  params_.geo_logger->local().log_debug_message(node, std::move(message));
1700  }
1701 
1702  /* In most cases when `NodeState` is accessed, the node has to be locked first to avoid race
1703  * conditions. */
1704  template<typename Function>
1706  NodeState &node_state,
1707  NodeTaskRunState *run_state,
1708  const Function &function)
1709  {
1710  LockedNode locked_node{node, node_state};
1711 
1712  node_state.mutex.lock();
1713  /* Isolate this thread because we don't want it to start executing another node. This other
1714  * node might want to lock the same mutex leading to a deadlock. */
1715  threading::isolate_task([&] { function(locked_node); });
1716  node_state.mutex.unlock();
1717 
1718  /* Then send notifications to the other nodes after the node state is unlocked. This avoids
1719  * locking two nodes at the same time on this thread and helps to prevent deadlocks. */
1720  for (const DOutputSocket &socket : locked_node.delayed_required_outputs) {
1721  this->send_output_required_notification(socket, run_state);
1722  }
1723  for (const DOutputSocket &socket : locked_node.delayed_unused_outputs) {
1724  this->send_output_unused_notification(socket, run_state);
1725  }
1726  for (const DNode &node_to_schedule : locked_node.delayed_scheduled_nodes) {
1727  if (run_state != nullptr && !run_state->next_node_to_run) {
1728  /* Execute the node on the same thread after the current node finished. */
1729  /* Currently, this assumes that it is always best to run the first node that is scheduled
1730  * on the same thread. That is usually correct, because the geometry socket which carries
1731  * the most data usually comes first in nodes. */
1732  run_state->next_node_to_run = node_to_schedule;
1733  }
1734  else {
1735  /* Push the node to the task pool so that another thread can start working on it. */
1736  this->add_node_to_task_pool(node_to_schedule);
1737  }
1738  }
1739  }
1740 };
1741 
1742 NodeParamsProvider::NodeParamsProvider(GeometryNodesEvaluator &evaluator,
1743  DNode dnode,
1744  NodeState &node_state,
1745  NodeTaskRunState *run_state)
1746  : evaluator_(evaluator), node_state_(node_state), run_state_(run_state)
1747 {
1748  this->dnode = dnode;
1749  this->self_object = evaluator.params_.self_object;
1750  this->modifier = &evaluator.params_.modifier_->modifier;
1751  this->depsgraph = evaluator.params_.depsgraph;
1752  this->logger = evaluator.params_.geo_logger;
1753 }
1754 
1756 {
1757  const DInputSocket socket = this->dnode.input_by_identifier(identifier);
1758  BLI_assert(socket);
1759 
1760  InputState &input_state = node_state_.inputs[socket->index()];
1761  if (!input_state.was_ready_for_execution) {
1762  return false;
1763  }
1764 
1765  if (socket->is_multi_input_socket()) {
1766  MultiInputValue &multi_value = *input_state.value.multi;
1767  return multi_value.all_values_available();
1768  }
1769  SingleInputValue &single_value = *input_state.value.single;
1770  return single_value.value != nullptr;
1771 }
1772 
1774 {
1775  const DOutputSocket socket = this->dnode.output_by_identifier(identifier);
1776  BLI_assert(socket);
1777 
1778  OutputState &output_state = node_state_.outputs[socket->index()];
1779  return !output_state.has_been_computed;
1780 }
1781 
1783 {
1784  const DInputSocket socket = this->dnode.input_by_identifier(identifier);
1785  BLI_assert(socket);
1786  BLI_assert(!socket->is_multi_input_socket());
1787  BLI_assert(this->can_get_input(identifier));
1788 
1789  InputState &input_state = node_state_.inputs[socket->index()];
1790  SingleInputValue &single_value = *input_state.value.single;
1791  void *value = single_value.value;
1792  single_value.value = nullptr;
1793  return {*input_state.type, value};
1794 }
1795 
1797 {
1798  const DInputSocket socket = this->dnode.input_by_identifier(identifier);
1799  BLI_assert(socket);
1800  BLI_assert(socket->is_multi_input_socket());
1801  BLI_assert(this->can_get_input(identifier));
1802 
1803  InputState &input_state = node_state_.inputs[socket->index()];
1804  MultiInputValue &multi_value = *input_state.value.multi;
1805 
1806  Vector<GMutablePointer> ret_values;
1807  for (void *&value : multi_value.values) {
1808  BLI_assert(value != nullptr);
1809  ret_values.append({*input_state.type, value});
1810  value = nullptr;
1811  }
1812  return ret_values;
1813 }
1814 
1816 {
1817  const DInputSocket socket = this->dnode.input_by_identifier(identifier);
1818  BLI_assert(socket);
1819  BLI_assert(!socket->is_multi_input_socket());
1820  BLI_assert(this->can_get_input(identifier));
1821 
1822  InputState &input_state = node_state_.inputs[socket->index()];
1823  SingleInputValue &single_value = *input_state.value.single;
1824  return {*input_state.type, single_value.value};
1825 }
1826 
1828 {
1829  LinearAllocator<> &allocator = evaluator_.local_allocators_.local();
1830  return {type, allocator.allocate(type.size(), type.alignment())};
1831 }
1832 
1834 {
1835  const DOutputSocket socket = this->dnode.output_by_identifier(identifier);
1836  BLI_assert(socket);
1837 
1838  OutputState &output_state = node_state_.outputs[socket->index()];
1839  BLI_assert(!output_state.has_been_computed);
1840  evaluator_.forward_output(socket, value, run_state_);
1841  output_state.has_been_computed = true;
1842 }
1843 
1845 {
1847  const DInputSocket socket = this->dnode.input_by_identifier(identifier);
1848  BLI_assert(socket);
1849 
1850  InputState &input_state = node_state_.inputs[socket->index()];
1851  if (input_state.was_ready_for_execution) {
1852  return false;
1853  }
1854  evaluator_.with_locked_node(this->dnode, node_state_, run_state_, [&](LockedNode &locked_node) {
1855  if (!evaluator_.set_input_required(locked_node, socket)) {
1856  /* Schedule the currently executed node again because the value is available now but was not
1857  * ready for the current execution. */
1858  evaluator_.schedule_node(locked_node);
1859  }
1860  });
1861  return true;
1862 }
1863 
1865 {
1866  const DInputSocket socket = this->dnode.input_by_identifier(identifier);
1867  BLI_assert(socket);
1868 
1869  evaluator_.with_locked_node(this->dnode, node_state_, run_state_, [&](LockedNode &locked_node) {
1870  evaluator_.set_input_unused(locked_node, socket);
1871  });
1872 }
1873 
1875 {
1876  const DOutputSocket socket = this->dnode.output_by_identifier(identifier);
1877  BLI_assert(socket);
1878 
1879  OutputState &output_state = node_state_.outputs[socket->index()];
1880  if (output_state.has_been_computed) {
1881  return false;
1882  }
1883  return output_state.output_usage_for_execution != ValueUsage::Unused;
1884 }
1885 
1887 {
1889  const DOutputSocket socket = this->dnode.output_by_identifier(identifier);
1890  BLI_assert(socket);
1891 
1892  OutputState &output_state = node_state_.outputs[socket->index()];
1893  if (output_state.has_been_computed) {
1894  return false;
1895  }
1896  return output_state.output_usage_for_execution == ValueUsage::Required;
1897 }
1898 
1900 {
1901  LinearAllocator<> &allocator = evaluator_.local_allocators_.local();
1902 
1903  for (const int i : this->dnode->outputs().index_range()) {
1904  OutputState &output_state = node_state_.outputs[i];
1905  if (output_state.has_been_computed) {
1906  continue;
1907  }
1908  if (output_state.output_usage_for_execution == ValueUsage::Unused) {
1909  continue;
1910  }
1911 
1912  const DOutputSocket socket = this->dnode.output(i);
1913  const CPPType *type = get_socket_cpp_type(socket);
1914  BLI_assert(type != nullptr);
1915  void *buffer = allocator.allocate(type->size(), type->alignment());
1916  type->value_initialize(buffer);
1917  evaluator_.forward_output(socket, {type, buffer}, run_state_);
1918  output_state.has_been_computed = true;
1919  }
1920 }
1921 
1923 {
1924  GeometryNodesEvaluator evaluator{params};
1925  evaluator.execute();
1926 }
1927 
1928 } // namespace blender::modifiers::geometry_nodes
#define GEO_NODE_SET_CURVE_HANDLES
Definition: BKE_node.h:1455
#define GEO_NODE_EXTRUDE_MESH
Definition: BKE_node.h:1493
#define FN_NODE_RANDOM_VALUE
Definition: BKE_node.h:1529
#define GEO_NODE_INSTANCE_ON_POINTS
Definition: BKE_node.h:1434
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
@ TASK_PRIORITY_HIGH
Definition: BLI_task.h:57
void * BLI_task_pool_user_data(TaskPool *pool)
Definition: task_pool.cc:525
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition: task_pool.cc:480
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition: task_pool.cc:390
void BLI_task_pool_free(TaskPool *pool)
Definition: task_pool.cc:440
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition: task_pool.cc:459
#define UNUSED_VARS(...)
#define UNUSED(x)
#define ELEM(...)
ThreadMutex mutex
@ GEO_NODE_CURVE_HANDLE_LEFT
@ SOCK_INT
@ SOCK_VECTOR
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
volatile int lock
void copy_construct(const void *src, void *dst) const
void destruct(void *ptr) const
int64_t size() const
int64_t alignment() const
void default_construct(void *ptr) const
const CPPType * type() const
static GVArray ForSingleRef(const CPPType &type, int64_t size, const void *value)
destruct_ptr< T > construct(Args &&...args)
void * allocate(const int64_t size, const int64_t alignment)
MutableSpan< T > construct_array(int64_t size, Args &&...args)
constexpr Span drop_front(int64_t n) const
Definition: BLI_span.hh:159
constexpr int64_t size() const
Definition: BLI_span.hh:240
constexpr IndexRange index_range() const
Definition: BLI_span.hh:401
constexpr bool is_empty() const
Definition: BLI_span.hh:248
bool is_empty() const
Definition: BLI_stack.hh:308
void push(const T &value)
Definition: BLI_stack.hh:213
void add_new(const Key &key)
const Key & lookup_key_as(const ForwardKey &key) const
bool contains_as(const ForwardKey &key) const
const Key * lookup_key_ptr_as(const ForwardKey &key) const
int64_t size() const
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
bool is_empty() const
Definition: BLI_vector.hh:706
IndexRange index_range() const
Definition: BLI_vector.hh:920
void resize(const int64_t new_size)
Definition: BLI_vector.hh:353
void reserve(const int64_t min_capacity)
Definition: BLI_vector.hh:340
void convert_to_uninitialized(const CPPType &from_type, const CPPType &to_type, const void *from_value, void *to_value) const
const ConversionFunctions * get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
GVArray try_convert(GVArray varray, const CPPType &to_type) const
virtual void call(IndexMask mask, MFParams params, MFContext context) const =0
const void * get_value_ptr(const void *value_or_field) const
void construct_from_field(void *dst, GField field) const
const CPPType & base_type() const
const GField * get_field_ptr(const void *value_or_field) const
GField as_field(const void *value_or_field) const
bool is_field(const void *value_or_field) const
void execute_unknown_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
static void run_node_from_task_pool(TaskPool *task_pool, void *task_data)
void forward_to_sockets_with_same_type(LinearAllocator<> &allocator, Span< DInputSocket > to_sockets, GMutablePointer value_to_forward, const DOutputSocket from_socket, NodeTaskRunState *run_state)
void destruct_input_value_if_exists(LockedNode &locked_node, const DInputSocket socket)
GMutablePointer get_value_from_socket(const DSocket socket, const CPPType &required_type)
void with_locked_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state, const Function &function)
void node_task_run(const DNode node, NodeTaskRunState *run_state)
void execute_multi_function_node__field(const DNode node, const nodes::NodeMultiFunctions::Item &fn_item, NodeState &node_state, LinearAllocator<> &allocator, Span< const void * > input_values, Span< const ValueOrFieldCPPType * > input_types, NodeTaskRunState *run_state)
void convert_value(const CPPType &from_type, const CPPType &to_type, const void *from_value, void *to_value)
void initialize_node_state(const DNode node, NodeState &node_state, LinearAllocator<> &allocator)
GeometryNodesEvaluator(GeometryNodesEvaluationParams &params)
void load_unlinked_input_value(LockedNode &locked_node, const DInputSocket input_socket, InputState &input_state, const DSocket origin_socket)
void add_value_to_input_socket(const DInputSocket socket, const DOutputSocket origin, GMutablePointer value, NodeTaskRunState *run_state)
void execute_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
void execute_multi_function_node(const DNode node, const nodes::NodeMultiFunctions::Item &fn_item, NodeState &node_state, NodeTaskRunState *run_state)
bool set_input_required(LockedNode &locked_node, const DInputSocket input_socket)
void execute_geometry_node(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
void execute_multi_function_node__value(const DNode node, const MultiFunction &fn, NodeState &node_state, LinearAllocator<> &allocator, Span< const void * > input_values, Span< const ValueOrFieldCPPType * > input_types, NodeTaskRunState *run_state)
void foreach_non_lazy_input(LockedNode &locked_node, FunctionRef< void(DInputSocket socket)> fn)
void destruct_node_state(const DNode node, NodeState &node_state)
void forward_output(const DOutputSocket from_socket, GMutablePointer value_to_forward, NodeTaskRunState *run_state)
void log_socket_value(DSocket socket, InputState &input_state, Span< void * > values)
void send_output_unused_notification(const DOutputSocket socket, NodeTaskRunState *run_state)
void construct_default_value(const CPPType &type, void *r_value)
void node_task_postprocessing(const DNode node, NodeState &node_state, bool was_executed, NodeTaskRunState *run_state)
bool node_task_preprocessing(const DNode node, NodeState &node_state, NodeTaskRunState *run_state)
void log_socket_value(Span< DSocket > sockets, GPointer value)
void send_output_required_notification(const DOutputSocket socket, NodeTaskRunState *run_state)
void set_input_unused(LockedNode &locked_node, const DInputSocket socket)
LockedNode(const DNode node, NodeState &node_state)
void set_output(StringRef identifier, GMutablePointer value) override
GPointer get_input(StringRef identifier) const override
bool lazy_output_is_required(StringRef identifier) const override
GMutablePointer alloc_output_value(const CPPType &type) override
bool can_set_output(StringRef identifier) const override
Vector< GMutablePointer > extract_multi_input(StringRef identifier) override
GMutablePointer extract_input(StringRef identifier) override
bool can_get_input(StringRef identifier) const override
bool output_is_required(StringRef identifier) const override
void foreach_origin_socket(FunctionRef< void(DSocket)> origin_fn) const
DInputSocket input_by_identifier(StringRef identifier) const
DOutputSocket output(int index) const
DOutputSocket output_by_identifier(StringRef identifier) const
DInputSocket input(int index) const
void foreach_target_socket(ForeachTargetSocketFn target_fn) const
const SocketRef * socket_ref() const
geometry_nodes_eval_log::GeoLogger * logger
Span< SocketDeclarationPtr > inputs() const
const Item & try_get(const DNode &node) const
Span< const InputSocketRef * > inputs() const
Span< const OutputSocketRef * > outputs() const
InputSocketFieldType input_field_type() const
const NodeRef & node() const
bNodeSocketType * typeinfo() const
bNodeSocket * bsocket() const
const InputSocketRef & as_input() const
void log_multi_value_socket(DSocket socket, Span< GPointer > values)
void log_execution_time(DNode node, std::chrono::microseconds exec_time)
void log_value_for_sockets(Span< DSocket > sockets, GPointer value)
OperationNode * node
void * user_data
TaskPool * task_pool
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_global float * buffer
ccl_global KernelShaderEvalInput * input
const int state
static unsigned a[3]
Definition: RandGen.cpp:78
const DataTypeConversions & get_implicit_type_conversions()
static Type to_type(const eGPUType type)
static bool node_supports_laziness(const DNode node)
static const CPPType * get_socket_cpp_type(const DSocket socket)
static void get_socket_value(const SocketRef &socket, void *r_value)
static bool get_implicit_socket_input(const SocketRef &socket, void *r_value)
void evaluate_geometry_nodes(GeometryNodesEvaluationParams &params)
static const CPPType * get_socket_cpp_type(const SocketRef &socket)
void isolate_task(const Function &function)
Definition: BLI_task.hh:125
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:51
std::chrono::steady_clock Clock
Definition: BLI_timeit.hh:13
void destruct_n(T *ptr, int64_t n)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
unsigned char uint8_t
Definition: stdint.h:78
unsigned __int64 uint64_t
Definition: stdint.h:90
Defines a socket type.
Definition: BKE_node.h:143
SocketGetGeometryNodesCPPValueFunction get_geometry_nodes_cpp_value
Definition: BKE_node.h:201
const CPPTypeHandle * geometry_nodes_cpp_type
Definition: BKE_node.h:199
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
struct bNodeType * typeinfo
short type
void * storage
void(* convert_single_to_initialized)(const void *src, void *dst)
union blender::modifiers::geometry_nodes::InputState::@1149 value
void add_value(const DSocket origin, void *value)
friend bool operator==(const NodeWithState &a, const DNode &b)
friend bool operator==(const DNode &a, const NodeWithState &b)
friend bool operator==(const NodeWithState &a, const NodeWithState &b)
std::shared_ptr< MultiFunction > owned_fn