[Bf-blender-cvs] [05dbbd83f00] master: Geometry Nodes: refactor implicit conversions

Jacques Lucke noreply at git.blender.org
Thu Apr 15 11:22:08 CEST 2021


Commit: 05dbbd83f00d270c00cb1a0904c504c31e1812af
Author: Jacques Lucke
Date:   Thu Apr 15 11:21:35 2021 +0200
Branches: master
https://developer.blender.org/rB05dbbd83f00d270c00cb1a0904c504c31e1812af

Geometry Nodes: refactor implicit conversions

This refactor simplifies having standalone function pointer that
does a single conversion. It also speeds up implicit type conversion
of attributes.

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

M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/modifiers/intern/MOD_nodes.cc
M	source/blender/nodes/NOD_type_conversions.hh
M	source/blender/nodes/intern/node_tree_multi_function.cc
M	source/blender/nodes/intern/type_conversions.cc

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

diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 8542c9d35a4..ac582fc30e7 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -210,23 +210,25 @@ class ConvertedReadAttribute final : public ReadAttribute {
   const CPPType &from_type_;
   const CPPType &to_type_;
   ReadAttributePtr base_attribute_;
-  const nodes::DataTypeConversions &conversions_;
+  void (*convert_)(const void *src, void *dst);
 
  public:
   ConvertedReadAttribute(ReadAttributePtr base_attribute, const CPPType &to_type)
       : ReadAttribute(base_attribute->domain(), to_type, base_attribute->size()),
         from_type_(base_attribute->cpp_type()),
         to_type_(to_type),
-        base_attribute_(std::move(base_attribute)),
-        conversions_(nodes::get_implicit_type_conversions())
+        base_attribute_(std::move(base_attribute))
   {
+    const nodes::DataTypeConversions &conversions = nodes::get_implicit_type_conversions();
+    convert_ = conversions.get_conversion_functions(base_attribute_->cpp_type(), to_type)
+                   ->convert_single_to_uninitialized;
   }
 
   void get_internal(const int64_t index, void *r_value) const override
   {
     BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer);
     base_attribute_->get(index, buffer);
-    conversions_.convert(from_type_, to_type_, buffer, r_value);
+    convert_(buffer, r_value);
   }
 };
 
@@ -989,7 +991,7 @@ blender::bke::ReadAttributePtr GeometryComponent::attribute_get_constant_for_rea
   BLI_assert(conversions.is_convertible(*in_cpp_type, *out_cpp_type));
 
   void *out_value = alloca(out_cpp_type->size());
