[Bf-blender-cvs] [4dccb3767a0] functions: optimize some math nodes

Jacques Lucke noreply at git.blender.org
Tue Dec 10 14:37:42 CET 2019


Commit: 4dccb3767a05f4ca959a32d19540927b370955a6
Author: Jacques Lucke
Date:   Tue Dec 10 14:30:07 2019 +0100
Branches: functions
https://developer.blender.org/rB4dccb3767a05f4ca959a32d19540927b370955a6

optimize some math nodes

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

M	source/blender/blenlib/BLI_virtual_list_ref.h
M	source/blender/functions/intern/inlined_tree_multi_function_network/mappings_nodes.cc

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

diff --git a/source/blender/blenlib/BLI_virtual_list_ref.h b/source/blender/blenlib/BLI_virtual_list_ref.h
index 80d46bed8d0..b9727b4920d 100644
--- a/source/blender/blenlib/BLI_virtual_list_ref.h
+++ b/source/blender/blenlib/BLI_virtual_list_ref.h
@@ -150,9 +150,16 @@ template<typename T> class VirtualListRef {
 
   ArrayRef<T> as_full_array() const
   {
+    BLI_assert(m_category == Category::FullArray);
     return ArrayRef<T>(m_data.full_array.data, m_virtual_size);
   }
 
+  const T &as_single_element() const
+  {
+    BLI_assert(this->is_single_element());
+    return (*this)[0];
+  }
+
   bool is_single_element() const
   {
     switch (m_category) {
diff --git a/source/blender/functions/intern/inlined_tree_multi_function_network/mappings_nodes.cc b/source/blender/functions/intern/inlined_tree_multi_function_network/mappings_nodes.cc
index a8c3d22212a..ae9e74c76ab 100644
--- a/source/blender/functions/intern/inlined_tree_multi_function_network/mappings_nodes.cc
+++ b/source/blender/functions/intern/inlined_tree_multi_function_network/mappings_nodes.cc
@@ -124,14 +124,29 @@ static void INSERT_time_info(VNodeMFNetworkBuilder &builder)
   builder.set_constructed_matching_fn<MF_ContextCurrentFrame>();
 }
 
-template<typename InT, typename OutT>
-static void build_math_fn(VNodeMFNetworkBuilder &builder, OutT (*func)(InT))
-{
-  auto fn = [=](MFMask mask, VirtualListRef<InT> inputs, MutableArrayRef<OutT> outputs) -> void {
-    for (uint i : mask.indices()) {
-      new (&outputs[i]) OutT(func(inputs[i]));
+template<typename InT, typename OutT, typename FuncT>
+static std::function<void(MFMask mask, VirtualListRef<InT>, MutableArrayRef<OutT>)>
+vectorize_function_1in_1out(FuncT func)
+{
+  return [=](MFMask mask, VirtualListRef<InT> inputs, MutableArrayRef<OutT> outputs) {
+    if (inputs.is_non_single_full_array()) {
+      ArrayRef<InT> in_array = inputs.as_full_array();
+      mask.foreach_index([=](uint i) { outputs[i] = func(in_array[i]); });
+    }
+    else if (inputs.is_single_element()) {
+      InT in_single = inputs.as_single_element();
+      outputs.fill_indices(mask.indices(), in_single);
+    }
+    else {
+      mask.foreach_index([=](uint i) { outputs[i] = func(inputs[i]); });
     }
   };
+}
+
+template<typename InT, typename OutT, typename FuncT>
+static void build_math_fn_1in_1out(VNodeMFNetworkBuilder &builder, FuncT func)
+{
+  auto fn = vectorize_function_1in_1out<InT, OutT>(func);
 
   builder.set_vectorized_constructed_matching_fn<MF_Custom_In1_Out1<InT, OutT>>(
       {"use_list"}, builder.xnode().name(), fn);
@@ -154,17 +169,17 @@ vectorize_function_2in_1out(FuncT func)
     }
     else if (inputs1.is_non_single_full_array() && inputs2.is_single_element()) {
       ArrayRef<InT1> in1_array = inputs1.as_full_array();
-      InT2 in2_single = inputs2[0];
+      InT2 in2_single = inputs2.as_single_element();
       mask.foreach_index([=](uint i) { new (&outputs[i]) OutT(func(in1_array[i], in2_single)); });
     }
     else if (inputs1.is_single_element() && inputs2.is_non_single_full_array()) {
-      InT1 in1_single = inputs1[0];
+      InT1 in1_single = inputs1.as_single_element();
       ArrayRef<InT2> in2_array = inputs2.as_full_array();
       mask.foreach_index([=](uint i) { new (&outputs[i]) OutT(func(in1_single, in2_array[i])); });
     }
     else if (inputs1.is_single_element() && inputs2.is_single_element()) {
-      InT1 in1_single = inputs1[0];
-      InT2 in2_single = inputs2[0];
+      InT1 in1_single = inputs1.as_single_element();
+      InT2 in2_single = inputs2.as_single_element();
       OutT out_single = func(in1_single, in2_single);
       outputs.fill_indices(mask.indices(), out_single);
     }
@@ -248,26 +263,23 @@ static void INSERT_power_floats(VNodeMFNetworkBuilder &builder)
 
 static void INSERT_sqrt_float(VNodeMFNetworkBuilder &builder)
 {
-  build_math_fn(
-      builder, +[](float a) -> float { return (a >= 0.0f) ? (float)std::sqrt(a) : 0.0f; });
+  build_math_fn_1in_1out<float, float>(
+      builder, [](float a) -> float { return (a >= 0.0f) ? (float)std::sqrt(a) : 0.0f; });
 }
 
 static void INSERT_abs_float(VNodeMFNetworkBuilder &builder)
 {
-  build_math_fn(
-      builder, +[](float a) -> float { return std::abs(a); });
+  build_math_fn_1in_1out<float, float>(builder, [](float a) -> float { return std::abs(a); });
 }
 
 static void INSERT_sine_float(VNodeMFNetworkBuilder &builder)
 {
-  build_math_fn(
-      builder, +[](float a) -> float { return std::sin(a); });
+  build_math_fn_1in_1out<float, float>(builder, [](float a) -> float { return std::sin(a); });
 }
 
 static void INSERT_cosine_float(VNodeMFNetworkBuilder &builder)
 {
-  build_math_fn(
-      builder, +[](float a) -> float { return std::cos(a); });
+  build_math_fn_1in_1out<float, float>(builder, [](float a) -> float { return std::cos(a); });
 }
 
 static void INSERT_add_vectors(VNodeMFNetworkBuilder &builder)
@@ -333,8 +345,7 @@ static void INSERT_boolean_or(VNodeMFNetworkBuilder &builder)
 
 static void INSERT_boolean_not(VNodeMFNetworkBuilder &builder)
 {
-  build_math_fn(
-      builder, +[](bool a) -> bool { return !a; });
+  build_math_fn_1in_1out<bool, bool>(builder, [](bool a) -> bool { return !a; });
 }
 
 static void INSERT_compare(VNodeMFNetworkBuilder &builder)



More information about the Bf-blender-cvs mailing list