[Bf-blender-cvs] [d932728ac11] temp-attribute-processor: initial working version

Jacques Lucke noreply at git.blender.org
Thu May 27 12:51:42 CEST 2021


Commit: d932728ac11145a89183c2cd9ca010748b6b0880
Author: Jacques Lucke
Date:   Tue May 25 18:41:45 2021 +0200
Branches: temp-attribute-processor
https://developer.blender.org/rBd932728ac11145a89183c2cd9ca010748b6b0880

initial working version

===================================================================

M	source/blender/blenkernel/intern/node.cc
M	source/blender/nodes/NOD_derived_node_tree.hh
M	source/blender/nodes/NOD_node_tree_multi_function.hh
M	source/blender/nodes/geometry/nodes/node_geo_attribute_processor.cc

===================================================================

diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 29340d4b8b8..902759cd320 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -3633,7 +3633,8 @@ bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
     return true;
   }
   LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
-    if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
+    if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP, GEO_NODE_ATTRIBUTE_PROCESSOR) &&
+        node->id) {
       if (ntreeHasTree((bNodeTree *)node->id, lookup)) {
         return true;
       }
diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh
index 7ff05449c0b..66fb49234bc 100644
--- a/source/blender/nodes/NOD_derived_node_tree.hh
+++ b/source/blender/nodes/NOD_derived_node_tree.hh
@@ -359,7 +359,7 @@ inline DInputSocket::DInputSocket(const DTreeContext *context, const InputSocket
 
 inline DInputSocket::DInputSocket(const DSocket &base_socket) : DSocket(base_socket)
 {
-  BLI_assert(base_socket->is_input());
+  BLI_assert(!base_socket || base_socket->is_input());
 }
 
 inline const InputSocketRef *DInputSocket::socket_ref() const
@@ -383,7 +383,7 @@ inline DOutputSocket::DOutputSocket(const DTreeContext *context, const OutputSoc
 
 inline DOutputSocket::DOutputSocket(const DSocket &base_socket) : DSocket(base_socket)
 {
-  BLI_assert(base_socket->is_output());
+  BLI_assert(!base_socket || base_socket->is_output());
 }
 
 inline const OutputSocketRef *DOutputSocket::socket_ref() const
diff --git a/source/blender/nodes/NOD_node_tree_multi_function.hh b/source/blender/nodes/NOD_node_tree_multi_function.hh
index e3f31e011e4..bfb3393d56d 100644
--- a/source/blender/nodes/NOD_node_tree_multi_function.hh
+++ b/source/blender/nodes/NOD_node_tree_multi_function.hh
@@ -49,6 +49,7 @@ class MFNetworkTreeMap {
   const DerivedNodeTree &tree_;
   fn::MFNetwork &network_;
   MultiValueMap<DSocket, fn::MFSocket *> sockets_by_dsocket_;
+  Map<const fn::MFSocket *, DSocket> dsocket_by_sockets_;
 
  public:
   MFNetworkTreeMap(const DerivedNodeTree &tree, fn::MFNetwork &network)
@@ -76,11 +77,13 @@ class MFNetworkTreeMap {
     BLI_assert(dsocket->is_input() == socket.is_input());
     BLI_assert(dsocket->is_input() || sockets_by_dsocket_.lookup(dsocket).is_empty());
     sockets_by_dsocket_.add(dsocket, &socket);
+    dsocket_by_sockets_.add_new(&socket, dsocket);
   }
 
   void add(const DInputSocket &dsocket, fn::MFInputSocket &socket)
   {
     sockets_by_dsocket_.add(dsocket, &socket);
+    dsocket_by_sockets_.add_new(&socket, dsocket);
   }
 
   void add(const DOutputSocket &dsocket, fn::MFOutputSocket &socket)
@@ -88,6 +91,7 @@ class MFNetworkTreeMap {
     /* There can be at most one matching output socket. */
     BLI_assert(sockets_by_dsocket_.lookup(dsocket).is_empty());
     sockets_by_dsocket_.add(dsocket, &socket);
+    dsocket_by_sockets_.add_new(&socket, dsocket);
   }
 
   void add(const DTreeContext &context,
@@ -180,6 +184,11 @@ class MFNetworkTreeMap {
     return socket;
   }
 
+  DOutputSocket try_lookup(const fn::MFOutputSocket &socket)
+  {
+    return DOutputSocket(dsocket_by_sockets_.lookup_default(&socket, {}));
+  }
+
   bool is_mapped(const DSocket &dsocket) const
   {
     return !sockets_by_dsocket_.lookup(dsocket).is_empty();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_processor.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_processor.cc
index 0ff8af4ed0a..1739f286858 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_processor.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_processor.cc
@@ -28,6 +28,8 @@
 
 #include "NOD_node_tree_multi_function.hh"
 
+#include "FN_multi_function_network_evaluation.hh"
+
 #include "node_geometry_util.hh"
 
 static void geo_node_attribute_processor_layout(uiLayout *layout, bContext *C, PointerRNA *ptr)
@@ -223,28 +225,154 @@ static void geo_node_attribute_processor_update(bNodeTree *UNUSED(ntree), bNode
   }
 }
 
-static void geo_node_attribute_processor_exec(GeoNodeExecParams params)
+static CustomDataType get_custom_data_type(bNodeSocketType *typeinfo)
+{
+  switch (typeinfo->type) {
+    case SOCK_FLOAT:
+      return CD_PROP_FLOAT;
+    case SOCK_VECTOR:
+      return CD_PROP_FLOAT3;
+    case SOCK_RGBA:
+      return CD_PROP_COLOR;
+    case SOCK_BOOLEAN:
+      return CD_PROP_BOOL;
+    case SOCK_INT:
+      return CD_PROP_INT32;
+  }
+  BLI_assert_unreachable();
+  return CD_PROP_FLOAT;
+}
+
+static void process_attributes(GeoNodeExecParams &geo_params, GeometrySet &geometry_set)
 {
-  const bNode &node = params.node();
+  const bNode &node = geo_params.node();
   const NodeGeometryAttributeProcessor &storage = *(NodeGeometryAttributeProcessor *)node.storage;
   bNodeTree *group = (bNodeTree *)node.id;
-
-  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+  const AttributeDomain domain = (AttributeDomain)storage.domain;
 
   if (group == nullptr) {
-    params.set_output("Geometry", geometry_set);
     return;
   }
 
   geometry_set = geometry_set_realize_instances(geometry_set);
 
+  if (!geometry_set.has_mesh()) {
+    return;
+  }
+  GeometryComponent &component = geometry_set.get_component_for_write<MeshComponent>();
+  const int domain_size = component.attribute_domain_size(domain);
+  if (domain_size == 0) {
+    return;
+  }
+
   NodeTreeRefMap tree_refs;
   DerivedNodeTree tree{*group, tree_refs};
   fn::MFNetwork network;
   ResourceScope scope;
   MFNetworkTreeMap network_map = insert_node_tree_into_mf_network(network, tree, scope);
-  std::cout << network.to_dot() << "\n\n";
 
+  Vector<const fn::MFOutputSocket *> fn_input_sockets;
+  Vector<const fn::MFInputSocket *> fn_output_sockets;
+
+  const DTreeContext &root_context = tree.root_context();
+  const NodeTreeRef &root_tree_ref = root_context.tree();
+
+  Span<const NodeRef *> input_nodes = root_tree_ref.nodes_by_type("NodeGroupInput");
+  Span<const NodeRef *> output_nodes = root_tree_ref.nodes_by_type("NodeGroupOutput");
+
+  if (output_nodes.size() != 1) {
+    return;
+  }
+
+  const DNode output_node{&root_context, output_nodes[0]};
+  Vector<fn::MFInputSocket *> network_outputs;
+  for (const InputSocketRef *socket_ref : output_node->inputs().drop_back(1)) {
+    const DInputSocket socket{&root_context, socket_ref};
+    network_outputs.append(network_map.lookup(socket).first());
+  }
+
+  VectorSet<const fn::MFOutputSocket *> network_inputs;
+  VectorSet<const fn::MFInputSocket *> unlinked_inputs;
+  network.find_dependencies(network_outputs, network_inputs, unlinked_inputs);
+  BLI_assert(unlinked_inputs.is_empty());
+
+  Vector<DOutputSocket> used_group_inputs;
+  for (const fn::MFOutputSocket *dummy_socket : network_inputs) {
+    const DOutputSocket dsocket = network_map.try_lookup(*dummy_socket);
+    BLI_assert(dsocket);
+    used_group_inputs.append(dsocket);
+  }
+
+  fn::MFNetworkEvaluator network_fn{Vector<const fn::MFOutputSocket *>(network_inputs.as_span()),
+                                    Vector<const fn::MFInputSocket *>(network_outputs.as_span())};
+
+  fn::MFParamsBuilder fn_params{network_fn, domain_size};
+  fn::MFContextBuilder context;
+
+  Vector<GVArrayPtr> input_gvarrays;
+
+  for (const DOutputSocket &dsocket : used_group_inputs) {
+    const int index = dsocket->index();
+    const AttributeProcessorInput *input_settings = (AttributeProcessorInput *)BLI_findlink(
+        &storage.group_inputs, index);
+    const bNodeSocket *interface_socket = (bNodeSocket *)BLI_findlink(&group->inputs, index);
+    switch ((GeometryNodeAttributeProcessorInputMode)input_settings->input_mode) {
+      case GEO_NODE_ATTRIBUTE_PROCESSOR_INPUT_MODE_DEFAULT: {
+        const StringRefNull attribute_name = interface_socket->name;
+        const CustomDataType type = get_custom_data_type(interface_socket->typeinfo);
+        GVArrayPtr attribute = component.attribute_get_for_read(attribute_name, domain, type);
+        fn_params.add_readonly_single_input(*attribute);
+        input_gvarrays.append(std::move(attribute));
+        break;
+      }
+      case GEO_NODE_ATTRIBUTE_PROCESSOR_INPUT_MODE_CUSTOM_ATTRIBUTE: {
+        return;
+        break;
+      }
+      case GEO_NODE_ATTRIBUTE_PROCESSOR_INPUT_MODE_CUSTOM_VALUE: {
+        return;
+        break;
+      }
+    }
+  }
+
+  Vector<std::unique_ptr<OutputAttribute>> output_attributes;
+  for (const InputSocketRef *socket_ref : output_node->inputs().drop_back(1)) {
+    const DInputSocket socket{&root_context, socket_ref};
+    const int index = socket->index();
+    const AttributeProcessorOutput *output_settings = (AttributeProcessorOutput *)BLI_findlink(
+        &storage.group_outputs, index);
+    const bNodeSocket *interface_socket = (bNodeSocket *)BLI_findlink(&group->outputs, index);
+    switch ((GeometryNodeAttributeProcessorOutputMode)output_settings->output_mode) {
+      case GEO_NODE_ATTRIBUTE_PROCESSOR_OUTPUT_MODE_DEFAULT: {
+        const StringRefNull attribute_name = interface_socket->name;
+        const CustomDataType type = get_custom_data_type(interface_socket->typeinfo);
+        auto attribute = std::make_unique<OutputAttribute>(
+            component.attribute_try_get_for_output_only(attribute_name, domain, type));
+        GMutableSpan attribute_span = attribute->as_span();
+        /* Destruct because the function expects an uninitialized array. */
+        attribute_span.type().destruct_n(attribute_span.data(), domain_size);
+        fn_params.add_uninitialized_single_output(attribute_span);
+        output_attributes.append(std::move(attribute));
+        break;
+      }
+      case GEO_NODE_ATTRIBUTE_PROCESSOR_OUTPUT_MODE_CUSTOM: {
+        return;
+      }
+    }
+  }
+
+  network_fn.call(IndexRange(domain_size), fn_params, context);
+
+  for (std::unique_ptr<OutputAttribute> &output_attribute : output_attributes) {
+    output_attribute->save();
+  }
+}
+
+static void geo_node_attribute_processor_exec(GeoNodeExecParams params)
+{
+  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
+  pr

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list