-  conversions.convert(*in_cpp_type, *out_cpp_type, value, out_value);
+  conversions.convert_to_uninitialized(*in_cpp_type, *out_cpp_type, value, out_value);
 
   const int domain_size = this->attribute_domain_size(domain);
   blender::bke::ReadAttributePtr attribute = std::make_unique<blender::bke::ConstantReadAttribute>(
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index 9329bc85e66..4a384063571 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -583,7 +583,8 @@ class GeometryNodesEvaluator {
       else {
         void *buffer = allocator_.allocate(to_type.size(), to_type.alignment());
         if (conversions_.is_convertible(from_type, to_type)) {
-          conversions_.convert(from_type, to_type, value_to_forward.get(), buffer);
+          conversions_.convert_to_uninitialized(
+              from_type, to_type, value_to_forward.get(), buffer);
         }
         else {
           to_type.copy_to_uninitialized(to_type.default_value(), buffer);
@@ -653,7 +654,7 @@ class GeometryNodesEvaluator {
     if (conversions_.is_convertible(type, required_type)) {
       void *converted_buffer = allocator_.allocate(required_type.size(),
                                                    required_type.alignment());
-      conversions_.convert(type, required_type, buffer, converted_buffer);
+      conversions_.convert_to_uninitialized(type, required_type, buffer, converted_buffer);
       type.destruct(buffer);
       return {required_type, converted_buffer};
     }
diff --git a/source/blender/nodes/NOD_type_conversions.hh b/source/blender/nodes/NOD_type_conversions.hh
index e23fddab58b..34225208fe6 100644
--- a/source/blender/nodes/NOD_type_conversions.hh
+++ b/source/blender/nodes/NOD_type_conversions.hh
@@ -21,20 +21,45 @@
 namespace blender::nodes {
 
 using fn::CPPType;
+using fn::GVArray;
+
+struct ConversionFunctions {
+  const fn::MultiFunction *multi_function;
+  void (*convert_single_to_initialized)(const void *src, void *dst);
+  void (*convert_single_to_uninitialized)(const void *src, void *dst);
+};
 
 class DataTypeConversions {
  private:
-  Map<std::pair<fn::MFDataType, fn::MFDataType>, const fn::MultiFunction *> conversions_;
+  Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_;
 
  public:
-  void add(fn::MFDataType from_type, fn::MFDataType to_type, const fn::MultiFunction &fn)
+  void add(fn::MFDataType from_type,
+           fn::MFDataType to_type,
+           const fn::MultiFunction &fn,
+           void (*convert_single_to_initialized)(const void *src, void *dst),
+           void (*convert_single_to_uninitialized)(const void *src, void *dst))
+  {
+    conversions_.add_new({from_type, to_type},
+                         {&fn, convert_single_to_initialized, convert_single_to_uninitialized});
+  }
+
+  const ConversionFunctions *get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const
+  {
+    return conversions_.lookup_ptr({from, to});
+  }
+
+  const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
   {
-    conversions_.add_new({from_type, to_type}, &fn);
+    return this->get_conversion_functions(fn::MFDataType::ForSingle(from),
+                                          fn::MFDataType::ForSingle(to));
   }
 
-  const fn::MultiFunction *get_conversion(fn::MFDataType from, fn::MFDataType to) const
+  const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from,
+                                                         fn::MFDataType to) const
   {
-    return conversions_.lookup_default({from, to}, nullptr);
+    const ConversionFunctions *functions = this->get_conversion_functions(from, to);
+    return functions ? functions->multi_function : nullptr;
   }
 
   bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
@@ -43,10 +68,10 @@ class DataTypeConversions {
         {fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)});
   }
 
-  void convert(const CPPType &from_type,
-               const CPPType &to_type,
-               const void *from_value,
-               void *to_value) const;
+  void convert_to_uninitialized(const CPPType &from_type,
+                                const CPPType &to_type,
+                                const void *from_value,
+                                void *to_value) const;
 };
 
 const DataTypeConversions &get_implicit_type_conversions();
diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc
index ea6b2e870ca..7ab6495f733 100644
--- a/source/blender/nodes/intern/node_tree_multi_function.cc
+++ b/source/blender/nodes/intern/node_tree_multi_function.cc
@@ -219,8 +219,8 @@ static void insert_links_and_unlinked_inputs(CommonMFNetworkBuilderData &common)
       const fn::MFDataType from_type = from_socket->data_type();
 
       if (from_type != to_type) {
-        const fn::MultiFunction *conversion_fn = get_implicit_type_conversions().get_conversion(
-            from_type, to_type);
+        const fn::MultiFunction *conversion_fn =
+            get_implicit_type_conversions().get_conversion_multi_function(from_type, to_type);
         if (conversion_fn != nullptr) {
           fn::MFNode &node = common.network.add_function(*conversion_fn);
           common.network.add_link(*from_socket, node.input(0));
diff --git a/source/blender/nodes/intern/type_conversions.cc b/source/blender/nodes/intern/type_conversions.cc
index 0f6bfa1d6d1..1c1b7c7feb5 100644
--- a/source/blender/nodes/intern/type_conversions.cc
+++ b/source/blender/nodes/intern/type_conversions.cc
@@ -26,83 +26,192 @@ namespace blender::nodes {
 
 using fn::MFDataType;
 
-template<typename From, typename To>
+template<typename From, typename To, To (*ConversionF)(const From &)>
 static void add_implicit_conversion(DataTypeConversions &conversions)
 {
-  static fn::CustomMF_Convert<From, To> function;
-  conversions.add(fn::MFDataType::ForSingle<From>(), fn::MFDataType::ForSingle<To>(), function);
+  const CPPType &from_type = CPPType::get<From>();
+  const CPPType &to_type = CPPType::get<To>();
+  const std::string conversion_name = from_type.name() + " to " + to_type.name();
+
+  static fn::CustomMF_SI_SO<From, To> multi_function{conversion_name, ConversionF};
+  static auto convert_single_to_initialized = [](const void *src, void *dst) {
+    *(To *)dst = ConversionF(*(const From *)src);
+  };
+  static auto convert_single_to_uninitialized = [](const void *src, void *dst) {
+    new (dst) To(ConversionF(*(const From *)src));
+  };
+  conversions.add(fn::MFDataType::ForSingle<From>(),
+                  fn::MFDataType::ForSingle<To>(),
+                  multi_function,
+                  convert_single_to_initialized,
+                  convert_single_to_uninitialized);
 }
 
-template<typename From, typename To, typename ConversionF>
-static void add_implicit_conversion(DataTypeConversions &conversions,
-                                    StringRef name,
-                                    ConversionF conversion)
+static float2 float_to_float2(const float &a)
 {
-  static fn::CustomMF_SI_SO<From, To> function{name, conversion};
-  conversions.add(fn::MFDataType::ForSingle<From>(), fn::MFDataType::ForSingle<To>(), function);
+  return float2(a);
+}
+static float3 float_to_float3(const float &a)
+{
+  return float3(a);
+}
+static int32_t float_to_int(const float &a)
+{
+  return (int32_t)a;
+}
+static bool float_to_bool(const float &a)
+{
+  return a > 0.0f;
+}
+static Color4f float_to_color(const float &a)
+{
+  return Color4f(a, a, a, 1.0f);
+}
+
+static float3 float2_to_float3(const float2 &a)
+{
+  return float3(a.x, a.y, 0.0f);
+}
+static float float2_to_float(const float2 &a)
+{
+  return (a.x + a.y) / 2.0f;
+}
+static int float2_to_int(const float2 &a)
+{
+  return (int32_t)((a.x + a.y) / 2.0f);
+}
+static bool float2_to_bool(const float2 &a)
+{
+  return !is_zero_v2(a);
+}
+static Color4f float2_to_color(const float2 &a)
+{
+  return Color4f(a.x, a.y, 0.0f, 1.0f);
+}
+
+static bool float3_to_bool(const float3 &a)
+{
+  return !is_zero_v3(a);
+}
+static float float3_to_float(const float3 &a)
+{
+  return (a.x + a.y + a.z) / 3.0f;
+}
+static int float3_to_int(const float3 &a)
+{
+  return (int)((a.x + a.y + a.z) / 3.0f);
+}
+static float2 float3_to_float2(const float3 &a)
+{
+  return f

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list