From 47276b84701727c2f187c77f1ec502b4ca4963bd Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Tue, 23 Nov 2021 14:47:25 +0100 Subject: Geometry Nodes: reduce overhead when processing single values Currently the geometry nodes evaluator always stores a field for every type that supports it, even if it is just a single value. This results in a lot of overhead when there are many sockets that just contain a single value, which is often the case. This introduces a new `ValueOrField` type that is used by the geometry nodes evaluator. Now a field will only be created when it is actually necessary. See D13307 for more details. In extrem cases this can speed up the evaluation 2-3x (those cases are probably never hit in practice though, but it's good to get rid of unnecessary overhead nevertheless). Differential Revision: https://developer.blender.org/D13307 --- source/blender/nodes/NOD_geometry_exec.hh | 43 +++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'source/blender/nodes/NOD_geometry_exec.hh') diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 700f32ee414..6b6e8a89240 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -59,6 +59,7 @@ using fn::GVArray; using fn::GVArray_GSpan; using fn::GVMutableArray; using fn::GVMutableArray_GSpan; +using fn::ValueOrField; using geometry_nodes_eval_log::NodeWarningType; /** @@ -129,7 +130,7 @@ class GeoNodeExecParams { } template - static inline constexpr bool is_stored_as_field_v = std::is_same_v || + static inline constexpr bool is_field_base_type_v = std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v || @@ -157,9 +158,15 @@ class GeoNodeExecParams { */ template T extract_input(StringRef identifier) { - if constexpr (is_stored_as_field_v) { - Field field = this->extract_input>(identifier); - return fn::evaluate_constant_field(field); + if constexpr (is_field_base_type_v) { + ValueOrField value_or_field = this->extract_input>(identifier); + return value_or_field.as_value(); + } + else if constexpr (fn::is_field_v) { + using BaseType = typename T::base_type; + ValueOrField value_or_field = this->extract_input>( + identifier); + return value_or_field.as_field(); } else { #ifdef DEBUG @@ -186,9 +193,9 @@ class GeoNodeExecParams { Vector gvalues = provider_->extract_multi_input(identifier); Vector values; for (GMutablePointer gvalue : gvalues) { - if constexpr (is_stored_as_field_v) { - const Field field = gvalue.relocate_out>(); - values.append(fn::evaluate_constant_field(field)); + if constexpr (is_field_base_type_v) { + const ValueOrField value_or_field = gvalue.relocate_out>(); + values.append(value_or_field.as_value()); } else { values.append(gvalue.relocate_out()); @@ -200,11 +207,16 @@ class GeoNodeExecParams { /** * Get the input value for the input socket with the given identifier. */ - template const T get_input(StringRef identifier) const + template T get_input(StringRef identifier) const { - if constexpr (is_stored_as_field_v) { - const Field &field = this->get_input>(identifier); - return fn::evaluate_constant_field(field); + if constexpr (is_field_base_type_v) { + ValueOrField value_or_field = this->get_input>(identifier); + return value_or_field.as_value(); + } + else if constexpr (fn::is_field_v) { + using BaseType = typename T::base_type; + ValueOrField value_or_field = this->get_input>(identifier); + return value_or_field.as_field(); } else { #ifdef DEBUG @@ -226,9 +238,12 @@ class GeoNodeExecParams { template void set_output(StringRef identifier, T &&value) { using StoredT = std::decay_t; - if constexpr (is_stored_as_field_v) { - this->set_output>(identifier, - fn::make_constant_field(std::forward(value))); + if constexpr (is_field_base_type_v) { + this->set_output(identifier, ValueOrField(std::forward(value))); + } + else if constexpr (fn::is_field_v) { + using BaseType = typename StoredT::base_type; + this->set_output(identifier, ValueOrField(std::forward(value))); } else { const CPPType &type = CPPType::get(); -- cgit v1.2.3