diff options
author | Hans Goudey <h.goudey@me.com> | 2022-08-03 03:22:10 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-08-03 03:23:13 +0300 |
commit | 43918ec28d12124cfa32b3e84ead1bfb65501f6f (patch) | |
tree | e895a7a29dae1ca747f370d82c15e0ce4cc447d1 /source/blender/blenkernel/intern/type_conversions.cc | |
parent | fc1a53eb7b975d831bfb4fa783d52570e90044f7 (diff) |
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.
Diffstat (limited to 'source/blender/blenkernel/intern/type_conversions.cc')
-rw-r--r-- | source/blender/blenkernel/intern/type_conversions.cc | 61 |
1 files changed, 53 insertions, 8 deletions
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)})}; } |