[Bf-blender-cvs] [43918ec28d1] master: Geometry Nodes: Speed up reading attribute with different type

Hans Goudey noreply at git.blender.org
Wed Aug 3 02:25:35 CEST 2022


Commit: 43918ec28d12124cfa32b3e84ead1bfb65501f6f
Author: Hans Goudey
Date:   Tue Aug 2 19:22:10 2022 -0500
Branches: master
https://developer.blender.org/rB43918ec28d12124cfa32b3e84ead1bfb65501f6f

Geometry Nodes: Speed up reading attribute with different type

The virtual array created by the implicit conversions had a lot of
overhead when converting many values. Implement "materialize"
functions to avoid a virtual function call for every element.
This gave me a 20x improvement when copying the values
from a float attribute as a boolean, though I doubt there are
any real world situations where it's that noticible.

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

M	source/blender/blenkernel/intern/type_conversions.cc

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

diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc
index 0b5d6ad7b10..a01f5d19088 100644
--- a/source/blender/blenkernel/intern/type_conversions.cc
+++ b/source/blender/blenkernel/intern/type_conversions.cc
@@ -367,20 +367,38 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
   functions->convert_single_to_uninitialized(from_value, to_value);
 }
 
+static void call_convert_to_uninitialized_fn(const GVArray &from,
+                                             const fn::MultiFunction &fn,
+                                             const IndexMask mask,
+                                             GMutableSpan to)
+{
+  fn::MFParamsBuilder params{fn, from.size()};
+  params.add_readonly_single_input(from);
+  params.add_uninitialized_single_output(to);
+  fn::MFContextBuilder context;
+  fn.call_auto(mask, params, context);
+}
+
+static void call_convert_to_uninitialized_fn(const GVArray &from,
+                                             const fn::MultiFunction &fn,
+                                             GMutableSpan to)
+{
+  call_convert_to_uninitialized_fn(from, fn, IndexMask(from.size()), to);
+}
+
 void DataTypeConversions::convert_to_initialized_n(GSpan from_span, GMutableSpan to_span) const
 {
   const CPPType &from_type = from_span.type();
   const CPPType &to_type = to_span.type();
+
   BLI_assert(from_span.size() == to_span.size());
   BLI_assert(this->is_convertible(from_type, to_type));
+
   const fn::MultiFunction *fn = this->get_conversion_multi_function(
       MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type));
-  fn::MFParamsBuilder params{*fn, from_span.size()};
-  params.add_readonly_single_input(from_span);
+
   to_type.destruct_n(to_span.data(), to_span.size());
-  params.add_uninitialized_single_output(to_span);
-  fn::MFContextBuilder context;
-  fn->call_auto(IndexRange(from_span.size()), params, context);
+  call_convert_to_uninitialized_fn(GVArray::ForSpan(from_span), *fn, to_span);
 }
 
 class GVArray_For_ConvertedGVArray : public GVArrayImpl {
@@ -414,6 +432,20 @@ class GVArray_For_ConvertedGVArray : public GVArrayImpl {
     old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value);
     from_type_.destruct(buffer);
   }
+
+  void materialize(const IndexMask mask, void *dst) const override
+  {
+    type_->destruct_n(dst, mask.min_array_size());
+    this->materialize_to_uninitialized(mask, dst);
+  }
+
+  void materialize_to_uninitialized(const IndexMask mask, void *dst) const override
+  {
+    call_convert_to_uninitialized_fn(varray_,
+                                     *old_to_new_conversions_.multi_function,
+                                     mask,
+                                     {this->type(), dst, mask.min_array_size()});
+  }
 };
 
 class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArrayImpl {
@@ -458,6 +490,20 @@ class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArrayImpl {
     new_to_old_conversions_.convert_single_to_uninitialized(value, buffer);
     varray_.set_by_relocate(index, buffer);
   }
+
+  void materialize(const IndexMask mask, void *dst) const override
+  {
+    type_->destruct_n(dst, mask.min_array_size());
+    this->materialize_to_uninitialized(mask, dst);
+  }
+
+  void materialize_to_uninitialized(const IndexMask mask, void *dst) const override
+  {
+    call_convert_to_uninitialized_fn(varray_,
+                                     *old_to_new_conversions_.multi_function,
+                                     mask,
+                                     {this->type(), dst, mask.min_array_size()});
+  }
 };
 
 GVArray DataTypeConversions::try_convert(GVArray varray, const CPPType &to_type) const
@@ -495,9 +541,8 @@ fn::GField DataTypeConversions::try_convert(fn::GField field, const CPPType &to_
   if (!this->is_convertible(from_type, to_type)) {
     return {};
   }
-  const fn::MultiFunction &fn =
-      *bke::get_implicit_type_conversions().get_conversion_multi_function(
-          fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type));
+  const fn::MultiFunction &fn = *this->get_conversion_multi_function(
+      fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type));
   return {std::make_shared<fn::FieldOperation>(fn, Vector<fn::GField>{std::move(field)})};
 }



More information about the Bf-blender-cvs mailing list