From b3146200a8c4265de7fba2e2d40ef84f99d979e2 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sat, 7 Jan 2023 16:19:59 +0100 Subject: [PATCH] Functions: refactor multi-function builder API * New `build_mf` namespace for the multi-function builders. * The type name of the created multi-functions is now "private", i.e. the caller has to use `auto`. This has the benefit that the implementation can change more freely without affecting the caller. * `CustomMF` does not use `std::function` internally anymore. This reduces some overhead during code generation and at run-time. * `CustomMF` now supports single-mutable parameters. --- .../intern/geometry_component_curves.cc | 24 +- .../intern/geometry_component_mesh.cc | 4 +- .../blenkernel/intern/type_conversions.cc | 4 +- .../functions/FN_multi_function_builder.hh | 518 +++++++++--------- source/blender/functions/intern/field.cc | 4 +- .../blender/functions/tests/FN_field_test.cc | 28 +- .../tests/FN_multi_function_procedure_test.cc | 30 +- .../functions/tests/FN_multi_function_test.cc | 92 ---- .../geometry/intern/resample_curves.cc | 8 +- source/blender/nodes/NOD_math_functions.hh | 38 +- .../function/nodes/node_fn_boolean_math.cc | 37 +- .../function/nodes/node_fn_combine_color.cc | 12 +- .../nodes/function/nodes/node_fn_compare.cc | 196 +++---- .../function/nodes/node_fn_float_to_int.cc | 18 +- .../function/nodes/node_fn_random_value.cc | 77 ++- .../function/nodes/node_fn_replace_string.cc | 10 +- .../function/nodes/node_fn_rotate_euler.cc | 24 +- .../function/nodes/node_fn_slice_string.cc | 4 +- .../function/nodes/node_fn_string_length.cc | 4 +- .../function/nodes/node_fn_value_to_string.cc | 4 +- .../geometry/nodes/node_geo_extrude_mesh.cc | 4 +- .../geometry/nodes/node_geo_mesh_to_points.cc | 4 +- .../nodes/geometry/nodes/node_geo_switch.cc | 4 +- .../nodes/shader/nodes/node_shader_clamp.cc | 8 +- .../shader/nodes/node_shader_map_range.cc | 185 +++---- .../nodes/shader/nodes/node_shader_math.cc | 12 +- .../nodes/shader/nodes/node_shader_mix.cc | 24 +- .../shader/nodes/node_shader_sepcomb_rgb.cc | 4 +- .../shader/nodes/node_shader_sepcomb_xyz.cc | 4 +- .../shader/nodes/node_shader_vector_math.cc | 28 +- .../shader/nodes/node_shader_vector_rotate.cc | 40 +- 31 files changed, 637 insertions(+), 816 deletions(-) diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index debcb35699e..d1d0af2b725 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -440,12 +440,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() make_array_write_attribute, tag_component_positions_changed); - static const fn::CustomMF_SI_SO handle_type_clamp{ + static auto handle_type_clamp = fn::build_mf::SI1_SO( "Handle Type Validate", [](int8_t value) { return std::clamp(value, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right", ATTR_DOMAIN_POINT, CD_PROP_INT8, @@ -484,10 +484,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() make_array_write_attribute, tag_component_positions_changed); - static const fn::CustomMF_SI_SO nurbs_order_clamp{ + static const auto nurbs_order_clamp = fn::build_mf::SI1_SO( "NURBS Order Validate", [](int8_t value) { return std::max(value, 0); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order", ATTR_DOMAIN_CURVE, CD_PROP_INT8, @@ -501,12 +501,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() tag_component_topology_changed, AttributeValidator{&nurbs_order_clamp}); - static const fn::CustomMF_SI_SO normal_mode_clamp{ + static const auto normal_mode_clamp = fn::build_mf::SI1_SO( "Normal Mode Validate", [](int8_t value) { return std::clamp(value, NORMAL_MODE_MINIMUM_TWIST, NORMAL_MODE_Z_UP); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider normal_mode("normal_mode", ATTR_DOMAIN_CURVE, CD_PROP_INT8, @@ -520,12 +520,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() tag_component_normals_changed, AttributeValidator{&normal_mode_clamp}); - static const fn::CustomMF_SI_SO knots_mode_clamp{ + static const auto knots_mode_clamp = fn::build_mf::SI1_SO( "Knots Mode Validate", [](int8_t value) { return std::clamp(value, NURBS_KNOT_MODE_NORMAL, NURBS_KNOT_MODE_ENDPOINT_BEZIER); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode", ATTR_DOMAIN_CURVE, CD_PROP_INT8, @@ -539,12 +539,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() tag_component_topology_changed, AttributeValidator{&knots_mode_clamp}); - static const fn::CustomMF_SI_SO curve_type_clamp{ + static const auto curve_type_clamp = fn::build_mf::SI1_SO( "Curve Type Validate", [](int8_t value) { return std::clamp(value, CURVE_TYPE_CATMULL_ROM, CURVE_TYPES_NUM); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider curve_type("curve_type", ATTR_DOMAIN_CURVE, CD_PROP_INT8, @@ -558,10 +558,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve() tag_component_curve_types_changed, AttributeValidator{&curve_type_clamp}); - static const fn::CustomMF_SI_SO resolution_clamp{ + static const auto resolution_clamp = fn::build_mf::SI1_SO( "Resolution Validate", [](int value) { return std::max(value, 1); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider resolution("resolution", ATTR_DOMAIN_CURVE, CD_PROP_INT32, diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index 855d422251d..b18bdc62d82 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -1264,13 +1264,13 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh() make_array_write_attribute, nullptr); - static const fn::CustomMF_SI_SO material_index_clamp{ + static const auto material_index_clamp = fn::build_mf::SI1_SO( "Material Index Validate", [](int value) { /* Use #short for the maximum since many areas still use that type for indices. */ return std::clamp(value, 0, std::numeric_limits::max()); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static BuiltinCustomDataLayerProvider material_index("material_index", ATTR_DOMAIN_FACE, CD_PROP_INT32, diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc index c3d8f84d5c3..5aca83d415d 100644 --- a/source/blender/blenkernel/intern/type_conversions.cc +++ b/source/blender/blenkernel/intern/type_conversions.cc @@ -20,12 +20,12 @@ static void add_implicit_conversion(DataTypeConversions &conversions) static const CPPType &to_type = CPPType::get(); static const std::string conversion_name = from_type.name() + " to " + to_type.name(); - static fn::CustomMF_SI_SO multi_function{ + static auto multi_function = fn::build_mf::SI1_SO( conversion_name.c_str(), /* Use lambda instead of passing #ConversionF directly, because otherwise the compiler won't * inline the function. */ [](const From &a) { return ConversionF(a); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); static auto convert_single_to_initialized = [](const void *src, void *dst) { *(To *)dst = ConversionF(*(const From *)src); }; diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh index b0876c13729..3a491a63e6c 100644 --- a/source/blender/functions/FN_multi_function_builder.hh +++ b/source/blender/functions/FN_multi_function_builder.hh @@ -8,17 +8,15 @@ * This file contains several utilities to create multi-functions with less redundant code. */ -#include - #include "FN_multi_function.hh" -namespace blender::fn { +namespace blender::fn::build_mf { /** * These presets determine what code is generated for a #CustomMF. Different presets make different * trade-offs between run-time performance and compile-time/binary size. */ -namespace CustomMF_presets { +namespace exec_presets { /** Method to execute a function in case devirtualization was not possible. */ enum class FallbackMode { @@ -63,7 +61,7 @@ struct AllSpanOrSingle { auto create_devirtualizers(TypeSequence /*param_tags*/, std::index_sequence /*indices*/, const IndexMask &mask, - const std::tuple &loaded_params) + const std::tuple &loaded_params) const { return std::make_tuple(IndexMaskDevirtualizer{mask}, [&]() { typedef ParamTags ParamTag; @@ -72,7 +70,9 @@ struct AllSpanOrSingle { const GVArrayImpl &varray_impl = *std::get(loaded_params); return GVArrayDevirtualizer{varray_impl}; } - else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { + else if constexpr (ELEM(ParamTag::category, + MFParamCategory::SingleOutput, + MFParamCategory::SingleMutable)) { T *ptr = std::get(loaded_params); return BasicDevirtualizer{ptr}; } @@ -93,7 +93,7 @@ template struct SomeSpanOrSingle { auto create_devirtualizers(TypeSequence /*param_tags*/, std::index_sequence /*indices*/, const IndexMask &mask, - const std::tuple &loaded_params) + const std::tuple &loaded_params) const { return std::make_tuple(IndexMaskDevirtualizer{mask}, [&]() { typedef ParamTags ParamTag; @@ -104,7 +104,9 @@ template struct SomeSpanOrSingle { const GVArrayImpl &varray_impl = *std::get(loaded_params); return GVArrayDevirtualizer{varray_impl}; } - else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { + else if constexpr (ELEM(ParamTag::category, + MFParamCategory::SingleOutput, + MFParamCategory::SingleMutable)) { T *ptr = std::get(loaded_params); return BasicDevirtualizer{ptr}; } @@ -112,7 +114,7 @@ template struct SomeSpanOrSingle { } }; -} // namespace CustomMF_presets +} // namespace exec_presets namespace detail { @@ -142,23 +144,23 @@ void execute_array(TypeSequence /*param_tags*/, * reference, because the pointer points to uninitialized memory. */ return args + i; } + else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) { + /* For mutables, pass a mutable reference to the function. */ + return args[i]; + } }()...); } } -} // namespace detail - -namespace materialize_detail { - -enum class ArgMode { +enum class MaterializeArgMode { Unknown, Single, Span, Materialized, }; -template struct ArgInfo { - ArgMode mode = ArgMode::Unknown; +template struct MaterializeArgInfo { + MaterializeArgMode mode = MaterializeArgMode::Unknown; Span internal_span; }; @@ -182,9 +184,11 @@ void execute_materialized_impl(TypeSequence /*param_tags*/, return chunks[in_i]; } else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { - /* For outputs, a pointer is passed, because the memory is uninitialized. */ return chunks + out_i; } + else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) { + return chunks[out_i]; + } }()...); } } @@ -217,7 +221,7 @@ void execute_materialized(TypeSequence /* param_tags */, std::tuple...> buffers; /* Information about every parameter. */ - std::tuple...> args_info; + std::tuple...> args_info; ( /* Setup information for all parameters. */ @@ -225,7 +229,7 @@ void execute_materialized(TypeSequence /* param_tags */, /* Use `typedef` instead of `using` to work around a compiler bug. */ typedef ParamTags ParamTag; typedef typename ParamTag::base_type T; - [[maybe_unused]] ArgInfo &arg_info = std::get(args_info); + [[maybe_unused]] MaterializeArgInfo &arg_info = std::get(args_info); if constexpr (ParamTag::category == MFParamCategory::SingleInput) { const GVArrayImpl &varray_impl = *std::get(loaded_params); const CommonVArrayInfo common_info = varray_impl.common_info(); @@ -236,7 +240,7 @@ void execute_materialized(TypeSequence /* param_tags */, const T &in_single = *static_cast(common_info.data); uninitialized_fill_n(in_chunk.data(), in_chunk.size(), in_single); std::get(buffers) = in_chunk; - arg_info.mode = ArgMode::Single; + arg_info.mode = MaterializeArgMode::Single; } else if (common_info.type == CommonVArrayInfo::Type::Span) { /* Remember the span so that it doesn't have to be retrieved in every iteration. */ @@ -264,9 +268,9 @@ void execute_materialized(TypeSequence /* param_tags */, [&] { using ParamTag = ParamTags; using T = typename ParamTag::base_type; - [[maybe_unused]] ArgInfo &arg_info = std::get(args_info); + [[maybe_unused]] MaterializeArgInfo &arg_info = std::get(args_info); if constexpr (ParamTag::category == MFParamCategory::SingleInput) { - if (arg_info.mode == ArgMode::Single) { + if (arg_info.mode == MaterializeArgMode::Single) { /* The single value has been filled into a buffer already reused for every chunk. */ return Span(std::get(buffers)); } @@ -276,7 +280,7 @@ void execute_materialized(TypeSequence /* param_tags */, /* In this case we can just use an existing span instead of "compressing" it into * a new temporary buffer. */ const IndexRange sliced_mask_range = sliced_mask.as_range(); - arg_info.mode = ArgMode::Span; + arg_info.mode = MaterializeArgMode::Span; return arg_info.internal_span.slice(sliced_mask_range); } } @@ -287,11 +291,13 @@ void execute_materialized(TypeSequence /* param_tags */, varray_impl.materialize_compressed_to_uninitialized(sliced_mask, in_chunk.data()); /* Remember that this parameter has been materialized, so that the values are * destructed properly when the chunk is done. */ - arg_info.mode = ArgMode::Materialized; + arg_info.mode = MaterializeArgMode::Materialized; return Span(in_chunk); } } - else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { + else if constexpr (ELEM(ParamTag::category, + MFParamCategory::SingleOutput, + MFParamCategory::SingleMutable)) { /* For outputs, just pass a pointer. This is important so that `__restrict` works. */ return std::get(loaded_params); } @@ -303,9 +309,9 @@ void execute_materialized(TypeSequence /* param_tags */, /* Use `typedef` instead of `using` to work around a compiler bug. */ typedef ParamTags ParamTag; typedef typename ParamTag::base_type T; - [[maybe_unused]] ArgInfo &arg_info = std::get(args_info); + [[maybe_unused]] MaterializeArgInfo &arg_info = std::get(args_info); if constexpr (ParamTag::category == MFParamCategory::SingleInput) { - if (arg_info.mode == ArgMode::Materialized) { + if (arg_info.mode == MaterializeArgMode::Materialized) { T *in_chunk = std::get(buffers_owner).ptr(); destruct_n(in_chunk, chunk_size); } @@ -320,9 +326,9 @@ void execute_materialized(TypeSequence /* param_tags */, /* Use `typedef` instead of `using` to work around a compiler bug. */ typedef ParamTags ParamTag; typedef typename ParamTag::base_type T; - [[maybe_unused]] ArgInfo &arg_info = std::get(args_info); + [[maybe_unused]] MaterializeArgInfo &arg_info = std::get(args_info); if constexpr (ParamTag::category == MFParamCategory::SingleInput) { - if (arg_info.mode == ArgMode::Single) { + if (arg_info.mode == MaterializeArgMode::Single) { MutableSpan in_chunk = std::get(buffers); destruct_n(in_chunk.data(), in_chunk.size()); } @@ -330,272 +336,254 @@ void execute_materialized(TypeSequence /* param_tags */, }(), ...); } -} // namespace materialize_detail -template class CustomMF : public MultiFunction { - private: - std::function fn_; - MFSignature signature_; +template +inline void execute_element_fn_as_multi_function(const ElementFn element_fn, + const ExecPreset exec_preset, + const IndexMask mask, + MFParams params, + TypeSequence /*param_tags*/, + std::index_sequence /*indices*/) +{ - using TagsSequence = TypeSequence; + /* Load parameters from #MFParams. */ + /* Contains `const GVArrayImpl *` for inputs and `T *` for outputs. */ + const auto loaded_params = std::make_tuple([&]() { + /* Use `typedef` instead of `using` to work around a compiler bug. */ + typedef ParamTags ParamTag; + typedef typename ParamTag::base_type T; - public: - template - CustomMF(const char *name, - ElementFn element_fn, - ExecPreset exec_preset = CustomMF_presets::Materialized()) - { - MFSignatureBuilder signature{name}; - add_signature_parameters(signature, std::make_index_sequence()); - signature_ = signature.build(); - this->set_signature(&signature_); + if constexpr (ParamTag::category == MFParamCategory::SingleInput) { + return params.readonly_single_input(I).get_implementation(); + } + else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { + return static_cast(params.uninitialized_single_output(I).data()); + } + else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) { + return static_cast(params.single_mutable(I).data()); + } + }()...); - fn_ = [element_fn, exec_preset](IndexMask mask, MFParams params) { - execute( - element_fn, exec_preset, mask, params, std::make_index_sequence()); - }; + /* Try execute devirtualized if enabled and the input types allow it. */ + bool executed_devirtualized = false; + if constexpr (ExecPreset::use_devirtualization) { + const auto devirtualizers = exec_preset.create_devirtualizers( + TypeSequence(), std::index_sequence(), mask, loaded_params); + executed_devirtualized = call_with_devirtualized_parameters( + devirtualizers, [&](auto &&...args) { + execute_array(TypeSequence(), + std::index_sequence(), + element_fn, + std::forward(args)...); + }); } - template - static void execute(ElementFn element_fn, - ExecPreset exec_preset, - IndexMask mask, - MFParams params, - std::index_sequence /*indices*/) - { - /* Contains `const GVArrayImpl *` for inputs and `T *` for outputs. */ - const auto loaded_params = std::make_tuple([&]() { - /* Use `typedef` instead of `using` to work around a compiler bug. */ - typedef typename TagsSequence::template at_index ParamTag; - typedef typename ParamTag::base_type T; - - if constexpr (ParamTag::category == MFParamCategory::SingleInput) { - return params.readonly_single_input(I).get_implementation(); - } - else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { - return static_cast(params.uninitialized_single_output(I).data()); - } - }()...); - - /* First try devirtualized execution, since this is the most efficient. */ - bool executed_devirtualized = false; - if constexpr (ExecPreset::use_devirtualization) { - const auto devirtualizers = exec_preset.create_devirtualizers( - TagsSequence(), std::index_sequence(), mask, loaded_params); - executed_devirtualized = call_with_devirtualized_parameters( - devirtualizers, [&](auto &&...args) { - detail::execute_array(TagsSequence(), - std::index_sequence(), - element_fn, - std::forward(args)...); - }); + /* If devirtualized execution was disabled or not possible, use a fallback method which is + * slower but always works. */ + if (!executed_devirtualized) { + /* The materialized method is most common because it avoids most virtual function overhead but + * still instantiates the function only once. */ + if constexpr (ExecPreset::fallback_mode == exec_presets::FallbackMode::Materialized) { + execute_materialized(TypeSequence(), + std::index_sequence(), + element_fn, + mask, + loaded_params); } - - /* If devirtualized execution was disabled or not possible, use a fallback method which is - * slower but always works. */ - if (!executed_devirtualized) { - if constexpr (ExecPreset::fallback_mode == CustomMF_presets::FallbackMode::Materialized) { - materialize_detail::execute_materialized( - TagsSequence(), std::index_sequence(), element_fn, mask, loaded_params); - } - else { - detail::execute_array( - TagsSequence(), std::index_sequence(), element_fn, mask, [&]() { - /* Use `typedef` instead of `using` to work around a compiler bug. */ - typedef typename TagsSequence::template at_index ParamTag; - typedef typename ParamTag::base_type T; - if constexpr (ParamTag::category == MFParamCategory::SingleInput) { - const GVArrayImpl &varray_impl = *std::get(loaded_params); - return GVArray(&varray_impl).typed(); - } - else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { - T *ptr = std::get(loaded_params); - return ptr; - } - }()...); - } + else { + /* This fallback is slower because it uses virtual method calls for every element. */ + execute_array( + TypeSequence(), std::index_sequence(), element_fn, mask, [&]() { + /* Use `typedef` instead of `using` to work around a compiler bug. */ + typedef ParamTags ParamTag; + typedef typename ParamTag::base_type T; + if constexpr (ParamTag::category == MFParamCategory::SingleInput) { + const GVArrayImpl &varray_impl = *std::get(loaded_params); + return GVArray(&varray_impl).typed(); + } + else if constexpr (ELEM(ParamTag::category, + MFParamCategory::SingleOutput, + MFParamCategory::SingleMutable)) { + T *ptr = std::get(loaded_params); + return ptr; + } + }()...); } } - - template - static void add_signature_parameters(MFSignatureBuilder &signature, - std::index_sequence /* indices */) - { - ( - /* Loop over all parameter types and add an entry for each in the signature. */ - [&] { - /* Use `typedef` instead of `using` to work around a compiler bug. */ - typedef typename TagsSequence::template at_index ParamTag; - signature.add(ParamTag(), ""); - }(), - ...); - } - - void call(IndexMask mask, MFParams params, MFContext /*context*/) const override - { - fn_(mask, params); - } -}; +} /** - * Generates a multi-function with the following parameters: - * 1. single input (SI) of type In1 - * 2. single output (SO) of type Out1 - * - * This example creates a function that adds 10 to the incoming values: - * `CustomMF_SI_SO fn("add 10", [](int value) { return value + 10; });` + * `element_fn` is expected to return nothing and to have the following parameters: + * - For single-inputs: const value or reference. + * - For single-mutables: non-const reference. + * - For single-outputs: non-const pointer. */ -template -class CustomMF_SI_SO : public CustomMF, - MFParamTag> { - public: - template - CustomMF_SI_SO(const char *name, - ElementFn element_fn, - ExecPreset exec_preset = CustomMF_presets::Materialized()) - : CustomMF, - MFParamTag>( - name, - [element_fn](const In1 &in1, Out1 *out1) { new (out1) Out1(element_fn(in1)); }, - exec_preset) - { - } -}; +template +inline auto build_multi_function_call_from_element_fn(const ElementFn element_fn, + const ExecPreset exec_preset, + TypeSequence /*param_tags*/) +{ + return [element_fn, exec_preset](const IndexMask mask, MFParams params) { + execute_element_fn_as_multi_function(element_fn, + exec_preset, + mask, + params, + TypeSequence(), + std::make_index_sequence()); + }; +} /** - * Generates a multi-function with the following parameters: - * 1. single input (SI) of type In1 - * 2. single input (SI) of type In2 - * 3. single output (SO) of type Out1 + * A multi function that just invokes the provided function in its #call method. */ -template -class CustomMF_SI_SI_SO : public CustomMF, - MFParamTag, - MFParamTag> { - public: - template - CustomMF_SI_SI_SO(const char *name, - ElementFn element_fn, - ExecPreset exec_preset = CustomMF_presets::Materialized()) - : CustomMF, - MFParamTag, - MFParamTag>( - name, - [element_fn](const In1 &in1, const In2 &in2, Out1 *out1) { - new (out1) Out1(element_fn(in1, in2)); - }, - exec_preset) - { - } -}; - -/** - * Generates a multi-function with the following parameters: - * 1. single input (SI) of type In1 - * 2. single input (SI) of type In2 - * 3. single input (SI) of type In3 - * 4. single output (SO) of type Out1 - */ -template -class CustomMF_SI_SI_SI_SO : public CustomMF, - MFParamTag, - MFParamTag, - MFParamTag> { - public: - template - CustomMF_SI_SI_SI_SO(const char *name, - ElementFn element_fn, - ExecPreset exec_preset = CustomMF_presets::Materialized()) - : CustomMF, - MFParamTag, - MFParamTag, - MFParamTag>( - name, - [element_fn](const In1 &in1, const In2 &in2, const In3 &in3, Out1 *out1) { - new (out1) Out1(element_fn(in1, in2, in3)); - }, - exec_preset) - { - } -}; - -/** - * Generates a multi-function with the following parameters: - * 1. single input (SI) of type In1 - * 2. single input (SI) of type In2 - * 3. single input (SI) of type In3 - * 4. single input (SI) of type In4 - * 5. single output (SO) of type Out1 - */ -template -class CustomMF_SI_SI_SI_SI_SO : public CustomMF, - MFParamTag, - MFParamTag, - MFParamTag, - MFParamTag> { - public: - template - CustomMF_SI_SI_SI_SI_SO(const char *name, - ElementFn element_fn, - ExecPreset exec_preset = CustomMF_presets::Materialized()) - : CustomMF, - MFParamTag, - MFParamTag, - MFParamTag, - MFParamTag>( - name, - [element_fn]( - const In1 &in1, const In2 &in2, const In3 &in3, const In4 &in4, Out1 *out1) { - new (out1) Out1(element_fn(in1, in2, in3, in4)); - }, - exec_preset) - { - } -}; - -/** - * Generates a multi-function with the following parameters: - * 1. single mutable (SM) of type Mut1 - */ -template class CustomMF_SM : public MultiFunction { +template class CustomMF : public MultiFunction { private: - using FunctionT = std::function)>; - FunctionT function_; MFSignature signature_; + CallFn call_fn_; public: - CustomMF_SM(const char *name, FunctionT function) : function_(std::move(function)) + CustomMF(const char *name, CallFn call_fn, TypeSequence /*param_tags*/) + : call_fn_(std::move(call_fn)) { MFSignatureBuilder signature{name}; - signature.single_mutable("Mut1"); + /* Loop over all parameter types and add an entry for each in the signature. */ + ([&] { signature.add(ParamTags(), ""); }(), ...); signature_ = signature.build(); this->set_signature(&signature_); } - template - CustomMF_SM(const char *name, ElementFuncT element_fn) - : CustomMF_SM(name, CustomMF_SM::create_function(element_fn)) - { - } - - template static FunctionT create_function(ElementFuncT element_fn) - { - return [=](IndexMask mask, MutableSpan mut1) { - mask.to_best_mask_type([&](const auto &mask) { - for (const int64_t i : mask) { - element_fn(mut1[i]); - } - }); - }; - } - void call(IndexMask mask, MFParams params, MFContext /*context*/) const override { - MutableSpan mut1 = params.single_mutable(0); - function_(mask, mut1); + call_fn_(mask, params); } }; +template +inline auto build_multi_function_with_n_inputs_one_output(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset, + TypeSequence /*in_types*/) +{ + constexpr auto param_tags = TypeSequence..., + MFParamTag>(); + auto call_fn = build_multi_function_call_from_element_fn( + [element_fn](const In &...in, Out *out) { new (out) Out(element_fn(in...)); }, + exec_preset, + param_tags); + return CustomMF(name, call_fn, param_tags); +} + +} // namespace detail + +/** Build multi-function with 1 single-input and 1 single-output parameter. */ +template +inline auto SI1_SO(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::Materialized()) +{ + return detail::build_multi_function_with_n_inputs_one_output( + name, element_fn, exec_preset, TypeSequence()); +} + +/** Build multi-function with 2 single-input and 1 single-output parameter. */ +template +inline auto SI2_SO(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::Materialized()) +{ + return detail::build_multi_function_with_n_inputs_one_output( + name, element_fn, exec_preset, TypeSequence()); +} + +/** Build multi-function with 3 single-input and 1 single-output parameter. */ +template +inline auto SI3_SO(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::Materialized()) +{ + return detail::build_multi_function_with_n_inputs_one_output( + name, element_fn, exec_preset, TypeSequence()); +} + +/** Build multi-function with 4 single-input and 1 single-output parameter. */ +template +inline auto SI4_SO(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::Materialized()) +{ + return detail::build_multi_function_with_n_inputs_one_output( + name, element_fn, exec_preset, TypeSequence()); +} + +/** Build multi-function with 5 single-input and 1 single-output parameter. */ +template +inline auto SI5_SO(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::Materialized()) +{ + return detail::build_multi_function_with_n_inputs_one_output( + name, element_fn, exec_preset, TypeSequence()); +} + +/** Build multi-function with 6 single-input and 1 single-output parameter. */ +template +inline auto SI6_SO(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::Materialized()) +{ + return detail::build_multi_function_with_n_inputs_one_output( + name, element_fn, exec_preset, TypeSequence()); +} + +/** Build multi-function with 1 single-mutable parameter. */ +template +inline auto SM(const char *name, + const ElementFn element_fn, + const ExecPreset exec_preset = exec_presets::AllSpanOrSingle()) +{ + constexpr auto param_tags = TypeSequence>(); + auto call_fn = detail::build_multi_function_call_from_element_fn( + element_fn, exec_preset, param_tags); + return detail::CustomMF(name, call_fn, param_tags); +} + +} // namespace blender::fn::build_mf + +namespace blender::fn { + /** * A multi-function that outputs the same value every time. The value is not owned by an instance * of this function. If #make_value_copy is false, the caller is responsible for destructing and diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc index a9d26fa09f1..6a5a31eb17d 100644 --- a/source/blender/functions/intern/field.cc +++ b/source/blender/functions/intern/field.cc @@ -519,8 +519,8 @@ GField make_field_constant_if_possible(GField field) Field invert_boolean_field(const Field &field) { - static CustomMF_SI_SO not_fn{ - "Not", [](bool a) { return !a; }, CustomMF_presets::AllSpanOrSingle()}; + static auto not_fn = build_mf::SI1_SO( + "Not", [](bool a) { return !a; }, build_mf::exec_presets::AllSpanOrSingle()); auto not_op = std::make_shared(FieldOperation(not_fn, {field})); return Field(not_op); } diff --git a/source/blender/functions/tests/FN_field_test.cc b/source/blender/functions/tests/FN_field_test.cc index 8c5cc817174..3e5c201195f 100644 --- a/source/blender/functions/tests/FN_field_test.cc +++ b/source/blender/functions/tests/FN_field_test.cc @@ -104,11 +104,9 @@ TEST(field, InputAndFunction) { GField index_field{std::make_shared()}; - std::unique_ptr add_fn = std::make_unique>( - "add", [](int a, int b) { return a + b; }); - GField output_field{std::make_shared( - FieldOperation(std::move(add_fn), {index_field, index_field})), - 0}; + auto add_fn = build_mf::SI2_SO("add", [](int a, int b) { return a + b; }); + GField output_field{ + std::make_shared(FieldOperation(add_fn, {index_field, index_field})), 0}; Array result(10); @@ -129,16 +127,12 @@ TEST(field, TwoFunctions) { GField index_field{std::make_shared()}; - std::unique_ptr add_fn = std::make_unique>( - "add", [](int a, int b) { return a + b; }); - GField add_field{std::make_shared( - FieldOperation(std::move(add_fn), {index_field, index_field})), - 0}; + auto add_fn = build_mf::SI2_SO("add", [](int a, int b) { return a + b; }); + GField add_field{ + std::make_shared(FieldOperation(add_fn, {index_field, index_field})), 0}; - std::unique_ptr add_10_fn = std::make_unique>( - "add_10", [](int a) { return a + 10; }); - GField result_field{ - std::make_shared(FieldOperation(std::move(add_10_fn), {add_field})), 0}; + auto add_10_fn = build_mf::SI1_SO("add_10", [](int a) { return a + 10; }); + GField result_field{std::make_shared(FieldOperation(add_10_fn, {add_field})), 0}; Array result(10); @@ -230,11 +224,9 @@ TEST(field, TwoFunctionsTwoOutputs) Field result_field_1{fn, 0}; Field intermediate_field{fn, 1}; - std::unique_ptr add_10_fn = std::make_unique>( - "add_10", [](int a) { return a + 10; }); + auto add_10_fn = build_mf::SI1_SO("add_10", [](int a) { return a + 10; }); Field result_field_2{ - std::make_shared(FieldOperation(std::move(add_10_fn), {intermediate_field})), - 0}; + std::make_shared(FieldOperation(add_10_fn, {intermediate_field})), 0}; FieldContext field_context; FieldEvaluator field_evaluator{field_context, &mask}; diff --git a/source/blender/functions/tests/FN_multi_function_procedure_test.cc b/source/blender/functions/tests/FN_multi_function_procedure_test.cc index e7cedb40f83..aa8549dad44 100644 --- a/source/blender/functions/tests/FN_multi_function_procedure_test.cc +++ b/source/blender/functions/tests/FN_multi_function_procedure_test.cc @@ -19,7 +19,7 @@ TEST(multi_function_procedure, ConstantOutput) */ CustomMF_Constant constant_fn{5}; - CustomMF_SI_SI_SO add_fn{"Add", [](int a, int b) { return a + b; }}; + auto add_fn = build_mf::SI2_SO("Add", [](int a, int b) { return a + b; }); MFProcedure procedure; MFProcedureBuilder builder{procedure}; @@ -56,8 +56,8 @@ TEST(multi_function_procedure, SimpleTest) * } */ - CustomMF_SI_SI_SO add_fn{"add", [](int a, int b) { return a + b; }}; - CustomMF_SM add_10_fn{"add_10", [](int &a) { a += 10; }}; + auto add_fn = fn::build_mf::SI2_SO("add", [](int a, int b) { return a + b; }); + auto add_10_fn = fn::build_mf::SM("add_10", [](int &a) { a += 10; }); MFProcedure procedure; MFProcedureBuilder builder{procedure}; @@ -106,8 +106,8 @@ TEST(multi_function_procedure, BranchTest) * } */ - CustomMF_SM add_10_fn{"add_10", [](int &a) { a += 10; }}; - CustomMF_SM add_100_fn{"add_100", [](int &a) { a += 100; }}; + auto add_10_fn = build_mf::SM("add_10", [](int &a) { a += 10; }); + auto add_100_fn = build_mf::SM("add_100", [](int &a) { a += 100; }); MFProcedure procedure; MFProcedureBuilder builder{procedure}; @@ -153,10 +153,10 @@ TEST(multi_function_procedure, EvaluateOne) */ int tot_evaluations = 0; - CustomMF_SI_SO add_10_fn{"add_10", [&](int a) { - tot_evaluations++; - return a + 10; - }}; + const auto add_10_fn = fn::build_mf::SI1_SO("add_10", [&](int a) { + tot_evaluations++; + return a + 10; + }); MFProcedure procedure; MFProcedureBuilder builder{procedure}; @@ -205,11 +205,11 @@ TEST(multi_function_procedure, SimpleLoop) CustomMF_Constant const_1_fn{1}; CustomMF_Constant const_0_fn{0}; - CustomMF_SI_SI_SO greater_or_equal_fn{"greater or equal", - [](int a, int b) { return a >= b; }}; - CustomMF_SM double_fn{"double", [](int &a) { a *= 2; }}; - CustomMF_SM add_1000_fn{"add 1000", [](int &a) { a += 1000; }}; - CustomMF_SM add_1_fn{"add 1", [](int &a) { a += 1; }}; + auto greater_or_equal_fn = fn::build_mf::SI2_SO( + "greater or equal", [](int a, int b) { return a >= b; }); + auto double_fn = build_mf::SM("double", [](int &a) { a *= 2; }); + auto add_1000_fn = build_mf::SM("add 1000", [](int &a) { a += 1000; }); + auto add_1_fn = build_mf::SM("add 1", [](int &a) { a += 1; }); MFProcedure procedure; MFProcedureBuilder builder{procedure}; @@ -338,7 +338,7 @@ TEST(multi_function_procedure, BufferReuse) * } */ - CustomMF_SI_SO add_10_fn{"add 10", [](int a) { return a + 10; }}; + auto add_10_fn = build_mf::SI1_SO("add 10", [](int a) { return a + 10; }); MFProcedure procedure; MFProcedureBuilder builder{procedure}; diff --git a/source/blender/functions/tests/FN_multi_function_test.cc b/source/blender/functions/tests/FN_multi_function_test.cc index ca788b0a6ee..7a582805e98 100644 --- a/source/blender/functions/tests/FN_multi_function_test.cc +++ b/source/blender/functions/tests/FN_multi_function_test.cc @@ -149,98 +149,6 @@ TEST(multi_function, GenericAppendFunction) EXPECT_EQ(vectors_ref[3][0], 1); } -TEST(multi_function, CustomMF_SI_SO) -{ - CustomMF_SI_SO fn("strlen", - [](const std::string &str) { return str.size(); }); - - Array strings = {"hello", "world", "test", "another test"}; - Array sizes(strings.size(), 0); - - MFParamsBuilder params(fn, strings.size()); - params.add_readonly_single_input(strings.as_span()); - params.add_uninitialized_single_output(sizes.as_mutable_span()); - - MFContextBuilder context; - - fn.call(IndexRange(strings.size()), params, context); - - EXPECT_EQ(sizes[0], 5); - EXPECT_EQ(sizes[1], 5); - EXPECT_EQ(sizes[2], 4); - EXPECT_EQ(sizes[3], 12); -} - -TEST(multi_function, CustomMF_SI_SI_SO) -{ - CustomMF_SI_SI_SO fn("mul", [](int a, int b) { return a * b; }); - - Array values_a = {4, 6, 8, 9}; - int value_b = 10; - Array outputs(values_a.size(), -1); - - MFParamsBuilder params(fn, values_a.size()); - params.add_readonly_single_input(values_a.as_span()); - params.add_readonly_single_input(&value_b); - params.add_uninitialized_single_output(outputs.as_mutable_span()); - - MFContextBuilder context; - - fn.call({0, 1, 3}, params, context); - - EXPECT_EQ(outputs[0], 40); - EXPECT_EQ(outputs[1], 60); - EXPECT_EQ(outputs[2], -1); - EXPECT_EQ(outputs[3], 90); -} - -TEST(multi_function, CustomMF_SI_SI_SI_SO) -{ - CustomMF_SI_SI_SI_SO fn{ - "custom", - [](int a, const std::string &b, bool c) { return uint(uint(a) + b.size() + uint(c)); }}; - - Array values_a = {5, 7, 3, 8}; - Array values_b = {"hello", "world", "another", "test"}; - Array values_c = {true, false, false, true}; - Array outputs(values_a.size(), 0); - - MFParamsBuilder params(fn, values_a.size()); - params.add_readonly_single_input(values_a.as_span()); - params.add_readonly_single_input(values_b.as_span()); - params.add_readonly_single_input(values_c.as_span()); - params.add_uninitialized_single_output(outputs.as_mutable_span()); - - MFContextBuilder context; - - fn.call({1, 2, 3}, params, context); - - EXPECT_EQ(outputs[0], 0); - EXPECT_EQ(outputs[1], 12); - EXPECT_EQ(outputs[2], 10); - EXPECT_EQ(outputs[3], 13); -} - -TEST(multi_function, CustomMF_SM) -{ - CustomMF_SM fn("AddSuffix", [](std::string &value) { value += " test"; }); - - Array values = {"a", "b", "c", "d", "e"}; - - MFParamsBuilder params(fn, values.size()); - params.add_single_mutable(values.as_mutable_span()); - - MFContextBuilder context; - - fn.call({1, 2, 3}, params, context); - - EXPECT_EQ(values[0], "a"); - EXPECT_EQ(values[1], "b test"); - EXPECT_EQ(values[2], "c test"); - EXPECT_EQ(values[3], "d test"); - EXPECT_EQ(values[4], "e"); -} - TEST(multi_function, CustomMF_Constant) { CustomMF_Constant fn{42}; diff --git a/source/blender/geometry/intern/resample_curves.cc b/source/blender/geometry/intern/resample_curves.cc index cccf659ac5e..358c7ced488 100644 --- a/source/blender/geometry/intern/resample_curves.cc +++ b/source/blender/geometry/intern/resample_curves.cc @@ -17,10 +17,10 @@ namespace blender::geometry { static fn::Field get_count_input_max_one(const fn::Field &count_field) { - static fn::CustomMF_SI_SO max_one_fn( + static auto max_one_fn = fn::build_mf::SI1_SO( "Clamp Above One", [](int value) { return std::max(1, value); }, - fn::CustomMF_presets::AllSpanOrSingle()); + fn::build_mf::exec_presets::AllSpanOrSingle()); auto clamp_op = std::make_shared( fn::FieldOperation(max_one_fn, {count_field})); @@ -29,7 +29,7 @@ static fn::Field get_count_input_max_one(const fn::Field &count_field) static fn::Field get_count_input_from_length(const fn::Field &length_field) { - static fn::CustomMF_SI_SI_SO get_count_fn( + static auto get_count_fn = fn::build_mf::SI2_SO( "Length Input to Count", [](const float curve_length, const float sample_length) { /* Find the number of sampled segments by dividing the total length by @@ -37,7 +37,7 @@ static fn::Field get_count_input_from_length(const fn::Field &length const int count = int(curve_length / sample_length) + 1; return std::max(1, count); }, - fn::CustomMF_presets::AllSpanOrSingle()); + fn::build_mf::exec_presets::AllSpanOrSingle()); auto get_count_op = std::make_shared(fn::FieldOperation( get_count_fn, diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh index 51057f600f4..b7637fb2c66 100644 --- a/source/blender/nodes/NOD_math_functions.hh +++ b/source/blender/nodes/NOD_math_functions.hh @@ -51,8 +51,8 @@ inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&cal return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); - static auto exec_preset_slow = fn::CustomMF_presets::Materialized(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); /* This is just an utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -118,8 +118,8 @@ inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback && return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); - static auto exec_preset_slow = fn::CustomMF_presets::Materialized(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); /* This is just an utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -180,21 +180,21 @@ inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback switch (operation) { case NODE_MATH_MULTIPLY_ADD: - return dispatch(fn::CustomMF_presets::AllSpanOrSingle(), + return dispatch(fn::build_mf::exec_presets::AllSpanOrSingle(), [](float a, float b, float c) { return a * b + c; }); case NODE_MATH_COMPARE: - return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0, 1>(), + return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(), [](float a, float b, float c) -> float { return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f; }); case NODE_MATH_SMOOTH_MIN: - return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0, 1>(), + return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(), [](float a, float b, float c) { return smoothminf(a, b, c); }); case NODE_MATH_SMOOTH_MAX: - return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0, 1>(), + return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(), [](float a, float b, float c) { return -smoothminf(-a, -b, c); }); case NODE_MATH_WRAP: - return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0>(), + return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0>(), [](float a, float b, float c) { return wrapf(a, b, c); }); } return false; @@ -214,8 +214,8 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl3(const NodeVectorMathOperation return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); - static auto exec_preset_slow = fn::CustomMF_presets::Materialized(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -269,7 +269,7 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl(const NodeVectorMathOperation return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -302,8 +302,8 @@ inline bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOpera return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); - static auto exec_preset_slow = fn::CustomMF_presets::Materialized(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -341,7 +341,7 @@ inline bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperat return false; } - static auto exec_preset_slow = fn::CustomMF_presets::Materialized(); + static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -373,7 +373,7 @@ inline bool try_dispatch_float_math_fl3_to_fl(const NodeVectorMathOperation oper return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -402,7 +402,7 @@ inline bool try_dispatch_float_math_fl3_fl_to_fl3(const NodeVectorMathOperation return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { @@ -433,8 +433,8 @@ inline bool try_dispatch_float_math_fl3_to_fl3(const NodeVectorMathOperation ope return false; } - static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle(); - static auto exec_preset_slow = fn::CustomMF_presets::Materialized(); + static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); /* This is just a utility function to keep the individual cases smaller. */ auto dispatch = [&](auto exec_preset, auto math_function) -> bool { diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc index 849e03ca77f..02e15fe7853 100644 --- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc +++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc @@ -67,24 +67,25 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms) static const fn::MultiFunction *get_multi_function(const bNode &bnode) { - static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle(); - static fn::CustomMF_SI_SI_SO and_fn{ - "And", [](bool a, bool b) { return a && b; }, exec_preset}; - static fn::CustomMF_SI_SI_SO or_fn{ - "Or", [](bool a, bool b) { return a || b; }, exec_preset}; - static fn::CustomMF_SI_SO not_fn{"Not", [](bool a) { return !a; }, exec_preset}; - static fn::CustomMF_SI_SI_SO nand_fn{ - "Not And", [](bool a, bool b) { return !(a && b); }, exec_preset}; - static fn::CustomMF_SI_SI_SO nor_fn{ - "Nor", [](bool a, bool b) { return !(a || b); }, exec_preset}; - static fn::CustomMF_SI_SI_SO xnor_fn{ - "Equal", [](bool a, bool b) { return a == b; }, exec_preset}; - static fn::CustomMF_SI_SI_SO xor_fn{ - "Not Equal", [](bool a, bool b) { return a != b; }, exec_preset}; - static fn::CustomMF_SI_SI_SO imply_fn{ - "Imply", [](bool a, bool b) { return !a || b; }, exec_preset}; - static fn::CustomMF_SI_SI_SO nimply_fn{ - "Subtract", [](bool a, bool b) { return a && !b; }, exec_preset}; + static auto exec_preset = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto and_fn = fn::build_mf::SI2_SO( + "And", [](bool a, bool b) { return a && b; }, exec_preset); + static auto or_fn = fn::build_mf::SI2_SO( + "Or", [](bool a, bool b) { return a || b; }, exec_preset); + static auto not_fn = fn::build_mf::SI1_SO( + "Not", [](bool a) { return !a; }, exec_preset); + static auto nand_fn = fn::build_mf::SI2_SO( + "Not And", [](bool a, bool b) { return !(a && b); }, exec_preset); + static auto nor_fn = fn::build_mf::SI2_SO( + "Nor", [](bool a, bool b) { return !(a || b); }, exec_preset); + static auto xnor_fn = fn::build_mf::SI2_SO( + "Equal", [](bool a, bool b) { return a == b; }, exec_preset); + static auto xor_fn = fn::build_mf::SI2_SO( + "Not Equal", [](bool a, bool b) { return a != b; }, exec_preset); + static auto imply_fn = fn::build_mf::SI2_SO( + "Imply", [](bool a, bool b) { return !a || b; }, exec_preset); + static auto nimply_fn = fn::build_mf::SI2_SO( + "Subtract", [](bool a, bool b) { return a && !b; }, exec_preset); switch (bnode.custom1) { case NODE_BOOLEAN_MATH_AND: diff --git a/source/blender/nodes/function/nodes/node_fn_combine_color.cc b/source/blender/nodes/function/nodes/node_fn_combine_color.cc index 318c8997f9a..9b395767ec3 100644 --- a/source/blender/nodes/function/nodes/node_fn_combine_color.cc +++ b/source/blender/nodes/function/nodes/node_fn_combine_color.cc @@ -53,22 +53,22 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode) { const NodeCombSepColor &storage = node_storage(bnode); - static fn::CustomMF_SI_SI_SI_SI_SO rgba_fn{ - "RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }}; - static fn::CustomMF_SI_SI_SI_SI_SO hsva_fn{ + static auto rgba_fn = fn::build_mf::SI4_SO( + "RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }); + static auto hsva_fn = fn::build_mf::SI4_SO( "HSV", [](float h, float s, float v, float a) { ColorGeometry4f r_color; hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b); r_color.a = a; return r_color; - }}; - static fn::CustomMF_SI_SI_SI_SI_SO hsla_fn{ + }); + static auto hsla_fn = fn::build_mf::SI4_SO( "HSL", [](float h, float s, float l, float a) { ColorGeometry4f color; hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b); color.a = a; return color; - }}; + }); switch (storage.mode) { case NODE_COMBSEP_COLOR_RGB: diff --git a/source/blender/nodes/function/nodes/node_fn_compare.cc b/source/blender/nodes/function/nodes/node_fn_compare.cc index d73cb8cd558..e272880fe4b 100644 --- a/source/blender/nodes/function/nodes/node_fn_compare.cc +++ b/source/blender/nodes/function/nodes/node_fn_compare.cc @@ -168,77 +168,77 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) { const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage; - static auto exec_preset_all = fn::CustomMF_presets::AllSpanOrSingle(); - static auto exec_preset_first_two = fn::CustomMF_presets::SomeSpanOrSingle<0, 1>(); + static auto exec_preset_all = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto exec_preset_first_two = fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(); switch (data->data_type) { case SOCK_FLOAT: switch (data->operation) { case NODE_COMPARE_LESS_THAN: { - static fn::CustomMF_SI_SI_SO fn{ - "Less Than", [](float a, float b) { return a < b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Less Than", [](float a, float b) { return a < b; }, exec_preset_all); return &fn; } case NODE_COMPARE_LESS_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Less Equal", [](float a, float b) { return a <= b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Less Equal", [](float a, float b) { return a <= b; }, exec_preset_all); return &fn; } case NODE_COMPARE_GREATER_THAN: { - static fn::CustomMF_SI_SI_SO fn{ - "Greater Than", [](float a, float b) { return a > b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Greater Than", [](float a, float b) { return a > b; }, exec_preset_all); return &fn; } case NODE_COMPARE_GREATER_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Greater Equal", [](float a, float b) { return a >= b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Greater Equal", [](float a, float b) { return a >= b; }, exec_preset_all); return &fn; } case NODE_COMPARE_EQUAL: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Equal", [](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_NOT_EQUAL: - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Not Equal", [](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } break; case SOCK_INT: switch (data->operation) { case NODE_COMPARE_LESS_THAN: { - static fn::CustomMF_SI_SI_SO fn{ - "Less Than", [](int a, int b) { return a < b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Less Than", [](int a, int b) { return a < b; }, exec_preset_all); return &fn; } case NODE_COMPARE_LESS_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Less Equal", [](int a, int b) { return a <= b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Less Equal", [](int a, int b) { return a <= b; }, exec_preset_all); return &fn; } case NODE_COMPARE_GREATER_THAN: { - static fn::CustomMF_SI_SI_SO fn{ - "Greater Than", [](int a, int b) { return a > b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Greater Than", [](int a, int b) { return a > b; }, exec_preset_all); return &fn; } case NODE_COMPARE_GREATER_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Greater Equal", [](int a, int b) { return a >= b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Greater Equal", [](int a, int b) { return a >= b; }, exec_preset_all); return &fn; } case NODE_COMPARE_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Equal", [](int a, int b) { return a == b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Equal", [](int a, int b) { return a == b; }, exec_preset_all); return &fn; } case NODE_COMPARE_NOT_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Not Equal", [](int a, int b) { return a != b; }, exec_preset_all}; + static auto fn = fn::build_mf::SI2_SO( + "Not Equal", [](int a, int b) { return a != b; }, exec_preset_all); return &fn; } } @@ -248,38 +248,38 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case NODE_COMPARE_LESS_THAN: switch (data->mode) { case NODE_COMPARE_MODE_AVERAGE: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Less Than - Average", [](float3 a, float3 b) { return component_average(a) < component_average(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_DOT_PRODUCT: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Less Than - Dot Product", [](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DIRECTION: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Less Than - Direction", [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_ELEMENT: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Less Than - Element-wise", [](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_LENGTH: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Less Than - Length", [](float3 a, float3 b) { return math::length(a) < math::length(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } } @@ -287,38 +287,38 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case NODE_COMPARE_LESS_EQUAL: switch (data->mode) { case NODE_COMPARE_MODE_AVERAGE: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Less Equal - Average", [](float3 a, float3 b) { return component_average(a) <= component_average(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_DOT_PRODUCT: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Less Equal - Dot Product", [](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DIRECTION: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Less Equal - Direction", [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_ELEMENT: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Less Equal - Element-wise", [](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_LENGTH: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Less Equal - Length", [](float3 a, float3 b) { return math::length(a) <= math::length(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } } @@ -326,38 +326,38 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case NODE_COMPARE_GREATER_THAN: switch (data->mode) { case NODE_COMPARE_MODE_AVERAGE: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Greater Than - Average", [](float3 a, float3 b) { return component_average(a) > component_average(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_DOT_PRODUCT: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Greater Than - Dot Product", [](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DIRECTION: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Greater Than - Direction", [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_ELEMENT: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Greater Than - Element-wise", [](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_LENGTH: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Greater Than - Length", [](float3 a, float3 b) { return math::length(a) > math::length(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } } @@ -365,38 +365,38 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case NODE_COMPARE_GREATER_EQUAL: switch (data->mode) { case NODE_COMPARE_MODE_AVERAGE: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Greater Equal - Average", [](float3 a, float3 b) { return component_average(a) >= component_average(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_DOT_PRODUCT: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Greater Equal - Dot Product", [](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DIRECTION: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Greater Equal - Direction", [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_ELEMENT: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Greater Equal - Element-wise", [](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_MODE_LENGTH: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Greater Equal - Length", [](float3 a, float3 b) { return math::length(a) >= math::length(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } } @@ -404,49 +404,49 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case NODE_COMPARE_EQUAL: switch (data->mode) { case NODE_COMPARE_MODE_AVERAGE: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Equal - Average", [](float3 a, float3 b, float epsilon) { return abs(component_average(a) - component_average(b)) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DOT_PRODUCT: { - static fn::CustomMF_SI_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI4_SO( "Equal - Dot Product", [](float3 a, float3 b, float comp, float epsilon) { return abs(math::dot(a, b) - comp) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DIRECTION: { - static fn::CustomMF_SI_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI4_SO( "Equal - Direction", [](float3 a, float3 b, float angle, float epsilon) { return abs(angle_v3v3(a, b) - angle) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_ELEMENT: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Equal - Element-wise", [](float3 a, float3 b, float epsilon) { return abs(a.x - b.x) <= epsilon && abs(a.y - b.y) <= epsilon && abs(a.z - b.z) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_LENGTH: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Equal - Length", [](float3 a, float3 b, float epsilon) { return abs(math::length(a) - math::length(b)) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } } @@ -454,49 +454,49 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case NODE_COMPARE_NOT_EQUAL: switch (data->mode) { case NODE_COMPARE_MODE_AVERAGE: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Not Equal - Average", [](float3 a, float3 b, float epsilon) { return abs(component_average(a) - component_average(b)) > epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DOT_PRODUCT: { - static fn::CustomMF_SI_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI4_SO( "Not Equal - Dot Product", [](float3 a, float3 b, float comp, float epsilon) { return abs(math::dot(a, b) - comp) >= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_DIRECTION: { - static fn::CustomMF_SI_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI4_SO( "Not Equal - Direction", [](float3 a, float3 b, float angle, float epsilon) { return abs(angle_v3v3(a, b) - angle) > epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_ELEMENT: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Not Equal - Element-wise", [](float3 a, float3 b, float epsilon) { return abs(a.x - b.x) > epsilon || abs(a.y - b.y) > epsilon || abs(a.z - b.z) > epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_MODE_LENGTH: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Not Equal - Length", [](float3 a, float3 b, float epsilon) { return abs(math::length(a) - math::length(b)) > epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } } @@ -506,41 +506,41 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case SOCK_RGBA: switch (data->operation) { case NODE_COMPARE_EQUAL: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Equal", [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) { return abs(a.r - b.r) <= epsilon && abs(a.g - b.g) <= epsilon && abs(a.b - b.b) <= epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_NOT_EQUAL: { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Not Equal", [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) { return abs(a.r - b.r) > epsilon || abs(a.g - b.g) > epsilon || abs(a.b - b.b) > epsilon; }, - exec_preset_first_two}; + exec_preset_first_two); return &fn; } case NODE_COMPARE_COLOR_BRIGHTER: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Brighter", [](ColorGeometry4f a, ColorGeometry4f b) { return rgb_to_grayscale(a) > rgb_to_grayscale(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } case NODE_COMPARE_COLOR_DARKER: { - static fn::CustomMF_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI2_SO( "Darker", [](ColorGeometry4f a, ColorGeometry4f b) { return rgb_to_grayscale(a) < rgb_to_grayscale(b); }, - exec_preset_all}; + exec_preset_all); return &fn; } } @@ -548,13 +548,13 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) case SOCK_STRING: switch (data->operation) { case NODE_COMPARE_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Equal", [](std::string a, std::string b) { return a == b; }}; + static auto fn = fn::build_mf::SI2_SO( + "Equal", [](std::string a, std::string b) { return a == b; }); return &fn; } case NODE_COMPARE_NOT_EQUAL: { - static fn::CustomMF_SI_SI_SO fn{ - "Not Equal", [](std::string a, std::string b) { return a != b; }}; + static auto fn = fn::build_mf::SI2_SO( + "Not Equal", [](std::string a, std::string b) { return a != b; }); return &fn; } } diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc index 95922de4e20..de68b00874f 100644 --- a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc +++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc @@ -38,15 +38,15 @@ static void node_label(const bNodeTree * /*tree*/, const bNode *node, char *labe static const fn::MultiFunction *get_multi_function(const bNode &bnode) { - static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle(); - static fn::CustomMF_SI_SO round_fn{ - "Round", [](float a) { return int(round(a)); }, exec_preset}; - static fn::CustomMF_SI_SO floor_fn{ - "Floor", [](float a) { return int(floor(a)); }, exec_preset}; - static fn::CustomMF_SI_SO ceil_fn{ - "Ceiling", [](float a) { return int(ceil(a)); }, exec_preset}; - static fn::CustomMF_SI_SO trunc_fn{ - "Truncate", [](float a) { return int(trunc(a)); }, exec_preset}; + static auto exec_preset = fn::build_mf::exec_presets::AllSpanOrSingle(); + static auto round_fn = fn::build_mf::SI1_SO( + "Round", [](float a) { return int(round(a)); }, exec_preset); + static auto floor_fn = fn::build_mf::SI1_SO( + "Floor", [](float a) { return int(floor(a)); }, exec_preset); + static auto ceil_fn = fn::build_mf::SI1_SO( + "Ceiling", [](float a) { return int(ceil(a)); }, exec_preset); + static auto trunc_fn = fn::build_mf::SI1_SO( + "Truncate", [](float a) { return int(trunc(a)); }, exec_preset); switch (static_cast(bnode.custom1)) { case FN_NODE_FLOAT_TO_INT_ROUND: diff --git a/source/blender/nodes/function/nodes/node_fn_random_value.cc b/source/blender/nodes/function/nodes/node_fn_random_value.cc index b021ff07f04..1dfd8074349 100644 --- a/source/blender/nodes/function/nodes/node_fn_random_value.cc +++ b/source/blender/nodes/function/nodes/node_fn_random_value.cc @@ -141,64 +141,49 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder) switch (data_type) { case CD_PROP_FLOAT3: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Random Vector", - [](float3 min_value, float3 max_value, int id, int seed, float3 *r_value) { - const float x = noise::hash_to_float(seed, id, 0); - const float y = noise::hash_to_float(seed, id, 1); - const float z = noise::hash_to_float(seed, id, 2); - *r_value = float3(x, y, z) * (max_value - min_value) + min_value; - }, - fn::CustomMF_presets::SomeSpanOrSingle<2>()}; + static auto fn = fn::build_mf::SI4_SO( + "Random Vector", + [](float3 min_value, float3 max_value, int id, int seed) -> float3 { + const float x = noise::hash_to_float(seed, id, 0); + const float y = noise::hash_to_float(seed, id, 1); + const float z = noise::hash_to_float(seed, id, 2); + return float3(x, y, z) * (max_value - min_value) + min_value; + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<2>()); builder.set_matching_fn(fn); break; } case CD_PROP_FLOAT: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Random Float", - [](float min_value, float max_value, int id, int seed, float *r_value) { - const float value = noise::hash_to_float(seed, id); - *r_value = value * (max_value - min_value) + min_value; - }, - fn::CustomMF_presets::SomeSpanOrSingle<2>()}; + static auto fn = fn::build_mf::SI4_SO( + "Random Float", + [](float min_value, float max_value, int id, int seed) -> float { + const float value = noise::hash_to_float(seed, id); + return value * (max_value - min_value) + min_value; + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<2>()); builder.set_matching_fn(fn); break; } case CD_PROP_INT32: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Random Int", - [](int min_value, int max_value, int id, int seed, int *r_value) { - const float value = noise::hash_to_float(id, seed); - /* Add one to the maximum and use floor to produce an even - * distribution for the first and last values (See T93591). */ - *r_value = floor(value * (max_value + 1 - min_value) + min_value); - }, - fn::CustomMF_presets::SomeSpanOrSingle<2>()}; + static auto fn = fn::build_mf::SI4_SO( + "Random Int", + [](int min_value, int max_value, int id, int seed) -> int { + const float value = noise::hash_to_float(id, seed); + /* Add one to the maximum and use floor to produce an even + * distribution for the first and last values (See T93591). */ + return floor(value * (max_value + 1 - min_value) + min_value); + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<2>()); builder.set_matching_fn(fn); break; } case CD_PROP_BOOL: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Random Bool", - [](float probability, int id, int seed, bool *r_value) { - *r_value = noise::hash_to_float(id, seed) <= probability; - }, - fn::CustomMF_presets::SomeSpanOrSingle<1>()}; + static auto fn = fn::build_mf::SI3_SO( + "Random Bool", + [](float probability, int id, int seed) -> bool { + return noise::hash_to_float(id, seed) <= probability; + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<1>()); builder.set_matching_fn(fn); break; } diff --git a/source/blender/nodes/function/nodes/node_fn_replace_string.cc b/source/blender/nodes/function/nodes/node_fn_replace_string.cc index 3a388bedbc7..3b941018c6c 100644 --- a/source/blender/nodes/function/nodes/node_fn_replace_string.cc +++ b/source/blender/nodes/function/nodes/node_fn_replace_string.cc @@ -30,10 +30,12 @@ static std::string replace_all(const StringRefNull str, static void node_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SI_SI_SO substring_fn{ - "Replace", [](const std::string &str, const std::string &find, const std::string &replace) { - return replace_all(str, find, replace); - }}; + static auto substring_fn = + fn::build_mf::SI3_SO( + "Replace", + [](const std::string &str, const std::string &find, const std::string &replace) { + return replace_all(str, find, replace); + }); builder.set_matching_fn(&substring_fn); } diff --git a/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc b/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc index 7fd9762b4e0..0cdb876edb3 100644 --- a/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc +++ b/source/blender/nodes/function/nodes/node_fn_rotate_euler.cc @@ -54,7 +54,7 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) static const fn::MultiFunction *get_multi_function(const bNode &bnode) { - static fn::CustomMF_SI_SI_SO obj_euler_rot{ + static auto obj_euler_rot = fn::build_mf::SI2_SO( "Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) { float input_mat[3][3]; eul_to_mat3(input_mat, input); @@ -65,8 +65,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode) float3 result; mat3_to_eul(result, mat_res); return result; - }}; - static fn::CustomMF_SI_SI_SI_SO obj_AA_rot{ + }); + static auto obj_AA_rot = fn::build_mf::SI3_SO( "Rotate Euler by AxisAngle/Object", [](const float3 &input, const float3 &axis, float angle) { float input_mat[3][3]; @@ -78,8 +78,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode) float3 result; mat3_to_eul(result, mat_res); return result; - }}; - static fn::CustomMF_SI_SI_SO local_euler_rot{ + }); + static auto local_euler_rot = fn::build_mf::SI2_SO( "Rotate Euler by Euler/Local", [](const float3 &input, const float3 &rotation) { float input_mat[3][3]; eul_to_mat3(input_mat, input); @@ -90,8 +90,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode) float3 result; mat3_to_eul(result, mat_res); return result; - }}; - static fn::CustomMF_SI_SI_SI_SO local_AA_rot{ + }); + static auto local_AA_rot = fn::build_mf::SI3_SO( "Rotate Euler by AxisAngle/Local", [](const float3 &input, const float3 &axis, float angle) { float input_mat[3][3]; eul_to_mat3(input_mat, input); @@ -102,14 +102,18 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode) float3 result; mat3_to_eul(result, mat_res); return result; - }}; + }); short type = bnode.custom1; short space = bnode.custom2; if (type == FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE) { - return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? &obj_AA_rot : &local_AA_rot; + return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? + static_cast(&obj_AA_rot) : + &local_AA_rot; } if (type == FN_NODE_ROTATE_EULER_TYPE_EULER) { - return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? &obj_euler_rot : &local_euler_rot; + return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? + static_cast(&obj_euler_rot) : + &local_euler_rot; } BLI_assert_unreachable(); return nullptr; diff --git a/source/blender/nodes/function/nodes/node_fn_slice_string.cc b/source/blender/nodes/function/nodes/node_fn_slice_string.cc index 9ce928e2cc7..3785a6e74b3 100644 --- a/source/blender/nodes/function/nodes/node_fn_slice_string.cc +++ b/source/blender/nodes/function/nodes/node_fn_slice_string.cc @@ -16,13 +16,13 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SI_SI_SO slice_fn{ + static auto slice_fn = fn::build_mf::SI3_SO( "Slice", [](const std::string &str, int a, int b) { const int len = BLI_strlen_utf8(str.c_str()); const int start = BLI_str_utf8_offset_from_index(str.c_str(), std::clamp(a, 0, len)); const int end = BLI_str_utf8_offset_from_index(str.c_str(), std::clamp(a + b, 0, len)); return str.substr(start, std::max(end - start, 0)); - }}; + }); builder.set_matching_fn(&slice_fn); } diff --git a/source/blender/nodes/function/nodes/node_fn_string_length.cc b/source/blender/nodes/function/nodes/node_fn_string_length.cc index 02bab0b8fbf..6ced713f8f4 100644 --- a/source/blender/nodes/function/nodes/node_fn_string_length.cc +++ b/source/blender/nodes/function/nodes/node_fn_string_length.cc @@ -16,8 +16,8 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SO str_len_fn{ - "String Length", [](const std::string &a) { return BLI_strlen_utf8(a.c_str()); }}; + static auto str_len_fn = fn::build_mf::SI1_SO( + "String Length", [](const std::string &a) { return BLI_strlen_utf8(a.c_str()); }); builder.set_matching_fn(&str_len_fn); } diff --git a/source/blender/nodes/function/nodes/node_fn_value_to_string.cc b/source/blender/nodes/function/nodes/node_fn_value_to_string.cc index 12c0fe48327..0b542fc8405 100644 --- a/source/blender/nodes/function/nodes/node_fn_value_to_string.cc +++ b/source/blender/nodes/function/nodes/node_fn_value_to_string.cc @@ -14,12 +14,12 @@ static void node_declare(NodeDeclarationBuilder &b) static void node_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SI_SO to_str_fn{ + static auto to_str_fn = fn::build_mf::SI2_SO( "Value To String", [](float a, int b) { std::stringstream stream; stream << std::fixed << std::setprecision(std::max(0, b)) << a; return stream.str(); - }}; + }); builder.set_matching_fn(&to_str_fn); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 27f34db2f9f..bbb63babde4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -1325,10 +1325,10 @@ static void node_geo_exec(GeoNodeExecParams params) /* Create a combined field from the offset and the scale so the field evaluator * can take care of the multiplication and to simplify each extrude function. */ - static fn::CustomMF_SI_SI_SO multiply_fn{ + static auto multiply_fn = fn::build_mf::SI2_SO( "Scale", [](const float3 &offset, const float scale) { return offset * scale; }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); std::shared_ptr multiply_op = std::make_shared( FieldOperation(multiply_fn, {std::move(offset_field), std::move(scale_field)})); const Field final_offset{std::move(multiply_op)}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc index f551faee2e0..c8100ea4c82 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc @@ -121,10 +121,10 @@ static void node_geo_exec(GeoNodeExecParams params) /* Use another multi-function operation to make sure the input radius is greater than zero. * TODO: Use mutable multi-function once that is supported. */ - static fn::CustomMF_SI_SO max_zero_fn( + static auto max_zero_fn = fn::build_mf::SI1_SO( __func__, [](float value) { return std::max(0.0f, value); }, - fn::CustomMF_presets::AllSpanOrSingle()); + fn::build_mf::exec_presets::AllSpanOrSingle()); auto max_zero_op = std::make_shared( FieldOperation(max_zero_fn, {std::move(radius)})); Field positive_radius(std::move(max_zero_op), 0); diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc index 75136013e7e..04ff3d79fc4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc @@ -171,10 +171,10 @@ template void switch_fields(GeoNodeExecParams ¶ms, const StringR Field falses_field = params.extract_input>(name_false); Field trues_field = params.extract_input>(name_true); - static fn::CustomMF_SI_SI_SI_SO switch_fn{ + static auto switch_fn = fn::build_mf::SI3_SO( "Switch", [](bool condition, const T &false_value, const T &true_value) { return condition ? true_value : false_value; - }}; + }); auto switch_op = std::make_shared(FieldOperation( std::move(switch_fn), diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.cc b/source/blender/nodes/shader/nodes/node_shader_clamp.cc index 5b7c216c4c3..08480c2d130 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.cc +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.cc @@ -44,17 +44,17 @@ static int gpu_shader_clamp(GPUMaterial *mat, static void sh_node_clamp_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SI_SI_SO minmax_fn{ + static auto minmax_fn = fn::build_mf::SI3_SO( "Clamp (Min Max)", - [](float value, float min, float max) { return std::min(std::max(value, min), max); }}; - static fn::CustomMF_SI_SI_SI_SO range_fn{ + [](float value, float min, float max) { return std::min(std::max(value, min), max); }); + static auto range_fn = fn::build_mf::SI3_SO( "Clamp (Range)", [](float value, float a, float b) { if (a < b) { return clamp_f(value, a, b); } return clamp_f(value, b, a); - }}; + }); int clamp_type = builder.node().custom1; if (clamp_type == NODE_CLAMP_MINMAX) { diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc index a906ee40b42..eeebabe3f00 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc @@ -233,103 +233,74 @@ static float3 clamp_range(const float3 value, const float3 min, const float3 max template static auto build_float_linear() { - return fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag>{ + return fn::build_mf::SI5_SO( Clamp ? "Map Range (clamped)" : "Map Range (unclamped)", - [](float value, float from_min, float from_max, float to_min, float to_max, float *r_value) { + [](float value, float from_min, float from_max, float to_min, float to_max) -> float { const float factor = safe_divide(value - from_min, from_max - from_min); float result = to_min + factor * (to_max - to_min); if constexpr (Clamp) { result = clamp_range(result, to_min, to_max); } - *r_value = result; + return result; }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); } template static auto build_float_stepped() { - return fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag>{ + return fn::build_mf::SI6_SO( Clamp ? "Map Range Stepped (clamped)" : "Map Range Stepped (unclamped)", - [](float value, - float from_min, - float from_max, - float to_min, - float to_max, - float steps, - float *r_value) { + [](float value, float from_min, float from_max, float to_min, float to_max, float steps) + -> float { float factor = safe_divide(value - from_min, from_max - from_min); factor = safe_divide(floorf(factor * (steps + 1.0f)), steps); float result = to_min + factor * (to_max - to_min); if constexpr (Clamp) { result = clamp_range(result, to_min, to_max); } - *r_value = result; + return result; }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); } template static auto build_vector_linear() { - return fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag>{ + return fn::build_mf::SI5_SO( Clamp ? "Vector Map Range (clamped)" : "Vector Map Range (unclamped)", [](const float3 &value, const float3 &from_min, const float3 &from_max, const float3 &to_min, - const float3 &to_max, - float3 *r_value) { + const float3 &to_max) -> float3 { float3 factor = math::safe_divide(value - from_min, from_max - from_min); float3 result = factor * (to_max - to_min) + to_min; if constexpr (Clamp) { result = clamp_range(result, to_min, to_max); } - *r_value = result; + return result; }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); } template static auto build_vector_stepped() { - return fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag>{ + return fn::build_mf::SI6_SO( Clamp ? "Vector Map Range Stepped (clamped)" : "Vector Map Range Stepped (unclamped)", [](const float3 &value, const float3 &from_min, const float3 &from_max, const float3 &to_min, const float3 &to_max, - const float3 &steps, - float3 *r_value) { + const float3 &steps) -> float3 { float3 factor = math::safe_divide(value - from_min, from_max - from_min); factor = math::safe_divide(math::floor(factor * (steps + 1.0f)), steps); float3 result = factor * (to_max - to_min) + to_min; if constexpr (Clamp) { result = clamp_range(result, to_min, to_max); } - *r_value = result; + return result; }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); } static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &builder) @@ -364,48 +335,36 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui break; } case NODE_MAP_RANGE_SMOOTHSTEP: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Vector Map Range Smoothstep", - [](const float3 &value, - const float3 &from_min, - const float3 &from_max, - const float3 &to_min, - const float3 &to_max, - float3 *r_value) { - float3 factor = math::safe_divide(value - from_min, from_max - from_min); - clamp_v3(factor, 0.0f, 1.0f); - factor = (float3(3.0f) - 2.0f * factor) * (factor * factor); - *r_value = factor * (to_max - to_min) + to_min; - }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + static auto fn = fn::build_mf::SI5_SO( + "Vector Map Range Smoothstep", + [](const float3 &value, + const float3 &from_min, + const float3 &from_max, + const float3 &to_min, + const float3 &to_max) -> float3 { + float3 factor = math::safe_divide(value - from_min, from_max - from_min); + clamp_v3(factor, 0.0f, 1.0f); + factor = (float3(3.0f) - 2.0f * factor) * (factor * factor); + return factor * (to_max - to_min) + to_min; + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); builder.set_matching_fn(fn); break; } case NODE_MAP_RANGE_SMOOTHERSTEP: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Vector Map Range Smootherstep", - [](const float3 &value, - const float3 &from_min, - const float3 &from_max, - const float3 &to_min, - const float3 &to_max, - float3 *r_value) { - float3 factor = math::safe_divide(value - from_min, from_max - from_min); - clamp_v3(factor, 0.0f, 1.0f); - factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); - *r_value = factor * (to_max - to_min) + to_min; - }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + static auto fn = fn::build_mf::SI5_SO( + "Vector Map Range Smootherstep", + [](const float3 &value, + const float3 &from_min, + const float3 &from_max, + const float3 &to_min, + const float3 &to_max) -> float3 { + float3 factor = math::safe_divide(value - from_min, from_max - from_min); + clamp_v3(factor, 0.0f, 1.0f); + factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); + return factor * (to_max - to_min) + to_min; + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); builder.set_matching_fn(fn); break; } @@ -438,48 +397,30 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui break; } case NODE_MAP_RANGE_SMOOTHSTEP: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Map Range Smoothstep", - [](float value, - float from_min, - float from_max, - float to_min, - float to_max, - float *r_value) { - float factor = safe_divide(value - from_min, from_max - from_min); - factor = std::clamp(factor, 0.0f, 1.0f); - factor = (3.0f - 2.0f * factor) * (factor * factor); - *r_value = to_min + factor * (to_max - to_min); - }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + static auto fn = fn::build_mf::SI5_SO( + "Map Range Smoothstep", + [](float value, float from_min, float from_max, float to_min, float to_max) + -> float { + float factor = safe_divide(value - from_min, from_max - from_min); + factor = std::clamp(factor, 0.0f, 1.0f); + factor = (3.0f - 2.0f * factor) * (factor * factor); + return to_min + factor * (to_max - to_min); + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); builder.set_matching_fn(fn); break; } case NODE_MAP_RANGE_SMOOTHERSTEP: { - static fn::CustomMF, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag, - fn::MFParamTag> - fn{"Map Range Smoothstep", - [](float value, - float from_min, - float from_max, - float to_min, - float to_max, - float *r_value) { - float factor = safe_divide(value - from_min, from_max - from_min); - factor = std::clamp(factor, 0.0f, 1.0f); - factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); - *r_value = to_min + factor * (to_max - to_min); - }, - fn::CustomMF_presets::SomeSpanOrSingle<0>()}; + static auto fn = fn::build_mf::SI5_SO( + "Map Range Smoothstep", + [](float value, float from_min, float from_max, float to_min, float to_max) + -> float { + float factor = safe_divide(value - from_min, from_max - from_min); + factor = std::clamp(factor, 0.0f, 1.0f); + factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); + return to_min + factor * (to_max - to_min); + }, + fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); builder.set_matching_fn(fn); break; } diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc index 5fe1bb48cc2..1a2c22862b3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_math.cc @@ -109,8 +109,8 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node) try_dispatch_float_math_fl_to_fl( mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SO fn{ - info.title_case_name.c_str(), function, devi_fn}; + static auto fn = fn::build_mf::SI1_SO( + info.title_case_name.c_str(), function, devi_fn); base_fn = &fn; }); if (base_fn != nullptr) { @@ -119,8 +119,8 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node) try_dispatch_float_math_fl_fl_to_fl( mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SO fn{ - info.title_case_name.c_str(), function, devi_fn}; + static auto fn = fn::build_mf::SI2_SO( + info.title_case_name.c_str(), function, devi_fn); base_fn = &fn; }); if (base_fn != nullptr) { @@ -129,8 +129,8 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node) try_dispatch_float_math_fl_fl_fl_to_fl( mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SI_SO fn{ - info.title_case_name.c_str(), function, devi_fn}; + static auto fn = fn::build_mf::SI3_SO( + info.title_case_name.c_str(), function, devi_fn); base_fn = &fn; }); if (base_fn != nullptr) { diff --git a/source/blender/nodes/shader/nodes/node_shader_mix.cc b/source/blender/nodes/shader/nodes/node_shader_mix.cc index a9bc1f7f98e..e8255f1f6af 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mix.cc +++ b/source/blender/nodes/shader/nodes/node_shader_mix.cc @@ -412,51 +412,51 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) switch (data->data_type) { case SOCK_FLOAT: { if (clamp_factor) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Clamp Mix Float", [](float t, const float a, const float b) { return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f)); - }}; + }); return &fn; } else { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Mix Float", [](const float t, const float a, const float b) { return math::interpolate(a, b, t); - }}; + }); return &fn; } } case SOCK_VECTOR: { if (clamp_factor) { if (uniform_factor) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Clamp Mix Vector", [](const float t, const float3 a, const float3 b) { return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f)); - }}; + }); return &fn; } else { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) { t = math::clamp(t, 0.0f, 1.0f); return a * (float3(1.0f) - t) + b * t; - }}; + }); return &fn; } } else { if (uniform_factor) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Mix Vector", [](const float t, const float3 a, const float3 b) { return math::interpolate(a, b, t); - }}; + }); return &fn; } else { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) { return a * (float3(1.0f) - t) + b * t; - }}; + }); return &fn; } } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc index 28c4eef823f..219f31eefd7 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_rgb.cc @@ -108,8 +108,8 @@ static int gpu_shader_combrgb(GPUMaterial *mat, static void sh_node_combrgb_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SI_SI_SO fn{ - "Combine RGB", [](float r, float g, float b) { return ColorGeometry4f(r, g, b, 1.0f); }}; + static auto fn = fn::build_mf::SI3_SO( + "Combine RGB", [](float r, float g, float b) { return ColorGeometry4f(r, g, b, 1.0f); }); builder.set_matching_fn(fn); } diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc index 131ae16ef1b..1ee6947480c 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc +++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc @@ -125,10 +125,10 @@ static int gpu_shader_combxyz(GPUMaterial *mat, static void sh_node_combxyz_build_multi_function(NodeMultiFunctionBuilder &builder) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Combine Vector", [](float x, float y, float z) { return float3(x, y, z); }, - fn::CustomMF_presets::AllSpanOrSingle()}; + fn::build_mf::exec_presets::AllSpanOrSingle()); builder.set_matching_fn(fn); } diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc index f7cf70aa8e1..96747139b87 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc @@ -233,8 +233,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_fl3_to_fl3( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI2_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -243,8 +243,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_fl3_fl3_to_fl3( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI3_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -253,8 +253,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_fl3_fl_to_fl3( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI3_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -263,8 +263,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_fl3_to_fl( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI2_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -273,8 +273,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_fl_to_fl3( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI2_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -283,8 +283,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_to_fl3( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI1_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { @@ -293,8 +293,8 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) try_dispatch_float_math_fl3_to_fl( operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { - static fn::CustomMF_SI_SO fn{ - info.title_case_name.c_str(), function, exec_preset}; + static auto fn = fn::build_mf::SI1_SO( + info.title_case_name.c_str(), function, exec_preset); multi_fn = &fn; }); if (multi_fn != nullptr) { diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc index bdf7360873d..d59c9271ccb 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.cc @@ -104,77 +104,77 @@ static const fn::MultiFunction *get_multi_function(const bNode &node) switch (mode) { case NODE_VECTOR_ROTATE_TYPE_AXIS: { if (invert) { - static fn::CustomMF_SI_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI4_SO( "Rotate Axis", [](const float3 &in, const float3 ¢er, const float3 &axis, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); - }}; + }); return &fn; } - static fn::CustomMF_SI_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI4_SO( "Rotate Axis", [](const float3 &in, const float3 ¢er, const float3 &axis, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); - }}; + }); return &fn; } case NODE_VECTOR_ROTATE_TYPE_AXIS_X: { float3 axis = float3(1.0f, 0.0f, 0.0f); if (invert) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate X-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); - }}; + }); return &fn; } - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate X-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); - }}; + }); return &fn; } case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: { float3 axis = float3(0.0f, 1.0f, 0.0f); if (invert) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate Y-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); - }}; + }); return &fn; } - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate Y-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); - }}; + }); return &fn; } case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: { float3 axis = float3(0.0f, 0.0f, 1.0f); if (invert) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate Z-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, -angle); - }}; + }); return &fn; } - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate Z-Axis", [=](const float3 &in, const float3 ¢er, float angle) { return sh_node_vector_rotate_around_axis(in, center, axis, angle); - }}; + }); return &fn; } case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: { if (invert) { - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate Euler", [](const float3 &in, const float3 ¢er, const float3 &rotation) { return sh_node_vector_rotate_euler(in, center, rotation, true); - }}; + }); return &fn; } - static fn::CustomMF_SI_SI_SI_SO fn{ + static auto fn = fn::build_mf::SI3_SO( "Rotate Euler", [](const float3 &in, const float3 ¢er, const float3 &rotation) { return sh_node_vector_rotate_euler(in, center, rotation, false); - }}; + }); return &fn; } default: