Functions: introduce multi-function namespace

This moves all multi-function related code in the `functions` module
into a new `multi_function` namespace. This is similar to how there
is a `lazy_function` namespace.

The main benefit of this is that many types names that were prefixed
with `MF` (for "multi function") can be simplified.

There is also a common shorthand for the `multi_function` namespace: `mf`.
This is also similar to lazy-functions where the shortened namespace
is called `lf`.
This commit is contained in:
2023-01-07 17:32:28 +01:00
parent a5b27f9858
commit eedcf1876a
87 changed files with 1437 additions and 1459 deletions

View File

@@ -17,7 +17,9 @@
struct Mesh; struct Mesh;
struct PointCloud; struct PointCloud;
namespace blender::fn { namespace blender::fn {
namespace multi_function {
class MultiFunction; class MultiFunction;
}
class GField; class GField;
} // namespace blender::fn } // namespace blender::fn
@@ -174,7 +176,7 @@ struct AttributeValidator {
/** /**
* Single input, single output function that corrects attribute values if necessary. * Single input, single output function that corrects attribute values if necessary.
*/ */
const fn::MultiFunction *function; const fn::multi_function::MultiFunction *function;
operator bool() const operator bool() const
{ {

View File

@@ -107,9 +107,6 @@ class GeoNodeExecParams;
class NodeDeclarationBuilder; class NodeDeclarationBuilder;
class GatherLinkSearchOpParams; class GatherLinkSearchOpParams;
} // namespace nodes } // namespace nodes
namespace fn {
class MFDataType;
} // namespace fn
namespace realtime_compositor { namespace realtime_compositor {
class Context; class Context;
class NodeOperation; class NodeOperation;

View File

@@ -8,19 +8,19 @@
namespace blender::bke { namespace blender::bke {
struct ConversionFunctions { struct ConversionFunctions {
const fn::MultiFunction *multi_function; const mf::MultiFunction *multi_function;
void (*convert_single_to_initialized)(const void *src, void *dst); void (*convert_single_to_initialized)(const void *src, void *dst);
void (*convert_single_to_uninitialized)(const void *src, void *dst); void (*convert_single_to_uninitialized)(const void *src, void *dst);
}; };
class DataTypeConversions { class DataTypeConversions {
private: private:
Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_; Map<std::pair<mf::DataType, mf::DataType>, ConversionFunctions> conversions_;
public: public:
void add(fn::MFDataType from_type, void add(mf::DataType from_type,
fn::MFDataType to_type, mf::DataType to_type,
const fn::MultiFunction &fn, const mf::MultiFunction &fn,
void (*convert_single_to_initialized)(const void *src, void *dst), void (*convert_single_to_initialized)(const void *src, void *dst),
void (*convert_single_to_uninitialized)(const void *src, void *dst)) void (*convert_single_to_uninitialized)(const void *src, void *dst))
{ {
@@ -28,19 +28,18 @@ class DataTypeConversions {
{&fn, convert_single_to_initialized, convert_single_to_uninitialized}); {&fn, convert_single_to_initialized, convert_single_to_uninitialized});
} }
const ConversionFunctions *get_conversion_functions(fn::MFDataType from, fn::MFDataType to) const const ConversionFunctions *get_conversion_functions(mf::DataType from, mf::DataType to) const
{ {
return conversions_.lookup_ptr({from, to}); return conversions_.lookup_ptr({from, to});
} }
const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
{ {
return this->get_conversion_functions(fn::MFDataType::ForSingle(from), return this->get_conversion_functions(mf::DataType::ForSingle(from),
fn::MFDataType::ForSingle(to)); mf::DataType::ForSingle(to));
} }
const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from, const mf::MultiFunction *get_conversion_multi_function(mf::DataType from, mf::DataType to) const
fn::MFDataType to) const
{ {
const ConversionFunctions *functions = this->get_conversion_functions(from, to); const ConversionFunctions *functions = this->get_conversion_functions(from, to);
return functions ? functions->multi_function : nullptr; return functions ? functions->multi_function : nullptr;
@@ -49,7 +48,7 @@ class DataTypeConversions {
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
{ {
return conversions_.contains( return conversions_.contains(
{fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)}); {mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type)});
} }
void convert_to_uninitialized(const CPPType &from_type, void convert_to_uninitialized(const CPPType &from_type,

View File

@@ -440,12 +440,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
make_array_write_attribute<float3>, make_array_write_attribute<float3>,
tag_component_positions_changed); tag_component_positions_changed);
static auto handle_type_clamp = fn::build_mf::SI1_SO<int8_t, int8_t>( static auto handle_type_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Handle Type Validate", "Handle Type Validate",
[](int8_t value) { [](int8_t value) {
return std::clamp<int8_t>(value, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN); return std::clamp<int8_t>(value, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN);
}, },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right", static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right",
ATTR_DOMAIN_POINT, ATTR_DOMAIN_POINT,
CD_PROP_INT8, CD_PROP_INT8,
@@ -484,10 +484,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
make_array_write_attribute<float>, make_array_write_attribute<float>,
tag_component_positions_changed); tag_component_positions_changed);
static const auto nurbs_order_clamp = fn::build_mf::SI1_SO<int8_t, int8_t>( static const auto nurbs_order_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"NURBS Order Validate", "NURBS Order Validate",
[](int8_t value) { return std::max<int8_t>(value, 0); }, [](int8_t value) { return std::max<int8_t>(value, 0); },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order", static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order",
ATTR_DOMAIN_CURVE, ATTR_DOMAIN_CURVE,
CD_PROP_INT8, CD_PROP_INT8,
@@ -501,12 +501,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_topology_changed, tag_component_topology_changed,
AttributeValidator{&nurbs_order_clamp}); AttributeValidator{&nurbs_order_clamp});
static const auto normal_mode_clamp = fn::build_mf::SI1_SO<int8_t, int8_t>( static const auto normal_mode_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Normal Mode Validate", "Normal Mode Validate",
[](int8_t value) { [](int8_t value) {
return std::clamp<int8_t>(value, NORMAL_MODE_MINIMUM_TWIST, NORMAL_MODE_Z_UP); return std::clamp<int8_t>(value, NORMAL_MODE_MINIMUM_TWIST, NORMAL_MODE_Z_UP);
}, },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider normal_mode("normal_mode", static BuiltinCustomDataLayerProvider normal_mode("normal_mode",
ATTR_DOMAIN_CURVE, ATTR_DOMAIN_CURVE,
CD_PROP_INT8, CD_PROP_INT8,
@@ -520,12 +520,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_normals_changed, tag_component_normals_changed,
AttributeValidator{&normal_mode_clamp}); AttributeValidator{&normal_mode_clamp});
static const auto knots_mode_clamp = fn::build_mf::SI1_SO<int8_t, int8_t>( static const auto knots_mode_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Knots Mode Validate", "Knots Mode Validate",
[](int8_t value) { [](int8_t value) {
return std::clamp<int8_t>(value, NURBS_KNOT_MODE_NORMAL, NURBS_KNOT_MODE_ENDPOINT_BEZIER); return std::clamp<int8_t>(value, NURBS_KNOT_MODE_NORMAL, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
}, },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode", static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode",
ATTR_DOMAIN_CURVE, ATTR_DOMAIN_CURVE,
CD_PROP_INT8, CD_PROP_INT8,
@@ -539,12 +539,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_topology_changed, tag_component_topology_changed,
AttributeValidator{&knots_mode_clamp}); AttributeValidator{&knots_mode_clamp});
static const auto curve_type_clamp = fn::build_mf::SI1_SO<int8_t, int8_t>( static const auto curve_type_clamp = mf::build::SI1_SO<int8_t, int8_t>(
"Curve Type Validate", "Curve Type Validate",
[](int8_t value) { [](int8_t value) {
return std::clamp<int8_t>(value, CURVE_TYPE_CATMULL_ROM, CURVE_TYPES_NUM); return std::clamp<int8_t>(value, CURVE_TYPE_CATMULL_ROM, CURVE_TYPES_NUM);
}, },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider curve_type("curve_type", static BuiltinCustomDataLayerProvider curve_type("curve_type",
ATTR_DOMAIN_CURVE, ATTR_DOMAIN_CURVE,
CD_PROP_INT8, CD_PROP_INT8,
@@ -558,10 +558,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
tag_component_curve_types_changed, tag_component_curve_types_changed,
AttributeValidator{&curve_type_clamp}); AttributeValidator{&curve_type_clamp});
static const auto resolution_clamp = fn::build_mf::SI1_SO<int, int>( static const auto resolution_clamp = mf::build::SI1_SO<int, int>(
"Resolution Validate", "Resolution Validate",
[](int value) { return std::max<int>(value, 1); }, [](int value) { return std::max<int>(value, 1); },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider resolution("resolution", static BuiltinCustomDataLayerProvider resolution("resolution",
ATTR_DOMAIN_CURVE, ATTR_DOMAIN_CURVE,
CD_PROP_INT32, CD_PROP_INT32,

View File

@@ -1264,13 +1264,13 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
make_array_write_attribute<int>, make_array_write_attribute<int>,
nullptr); nullptr);
static const auto material_index_clamp = fn::build_mf::SI1_SO<int, int>( static const auto material_index_clamp = mf::build::SI1_SO<int, int>(
"Material Index Validate", "Material Index Validate",
[](int value) { [](int value) {
/* Use #short for the maximum since many areas still use that type for indices. */ /* Use #short for the maximum since many areas still use that type for indices. */
return std::clamp<int>(value, 0, std::numeric_limits<short>::max()); return std::clamp<int>(value, 0, std::numeric_limits<short>::max());
}, },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static BuiltinCustomDataLayerProvider material_index("material_index", static BuiltinCustomDataLayerProvider material_index("material_index",
ATTR_DOMAIN_FACE, ATTR_DOMAIN_FACE,
CD_PROP_INT32, CD_PROP_INT32,

View File

@@ -11,7 +11,7 @@
namespace blender::bke { namespace blender::bke {
using fn::MFDataType; using mf::DataType;
template<typename From, typename To, To (*ConversionF)(const From &)> template<typename From, typename To, To (*ConversionF)(const From &)>
static void add_implicit_conversion(DataTypeConversions &conversions) static void add_implicit_conversion(DataTypeConversions &conversions)
@@ -20,20 +20,20 @@ static void add_implicit_conversion(DataTypeConversions &conversions)
static const CPPType &to_type = CPPType::get<To>(); static const CPPType &to_type = CPPType::get<To>();
static const std::string conversion_name = from_type.name() + " to " + to_type.name(); static const std::string conversion_name = from_type.name() + " to " + to_type.name();
static auto multi_function = fn::build_mf::SI1_SO<From, To>( static auto multi_function = mf::build::SI1_SO<From, To>(
conversion_name.c_str(), conversion_name.c_str(),
/* Use lambda instead of passing #ConversionF directly, because otherwise the compiler won't /* Use lambda instead of passing #ConversionF directly, because otherwise the compiler won't
* inline the function. */ * inline the function. */
[](const From &a) { return ConversionF(a); }, [](const From &a) { return ConversionF(a); },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
static auto convert_single_to_initialized = [](const void *src, void *dst) { static auto convert_single_to_initialized = [](const void *src, void *dst) {
*(To *)dst = ConversionF(*(const From *)src); *(To *)dst = ConversionF(*(const From *)src);
}; };
static auto convert_single_to_uninitialized = [](const void *src, void *dst) { static auto convert_single_to_uninitialized = [](const void *src, void *dst) {
new (dst) To(ConversionF(*(const From *)src)); new (dst) To(ConversionF(*(const From *)src));
}; };
conversions.add(fn::MFDataType::ForSingle<From>(), conversions.add(mf::DataType::ForSingle<From>(),
fn::MFDataType::ForSingle<To>(), mf::DataType::ForSingle<To>(),
multi_function, multi_function,
convert_single_to_initialized, convert_single_to_initialized,
convert_single_to_uninitialized); convert_single_to_uninitialized);
@@ -361,26 +361,26 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
} }
const ConversionFunctions *functions = this->get_conversion_functions( const ConversionFunctions *functions = this->get_conversion_functions(
MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type)); DataType::ForSingle(from_type), DataType::ForSingle(to_type));
BLI_assert(functions != nullptr); BLI_assert(functions != nullptr);
functions->convert_single_to_uninitialized(from_value, to_value); functions->convert_single_to_uninitialized(from_value, to_value);
} }
static void call_convert_to_uninitialized_fn(const GVArray &from, static void call_convert_to_uninitialized_fn(const GVArray &from,
const fn::MultiFunction &fn, const mf::MultiFunction &fn,
const IndexMask mask, const IndexMask mask,
GMutableSpan to) GMutableSpan to)
{ {
fn::MFParamsBuilder params{fn, mask.min_array_size()}; mf::ParamsBuilder params{fn, mask.min_array_size()};
params.add_readonly_single_input(from); params.add_readonly_single_input(from);
params.add_uninitialized_single_output(to); params.add_uninitialized_single_output(to);
fn::MFContextBuilder context; mf::ContextBuilder context;
fn.call_auto(mask, params, context); fn.call_auto(mask, params, context);
} }
static void call_convert_to_uninitialized_fn(const GVArray &from, static void call_convert_to_uninitialized_fn(const GVArray &from,
const fn::MultiFunction &fn, const mf::MultiFunction &fn,
GMutableSpan to) GMutableSpan to)
{ {
call_convert_to_uninitialized_fn(from, fn, IndexMask(from.size()), to); call_convert_to_uninitialized_fn(from, fn, IndexMask(from.size()), to);
@@ -394,8 +394,8 @@ void DataTypeConversions::convert_to_initialized_n(GSpan from_span, GMutableSpan
BLI_assert(from_span.size() == to_span.size()); BLI_assert(from_span.size() == to_span.size());
BLI_assert(this->is_convertible(from_type, to_type)); BLI_assert(this->is_convertible(from_type, to_type));
const fn::MultiFunction *fn = this->get_conversion_multi_function( const mf::MultiFunction *fn = this->get_conversion_multi_function(DataType::ForSingle(from_type),
MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type)); DataType::ForSingle(to_type));
to_type.destruct_n(to_span.data(), to_span.size()); to_type.destruct_n(to_span.data(), to_span.size());
call_convert_to_uninitialized_fn(GVArray::ForSpan(from_span), *fn, to_span); call_convert_to_uninitialized_fn(GVArray::ForSpan(from_span), *fn, to_span);
@@ -541,8 +541,8 @@ fn::GField DataTypeConversions::try_convert(fn::GField field, const CPPType &to_
if (!this->is_convertible(from_type, to_type)) { if (!this->is_convertible(from_type, to_type)) {
return {}; return {};
} }
const fn::MultiFunction &fn = *this->get_conversion_multi_function( const mf::MultiFunction &fn = *this->get_conversion_multi_function(
fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type)); mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type));
return {std::make_shared<fn::FieldOperation>(fn, Vector<fn::GField>{std::move(field)})}; return {std::make_shared<fn::FieldOperation>(fn, Vector<fn::GField>{std::move(field)})};
} }

View File

@@ -212,28 +212,28 @@ class FieldOperation : public FieldNode {
* The multi-function used by this node. It is optionally owned. * The multi-function used by this node. It is optionally owned.
* Multi-functions with mutable or vector parameters are not supported currently. * Multi-functions with mutable or vector parameters are not supported currently.
*/ */
std::shared_ptr<const MultiFunction> owned_function_; std::shared_ptr<const mf::MultiFunction> owned_function_;
const MultiFunction *function_; const mf::MultiFunction *function_;
/** Inputs to the operation. */ /** Inputs to the operation. */
blender::Vector<GField> inputs_; blender::Vector<GField> inputs_;
public: public:
FieldOperation(std::shared_ptr<const MultiFunction> function, Vector<GField> inputs = {}); FieldOperation(std::shared_ptr<const mf::MultiFunction> function, Vector<GField> inputs = {});
FieldOperation(const MultiFunction &function, Vector<GField> inputs = {}); FieldOperation(const mf::MultiFunction &function, Vector<GField> inputs = {});
~FieldOperation(); ~FieldOperation();
Span<GField> inputs() const; Span<GField> inputs() const;
const MultiFunction &multi_function() const; const mf::MultiFunction &multi_function() const;
const CPPType &output_cpp_type(int output_index) const override; const CPPType &output_cpp_type(int output_index) const override;
static std::shared_ptr<FieldOperation> Create(std::shared_ptr<const MultiFunction> function, static std::shared_ptr<FieldOperation> Create(std::shared_ptr<const mf::MultiFunction> function,
Vector<GField> inputs = {}) Vector<GField> inputs = {})
{ {
return std::make_shared<FieldOperation>(FieldOperation(std::move(function), inputs)); return std::make_shared<FieldOperation>(FieldOperation(std::move(function), inputs));
} }
static std::shared_ptr<FieldOperation> Create(const MultiFunction &function, static std::shared_ptr<FieldOperation> Create(const mf::MultiFunction &function,
Vector<GField> inputs = {}) Vector<GField> inputs = {})
{ {
return std::make_shared<FieldOperation>(FieldOperation(function, inputs)); return std::make_shared<FieldOperation>(FieldOperation(function, inputs));
@@ -640,7 +640,7 @@ inline Span<GField> FieldOperation::inputs() const
return inputs_; return inputs_;
} }
inline const MultiFunction &FieldOperation::multi_function() const inline const mf::MultiFunction &FieldOperation::multi_function() const
{ {
return *function_; return *function_;
} }
@@ -649,7 +649,7 @@ inline const CPPType &FieldOperation::output_cpp_type(int output_index) const
{ {
int output_counter = 0; int output_counter = 0;
for (const int param_index : function_->param_indices()) { for (const int param_index : function_->param_indices()) {
MFParamType param_type = function_->param_type(param_index); mf::ParamType param_type = function_->param_type(param_index);
if (param_type.is_output()) { if (param_type.is_output()) {
if (output_counter == output_index) { if (output_counter == output_index) {
return param_type.data_type().single_type(); return param_type.data_type().single_type();

View File

@@ -470,3 +470,7 @@ inline void Params::assert_valid_thread() const
/** \} */ /** \} */
} // namespace blender::fn::lazy_function } // namespace blender::fn::lazy_function
namespace blender {
namespace lf = fn::lazy_function;
}

View File

@@ -22,7 +22,7 @@
* arrays are not owned by MFParams. * arrays are not owned by MFParams.
* - `IndexMask`: An array of indices indicating which indices in the provided arrays should be * - `IndexMask`: An array of indices indicating which indices in the provided arrays should be
* touched/processed. * touched/processed.
* - `MFContext`: Further information for the called function. * - `Context`: Further information for the called function.
* *
* A new multi-function is generally implemented as follows: * A new multi-function is generally implemented as follows:
* 1. Create a new subclass of MultiFunction. * 1. Create a new subclass of MultiFunction.
@@ -35,11 +35,11 @@
#include "FN_multi_function_context.hh" #include "FN_multi_function_context.hh"
#include "FN_multi_function_params.hh" #include "FN_multi_function_params.hh"
namespace blender::fn { namespace blender::fn::multi_function {
class MultiFunction { class MultiFunction {
private: private:
const MFSignature *signature_ref_ = nullptr; const Signature *signature_ref_ = nullptr;
public: public:
virtual ~MultiFunction() virtual ~MultiFunction()
@@ -52,8 +52,8 @@ class MultiFunction {
* - Automatic index mask offsetting to avoid large temporary intermediate arrays that are mostly * - Automatic index mask offsetting to avoid large temporary intermediate arrays that are mostly
* unused. * unused.
*/ */
void call_auto(IndexMask mask, MFParams params, MFContext context) const; void call_auto(IndexMask mask, MFParams params, Context context) const;
virtual void call(IndexMask mask, MFParams params, MFContext context) const = 0; virtual void call(IndexMask mask, MFParams params, Context context) const = 0;
virtual uint64_t hash() const virtual uint64_t hash() const
{ {
@@ -75,7 +75,7 @@ class MultiFunction {
return signature_ref_->params.index_range(); return signature_ref_->params.index_range();
} }
MFParamType param_type(int param_index) const ParamType param_type(int param_index) const
{ {
return signature_ref_->params[param_index].type; return signature_ref_->params[param_index].type;
} }
@@ -92,7 +92,7 @@ class MultiFunction {
virtual std::string debug_name() const; virtual std::string debug_name() const;
const MFSignature &signature() const const Signature &signature() const
{ {
BLI_assert(signature_ref_ != nullptr); BLI_assert(signature_ref_ != nullptr);
return *signature_ref_; return *signature_ref_;
@@ -128,7 +128,7 @@ class MultiFunction {
* child classes. No copy of the signature is made, so the caller has to make sure that the * child classes. No copy of the signature is made, so the caller has to make sure that the
* signature lives as long as the multi function. It is ok to embed the signature into the child * signature lives as long as the multi function. It is ok to embed the signature into the child
* class. */ * class. */
void set_signature(const MFSignature *signature) void set_signature(const Signature *signature)
{ {
/* Take a pointer as argument, so that it is more obvious that no copy is created. */ /* Take a pointer as argument, so that it is more obvious that no copy is created. */
BLI_assert(signature != nullptr); BLI_assert(signature != nullptr);
@@ -138,25 +138,18 @@ class MultiFunction {
virtual ExecutionHints get_execution_hints() const; virtual ExecutionHints get_execution_hints() const;
}; };
inline MFParamsBuilder::MFParamsBuilder(const MultiFunction &fn, int64_t mask_size) inline ParamsBuilder::ParamsBuilder(const MultiFunction &fn, int64_t mask_size)
: MFParamsBuilder(fn.signature(), IndexMask(mask_size)) : ParamsBuilder(fn.signature(), IndexMask(mask_size))
{ {
} }
inline MFParamsBuilder::MFParamsBuilder(const MultiFunction &fn, const IndexMask *mask) inline ParamsBuilder::ParamsBuilder(const MultiFunction &fn, const IndexMask *mask)
: MFParamsBuilder(fn.signature(), *mask) : ParamsBuilder(fn.signature(), *mask)
{ {
} }
namespace multi_function_types { } // namespace blender::fn::multi_function
using fn::MFContext;
using fn::MFContextBuilder;
using fn::MFDataType;
using fn::MFParamCategory;
using fn::MFParams;
using fn::MFParamsBuilder;
using fn::MFParamType;
using fn::MultiFunction;
} // namespace multi_function_types
} // namespace blender::fn namespace blender {
namespace mf = fn::multi_function;
}

View File

@@ -10,7 +10,7 @@
#include "FN_multi_function.hh" #include "FN_multi_function.hh"
namespace blender::fn::build_mf { namespace blender::fn::multi_function::build {
/** /**
* These presets determine what code is generated for a #CustomMF. Different presets make different * These presets determine what code is generated for a #CustomMF. Different presets make different
@@ -66,13 +66,13 @@ struct AllSpanOrSingle {
return std::make_tuple(IndexMaskDevirtualizer<true, true>{mask}, [&]() { return std::make_tuple(IndexMaskDevirtualizer<true, true>{mask}, [&]() {
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
const GVArrayImpl &varray_impl = *std::get<I>(loaded_params); const GVArrayImpl &varray_impl = *std::get<I>(loaded_params);
return GVArrayDevirtualizer<T, true, true>{varray_impl}; return GVArrayDevirtualizer<T, true, true>{varray_impl};
} }
else if constexpr (ELEM(ParamTag::category, else if constexpr (ELEM(ParamTag::category,
MFParamCategory::SingleOutput, ParamCategory::SingleOutput,
MFParamCategory::SingleMutable)) { ParamCategory::SingleMutable)) {
T *ptr = std::get<I>(loaded_params); T *ptr = std::get<I>(loaded_params);
return BasicDevirtualizer<T *>{ptr}; return BasicDevirtualizer<T *>{ptr};
} }
@@ -99,14 +99,14 @@ template<size_t... Indices> struct SomeSpanOrSingle {
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
constexpr bool UseSpan = ValueSequence<size_t, Indices...>::template contains<I>(); constexpr bool UseSpan = ValueSequence<size_t, Indices...>::template contains<I>();
const GVArrayImpl &varray_impl = *std::get<I>(loaded_params); const GVArrayImpl &varray_impl = *std::get<I>(loaded_params);
return GVArrayDevirtualizer<T, true, UseSpan>{varray_impl}; return GVArrayDevirtualizer<T, true, UseSpan>{varray_impl};
} }
else if constexpr (ELEM(ParamTag::category, else if constexpr (ELEM(ParamTag::category,
MFParamCategory::SingleOutput, ParamCategory::SingleOutput,
MFParamCategory::SingleMutable)) { ParamCategory::SingleMutable)) {
T *ptr = std::get<I>(loaded_params); T *ptr = std::get<I>(loaded_params);
return BasicDevirtualizer<T *>{ptr}; return BasicDevirtualizer<T *>{ptr};
} }
@@ -135,16 +135,16 @@ void execute_array(TypeSequence<ParamTags...> /*param_tags*/,
for (const int64_t i : mask) { for (const int64_t i : mask) {
element_fn([&]() -> decltype(auto) { element_fn([&]() -> decltype(auto) {
using ParamTag = typename TypeSequence<ParamTags...>::template at_index<I>; using ParamTag = typename TypeSequence<ParamTags...>::template at_index<I>;
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
/* For inputs, pass the value (or a reference to it) to the function. */ /* For inputs, pass the value (or a reference to it) to the function. */
return args[i]; return args[i];
} }
else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { else if constexpr (ParamTag::category == ParamCategory::SingleOutput) {
/* For outputs, pass a pointer to the function. This is done instead of passing a /* For outputs, pass a pointer to the function. This is done instead of passing a
* reference, because the pointer points to uninitialized memory. */ * reference, because the pointer points to uninitialized memory. */
return args + i; return args + i;
} }
else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) { else if constexpr (ParamTag::category == ParamCategory::SingleMutable) {
/* For mutables, pass a mutable reference to the function. */ /* For mutables, pass a mutable reference to the function. */
return args[i]; return args[i];
} }
@@ -180,13 +180,13 @@ void execute_materialized_impl(TypeSequence<ParamTags...> /*param_tags*/,
const int64_t out_i = out_mask[i]; const int64_t out_i = out_mask[i];
element_fn([&]() -> decltype(auto) { element_fn([&]() -> decltype(auto) {
using ParamTag = ParamTags; using ParamTag = ParamTags;
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
return chunks[in_i]; return chunks[in_i];
} }
else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { else if constexpr (ParamTag::category == ParamCategory::SingleOutput) {
return chunks + out_i; return chunks + out_i;
} }
else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) { else if constexpr (ParamTag::category == ParamCategory::SingleMutable) {
return chunks[out_i]; return chunks[out_i];
} }
}()...); }()...);
@@ -230,7 +230,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
[[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info); [[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info);
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
const GVArrayImpl &varray_impl = *std::get<I>(loaded_params); const GVArrayImpl &varray_impl = *std::get<I>(loaded_params);
const CommonVArrayInfo common_info = varray_impl.common_info(); const CommonVArrayInfo common_info = varray_impl.common_info();
if (common_info.type == CommonVArrayInfo::Type::Single) { if (common_info.type == CommonVArrayInfo::Type::Single) {
@@ -269,7 +269,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
using ParamTag = ParamTags; using ParamTag = ParamTags;
using T = typename ParamTag::base_type; using T = typename ParamTag::base_type;
[[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info); [[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info);
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
if (arg_info.mode == MaterializeArgMode::Single) { if (arg_info.mode == MaterializeArgMode::Single) {
/* The single value has been filled into a buffer already reused for every chunk. */ /* The single value has been filled into a buffer already reused for every chunk. */
return Span<T>(std::get<I>(buffers)); return Span<T>(std::get<I>(buffers));
@@ -296,8 +296,8 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
} }
} }
else if constexpr (ELEM(ParamTag::category, else if constexpr (ELEM(ParamTag::category,
MFParamCategory::SingleOutput, ParamCategory::SingleOutput,
MFParamCategory::SingleMutable)) { ParamCategory::SingleMutable)) {
/* For outputs, just pass a pointer. This is important so that `__restrict` works. */ /* For outputs, just pass a pointer. This is important so that `__restrict` works. */
return std::get<I>(loaded_params); return std::get<I>(loaded_params);
} }
@@ -310,7 +310,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
[[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info); [[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info);
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
if (arg_info.mode == MaterializeArgMode::Materialized) { if (arg_info.mode == MaterializeArgMode::Materialized) {
T *in_chunk = std::get<I>(buffers_owner).ptr(); T *in_chunk = std::get<I>(buffers_owner).ptr();
destruct_n(in_chunk, chunk_size); destruct_n(in_chunk, chunk_size);
@@ -327,7 +327,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
[[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info); [[maybe_unused]] MaterializeArgInfo<ParamTags> &arg_info = std::get<I>(args_info);
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
if (arg_info.mode == MaterializeArgMode::Single) { if (arg_info.mode == MaterializeArgMode::Single) {
MutableSpan<T> in_chunk = std::get<I>(buffers); MutableSpan<T> in_chunk = std::get<I>(buffers);
destruct_n(in_chunk.data(), in_chunk.size()); destruct_n(in_chunk.data(), in_chunk.size());
@@ -353,13 +353,13 @@ inline void execute_element_fn_as_multi_function(const ElementFn element_fn,
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
return params.readonly_single_input(I).get_implementation(); return params.readonly_single_input(I).get_implementation();
} }
else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) { else if constexpr (ParamTag::category == ParamCategory::SingleOutput) {
return static_cast<T *>(params.uninitialized_single_output(I).data()); return static_cast<T *>(params.uninitialized_single_output(I).data());
} }
else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) { else if constexpr (ParamTag::category == ParamCategory::SingleMutable) {
return static_cast<T *>(params.single_mutable(I).data()); return static_cast<T *>(params.single_mutable(I).data());
} }
}()...); }()...);
@@ -397,13 +397,13 @@ inline void execute_element_fn_as_multi_function(const ElementFn element_fn,
/* Use `typedef` instead of `using` to work around a compiler bug. */ /* Use `typedef` instead of `using` to work around a compiler bug. */
typedef ParamTags ParamTag; typedef ParamTags ParamTag;
typedef typename ParamTag::base_type T; typedef typename ParamTag::base_type T;
if constexpr (ParamTag::category == MFParamCategory::SingleInput) { if constexpr (ParamTag::category == ParamCategory::SingleInput) {
const GVArrayImpl &varray_impl = *std::get<I>(loaded_params); const GVArrayImpl &varray_impl = *std::get<I>(loaded_params);
return GVArray(&varray_impl).typed<T>(); return GVArray(&varray_impl).typed<T>();
} }
else if constexpr (ELEM(ParamTag::category, else if constexpr (ELEM(ParamTag::category,
MFParamCategory::SingleOutput, ParamCategory::SingleOutput,
MFParamCategory::SingleMutable)) { ParamCategory::SingleMutable)) {
T *ptr = std::get<I>(loaded_params); T *ptr = std::get<I>(loaded_params);
return ptr; return ptr;
} }
@@ -438,20 +438,20 @@ inline auto build_multi_function_call_from_element_fn(const ElementFn element_fn
*/ */
template<typename CallFn, typename... ParamTags> class CustomMF : public MultiFunction { template<typename CallFn, typename... ParamTags> class CustomMF : public MultiFunction {
private: private:
MFSignature signature_; Signature signature_;
CallFn call_fn_; CallFn call_fn_;
public: public:
CustomMF(const char *name, CallFn call_fn, TypeSequence<ParamTags...> /*param_tags*/) CustomMF(const char *name, CallFn call_fn, TypeSequence<ParamTags...> /*param_tags*/)
: call_fn_(std::move(call_fn)) : call_fn_(std::move(call_fn))
{ {
MFSignatureBuilder builder{name, signature_}; SignatureBuilder builder{name, signature_};
/* Loop over all parameter types and add an entry for each in the signature. */ /* Loop over all parameter types and add an entry for each in the signature. */
([&] { builder.add(ParamTags(), ""); }(), ...); ([&] { builder.add(ParamTags(), ""); }(), ...);
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
call_fn_(mask, params); call_fn_(mask, params);
} }
@@ -463,8 +463,8 @@ inline auto build_multi_function_with_n_inputs_one_output(const char *name,
const ExecPreset exec_preset, const ExecPreset exec_preset,
TypeSequence<In...> /*in_types*/) TypeSequence<In...> /*in_types*/)
{ {
constexpr auto param_tags = TypeSequence<MFParamTag<MFParamCategory::SingleInput, In>..., constexpr auto param_tags = TypeSequence<MFParamTag<ParamCategory::SingleInput, In>...,
MFParamTag<MFParamCategory::SingleOutput, Out>>(); MFParamTag<ParamCategory::SingleOutput, Out>>();
auto call_fn = build_multi_function_call_from_element_fn( auto call_fn = build_multi_function_call_from_element_fn(
[element_fn](const In &...in, Out *out) { new (out) Out(element_fn(in...)); }, [element_fn](const In &...in, Out *out) { new (out) Out(element_fn(in...)); },
exec_preset, exec_preset,
@@ -573,15 +573,15 @@ inline auto SM(const char *name,
const ElementFn element_fn, const ElementFn element_fn,
const ExecPreset exec_preset = exec_presets::AllSpanOrSingle()) const ExecPreset exec_preset = exec_presets::AllSpanOrSingle())
{ {
constexpr auto param_tags = TypeSequence<MFParamTag<MFParamCategory::SingleMutable, Mut1>>(); constexpr auto param_tags = TypeSequence<MFParamTag<ParamCategory::SingleMutable, Mut1>>();
auto call_fn = detail::build_multi_function_call_from_element_fn( auto call_fn = detail::build_multi_function_call_from_element_fn(
element_fn, exec_preset, param_tags); element_fn, exec_preset, param_tags);
return detail::CustomMF(name, call_fn, param_tags); return detail::CustomMF(name, call_fn, param_tags);
} }
} // namespace blender::fn::build_mf } // namespace blender::fn::multi_function::build
namespace blender::fn { namespace blender::fn::multi_function {
/** /**
* A multi-function that outputs the same value every time. The value is not owned by an instance * A multi-function that outputs the same value every time. The value is not owned by an instance
@@ -592,7 +592,7 @@ class CustomMF_GenericConstant : public MultiFunction {
private: private:
const CPPType &type_; const CPPType &type_;
const void *value_; const void *value_;
MFSignature signature_; Signature signature_;
bool owns_value_; bool owns_value_;
template<typename T> friend class CustomMF_Constant; template<typename T> friend class CustomMF_Constant;
@@ -600,7 +600,7 @@ class CustomMF_GenericConstant : public MultiFunction {
public: public:
CustomMF_GenericConstant(const CPPType &type, const void *value, bool make_value_copy); CustomMF_GenericConstant(const CPPType &type, const void *value, bool make_value_copy);
~CustomMF_GenericConstant(); ~CustomMF_GenericConstant();
void call(IndexMask mask, MFParams params, MFContext context) const override; void call(IndexMask mask, MFParams params, Context context) const override;
uint64_t hash() const override; uint64_t hash() const override;
bool equals(const MultiFunction &other) const override; bool equals(const MultiFunction &other) const override;
}; };
@@ -612,11 +612,11 @@ class CustomMF_GenericConstant : public MultiFunction {
class CustomMF_GenericConstantArray : public MultiFunction { class CustomMF_GenericConstantArray : public MultiFunction {
private: private:
GSpan array_; GSpan array_;
MFSignature signature_; Signature signature_;
public: public:
CustomMF_GenericConstantArray(GSpan array); CustomMF_GenericConstantArray(GSpan array);
void call(IndexMask mask, MFParams params, MFContext context) const override; void call(IndexMask mask, MFParams params, Context context) const override;
}; };
/** /**
@@ -625,17 +625,17 @@ class CustomMF_GenericConstantArray : public MultiFunction {
template<typename T> class CustomMF_Constant : public MultiFunction { template<typename T> class CustomMF_Constant : public MultiFunction {
private: private:
T value_; T value_;
MFSignature signature_; Signature signature_;
public: public:
template<typename U> CustomMF_Constant(U &&value) : value_(std::forward<U>(value)) template<typename U> CustomMF_Constant(U &&value) : value_(std::forward<U>(value))
{ {
MFSignatureBuilder builder{"Constant", signature_}; SignatureBuilder builder{"Constant", signature_};
builder.single_output<T>("Value"); builder.single_output<T>("Value");
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
MutableSpan<T> output = params.uninitialized_single_output<T>(0); MutableSpan<T> output = params.uninitialized_single_output<T>(0);
mask.to_best_mask_type([&](const auto &mask) { mask.to_best_mask_type([&](const auto &mask) {
@@ -671,20 +671,20 @@ template<typename T> class CustomMF_Constant : public MultiFunction {
class CustomMF_DefaultOutput : public MultiFunction { class CustomMF_DefaultOutput : public MultiFunction {
private: private:
int output_amount_; int output_amount_;
MFSignature signature_; Signature signature_;
public: public:
CustomMF_DefaultOutput(Span<MFDataType> input_types, Span<MFDataType> output_types); CustomMF_DefaultOutput(Span<DataType> input_types, Span<DataType> output_types);
void call(IndexMask mask, MFParams params, MFContext context) const override; void call(IndexMask mask, MFParams params, Context context) const override;
}; };
class CustomMF_GenericCopy : public MultiFunction { class CustomMF_GenericCopy : public MultiFunction {
private: private:
MFSignature signature_; Signature signature_;
public: public:
CustomMF_GenericCopy(MFDataType data_type); CustomMF_GenericCopy(DataType data_type);
void call(IndexMask mask, MFParams params, MFContext context) const override; void call(IndexMask mask, MFParams params, Context context) const override;
}; };
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -5,7 +5,7 @@
/** \file /** \file
* \ingroup fn * \ingroup fn
* *
* An #MFContext is passed along with every call to a multi-function. Right now it does nothing, * An #Context is passed along with every call to a multi-function. Right now it does nothing,
* but it can be used for the following purposes: * but it can be used for the following purposes:
* - Pass debug information up and down the function call stack. * - Pass debug information up and down the function call stack.
* - Pass reusable memory buffers to sub-functions to increase performance. * - Pass reusable memory buffers to sub-functions to increase performance.
@@ -16,18 +16,18 @@
#include "BLI_map.hh" #include "BLI_map.hh"
namespace blender::fn { namespace blender::fn::multi_function {
class MFContext; class Context;
class MFContextBuilder { class ContextBuilder {
}; };
class MFContext { class Context {
public: public:
MFContext(MFContextBuilder & /*builder*/) Context(ContextBuilder & /*builder*/)
{ {
} }
}; };
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -5,16 +5,16 @@
/** \file /** \file
* \ingroup fn * \ingroup fn
* *
* A MFDataType describes what type of data a multi-function gets as input, outputs or mutates. * A DataType describes what type of data a multi-function gets as input, outputs or mutates.
* Currently, only individual elements or vectors of elements are supported. Adding more data types * Currently, only individual elements or vectors of elements are supported. Adding more data types
* is possible when necessary. * is possible when necessary.
*/ */
#include "BLI_cpp_type.hh" #include "BLI_cpp_type.hh"
namespace blender::fn { namespace blender::fn::multi_function {
class MFDataType { class DataType {
public: public:
enum Category { enum Category {
Single, Single,
@@ -25,31 +25,31 @@ class MFDataType {
Category category_; Category category_;
const CPPType *type_; const CPPType *type_;
MFDataType(Category category, const CPPType &type) : category_(category), type_(&type) DataType(Category category, const CPPType &type) : category_(category), type_(&type)
{ {
} }
public: public:
MFDataType() = default; DataType() = default;
static MFDataType ForSingle(const CPPType &type) static DataType ForSingle(const CPPType &type)
{ {
return MFDataType(Single, type); return DataType(Single, type);
} }
static MFDataType ForVector(const CPPType &type) static DataType ForVector(const CPPType &type)
{ {
return MFDataType(Vector, type); return DataType(Vector, type);
} }
template<typename T> static MFDataType ForSingle() template<typename T> static DataType ForSingle()
{ {
return MFDataType::ForSingle(CPPType::get<T>()); return DataType::ForSingle(CPPType::get<T>());
} }
template<typename T> static MFDataType ForVector() template<typename T> static DataType ForVector()
{ {
return MFDataType::ForVector(CPPType::get<T>()); return DataType::ForVector(CPPType::get<T>());
} }
bool is_single() const bool is_single() const
@@ -79,8 +79,8 @@ class MFDataType {
return *type_; return *type_;
} }
friend bool operator==(const MFDataType &a, const MFDataType &b); friend bool operator==(const DataType &a, const DataType &b);
friend bool operator!=(const MFDataType &a, const MFDataType &b); friend bool operator!=(const DataType &a, const DataType &b);
std::string to_string() const std::string to_string() const
{ {
@@ -100,14 +100,14 @@ class MFDataType {
} }
}; };
inline bool operator==(const MFDataType &a, const MFDataType &b) inline bool operator==(const DataType &a, const DataType &b)
{ {
return a.category_ == b.category_ && a.type_ == b.type_; return a.category_ == b.category_ && a.type_ == b.type_;
} }
inline bool operator!=(const MFDataType &a, const MFDataType &b) inline bool operator!=(const DataType &a, const DataType &b)
{ {
return !(a == b); return !(a == b);
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -14,15 +14,15 @@
* - Mutable: A mutable parameter can be considered to be an input and output. The caller has to * - Mutable: A mutable parameter can be considered to be an input and output. The caller has to
* initialize the data, but the function is allowed to modify it. * initialize the data, but the function is allowed to modify it.
* *
* Furthermore, every parameter has a MFDataType that describes what kind of data is being passed * Furthermore, every parameter has a DataType that describes what kind of data is being passed
* around. * around.
*/ */
#include "FN_multi_function_data_type.hh" #include "FN_multi_function_data_type.hh"
namespace blender::fn { namespace blender::fn::multi_function {
enum class MFParamCategory { enum class ParamCategory {
SingleInput, SingleInput,
VectorInput, VectorInput,
SingleOutput, SingleOutput,
@@ -31,12 +31,12 @@ enum class MFParamCategory {
VectorMutable, VectorMutable,
}; };
template<MFParamCategory Category, typename T> struct MFParamTag { template<ParamCategory Category, typename T> struct MFParamTag {
static constexpr MFParamCategory category = Category; static constexpr ParamCategory category = Category;
using base_type = T; using base_type = T;
}; };
class MFParamType { class ParamType {
public: public:
enum InterfaceType { enum InterfaceType {
Input, Input,
@@ -46,45 +46,45 @@ class MFParamType {
private: private:
InterfaceType interface_type_; InterfaceType interface_type_;
MFDataType data_type_; DataType data_type_;
public: public:
MFParamType(InterfaceType interface_type, MFDataType data_type) ParamType(InterfaceType interface_type, DataType data_type)
: interface_type_(interface_type), data_type_(data_type) : interface_type_(interface_type), data_type_(data_type)
{ {
} }
static MFParamType ForSingleInput(const CPPType &type) static ParamType ForSingleInput(const CPPType &type)
{ {
return MFParamType(InterfaceType::Input, MFDataType::ForSingle(type)); return ParamType(InterfaceType::Input, DataType::ForSingle(type));
} }
static MFParamType ForVectorInput(const CPPType &base_type) static ParamType ForVectorInput(const CPPType &base_type)
{ {
return MFParamType(InterfaceType::Input, MFDataType::ForVector(base_type)); return ParamType(InterfaceType::Input, DataType::ForVector(base_type));
} }
static MFParamType ForSingleOutput(const CPPType &type) static ParamType ForSingleOutput(const CPPType &type)
{ {
return MFParamType(InterfaceType::Output, MFDataType::ForSingle(type)); return ParamType(InterfaceType::Output, DataType::ForSingle(type));
} }
static MFParamType ForVectorOutput(const CPPType &base_type) static ParamType ForVectorOutput(const CPPType &base_type)
{ {
return MFParamType(InterfaceType::Output, MFDataType::ForVector(base_type)); return ParamType(InterfaceType::Output, DataType::ForVector(base_type));
} }
static MFParamType ForMutableSingle(const CPPType &type) static ParamType ForMutableSingle(const CPPType &type)
{ {
return MFParamType(InterfaceType::Mutable, MFDataType::ForSingle(type)); return ParamType(InterfaceType::Mutable, DataType::ForSingle(type));
} }
static MFParamType ForMutableVector(const CPPType &base_type) static ParamType ForMutableVector(const CPPType &base_type)
{ {
return MFParamType(InterfaceType::Mutable, MFDataType::ForVector(base_type)); return ParamType(InterfaceType::Mutable, DataType::ForVector(base_type));
} }
MFDataType data_type() const DataType data_type() const
{ {
return data_type_; return data_type_;
} }
@@ -94,34 +94,34 @@ class MFParamType {
return interface_type_; return interface_type_;
} }
MFParamCategory category() const ParamCategory category() const
{ {
switch (data_type_.category()) { switch (data_type_.category()) {
case MFDataType::Single: { case DataType::Single: {
switch (interface_type_) { switch (interface_type_) {
case Input: case Input:
return MFParamCategory::SingleInput; return ParamCategory::SingleInput;
case Output: case Output:
return MFParamCategory::SingleOutput; return ParamCategory::SingleOutput;
case Mutable: case Mutable:
return MFParamCategory::SingleMutable; return ParamCategory::SingleMutable;
} }
break; break;
} }
case MFDataType::Vector: { case DataType::Vector: {
switch (interface_type_) { switch (interface_type_) {
case Input: case Input:
return MFParamCategory::VectorInput; return ParamCategory::VectorInput;
case Output: case Output:
return MFParamCategory::VectorOutput; return ParamCategory::VectorOutput;
case Mutable: case Mutable:
return MFParamCategory::VectorMutable; return ParamCategory::VectorMutable;
} }
break; break;
} }
} }
BLI_assert_unreachable(); BLI_assert_unreachable();
return MFParamCategory::SingleInput; return ParamCategory::SingleInput;
} }
bool is_input_or_mutable() const bool is_input_or_mutable() const
@@ -139,18 +139,18 @@ class MFParamType {
return interface_type_ == Output; return interface_type_ == Output;
} }
friend bool operator==(const MFParamType &a, const MFParamType &b); friend bool operator==(const ParamType &a, const ParamType &b);
friend bool operator!=(const MFParamType &a, const MFParamType &b); friend bool operator!=(const ParamType &a, const ParamType &b);
}; };
inline bool operator==(const MFParamType &a, const MFParamType &b) inline bool operator==(const ParamType &a, const ParamType &b)
{ {
return a.interface_type_ == b.interface_type_ && a.data_type_ == b.data_type_; return a.interface_type_ == b.interface_type_ && a.data_type_ == b.data_type_;
} }
inline bool operator!=(const MFParamType &a, const MFParamType &b) inline bool operator!=(const ParamType &a, const ParamType &b)
{ {
return !(a == b); return !(a == b);
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -5,9 +5,9 @@
/** \file /** \file
* \ingroup fn * \ingroup fn
* *
* This file provides an MFParams and MFParamsBuilder structure. * This file provides an MFParams and ParamsBuilder structure.
* *
* `MFParamsBuilder` is used by a function caller to be prepare all parameters that are passed into * `ParamsBuilder` is used by a function caller to be prepare all parameters that are passed into
* the function. `MFParams` is then used inside the called function to access the parameters. * the function. `MFParams` is then used inside the called function to access the parameters.
*/ */
@@ -21,12 +21,12 @@
#include "FN_multi_function_signature.hh" #include "FN_multi_function_signature.hh"
namespace blender::fn { namespace blender::fn::multi_function {
class MFParamsBuilder { class ParamsBuilder {
private: private:
ResourceScope scope_; ResourceScope scope_;
const MFSignature *signature_; const Signature *signature_;
IndexMask mask_; IndexMask mask_;
int64_t min_array_size_; int64_t min_array_size_;
Vector<std::variant<GVArray, GMutableSpan, const GVVectorArray *, GVectorArray *>> Vector<std::variant<GVArray, GMutableSpan, const GVVectorArray *, GVectorArray *>>
@@ -37,23 +37,23 @@ class MFParamsBuilder {
friend class MFParams; friend class MFParams;
MFParamsBuilder(const MFSignature &signature, const IndexMask mask) ParamsBuilder(const Signature &signature, const IndexMask mask)
: signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size()) : signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size())
{ {
actual_params_.reserve(signature.params.size()); actual_params_.reserve(signature.params.size());
} }
public: public:
MFParamsBuilder(const class MultiFunction &fn, int64_t size); ParamsBuilder(const class MultiFunction &fn, int64_t size);
/** /**
* The indices referenced by the #mask has to live longer than the params builder. This is * The indices referenced by the #mask has to live longer than the params builder. This is
* because the it might have to destruct elements for all masked indices in the end. * because the it might have to destruct elements for all masked indices in the end.
*/ */
MFParamsBuilder(const class MultiFunction &fn, const IndexMask *mask); ParamsBuilder(const class MultiFunction &fn, const IndexMask *mask);
template<typename T> void add_readonly_single_input_value(T value, StringRef expected_name = "") template<typename T> void add_readonly_single_input_value(T value, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForSingleInput(CPPType::get<T>()), expected_name); this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get<T>()), expected_name);
actual_params_.append_unchecked_as(std::in_place_type<GVArray>, actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
varray_tag::single{}, varray_tag::single{},
CPPType::get<T>(), CPPType::get<T>(),
@@ -62,7 +62,7 @@ class MFParamsBuilder {
} }
template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "") template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForSingleInput(CPPType::get<T>()), expected_name); this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get<T>()), expected_name);
actual_params_.append_unchecked_as(std::in_place_type<GVArray>, actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
varray_tag::single_ref{}, varray_tag::single_ref{},
CPPType::get<T>(), CPPType::get<T>(),
@@ -71,13 +71,13 @@ class MFParamsBuilder {
} }
void add_readonly_single_input(const GSpan span, StringRef expected_name = "") void add_readonly_single_input(const GSpan span, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForSingleInput(span.type()), expected_name); this->assert_current_param_type(ParamType::ForSingleInput(span.type()), expected_name);
BLI_assert(span.size() >= min_array_size_); BLI_assert(span.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<GVArray>, varray_tag::span{}, span); actual_params_.append_unchecked_as(std::in_place_type<GVArray>, varray_tag::span{}, span);
} }
void add_readonly_single_input(GPointer value, StringRef expected_name = "") void add_readonly_single_input(GPointer value, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForSingleInput(*value.type()), expected_name); this->assert_current_param_type(ParamType::ForSingleInput(*value.type()), expected_name);
actual_params_.append_unchecked_as(std::in_place_type<GVArray>, actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
varray_tag::single_ref{}, varray_tag::single_ref{},
*value.type(), *value.type(),
@@ -86,7 +86,7 @@ class MFParamsBuilder {
} }
void add_readonly_single_input(GVArray varray, StringRef expected_name = "") void add_readonly_single_input(GVArray varray, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForSingleInput(varray.type()), expected_name); this->assert_current_param_type(ParamType::ForSingleInput(varray.type()), expected_name);
BLI_assert(varray.size() >= min_array_size_); BLI_assert(varray.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<GVArray>, std::move(varray)); actual_params_.append_unchecked_as(std::in_place_type<GVArray>, std::move(varray));
} }
@@ -104,7 +104,7 @@ class MFParamsBuilder {
} }
void add_readonly_vector_input(const GVVectorArray &ref, StringRef expected_name = "") void add_readonly_vector_input(const GVVectorArray &ref, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForVectorInput(ref.type()), expected_name); this->assert_current_param_type(ParamType::ForVectorInput(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_); BLI_assert(ref.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<const GVVectorArray *>, &ref); actual_params_.append_unchecked_as(std::in_place_type<const GVVectorArray *>, &ref);
} }
@@ -116,7 +116,7 @@ class MFParamsBuilder {
} }
void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = "") void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForSingleOutput(ref.type()), expected_name); this->assert_current_param_type(ParamType::ForSingleOutput(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_); BLI_assert(ref.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref); actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
} }
@@ -124,8 +124,8 @@ class MFParamsBuilder {
{ {
this->assert_current_param_name(expected_name); this->assert_current_param_name(expected_name);
const int param_index = this->current_param_index(); const int param_index = this->current_param_index();
const MFParamType &param_type = signature_->params[param_index].type; const ParamType &param_type = signature_->params[param_index].type;
BLI_assert(param_type.category() == MFParamCategory::SingleOutput); BLI_assert(param_type.category() == ParamCategory::SingleOutput);
const CPPType &type = param_type.data_type().single_type(); const CPPType &type = param_type.data_type().single_type();
/* An empty span indicates that this is ignored. */ /* An empty span indicates that this is ignored. */
const GMutableSpan dummy_span{type}; const GMutableSpan dummy_span{type};
@@ -134,7 +134,7 @@ class MFParamsBuilder {
void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "") void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForVectorOutput(vector_array.type()), this->assert_current_param_type(ParamType::ForVectorOutput(vector_array.type()),
expected_name); expected_name);
BLI_assert(vector_array.size() >= min_array_size_); BLI_assert(vector_array.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array); actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
@@ -142,14 +142,14 @@ class MFParamsBuilder {
void add_single_mutable(GMutableSpan ref, StringRef expected_name = "") void add_single_mutable(GMutableSpan ref, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForMutableSingle(ref.type()), expected_name); this->assert_current_param_type(ParamType::ForMutableSingle(ref.type()), expected_name);
BLI_assert(ref.size() >= min_array_size_); BLI_assert(ref.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref); actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
} }
void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = "") void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = "")
{ {
this->assert_current_param_type(MFParamType::ForMutableVector(vector_array.type()), this->assert_current_param_type(ParamType::ForMutableVector(vector_array.type()),
expected_name); expected_name);
BLI_assert(vector_array.size() >= min_array_size_); BLI_assert(vector_array.size() >= min_array_size_);
actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array); actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
@@ -158,16 +158,16 @@ class MFParamsBuilder {
GMutableSpan computed_array(int param_index) GMutableSpan computed_array(int param_index)
{ {
BLI_assert(ELEM(signature_->params[param_index].type.category(), BLI_assert(ELEM(signature_->params[param_index].type.category(),
MFParamCategory::SingleOutput, ParamCategory::SingleOutput,
MFParamCategory::SingleMutable)); ParamCategory::SingleMutable));
return *std::get_if<GMutableSpan>(&actual_params_[param_index]); return *std::get_if<GMutableSpan>(&actual_params_[param_index]);
} }
GVectorArray &computed_vector_array(int param_index) GVectorArray &computed_vector_array(int param_index)
{ {
BLI_assert(ELEM(signature_->params[param_index].type.category(), BLI_assert(ELEM(signature_->params[param_index].type.category(),
MFParamCategory::VectorOutput, ParamCategory::VectorOutput,
MFParamCategory::VectorMutable)); ParamCategory::VectorMutable));
return **std::get_if<GVectorArray *>(&actual_params_[param_index]); return **std::get_if<GVectorArray *>(&actual_params_[param_index]);
} }
@@ -177,7 +177,7 @@ class MFParamsBuilder {
} }
private: private:
void assert_current_param_type(MFParamType param_type, StringRef expected_name = "") void assert_current_param_type(ParamType param_type, StringRef expected_name = "")
{ {
UNUSED_VARS_NDEBUG(param_type, expected_name); UNUSED_VARS_NDEBUG(param_type, expected_name);
#ifdef DEBUG #ifdef DEBUG
@@ -188,7 +188,7 @@ class MFParamsBuilder {
BLI_assert(actual_name == expected_name); BLI_assert(actual_name == expected_name);
} }
MFParamType expected_type = signature_->params[param_index].type; ParamType expected_type = signature_->params[param_index].type;
BLI_assert(expected_type == param_type); BLI_assert(expected_type == param_type);
#endif #endif
} }
@@ -214,10 +214,10 @@ class MFParamsBuilder {
class MFParams { class MFParams {
private: private:
MFParamsBuilder *builder_; ParamsBuilder *builder_;
public: public:
MFParams(MFParamsBuilder &builder) : builder_(&builder) MFParams(ParamsBuilder &builder) : builder_(&builder)
{ {
} }
@@ -228,7 +228,7 @@ class MFParams {
} }
const GVArray &readonly_single_input(int param_index, StringRef name = "") const GVArray &readonly_single_input(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::SingleInput); this->assert_correct_param(param_index, name, ParamCategory::SingleInput);
return *std::get_if<GVArray>(&builder_->actual_params_[param_index]); return *std::get_if<GVArray>(&builder_->actual_params_[param_index]);
} }
@@ -240,7 +240,7 @@ class MFParams {
*/ */
bool single_output_is_required(int param_index, StringRef name = "") bool single_output_is_required(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::SingleOutput); this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
return !std::get_if<GMutableSpan>(&builder_->actual_params_[param_index])->is_empty(); return !std::get_if<GMutableSpan>(&builder_->actual_params_[param_index])->is_empty();
} }
@@ -251,7 +251,7 @@ class MFParams {
} }
GMutableSpan uninitialized_single_output(int param_index, StringRef name = "") GMutableSpan uninitialized_single_output(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::SingleOutput); this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
GMutableSpan span = *std::get_if<GMutableSpan>(&builder_->actual_params_[param_index]); GMutableSpan span = *std::get_if<GMutableSpan>(&builder_->actual_params_[param_index]);
if (!span.is_empty()) { if (!span.is_empty()) {
return span; return span;
@@ -272,7 +272,7 @@ class MFParams {
} }
GMutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = "") GMutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::SingleOutput); this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
return *std::get_if<GMutableSpan>(&builder_->actual_params_[param_index]); return *std::get_if<GMutableSpan>(&builder_->actual_params_[param_index]);
} }
@@ -284,7 +284,7 @@ class MFParams {
} }
const GVVectorArray &readonly_vector_input(int param_index, StringRef name = "") const GVVectorArray &readonly_vector_input(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::VectorInput); this->assert_correct_param(param_index, name, ParamCategory::VectorInput);
return **std::get_if<const GVVectorArray *>(&builder_->actual_params_[param_index]); return **std::get_if<const GVVectorArray *>(&builder_->actual_params_[param_index]);
} }
@@ -295,7 +295,7 @@ class MFParams {
} }
GVectorArray &vector_output(int param_index, StringRef name = "") GVectorArray &vector_output(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::VectorOutput); this->assert_correct_param(param_index, name, ParamCategory::VectorOutput);
return **std::get_if<GVectorArray *>(&builder_->actual_params_[param_index]); return **std::get_if<GVectorArray *>(&builder_->actual_params_[param_index]);
} }
@@ -305,7 +305,7 @@ class MFParams {
} }
GMutableSpan single_mutable(int param_index, StringRef name = "") GMutableSpan single_mutable(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::SingleMutable); this->assert_correct_param(param_index, name, ParamCategory::SingleMutable);
return *std::get_if<GMutableSpan>(&builder_->actual_params_[param_index]); return *std::get_if<GMutableSpan>(&builder_->actual_params_[param_index]);
} }
@@ -316,12 +316,12 @@ class MFParams {
} }
GVectorArray &vector_mutable(int param_index, StringRef name = "") GVectorArray &vector_mutable(int param_index, StringRef name = "")
{ {
this->assert_correct_param(param_index, name, MFParamCategory::VectorMutable); this->assert_correct_param(param_index, name, ParamCategory::VectorMutable);
return **std::get_if<GVectorArray *>(&builder_->actual_params_[param_index]); return **std::get_if<GVectorArray *>(&builder_->actual_params_[param_index]);
} }
private: private:
void assert_correct_param(int param_index, StringRef name, MFParamType param_type) void assert_correct_param(int param_index, StringRef name, ParamType param_type)
{ {
UNUSED_VARS_NDEBUG(param_index, name, param_type); UNUSED_VARS_NDEBUG(param_index, name, param_type);
#ifdef DEBUG #ifdef DEBUG
@@ -332,7 +332,7 @@ class MFParams {
#endif #endif
} }
void assert_correct_param(int param_index, StringRef name, MFParamCategory category) void assert_correct_param(int param_index, StringRef name, ParamCategory category)
{ {
UNUSED_VARS_NDEBUG(param_index, name, category); UNUSED_VARS_NDEBUG(param_index, name, category);
#ifdef DEBUG #ifdef DEBUG
@@ -346,4 +346,4 @@ class MFParams {
GMutableSpan ensure_dummy_single_output(int param_index); GMutableSpan ensure_dummy_single_output(int param_index);
}; };
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -8,19 +8,19 @@
#include "FN_multi_function.hh" #include "FN_multi_function.hh"
namespace blender::fn { namespace blender::fn::multi_function {
class MFVariable; class Variable;
class MFInstruction; class Instruction;
class MFCallInstruction; class CallInstruction;
class MFBranchInstruction; class BranchInstruction;
class MFDestructInstruction; class DestructInstruction;
class MFDummyInstruction; class DummyInstruction;
class MFReturnInstruction; class ReturnInstruction;
class MFProcedure; class Procedure;
/** Every instruction has exactly one of these types. */ /** Every instruction has exactly one of these types. */
enum class MFInstructionType { enum class InstructionType {
Call, Call,
Branch, Branch,
Destruct, Destruct,
@@ -29,10 +29,10 @@ enum class MFInstructionType {
}; };
/** /**
* An #MFInstructionCursor points to a position in a multi-function procedure, where an instruction * An #InstructionCursor points to a position in a multi-function procedure, where an instruction
* can be inserted. * can be inserted.
*/ */
class MFInstructionCursor { class InstructionCursor {
public: public:
enum Type { enum Type {
None, None,
@@ -45,33 +45,33 @@ class MFInstructionCursor {
private: private:
Type type_ = None; Type type_ = None;
MFInstruction *instruction_ = nullptr; Instruction *instruction_ = nullptr;
/* Only used when it is a branch instruction. */ /* Only used when it is a branch instruction. */
bool branch_output_ = false; bool branch_output_ = false;
public: public:
MFInstructionCursor() = default; InstructionCursor() = default;
MFInstructionCursor(MFCallInstruction &instruction); InstructionCursor(CallInstruction &instruction);
MFInstructionCursor(MFDestructInstruction &instruction); InstructionCursor(DestructInstruction &instruction);
MFInstructionCursor(MFBranchInstruction &instruction, bool branch_output); InstructionCursor(BranchInstruction &instruction, bool branch_output);
MFInstructionCursor(MFDummyInstruction &instruction); InstructionCursor(DummyInstruction &instruction);
static MFInstructionCursor ForEntry(); static InstructionCursor ForEntry();
MFInstruction *next(MFProcedure &procedure) const; Instruction *next(Procedure &procedure) const;
void set_next(MFProcedure &procedure, MFInstruction *new_instruction) const; void set_next(Procedure &procedure, Instruction *new_instruction) const;
MFInstruction *instruction() const; Instruction *instruction() const;
Type type() const; Type type() const;
friend bool operator==(const MFInstructionCursor &a, const MFInstructionCursor &b) friend bool operator==(const InstructionCursor &a, const InstructionCursor &b)
{ {
return a.type_ == b.type_ && a.instruction_ == b.instruction_ && return a.type_ == b.type_ && a.instruction_ == b.instruction_ &&
a.branch_output_ == b.branch_output_; a.branch_output_ == b.branch_output_;
} }
friend bool operator!=(const MFInstructionCursor &a, const MFInstructionCursor &b) friend bool operator!=(const InstructionCursor &a, const InstructionCursor &b)
{ {
return !(a == b); return !(a == b);
} }
@@ -82,21 +82,21 @@ class MFInstructionCursor {
* either uninitialized or contains a value for every index (remember, a multi-function procedure * either uninitialized or contains a value for every index (remember, a multi-function procedure
* is always evaluated for many indices at the same time). * is always evaluated for many indices at the same time).
*/ */
class MFVariable : NonCopyable, NonMovable { class Variable : NonCopyable, NonMovable {
private: private:
MFDataType data_type_; DataType data_type_;
Vector<MFInstruction *> users_; Vector<Instruction *> users_;
std::string name_; std::string name_;
int index_in_graph_; int index_in_graph_;
friend MFProcedure; friend Procedure;
friend MFCallInstruction; friend CallInstruction;
friend MFBranchInstruction; friend BranchInstruction;
friend MFDestructInstruction; friend DestructInstruction;
public: public:
MFDataType data_type() const; DataType data_type() const;
Span<MFInstruction *> users(); Span<Instruction *> users();
StringRefNull name() const; StringRefNull name() const;
void set_name(std::string name); void set_name(std::string name);
@@ -105,78 +105,78 @@ class MFVariable : NonCopyable, NonMovable {
}; };
/** Base class for all instruction types. */ /** Base class for all instruction types. */
class MFInstruction : NonCopyable, NonMovable { class Instruction : NonCopyable, NonMovable {
protected: protected:
MFInstructionType type_; InstructionType type_;
Vector<MFInstructionCursor> prev_; Vector<InstructionCursor> prev_;
friend MFProcedure; friend Procedure;
friend MFCallInstruction; friend CallInstruction;
friend MFBranchInstruction; friend BranchInstruction;
friend MFDestructInstruction; friend DestructInstruction;
friend MFDummyInstruction; friend DummyInstruction;
friend MFReturnInstruction; friend ReturnInstruction;
public: public:
MFInstructionType type() const; InstructionType type() const;
/** /**
* Other instructions that come before this instruction. There can be multiple previous * Other instructions that come before this instruction. There can be multiple previous
* instructions when branching is used in the procedure. * instructions when branching is used in the procedure.
*/ */
Span<MFInstructionCursor> prev() const; Span<InstructionCursor> prev() const;
}; };
/** /**
* References a multi-function that is evaluated when the instruction is executed. It also * References a multi-function that is evaluated when the instruction is executed. It also
* references the variables whose data will be passed into the multi-function. * references the variables whose data will be passed into the multi-function.
*/ */
class MFCallInstruction : public MFInstruction { class CallInstruction : public Instruction {
private: private:
const MultiFunction *fn_ = nullptr; const MultiFunction *fn_ = nullptr;
MFInstruction *next_ = nullptr; Instruction *next_ = nullptr;
MutableSpan<MFVariable *> params_; MutableSpan<Variable *> params_;
friend MFProcedure; friend Procedure;
public: public:
const MultiFunction &fn() const; const MultiFunction &fn() const;
MFInstruction *next(); Instruction *next();
const MFInstruction *next() const; const Instruction *next() const;
void set_next(MFInstruction *instruction); void set_next(Instruction *instruction);
void set_param_variable(int param_index, MFVariable *variable); void set_param_variable(int param_index, Variable *variable);
void set_params(Span<MFVariable *> variables); void set_params(Span<Variable *> variables);
Span<MFVariable *> params(); Span<Variable *> params();
Span<const MFVariable *> params() const; Span<const Variable *> params() const;
}; };
/** /**
* What makes a branch instruction special is that it has two successor instructions. One that will * What makes a branch instruction special is that it has two successor instructions. One that will
* be used when a condition variable was true, and one otherwise. * be used when a condition variable was true, and one otherwise.
*/ */
class MFBranchInstruction : public MFInstruction { class BranchInstruction : public Instruction {
private: private:
MFVariable *condition_ = nullptr; Variable *condition_ = nullptr;
MFInstruction *branch_true_ = nullptr; Instruction *branch_true_ = nullptr;
MFInstruction *branch_false_ = nullptr; Instruction *branch_false_ = nullptr;
friend MFProcedure; friend Procedure;
public: public:
MFVariable *condition(); Variable *condition();
const MFVariable *condition() const; const Variable *condition() const;
void set_condition(MFVariable *variable); void set_condition(Variable *variable);
MFInstruction *branch_true(); Instruction *branch_true();
const MFInstruction *branch_true() const; const Instruction *branch_true() const;
void set_branch_true(MFInstruction *instruction); void set_branch_true(Instruction *instruction);
MFInstruction *branch_false(); Instruction *branch_false();
const MFInstruction *branch_false() const; const Instruction *branch_false() const;
void set_branch_false(MFInstruction *instruction); void set_branch_false(Instruction *instruction);
}; };
/** /**
@@ -185,55 +185,55 @@ class MFBranchInstruction : public MFInstruction {
* destructed before the procedure ends. Destructing early is generally a good thing, because it * destructed before the procedure ends. Destructing early is generally a good thing, because it
* might help with memory buffer reuse, which decreases memory-usage and increases performance. * might help with memory buffer reuse, which decreases memory-usage and increases performance.
*/ */
class MFDestructInstruction : public MFInstruction { class DestructInstruction : public Instruction {
private: private:
MFVariable *variable_ = nullptr; Variable *variable_ = nullptr;
MFInstruction *next_ = nullptr; Instruction *next_ = nullptr;
friend MFProcedure; friend Procedure;
public: public:
MFVariable *variable(); Variable *variable();
const MFVariable *variable() const; const Variable *variable() const;
void set_variable(MFVariable *variable); void set_variable(Variable *variable);
MFInstruction *next(); Instruction *next();
const MFInstruction *next() const; const Instruction *next() const;
void set_next(MFInstruction *instruction); void set_next(Instruction *instruction);
}; };
/** /**
* This instruction does nothing, it just exists to building a procedure simpler in some cases. * This instruction does nothing, it just exists to building a procedure simpler in some cases.
*/ */
class MFDummyInstruction : public MFInstruction { class DummyInstruction : public Instruction {
private: private:
MFInstruction *next_ = nullptr; Instruction *next_ = nullptr;
friend MFProcedure; friend Procedure;
public: public:
MFInstruction *next(); Instruction *next();
const MFInstruction *next() const; const Instruction *next() const;
void set_next(MFInstruction *instruction); void set_next(Instruction *instruction);
}; };
/** /**
* This instruction ends the procedure. * This instruction ends the procedure.
*/ */
class MFReturnInstruction : public MFInstruction { class ReturnInstruction : public Instruction {
}; };
/** /**
* Inputs and outputs of the entire procedure network. * Inputs and outputs of the entire procedure network.
*/ */
struct MFParameter { struct MFParameter {
MFParamType::InterfaceType type; ParamType::InterfaceType type;
MFVariable *variable; Variable *variable;
}; };
struct ConstMFParameter { struct ConstMFParameter {
MFParamType::InterfaceType type; ParamType::InterfaceType type;
const MFVariable *variable; const Variable *variable;
}; };
/** /**
@@ -241,46 +241,46 @@ struct ConstMFParameter {
* variables and instructions that operate on those variables. Branching and looping within the * variables and instructions that operate on those variables. Branching and looping within the
* procedure is supported as well. * procedure is supported as well.
* *
* Typically, a #MFProcedure should be constructed using a #MFProcedureBuilder, which has many more * Typically, a #Procedure should be constructed using a #ProcedureBuilder, which has many more
* utility methods for common use cases. * utility methods for common use cases.
*/ */
class MFProcedure : NonCopyable, NonMovable { class Procedure : NonCopyable, NonMovable {
private: private:
LinearAllocator<> allocator_; LinearAllocator<> allocator_;
Vector<MFCallInstruction *> call_instructions_; Vector<CallInstruction *> call_instructions_;
Vector<MFBranchInstruction *> branch_instructions_; Vector<BranchInstruction *> branch_instructions_;
Vector<MFDestructInstruction *> destruct_instructions_; Vector<DestructInstruction *> destruct_instructions_;
Vector<MFDummyInstruction *> dummy_instructions_; Vector<DummyInstruction *> dummy_instructions_;
Vector<MFReturnInstruction *> return_instructions_; Vector<ReturnInstruction *> return_instructions_;
Vector<MFVariable *> variables_; Vector<Variable *> variables_;
Vector<MFParameter> params_; Vector<MFParameter> params_;
Vector<destruct_ptr<MultiFunction>> owned_functions_; Vector<destruct_ptr<MultiFunction>> owned_functions_;
MFInstruction *entry_ = nullptr; Instruction *entry_ = nullptr;
friend class MFProcedureDotExport; friend class ProcedureDotExport;
public: public:
MFProcedure() = default; Procedure() = default;
~MFProcedure(); ~Procedure();
MFVariable &new_variable(MFDataType data_type, std::string name = ""); Variable &new_variable(DataType data_type, std::string name = "");
MFCallInstruction &new_call_instruction(const MultiFunction &fn); CallInstruction &new_call_instruction(const MultiFunction &fn);
MFBranchInstruction &new_branch_instruction(); BranchInstruction &new_branch_instruction();
MFDestructInstruction &new_destruct_instruction(); DestructInstruction &new_destruct_instruction();
MFDummyInstruction &new_dummy_instruction(); DummyInstruction &new_dummy_instruction();
MFReturnInstruction &new_return_instruction(); ReturnInstruction &new_return_instruction();
void add_parameter(MFParamType::InterfaceType interface_type, MFVariable &variable); void add_parameter(ParamType::InterfaceType interface_type, Variable &variable);
Span<ConstMFParameter> params() const; Span<ConstMFParameter> params() const;
template<typename T, typename... Args> const MultiFunction &construct_function(Args &&...args); template<typename T, typename... Args> const MultiFunction &construct_function(Args &&...args);
MFInstruction *entry(); Instruction *entry();
const MFInstruction *entry() const; const Instruction *entry() const;
void set_entry(MFInstruction &entry); void set_entry(Instruction &entry);
Span<MFVariable *> variables(); Span<Variable *> variables();
Span<const MFVariable *> variables() const; Span<const Variable *> variables() const;
std::string to_dot() const; std::string to_dot() const;
@@ -298,59 +298,49 @@ class MFProcedure : NonCopyable, NonMovable {
bool can_be_uninitialized = false; bool can_be_uninitialized = false;
}; };
InitState find_initialization_state_before_instruction(const MFInstruction &target_instruction, InitState find_initialization_state_before_instruction(const Instruction &target_instruction,
const MFVariable &variable) const; const Variable &variable) const;
}; };
namespace multi_function_procedure_types {
using MFVariable = fn::MFVariable;
using MFInstruction = fn::MFInstruction;
using MFCallInstruction = fn::MFCallInstruction;
using MFBranchInstruction = fn::MFBranchInstruction;
using MFDestructInstruction = fn::MFDestructInstruction;
using MFProcedure = fn::MFProcedure;
} // namespace multi_function_procedure_types
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFInstructionCursor Inline Methods /** \name #InstructionCursor Inline Methods
* \{ */ * \{ */
inline MFInstructionCursor::MFInstructionCursor(MFCallInstruction &instruction) inline InstructionCursor::InstructionCursor(CallInstruction &instruction)
: type_(Call), instruction_(&instruction) : type_(Call), instruction_(&instruction)
{ {
} }
inline MFInstructionCursor::MFInstructionCursor(MFDestructInstruction &instruction) inline InstructionCursor::InstructionCursor(DestructInstruction &instruction)
: type_(Destruct), instruction_(&instruction) : type_(Destruct), instruction_(&instruction)
{ {
} }
inline MFInstructionCursor::MFInstructionCursor(MFBranchInstruction &instruction, inline InstructionCursor::InstructionCursor(BranchInstruction &instruction, bool branch_output)
bool branch_output)
: type_(Branch), instruction_(&instruction), branch_output_(branch_output) : type_(Branch), instruction_(&instruction), branch_output_(branch_output)
{ {
} }
inline MFInstructionCursor::MFInstructionCursor(MFDummyInstruction &instruction) inline InstructionCursor::InstructionCursor(DummyInstruction &instruction)
: type_(Dummy), instruction_(&instruction) : type_(Dummy), instruction_(&instruction)
{ {
} }
inline MFInstructionCursor MFInstructionCursor::ForEntry() inline InstructionCursor InstructionCursor::ForEntry()
{ {
MFInstructionCursor cursor; InstructionCursor cursor;
cursor.type_ = Type::Entry; cursor.type_ = Type::Entry;
return cursor; return cursor;
} }
inline MFInstruction *MFInstructionCursor::instruction() const inline Instruction *InstructionCursor::instruction() const
{ {
/* This isn't really const correct unfortunately, because to make it correct we'll need a const /* This isn't really const correct unfortunately, because to make it correct we'll need a const
* version of #MFInstructionCursor. */ * version of #InstructionCursor. */
return instruction_; return instruction_;
} }
inline MFInstructionCursor::Type MFInstructionCursor::type() const inline InstructionCursor::Type InstructionCursor::type() const
{ {
return type_; return type_;
} }
@@ -358,25 +348,25 @@ inline MFInstructionCursor::Type MFInstructionCursor::type() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFVariable Inline Methods /** \name #Variable Inline Methods
* \{ */ * \{ */
inline MFDataType MFVariable::data_type() const inline DataType Variable::data_type() const
{ {
return data_type_; return data_type_;
} }
inline Span<MFInstruction *> MFVariable::users() inline Span<Instruction *> Variable::users()
{ {
return users_; return users_;
} }
inline StringRefNull MFVariable::name() const inline StringRefNull Variable::name() const
{ {
return name_; return name_;
} }
inline int MFVariable::index_in_procedure() const inline int Variable::index_in_procedure() const
{ {
return index_in_graph_; return index_in_graph_;
} }
@@ -384,15 +374,15 @@ inline int MFVariable::index_in_procedure() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFInstruction Inline Methods /** \name #Instruction Inline Methods
* \{ */ * \{ */
inline MFInstructionType MFInstruction::type() const inline InstructionType Instruction::type() const
{ {
return type_; return type_;
} }
inline Span<MFInstructionCursor> MFInstruction::prev() const inline Span<InstructionCursor> Instruction::prev() const
{ {
return prev_; return prev_;
} }
@@ -400,30 +390,30 @@ inline Span<MFInstructionCursor> MFInstruction::prev() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFCallInstruction Inline Methods /** \name #CallInstruction Inline Methods
* \{ */ * \{ */
inline const MultiFunction &MFCallInstruction::fn() const inline const MultiFunction &CallInstruction::fn() const
{ {
return *fn_; return *fn_;
} }
inline MFInstruction *MFCallInstruction::next() inline Instruction *CallInstruction::next()
{ {
return next_; return next_;
} }
inline const MFInstruction *MFCallInstruction::next() const inline const Instruction *CallInstruction::next() const
{ {
return next_; return next_;
} }
inline Span<MFVariable *> MFCallInstruction::params() inline Span<Variable *> CallInstruction::params()
{ {
return params_; return params_;
} }
inline Span<const MFVariable *> MFCallInstruction::params() const inline Span<const Variable *> CallInstruction::params() const
{ {
return params_; return params_;
} }
@@ -431,35 +421,35 @@ inline Span<const MFVariable *> MFCallInstruction::params() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFBranchInstruction Inline Methods /** \name #BranchInstruction Inline Methods
* \{ */ * \{ */
inline MFVariable *MFBranchInstruction::condition() inline Variable *BranchInstruction::condition()
{ {
return condition_; return condition_;
} }
inline const MFVariable *MFBranchInstruction::condition() const inline const Variable *BranchInstruction::condition() const
{ {
return condition_; return condition_;
} }
inline MFInstruction *MFBranchInstruction::branch_true() inline Instruction *BranchInstruction::branch_true()
{ {
return branch_true_; return branch_true_;
} }
inline const MFInstruction *MFBranchInstruction::branch_true() const inline const Instruction *BranchInstruction::branch_true() const
{ {
return branch_true_; return branch_true_;
} }
inline MFInstruction *MFBranchInstruction::branch_false() inline Instruction *BranchInstruction::branch_false()
{ {
return branch_false_; return branch_false_;
} }
inline const MFInstruction *MFBranchInstruction::branch_false() const inline const Instruction *BranchInstruction::branch_false() const
{ {
return branch_false_; return branch_false_;
} }
@@ -467,25 +457,25 @@ inline const MFInstruction *MFBranchInstruction::branch_false() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFDestructInstruction Inline Methods /** \name #DestructInstruction Inline Methods
* \{ */ * \{ */
inline MFVariable *MFDestructInstruction::variable() inline Variable *DestructInstruction::variable()
{ {
return variable_; return variable_;
} }
inline const MFVariable *MFDestructInstruction::variable() const inline const Variable *DestructInstruction::variable() const
{ {
return variable_; return variable_;
} }
inline MFInstruction *MFDestructInstruction::next() inline Instruction *DestructInstruction::next()
{ {
return next_; return next_;
} }
inline const MFInstruction *MFDestructInstruction::next() const inline const Instruction *DestructInstruction::next() const
{ {
return next_; return next_;
} }
@@ -493,15 +483,15 @@ inline const MFInstruction *MFDestructInstruction::next() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFDummyInstruction Inline Methods /** \name #DummyInstruction Inline Methods
* \{ */ * \{ */
inline MFInstruction *MFDummyInstruction::next() inline Instruction *DummyInstruction::next()
{ {
return next_; return next_;
} }
inline const MFInstruction *MFDummyInstruction::next() const inline const Instruction *DummyInstruction::next() const
{ {
return next_; return next_;
} }
@@ -509,37 +499,37 @@ inline const MFInstruction *MFDummyInstruction::next() const
/** \} */ /** \} */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name #MFProcedure Inline Methods /** \name #Procedure Inline Methods
* \{ */ * \{ */
inline Span<ConstMFParameter> MFProcedure::params() const inline Span<ConstMFParameter> Procedure::params() const
{ {
static_assert(sizeof(MFParameter) == sizeof(ConstMFParameter)); static_assert(sizeof(MFParameter) == sizeof(ConstMFParameter));
return params_.as_span().cast<ConstMFParameter>(); return params_.as_span().cast<ConstMFParameter>();
} }
inline MFInstruction *MFProcedure::entry() inline Instruction *Procedure::entry()
{ {
return entry_; return entry_;
} }
inline const MFInstruction *MFProcedure::entry() const inline const Instruction *Procedure::entry() const
{ {
return entry_; return entry_;
} }
inline Span<MFVariable *> MFProcedure::variables() inline Span<Variable *> Procedure::variables()
{ {
return variables_; return variables_;
} }
inline Span<const MFVariable *> MFProcedure::variables() const inline Span<const Variable *> Procedure::variables() const
{ {
return variables_; return variables_;
} }
template<typename T, typename... Args> template<typename T, typename... Args>
inline const MultiFunction &MFProcedure::construct_function(Args &&...args) inline const MultiFunction &Procedure::construct_function(Args &&...args)
{ {
destruct_ptr<T> fn = allocator_.construct<T>(std::forward<Args>(args)...); destruct_ptr<T> fn = allocator_.construct<T>(std::forward<Args>(args)...);
const MultiFunction &fn_ref = *fn; const MultiFunction &fn_ref = *fn;
@@ -549,4 +539,4 @@ inline const MultiFunction &MFProcedure::construct_function(Args &&...args)
/** \} */ /** \} */
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -8,182 +8,181 @@
#include "FN_multi_function_procedure.hh" #include "FN_multi_function_procedure.hh"
namespace blender::fn { namespace blender::fn::multi_function {
/** /**
* Utility class to build a #MFProcedure. * Utility class to build a #Procedure.
*/ */
class MFProcedureBuilder { class ProcedureBuilder {
private: private:
/** Procedure that is being build. */ /** Procedure that is being build. */
MFProcedure *procedure_ = nullptr; Procedure *procedure_ = nullptr;
/** Cursors where the next instruction should be inserted. */ /** Cursors where the next instruction should be inserted. */
Vector<MFInstructionCursor> cursors_; Vector<InstructionCursor> cursors_;
public: public:
struct Branch; struct Branch;
struct Loop; struct Loop;
MFProcedureBuilder(MFProcedure &procedure, ProcedureBuilder(Procedure &procedure,
MFInstructionCursor initial_cursor = MFInstructionCursor::ForEntry()); InstructionCursor initial_cursor = InstructionCursor::ForEntry());
MFProcedureBuilder(Span<MFProcedureBuilder *> builders); ProcedureBuilder(Span<ProcedureBuilder *> builders);
MFProcedureBuilder(Branch &branch); ProcedureBuilder(Branch &branch);
void set_cursor(const MFInstructionCursor &cursor); void set_cursor(const InstructionCursor &cursor);
void set_cursor(Span<MFInstructionCursor> cursors); void set_cursor(Span<InstructionCursor> cursors);
void set_cursor(Span<MFProcedureBuilder *> builders); void set_cursor(Span<ProcedureBuilder *> builders);
void set_cursor_after_branch(Branch &branch); void set_cursor_after_branch(Branch &branch);
void set_cursor_after_loop(Loop &loop); void set_cursor_after_loop(Loop &loop);
void add_destruct(MFVariable &variable); void add_destruct(Variable &variable);
void add_destruct(Span<MFVariable *> variables); void add_destruct(Span<Variable *> variables);
MFReturnInstruction &add_return(); ReturnInstruction &add_return();
Branch add_branch(MFVariable &condition); Branch add_branch(Variable &condition);
Loop add_loop(); Loop add_loop();
void add_loop_continue(Loop &loop); void add_loop_continue(Loop &loop);
void add_loop_break(Loop &loop); void add_loop_break(Loop &loop);
MFCallInstruction &add_call_with_no_variables(const MultiFunction &fn); CallInstruction &add_call_with_no_variables(const MultiFunction &fn);
MFCallInstruction &add_call_with_all_variables(const MultiFunction &fn, CallInstruction &add_call_with_all_variables(const MultiFunction &fn,
Span<MFVariable *> param_variables); Span<Variable *> param_variables);
Vector<MFVariable *> add_call(const MultiFunction &fn, Vector<Variable *> add_call(const MultiFunction &fn,
Span<MFVariable *> input_and_mutable_variables = {}); Span<Variable *> input_and_mutable_variables = {});
template<int OutputN> template<int OutputN>
std::array<MFVariable *, OutputN> add_call(const MultiFunction &fn, std::array<Variable *, OutputN> add_call(const MultiFunction &fn,
Span<MFVariable *> input_and_mutable_variables = {}); Span<Variable *> input_and_mutable_variables = {});
void add_parameter(MFParamType::InterfaceType interface_type, MFVariable &variable); void add_parameter(ParamType::InterfaceType interface_type, Variable &variable);
MFVariable &add_parameter(MFParamType param_type, std::string name = ""); Variable &add_parameter(ParamType param_type, std::string name = "");
MFVariable &add_input_parameter(MFDataType data_type, std::string name = ""); Variable &add_input_parameter(DataType data_type, std::string name = "");
template<typename T> MFVariable &add_single_input_parameter(std::string name = ""); template<typename T> Variable &add_single_input_parameter(std::string name = "");
template<typename T> MFVariable &add_single_mutable_parameter(std::string name = ""); template<typename T> Variable &add_single_mutable_parameter(std::string name = "");
void add_output_parameter(MFVariable &variable); void add_output_parameter(Variable &variable);
private: private:
void link_to_cursors(MFInstruction *instruction); void link_to_cursors(Instruction *instruction);
}; };
struct MFProcedureBuilder::Branch { struct ProcedureBuilder::Branch {
MFProcedureBuilder branch_true; ProcedureBuilder branch_true;
MFProcedureBuilder branch_false; ProcedureBuilder branch_false;
}; };
struct MFProcedureBuilder::Loop { struct ProcedureBuilder::Loop {
MFInstruction *begin = nullptr; Instruction *begin = nullptr;
MFDummyInstruction *end = nullptr; DummyInstruction *end = nullptr;
}; };
/* -------------------------------------------------------------------- /* --------------------------------------------------------------------
* MFProcedureBuilder inline methods. * ProcedureBuilder inline methods.
*/ */
inline MFProcedureBuilder::MFProcedureBuilder(Branch &branch) inline ProcedureBuilder::ProcedureBuilder(Branch &branch)
: MFProcedureBuilder(*branch.branch_true.procedure_) : ProcedureBuilder(*branch.branch_true.procedure_)
{ {
this->set_cursor_after_branch(branch); this->set_cursor_after_branch(branch);
} }
inline MFProcedureBuilder::MFProcedureBuilder(MFProcedure &procedure, inline ProcedureBuilder::ProcedureBuilder(Procedure &procedure, InstructionCursor initial_cursor)
MFInstructionCursor initial_cursor)
: procedure_(&procedure), cursors_({initial_cursor}) : procedure_(&procedure), cursors_({initial_cursor})
{ {
} }
inline MFProcedureBuilder::MFProcedureBuilder(Span<MFProcedureBuilder *> builders) inline ProcedureBuilder::ProcedureBuilder(Span<ProcedureBuilder *> builders)
: MFProcedureBuilder(*builders[0]->procedure_) : ProcedureBuilder(*builders[0]->procedure_)
{ {
this->set_cursor(builders); this->set_cursor(builders);
} }
inline void MFProcedureBuilder::set_cursor(const MFInstructionCursor &cursor) inline void ProcedureBuilder::set_cursor(const InstructionCursor &cursor)
{ {
cursors_ = {cursor}; cursors_ = {cursor};
} }
inline void MFProcedureBuilder::set_cursor(Span<MFInstructionCursor> cursors) inline void ProcedureBuilder::set_cursor(Span<InstructionCursor> cursors)
{ {
cursors_ = cursors; cursors_ = cursors;
} }
inline void MFProcedureBuilder::set_cursor_after_branch(Branch &branch) inline void ProcedureBuilder::set_cursor_after_branch(Branch &branch)
{ {
this->set_cursor({&branch.branch_false, &branch.branch_true}); this->set_cursor({&branch.branch_false, &branch.branch_true});
} }
inline void MFProcedureBuilder::set_cursor_after_loop(Loop &loop) inline void ProcedureBuilder::set_cursor_after_loop(Loop &loop)
{ {
this->set_cursor(MFInstructionCursor{*loop.end}); this->set_cursor(InstructionCursor{*loop.end});
} }
inline void MFProcedureBuilder::set_cursor(Span<MFProcedureBuilder *> builders) inline void ProcedureBuilder::set_cursor(Span<ProcedureBuilder *> builders)
{ {
cursors_.clear(); cursors_.clear();
for (MFProcedureBuilder *builder : builders) { for (ProcedureBuilder *builder : builders) {
cursors_.extend(builder->cursors_); cursors_.extend(builder->cursors_);
} }
} }
template<int OutputN> template<int OutputN>
inline std::array<MFVariable *, OutputN> MFProcedureBuilder::add_call( inline std::array<Variable *, OutputN> ProcedureBuilder::add_call(
const MultiFunction &fn, Span<MFVariable *> input_and_mutable_variables) const MultiFunction &fn, Span<Variable *> input_and_mutable_variables)
{ {
Vector<MFVariable *> output_variables = this->add_call(fn, input_and_mutable_variables); Vector<Variable *> output_variables = this->add_call(fn, input_and_mutable_variables);
BLI_assert(output_variables.size() == OutputN); BLI_assert(output_variables.size() == OutputN);
std::array<MFVariable *, OutputN> output_array; std::array<Variable *, OutputN> output_array;
initialized_copy_n(output_variables.data(), OutputN, output_array.data()); initialized_copy_n(output_variables.data(), OutputN, output_array.data());
return output_array; return output_array;
} }
inline void MFProcedureBuilder::add_parameter(MFParamType::InterfaceType interface_type, inline void ProcedureBuilder::add_parameter(ParamType::InterfaceType interface_type,
MFVariable &variable) Variable &variable)
{ {
procedure_->add_parameter(interface_type, variable); procedure_->add_parameter(interface_type, variable);
} }
inline MFVariable &MFProcedureBuilder::add_parameter(MFParamType param_type, std::string name) inline Variable &ProcedureBuilder::add_parameter(ParamType param_type, std::string name)
{ {
MFVariable &variable = procedure_->new_variable(param_type.data_type(), std::move(name)); Variable &variable = procedure_->new_variable(param_type.data_type(), std::move(name));
this->add_parameter(param_type.interface_type(), variable); this->add_parameter(param_type.interface_type(), variable);
return variable; return variable;
} }
inline MFVariable &MFProcedureBuilder::add_input_parameter(MFDataType data_type, std::string name) inline Variable &ProcedureBuilder::add_input_parameter(DataType data_type, std::string name)
{ {
return this->add_parameter(MFParamType(MFParamType::Input, data_type), std::move(name)); return this->add_parameter(ParamType(ParamType::Input, data_type), std::move(name));
} }
template<typename T> template<typename T>
inline MFVariable &MFProcedureBuilder::add_single_input_parameter(std::string name) inline Variable &ProcedureBuilder::add_single_input_parameter(std::string name)
{ {
return this->add_parameter(MFParamType::ForSingleInput(CPPType::get<T>()), std::move(name)); return this->add_parameter(ParamType::ForSingleInput(CPPType::get<T>()), std::move(name));
} }
template<typename T> template<typename T>
inline MFVariable &MFProcedureBuilder::add_single_mutable_parameter(std::string name) inline Variable &ProcedureBuilder::add_single_mutable_parameter(std::string name)
{ {
return this->add_parameter(MFParamType::ForMutableSingle(CPPType::get<T>()), std::move(name)); return this->add_parameter(ParamType::ForMutableSingle(CPPType::get<T>()), std::move(name));
} }
inline void MFProcedureBuilder::add_output_parameter(MFVariable &variable) inline void ProcedureBuilder::add_output_parameter(Variable &variable)
{ {
this->add_parameter(MFParamType::Output, variable); this->add_parameter(ParamType::Output, variable);
} }
inline void MFProcedureBuilder::link_to_cursors(MFInstruction *instruction) inline void ProcedureBuilder::link_to_cursors(Instruction *instruction)
{ {
for (MFInstructionCursor &cursor : cursors_) { for (InstructionCursor &cursor : cursors_) {
cursor.set_next(*procedure_, instruction); cursor.set_next(*procedure_, instruction);
} }
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -8,21 +8,21 @@
#include "FN_multi_function_procedure.hh" #include "FN_multi_function_procedure.hh"
namespace blender::fn { namespace blender::fn::multi_function {
/** A multi-function that executes a procedure internally. */ /** A multi-function that executes a procedure internally. */
class MFProcedureExecutor : public MultiFunction { class ProcedureExecutor : public MultiFunction {
private: private:
MFSignature signature_; Signature signature_;
const MFProcedure &procedure_; const Procedure &procedure_;
public: public:
MFProcedureExecutor(const MFProcedure &procedure); ProcedureExecutor(const Procedure &procedure);
void call(IndexMask mask, MFParams params, MFContext context) const override; void call(IndexMask mask, MFParams params, Context context) const override;
private: private:
ExecutionHints get_execution_hints() const override; ExecutionHints get_execution_hints() const override;
}; };
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -5,11 +5,11 @@
/** \file /** \file
* \ingroup fn * \ingroup fn
* *
* A #MFProcedure optimization pass takes an existing procedure and changes it in a way that * A #Procedure optimization pass takes an existing procedure and changes it in a way that
* improves its performance when executed. * improves its performance when executed.
* *
* Oftentimes it would also be possible to implement a specific optimization directly during * Oftentimes it would also be possible to implement a specific optimization directly during
* construction of the initial #MFProcedure. There is a trade-off between doing that or just * construction of the initial #Procedure. There is a trade-off between doing that or just
* building a "simple" procedure and then optimizing it uses separate optimization passes. * building a "simple" procedure and then optimizing it uses separate optimization passes.
* - Doing optimizations directly during construction is typically faster than doing it as a * - Doing optimizations directly during construction is typically faster than doing it as a
* separate pass. However, it would be much harder to turn the optimization off when it is not * separate pass. However, it would be much harder to turn the optimization off when it is not
@@ -23,10 +23,10 @@
#include "FN_multi_function_procedure.hh" #include "FN_multi_function_procedure.hh"
namespace blender::fn::procedure_optimization { namespace blender::fn::multi_function::procedure_optimization {
/** /**
* When generating a procedure, destruct instructions (#MFDestructInstruction) have to be inserted * When generating a procedure, destruct instructions (#DestructInstruction) have to be inserted
* for all variables that are not outputs. Often the simplest approach is to add these instructions * for all variables that are not outputs. Often the simplest approach is to add these instructions
* at the very end. However, when the procedure is executed this is not optimal, because many more * at the very end. However, when the procedure is executed this is not optimal, because many more
* variables are initialized at the same time than necessary. This inhibits the reuse of memory * variables are initialized at the same time than necessary. This inhibits the reuse of memory
@@ -42,6 +42,6 @@ namespace blender::fn::procedure_optimization {
* \param block_end_instr: The instruction that points to the last instruction within a linear * \param block_end_instr: The instruction that points to the last instruction within a linear
* chain of instructions. The algorithm moves instructions backward starting at this instruction. * chain of instructions. The algorithm moves instructions backward starting at this instruction.
*/ */
void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr); void move_destructs_up(Procedure &procedure, Instruction &block_end_instr);
} // namespace blender::fn::procedure_optimization } // namespace blender::fn::multi_function::procedure_optimization

View File

@@ -6,18 +6,18 @@
* \ingroup fn * \ingroup fn
* *
* The signature of a multi-function contains the functions name and expected parameters. New * The signature of a multi-function contains the functions name and expected parameters. New
* signatures should be build using the #MFSignatureBuilder class. * signatures should be build using the #SignatureBuilder class.
*/ */
#include "FN_multi_function_param_type.hh" #include "FN_multi_function_param_type.hh"
#include "BLI_vector.hh" #include "BLI_vector.hh"
namespace blender::fn { namespace blender::fn::multi_function {
struct MFSignature { struct Signature {
struct ParamInfo { struct ParamInfo {
MFParamType type; ParamType type;
const char *name; const char *name;
}; };
@@ -32,12 +32,12 @@ struct MFSignature {
Vector<ParamInfo> params; Vector<ParamInfo> params;
}; };
class MFSignatureBuilder { class SignatureBuilder {
private: private:
MFSignature &signature_; Signature &signature_;
public: public:
MFSignatureBuilder(const char *function_name, MFSignature &signature_to_build) SignatureBuilder(const char *function_name, Signature &signature_to_build)
: signature_(signature_to_build) : signature_(signature_to_build)
{ {
signature_.function_name = function_name; signature_.function_name = function_name;
@@ -51,7 +51,7 @@ class MFSignatureBuilder {
} }
void single_input(const char *name, const CPPType &type) void single_input(const char *name, const CPPType &type)
{ {
this->input(name, MFDataType::ForSingle(type)); this->input(name, DataType::ForSingle(type));
} }
template<typename T> void vector_input(const char *name) template<typename T> void vector_input(const char *name)
{ {
@@ -59,11 +59,11 @@ class MFSignatureBuilder {
} }
void vector_input(const char *name, const CPPType &base_type) void vector_input(const char *name, const CPPType &base_type)
{ {
this->input(name, MFDataType::ForVector(base_type)); this->input(name, DataType::ForVector(base_type));
} }
void input(const char *name, MFDataType data_type) void input(const char *name, DataType data_type)
{ {
signature_.params.append({MFParamType(MFParamType::Input, data_type), name}); signature_.params.append({ParamType(ParamType::Input, data_type), name});
} }
/* Output Parameter Types */ /* Output Parameter Types */
@@ -74,7 +74,7 @@ class MFSignatureBuilder {
} }
void single_output(const char *name, const CPPType &type) void single_output(const char *name, const CPPType &type)
{ {
this->output(name, MFDataType::ForSingle(type)); this->output(name, DataType::ForSingle(type));
} }
template<typename T> void vector_output(const char *name) template<typename T> void vector_output(const char *name)
{ {
@@ -82,11 +82,11 @@ class MFSignatureBuilder {
} }
void vector_output(const char *name, const CPPType &base_type) void vector_output(const char *name, const CPPType &base_type)
{ {
this->output(name, MFDataType::ForVector(base_type)); this->output(name, DataType::ForVector(base_type));
} }
void output(const char *name, MFDataType data_type) void output(const char *name, DataType data_type)
{ {
signature_.params.append({MFParamType(MFParamType::Output, data_type), name}); signature_.params.append({ParamType(ParamType::Output, data_type), name});
} }
/* Mutable Parameter Types */ /* Mutable Parameter Types */
@@ -97,7 +97,7 @@ class MFSignatureBuilder {
} }
void single_mutable(const char *name, const CPPType &type) void single_mutable(const char *name, const CPPType &type)
{ {
this->mutable_(name, MFDataType::ForSingle(type)); this->mutable_(name, DataType::ForSingle(type));
} }
template<typename T> void vector_mutable(const char *name) template<typename T> void vector_mutable(const char *name)
{ {
@@ -105,48 +105,48 @@ class MFSignatureBuilder {
} }
void vector_mutable(const char *name, const CPPType &base_type) void vector_mutable(const char *name, const CPPType &base_type)
{ {
this->mutable_(name, MFDataType::ForVector(base_type)); this->mutable_(name, DataType::ForVector(base_type));
} }
void mutable_(const char *name, MFDataType data_type) void mutable_(const char *name, DataType data_type)
{ {
signature_.params.append({MFParamType(MFParamType::Mutable, data_type), name}); signature_.params.append({ParamType(ParamType::Mutable, data_type), name});
} }
void add(const char *name, const MFParamType &param_type) void add(const char *name, const ParamType &param_type)
{ {
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: case ParamType::Input:
this->input(name, param_type.data_type()); this->input(name, param_type.data_type());
break; break;
case MFParamType::Mutable: case ParamType::Mutable:
this->mutable_(name, param_type.data_type()); this->mutable_(name, param_type.data_type());
break; break;
case MFParamType::Output: case ParamType::Output:
this->output(name, param_type.data_type()); this->output(name, param_type.data_type());
break; break;
} }
} }
template<MFParamCategory Category, typename T> template<ParamCategory Category, typename T>
void add(MFParamTag<Category, T> /* tag */, const char *name) void add(MFParamTag<Category, T> /* tag */, const char *name)
{ {
switch (Category) { switch (Category) {
case MFParamCategory::SingleInput: case ParamCategory::SingleInput:
this->single_input<T>(name); this->single_input<T>(name);
return; return;
case MFParamCategory::VectorInput: case ParamCategory::VectorInput:
this->vector_input<T>(name); this->vector_input<T>(name);
return; return;
case MFParamCategory::SingleOutput: case ParamCategory::SingleOutput:
this->single_output<T>(name); this->single_output<T>(name);
return; return;
case MFParamCategory::VectorOutput: case ParamCategory::VectorOutput:
this->vector_output<T>(name); this->vector_output<T>(name);
return; return;
case MFParamCategory::SingleMutable: case ParamCategory::SingleMutable:
this->single_mutable<T>(name); this->single_mutable<T>(name);
return; return;
case MFParamCategory::VectorMutable: case ParamCategory::VectorMutable:
this->vector_mutable<T>(name); this->vector_mutable<T>(name);
return; return;
} }
@@ -154,4 +154,4 @@ class MFSignatureBuilder {
} }
}; };
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -142,19 +142,19 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
/** /**
* Builds the #procedure so that it computes the fields. * Builds the #procedure so that it computes the fields.
*/ */
static void build_multi_function_procedure_for_fields(MFProcedure &procedure, static void build_multi_function_procedure_for_fields(mf::Procedure &procedure,
ResourceScope &scope, ResourceScope &scope,
const FieldTreeInfo &field_tree_info, const FieldTreeInfo &field_tree_info,
Span<GFieldRef> output_fields) Span<GFieldRef> output_fields)
{ {
MFProcedureBuilder builder{procedure}; mf::ProcedureBuilder builder{procedure};
/* Every input, intermediate and output field corresponds to a variable in the procedure. */ /* Every input, intermediate and output field corresponds to a variable in the procedure. */
Map<GFieldRef, MFVariable *> variable_by_field; Map<GFieldRef, mf::Variable *> variable_by_field;
/* Start by adding the field inputs as parameters to the procedure. */ /* Start by adding the field inputs as parameters to the procedure. */
for (const FieldInput &field_input : field_tree_info.deduplicated_field_inputs) { for (const FieldInput &field_input : field_tree_info.deduplicated_field_inputs) {
MFVariable &variable = builder.add_input_parameter( mf::Variable &variable = builder.add_input_parameter(
MFDataType::ForSingle(field_input.cpp_type()), field_input.debug_name()); mf::DataType::ForSingle(field_input.cpp_type()), field_input.debug_name());
variable_by_field.add_new({field_input, 0}, &variable); variable_by_field.add_new({field_input, 0}, &variable);
} }
@@ -196,20 +196,20 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
else { else {
/* All inputs variables are ready, now gather all variables that are used by the /* All inputs variables are ready, now gather all variables that are used by the
* function and call it. */ * function and call it. */
const MultiFunction &multi_function = operation_node.multi_function(); const mf::MultiFunction &multi_function = operation_node.multi_function();
Vector<MFVariable *> variables(multi_function.param_amount()); Vector<mf::Variable *> variables(multi_function.param_amount());
int param_input_index = 0; int param_input_index = 0;
int param_output_index = 0; int param_output_index = 0;
for (const int param_index : multi_function.param_indices()) { for (const int param_index : multi_function.param_indices()) {
const MFParamType param_type = multi_function.param_type(param_index); const mf::ParamType param_type = multi_function.param_type(param_index);
const MFParamType::InterfaceType interface_type = param_type.interface_type(); const mf::ParamType::InterfaceType interface_type = param_type.interface_type();
if (interface_type == MFParamType::Input) { if (interface_type == mf::ParamType::Input) {
const GField &input_field = operation_inputs[param_input_index]; const GField &input_field = operation_inputs[param_input_index];
variables[param_index] = variable_by_field.lookup(input_field); variables[param_index] = variable_by_field.lookup(input_field);
param_input_index++; param_input_index++;
} }
else if (interface_type == MFParamType::Output) { else if (interface_type == mf::ParamType::Output) {
const GFieldRef output_field{operation_node, param_output_index}; const GFieldRef output_field{operation_node, param_output_index};
const bool output_is_ignored = const bool output_is_ignored =
field_tree_info.field_users.lookup(output_field).is_empty() && field_tree_info.field_users.lookup(output_field).is_empty() &&
@@ -220,7 +220,7 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
} }
else { else {
/* Create a new variable for used outputs. */ /* Create a new variable for used outputs. */
MFVariable &new_variable = procedure.new_variable(param_type.data_type()); mf::Variable &new_variable = procedure.new_variable(param_type.data_type());
variables[param_index] = &new_variable; variables[param_index] = &new_variable;
variable_by_field.add_new(output_field, &new_variable); variable_by_field.add_new(output_field, &new_variable);
} }
@@ -236,9 +236,9 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
} }
case FieldNodeType::Constant: { case FieldNodeType::Constant: {
const FieldConstant &constant_node = static_cast<const FieldConstant &>(field_node); const FieldConstant &constant_node = static_cast<const FieldConstant &>(field_node);
const MultiFunction &fn = procedure.construct_function<CustomMF_GenericConstant>( const mf::MultiFunction &fn = procedure.construct_function<mf::CustomMF_GenericConstant>(
constant_node.type(), constant_node.value().get(), false); constant_node.type(), constant_node.value().get(), false);
MFVariable &new_variable = *builder.add_call<1>(fn)[0]; mf::Variable &new_variable = *builder.add_call<1>(fn)[0];
variable_by_field.add_new(field, &new_variable); variable_by_field.add_new(field, &new_variable);
break; break;
} }
@@ -247,13 +247,14 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
} }
/* Add output parameters to the procedure. */ /* Add output parameters to the procedure. */
Set<MFVariable *> already_output_variables; Set<mf::Variable *> already_output_variables;
for (const GFieldRef &field : output_fields) { for (const GFieldRef &field : output_fields) {
MFVariable *variable = variable_by_field.lookup(field); mf::Variable *variable = variable_by_field.lookup(field);
if (!already_output_variables.add(variable)) { if (!already_output_variables.add(variable)) {
/* One variable can be output at most once. To output the same value twice, we have to make /* One variable can be output at most once. To output the same value twice, we have to make
* a copy first. */ * a copy first. */
const MultiFunction &copy_fn = scope.construct<CustomMF_GenericCopy>(variable->data_type()); const mf::MultiFunction &copy_fn = scope.construct<mf::CustomMF_GenericCopy>(
variable->data_type());
variable = builder.add_call<1>(copy_fn, {variable})[0]; variable = builder.add_call<1>(copy_fn, {variable})[0];
} }
builder.add_output_parameter(*variable); builder.add_output_parameter(*variable);
@@ -264,13 +265,13 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
variable_by_field.remove(field); variable_by_field.remove(field);
} }
/* Add destructor calls for the remaining variables. */ /* Add destructor calls for the remaining variables. */
for (MFVariable *variable : variable_by_field.values()) { for (mf::Variable *variable : variable_by_field.values()) {
builder.add_destruct(*variable); builder.add_destruct(*variable);
} }
MFReturnInstruction &return_instr = builder.add_return(); mf::ReturnInstruction &return_instr = builder.add_return();
procedure_optimization::move_destructs_up(procedure, return_instr); mf::procedure_optimization::move_destructs_up(procedure, return_instr);
// std::cout << procedure.to_dot() << "\n"; // std::cout << procedure.to_dot() << "\n";
BLI_assert(procedure.validate()); BLI_assert(procedure.validate());
@@ -366,13 +367,13 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
/* Evaluate varying fields if necessary. */ /* Evaluate varying fields if necessary. */
if (!varying_fields_to_evaluate.is_empty()) { if (!varying_fields_to_evaluate.is_empty()) {
/* Build the procedure for those fields. */ /* Build the procedure for those fields. */
MFProcedure procedure; mf::Procedure procedure;
build_multi_function_procedure_for_fields( build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, varying_fields_to_evaluate); procedure, scope, field_tree_info, varying_fields_to_evaluate);
MFProcedureExecutor procedure_executor{procedure}; mf::ProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, &mask}; mf::ParamsBuilder mf_params{procedure_executor, &mask};
MFContextBuilder mf_context; mf::ContextBuilder mf_context;
/* Provide inputs to the procedure executor. */ /* Provide inputs to the procedure executor. */
for (const GVArray &varray : field_context_inputs) { for (const GVArray &varray : field_context_inputs) {
@@ -418,12 +419,12 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
/* Evaluate constant fields if necessary. */ /* Evaluate constant fields if necessary. */
if (!constant_fields_to_evaluate.is_empty()) { if (!constant_fields_to_evaluate.is_empty()) {
/* Build the procedure for those fields. */ /* Build the procedure for those fields. */
MFProcedure procedure; mf::Procedure procedure;
build_multi_function_procedure_for_fields( build_multi_function_procedure_for_fields(
procedure, scope, field_tree_info, constant_fields_to_evaluate); procedure, scope, field_tree_info, constant_fields_to_evaluate);
MFProcedureExecutor procedure_executor{procedure}; mf::ProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, 1}; mf::ParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context; mf::ContextBuilder mf_context;
/* Provide inputs to the procedure executor. */ /* Provide inputs to the procedure executor. */
for (const GVArray &varray : field_context_inputs) { for (const GVArray &varray : field_context_inputs) {
@@ -519,8 +520,8 @@ GField make_field_constant_if_possible(GField field)
Field<bool> invert_boolean_field(const Field<bool> &field) Field<bool> invert_boolean_field(const Field<bool> &field)
{ {
static auto not_fn = build_mf::SI1_SO<bool, bool>( static auto not_fn = mf::build::SI1_SO<bool, bool>(
"Not", [](bool a) { return !a; }, build_mf::exec_presets::AllSpanOrSingle()); "Not", [](bool a) { return !a; }, mf::build::exec_presets::AllSpanOrSingle());
auto not_op = std::make_shared<FieldOperation>(FieldOperation(not_fn, {field})); auto not_op = std::make_shared<FieldOperation>(FieldOperation(not_fn, {field}));
return Field<bool>(not_op); return Field<bool>(not_op);
} }
@@ -597,7 +598,7 @@ void FieldNode::for_each_field_input_recursive(FunctionRef<void(const FieldInput
/** \name #FieldOperation /** \name #FieldOperation
* \{ */ * \{ */
FieldOperation::FieldOperation(std::shared_ptr<const MultiFunction> function, FieldOperation::FieldOperation(std::shared_ptr<const mf::MultiFunction> function,
Vector<GField> inputs) Vector<GField> inputs)
: FieldOperation(*function, std::move(inputs)) : FieldOperation(*function, std::move(inputs))
{ {
@@ -662,7 +663,7 @@ static std::shared_ptr<const FieldInputs> combine_field_inputs(Span<GField> fiel
return new_field_inputs; return new_field_inputs;
} }
FieldOperation::FieldOperation(const MultiFunction &function, Vector<GField> inputs) FieldOperation::FieldOperation(const mf::MultiFunction &function, Vector<GField> inputs)
: FieldNode(FieldNodeType::Operation), function_(&function), inputs_(std::move(inputs)) : FieldNode(FieldNodeType::Operation), function_(&function), inputs_(std::move(inputs))
{ {
field_inputs_ = combine_field_inputs(inputs_); field_inputs_ = combine_field_inputs(inputs_);

View File

@@ -5,7 +5,7 @@
#include "BLI_task.hh" #include "BLI_task.hh"
#include "BLI_threads.h" #include "BLI_threads.h"
namespace blender::fn { namespace blender::fn::multi_function {
using ExecutionHints = MultiFunction::ExecutionHints; using ExecutionHints = MultiFunction::ExecutionHints;
@@ -22,10 +22,10 @@ ExecutionHints MultiFunction::get_execution_hints() const
static bool supports_threading_by_slicing_params(const MultiFunction &fn) static bool supports_threading_by_slicing_params(const MultiFunction &fn)
{ {
for (const int i : fn.param_indices()) { for (const int i : fn.param_indices()) {
const MFParamType param_type = fn.param_type(i); const ParamType param_type = fn.param_type(i);
if (ELEM(param_type.interface_type(), if (ELEM(param_type.interface_type(),
MFParamType::InterfaceType::Mutable, ParamType::InterfaceType::Mutable,
MFParamType::InterfaceType::Output)) { ParamType::InterfaceType::Output)) {
if (param_type.data_type().is_vector()) { if (param_type.data_type().is_vector()) {
return false; return false;
} }
@@ -52,7 +52,7 @@ static int64_t compute_grain_size(const ExecutionHints &hints, const IndexMask m
return grain_size; return grain_size;
} }
void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context) const void MultiFunction::call_auto(IndexMask mask, MFParams params, Context context) const
{ {
if (mask.is_empty()) { if (mask.is_empty()) {
return; return;
@@ -90,24 +90,24 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
Vector<int64_t> offset_mask_indices; Vector<int64_t> offset_mask_indices;
const IndexMask offset_mask = mask.slice_and_offset(sub_range, offset_mask_indices); const IndexMask offset_mask = mask.slice_and_offset(sub_range, offset_mask_indices);
MFParamsBuilder offset_params{*this, offset_mask.min_array_size()}; ParamsBuilder offset_params{*this, offset_mask.min_array_size()};
/* Slice all parameters so that for the actual function call. */ /* Slice all parameters so that for the actual function call. */
for (const int param_index : this->param_indices()) { for (const int param_index : this->param_indices()) {
const MFParamType param_type = this->param_type(param_index); const ParamType param_type = this->param_type(param_index);
switch (param_type.category()) { switch (param_type.category()) {
case MFParamCategory::SingleInput: { case ParamCategory::SingleInput: {
const GVArray &varray = params.readonly_single_input(param_index); const GVArray &varray = params.readonly_single_input(param_index);
offset_params.add_readonly_single_input(varray.slice(input_slice_range)); offset_params.add_readonly_single_input(varray.slice(input_slice_range));
break; break;
} }
case MFParamCategory::SingleMutable: { case ParamCategory::SingleMutable: {
const GMutableSpan span = params.single_mutable(param_index); const GMutableSpan span = params.single_mutable(param_index);
const GMutableSpan sliced_span = span.slice(input_slice_range); const GMutableSpan sliced_span = span.slice(input_slice_range);
offset_params.add_single_mutable(sliced_span); offset_params.add_single_mutable(sliced_span);
break; break;
} }
case MFParamCategory::SingleOutput: { case ParamCategory::SingleOutput: {
const GMutableSpan span = params.uninitialized_single_output_if_required(param_index); const GMutableSpan span = params.uninitialized_single_output_if_required(param_index);
if (span.is_empty()) { if (span.is_empty()) {
offset_params.add_ignored_single_output(); offset_params.add_ignored_single_output();
@@ -118,9 +118,9 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
} }
break; break;
} }
case MFParamCategory::VectorInput: case ParamCategory::VectorInput:
case MFParamCategory::VectorMutable: case ParamCategory::VectorMutable:
case MFParamCategory::VectorOutput: { case ParamCategory::VectorOutput: {
BLI_assert_unreachable(); BLI_assert_unreachable();
break; break;
} }
@@ -136,4 +136,4 @@ std::string MultiFunction::debug_name() const
return signature_ref_->function_name; return signature_ref_->function_name;
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -4,7 +4,7 @@
#include "BLI_hash.hh" #include "BLI_hash.hh"
namespace blender::fn { namespace blender::fn::multi_function {
CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type, CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
const void *value, const void *value,
@@ -18,7 +18,7 @@ CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
} }
value_ = value; value_ = value;
MFSignatureBuilder builder{"Constant", signature_}; SignatureBuilder builder{"Constant", signature_};
builder.single_output("Value", type); builder.single_output("Value", type);
this->set_signature(&signature_); this->set_signature(&signature_);
} }
@@ -31,7 +31,7 @@ CustomMF_GenericConstant::~CustomMF_GenericConstant()
} }
} }
void CustomMF_GenericConstant::call(IndexMask mask, MFParams params, MFContext /*context*/) const void CustomMF_GenericConstant::call(IndexMask mask, MFParams params, Context /*context*/) const
{ {
GMutableSpan output = params.uninitialized_single_output(0); GMutableSpan output = params.uninitialized_single_output(0);
type_.fill_construct_indices(value_, output.data(), mask); type_.fill_construct_indices(value_, output.data(), mask);
@@ -57,14 +57,14 @@ bool CustomMF_GenericConstant::equals(const MultiFunction &other) const
CustomMF_GenericConstantArray::CustomMF_GenericConstantArray(GSpan array) : array_(array) CustomMF_GenericConstantArray::CustomMF_GenericConstantArray(GSpan array) : array_(array)
{ {
const CPPType &type = array.type(); const CPPType &type = array.type();
MFSignatureBuilder builder{"Constant Vector", signature_}; SignatureBuilder builder{"Constant Vector", signature_};
builder.vector_output("Value", type); builder.vector_output("Value", type);
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void CustomMF_GenericConstantArray::call(IndexMask mask, void CustomMF_GenericConstantArray::call(IndexMask mask,
MFParams params, MFParams params,
MFContext /*context*/) const Context /*context*/) const
{ {
GVectorArray &vectors = params.vector_output(0); GVectorArray &vectors = params.vector_output(0);
for (int64_t i : mask) { for (int64_t i : mask) {
@@ -72,23 +72,23 @@ void CustomMF_GenericConstantArray::call(IndexMask mask,
} }
} }
CustomMF_DefaultOutput::CustomMF_DefaultOutput(Span<MFDataType> input_types, CustomMF_DefaultOutput::CustomMF_DefaultOutput(Span<DataType> input_types,
Span<MFDataType> output_types) Span<DataType> output_types)
: output_amount_(output_types.size()) : output_amount_(output_types.size())
{ {
MFSignatureBuilder builder{"Default Output", signature_}; SignatureBuilder builder{"Default Output", signature_};
for (MFDataType data_type : input_types) { for (DataType data_type : input_types) {
builder.input("Input", data_type); builder.input("Input", data_type);
} }
for (MFDataType data_type : output_types) { for (DataType data_type : output_types) {
builder.output("Output", data_type); builder.output("Output", data_type);
} }
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, MFContext /*context*/) const void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, Context /*context*/) const
{ {
for (int param_index : this->param_indices()) { for (int param_index : this->param_indices()) {
MFParamType param_type = this->param_type(param_index); ParamType param_type = this->param_type(param_index);
if (!param_type.is_output()) { if (!param_type.is_output()) {
continue; continue;
} }
@@ -101,25 +101,25 @@ void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, MFContext /*c
} }
} }
CustomMF_GenericCopy::CustomMF_GenericCopy(MFDataType data_type) CustomMF_GenericCopy::CustomMF_GenericCopy(DataType data_type)
{ {
MFSignatureBuilder builder{"Copy", signature_}; SignatureBuilder builder{"Copy", signature_};
builder.input("Input", data_type); builder.input("Input", data_type);
builder.output("Output", data_type); builder.output("Output", data_type);
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void CustomMF_GenericCopy::call(IndexMask mask, MFParams params, MFContext /*context*/) const void CustomMF_GenericCopy::call(IndexMask mask, MFParams params, Context /*context*/) const
{ {
const MFDataType data_type = this->param_type(0).data_type(); const DataType data_type = this->param_type(0).data_type();
switch (data_type.category()) { switch (data_type.category()) {
case MFDataType::Single: { case DataType::Single: {
const GVArray &inputs = params.readonly_single_input(0, "Input"); const GVArray &inputs = params.readonly_single_input(0, "Input");
GMutableSpan outputs = params.uninitialized_single_output(1, "Output"); GMutableSpan outputs = params.uninitialized_single_output(1, "Output");
inputs.materialize_to_uninitialized(mask, outputs.data()); inputs.materialize_to_uninitialized(mask, outputs.data());
break; break;
} }
case MFDataType::Vector: { case DataType::Vector: {
const GVVectorArray &inputs = params.readonly_vector_input(0, "Input"); const GVVectorArray &inputs = params.readonly_vector_input(0, "Input");
GVectorArray &outputs = params.vector_output(1, "Output"); GVectorArray &outputs = params.vector_output(1, "Output");
outputs.extend(mask, inputs); outputs.extend(mask, inputs);
@@ -128,4 +128,4 @@ void CustomMF_GenericCopy::call(IndexMask mask, MFParams params, MFContext /*con
} }
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -2,7 +2,7 @@
#include "FN_multi_function_params.hh" #include "FN_multi_function_params.hh"
namespace blender::fn { namespace blender::fn::multi_function {
GMutableSpan MFParams::ensure_dummy_single_output(int param_index) GMutableSpan MFParams::ensure_dummy_single_output(int param_index)
{ {
@@ -27,4 +27,4 @@ GMutableSpan MFParams::ensure_dummy_single_output(int param_index)
return span; return span;
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -5,9 +5,9 @@
#include "BLI_dot_export.hh" #include "BLI_dot_export.hh"
#include "BLI_stack.hh" #include "BLI_stack.hh"
namespace blender::fn { namespace blender::fn::multi_function {
void MFInstructionCursor::set_next(MFProcedure &procedure, MFInstruction *new_instruction) const void InstructionCursor::set_next(Procedure &procedure, Instruction *new_instruction) const
{ {
switch (type_) { switch (type_) {
case Type::None: { case Type::None: {
@@ -18,11 +18,11 @@ void MFInstructionCursor::set_next(MFProcedure &procedure, MFInstruction *new_in
break; break;
} }
case Type::Call: { case Type::Call: {
static_cast<MFCallInstruction *>(instruction_)->set_next(new_instruction); static_cast<CallInstruction *>(instruction_)->set_next(new_instruction);
break; break;
} }
case Type::Branch: { case Type::Branch: {
MFBranchInstruction &branch_instruction = *static_cast<MFBranchInstruction *>(instruction_); BranchInstruction &branch_instruction = *static_cast<BranchInstruction *>(instruction_);
if (branch_output_) { if (branch_output_) {
branch_instruction.set_branch_true(new_instruction); branch_instruction.set_branch_true(new_instruction);
} }
@@ -32,17 +32,17 @@ void MFInstructionCursor::set_next(MFProcedure &procedure, MFInstruction *new_in
break; break;
} }
case Type::Destruct: { case Type::Destruct: {
static_cast<MFDestructInstruction *>(instruction_)->set_next(new_instruction); static_cast<DestructInstruction *>(instruction_)->set_next(new_instruction);
break; break;
} }
case Type::Dummy: { case Type::Dummy: {
static_cast<MFDummyInstruction *>(instruction_)->set_next(new_instruction); static_cast<DummyInstruction *>(instruction_)->set_next(new_instruction);
break; break;
} }
} }
} }
MFInstruction *MFInstructionCursor::next(MFProcedure &procedure) const Instruction *InstructionCursor::next(Procedure &procedure) const
{ {
switch (type_) { switch (type_) {
case Type::None: case Type::None:
@@ -50,28 +50,28 @@ MFInstruction *MFInstructionCursor::next(MFProcedure &procedure) const
case Type::Entry: case Type::Entry:
return procedure.entry(); return procedure.entry();
case Type::Call: case Type::Call:
return static_cast<MFCallInstruction *>(instruction_)->next(); return static_cast<CallInstruction *>(instruction_)->next();
case Type::Branch: { case Type::Branch: {
MFBranchInstruction &branch_instruction = *static_cast<MFBranchInstruction *>(instruction_); BranchInstruction &branch_instruction = *static_cast<BranchInstruction *>(instruction_);
if (branch_output_) { if (branch_output_) {
return branch_instruction.branch_true(); return branch_instruction.branch_true();
} }
return branch_instruction.branch_false(); return branch_instruction.branch_false();
} }
case Type::Destruct: case Type::Destruct:
return static_cast<MFDestructInstruction *>(instruction_)->next(); return static_cast<DestructInstruction *>(instruction_)->next();
case Type::Dummy: case Type::Dummy:
return static_cast<MFDummyInstruction *>(instruction_)->next(); return static_cast<DummyInstruction *>(instruction_)->next();
} }
return nullptr; return nullptr;
} }
void MFVariable::set_name(std::string name) void Variable::set_name(std::string name)
{ {
name_ = std::move(name); name_ = std::move(name);
} }
void MFCallInstruction::set_next(MFInstruction *instruction) void CallInstruction::set_next(Instruction *instruction)
{ {
if (next_ != nullptr) { if (next_ != nullptr) {
next_->prev_.remove_first_occurrence_and_reorder(*this); next_->prev_.remove_first_occurrence_and_reorder(*this);
@@ -82,7 +82,7 @@ void MFCallInstruction::set_next(MFInstruction *instruction)
next_ = instruction; next_ = instruction;
} }
void MFCallInstruction::set_param_variable(int param_index, MFVariable *variable) void CallInstruction::set_param_variable(int param_index, Variable *variable)
{ {
if (params_[param_index] != nullptr) { if (params_[param_index] != nullptr) {
params_[param_index]->users_.remove_first_occurrence_and_reorder(this); params_[param_index]->users_.remove_first_occurrence_and_reorder(this);
@@ -94,7 +94,7 @@ void MFCallInstruction::set_param_variable(int param_index, MFVariable *variable
params_[param_index] = variable; params_[param_index] = variable;
} }
void MFCallInstruction::set_params(Span<MFVariable *> variables) void CallInstruction::set_params(Span<Variable *> variables)
{ {
BLI_assert(variables.size() == params_.size()); BLI_assert(variables.size() == params_.size());
for (const int i : variables.index_range()) { for (const int i : variables.index_range()) {
@@ -102,7 +102,7 @@ void MFCallInstruction::set_params(Span<MFVariable *> variables)
} }
} }
void MFBranchInstruction::set_condition(MFVariable *variable) void BranchInstruction::set_condition(Variable *variable)
{ {
if (condition_ != nullptr) { if (condition_ != nullptr) {
condition_->users_.remove_first_occurrence_and_reorder(this); condition_->users_.remove_first_occurrence_and_reorder(this);
@@ -113,7 +113,7 @@ void MFBranchInstruction::set_condition(MFVariable *variable)
condition_ = variable; condition_ = variable;
} }
void MFBranchInstruction::set_branch_true(MFInstruction *instruction) void BranchInstruction::set_branch_true(Instruction *instruction)
{ {
if (branch_true_ != nullptr) { if (branch_true_ != nullptr) {
branch_true_->prev_.remove_first_occurrence_and_reorder({*this, true}); branch_true_->prev_.remove_first_occurrence_and_reorder({*this, true});
@@ -124,7 +124,7 @@ void MFBranchInstruction::set_branch_true(MFInstruction *instruction)
branch_true_ = instruction; branch_true_ = instruction;
} }
void MFBranchInstruction::set_branch_false(MFInstruction *instruction) void BranchInstruction::set_branch_false(Instruction *instruction)
{ {
if (branch_false_ != nullptr) { if (branch_false_ != nullptr) {
branch_false_->prev_.remove_first_occurrence_and_reorder({*this, false}); branch_false_->prev_.remove_first_occurrence_and_reorder({*this, false});
@@ -135,7 +135,7 @@ void MFBranchInstruction::set_branch_false(MFInstruction *instruction)
branch_false_ = instruction; branch_false_ = instruction;
} }
void MFDestructInstruction::set_variable(MFVariable *variable) void DestructInstruction::set_variable(Variable *variable)
{ {
if (variable_ != nullptr) { if (variable_ != nullptr) {
variable_->users_.remove_first_occurrence_and_reorder(this); variable_->users_.remove_first_occurrence_and_reorder(this);
@@ -146,7 +146,7 @@ void MFDestructInstruction::set_variable(MFVariable *variable)
variable_ = variable; variable_ = variable;
} }
void MFDestructInstruction::set_next(MFInstruction *instruction) void DestructInstruction::set_next(Instruction *instruction)
{ {
if (next_ != nullptr) { if (next_ != nullptr) {
next_->prev_.remove_first_occurrence_and_reorder(*this); next_->prev_.remove_first_occurrence_and_reorder(*this);
@@ -157,7 +157,7 @@ void MFDestructInstruction::set_next(MFInstruction *instruction)
next_ = instruction; next_ = instruction;
} }
void MFDummyInstruction::set_next(MFInstruction *instruction) void DummyInstruction::set_next(Instruction *instruction)
{ {
if (next_ != nullptr) { if (next_ != nullptr) {
next_->prev_.remove_first_occurrence_and_reorder(*this); next_->prev_.remove_first_occurrence_and_reorder(*this);
@@ -168,9 +168,9 @@ void MFDummyInstruction::set_next(MFInstruction *instruction)
next_ = instruction; next_ = instruction;
} }
MFVariable &MFProcedure::new_variable(MFDataType data_type, std::string name) Variable &Procedure::new_variable(DataType data_type, std::string name)
{ {
MFVariable &variable = *allocator_.construct<MFVariable>().release(); Variable &variable = *allocator_.construct<Variable>().release();
variable.name_ = std::move(name); variable.name_ = std::move(name);
variable.data_type_ = data_type; variable.data_type_ = data_type;
variable.index_in_graph_ = variables_.size(); variable.index_in_graph_ = variables_.size();
@@ -178,86 +178,86 @@ MFVariable &MFProcedure::new_variable(MFDataType data_type, std::string name)
return variable; return variable;
} }
MFCallInstruction &MFProcedure::new_call_instruction(const MultiFunction &fn) CallInstruction &Procedure::new_call_instruction(const MultiFunction &fn)
{ {
MFCallInstruction &instruction = *allocator_.construct<MFCallInstruction>().release(); CallInstruction &instruction = *allocator_.construct<CallInstruction>().release();
instruction.type_ = MFInstructionType::Call; instruction.type_ = InstructionType::Call;
instruction.fn_ = &fn; instruction.fn_ = &fn;
instruction.params_ = allocator_.allocate_array<MFVariable *>(fn.param_amount()); instruction.params_ = allocator_.allocate_array<Variable *>(fn.param_amount());
instruction.params_.fill(nullptr); instruction.params_.fill(nullptr);
call_instructions_.append(&instruction); call_instructions_.append(&instruction);
return instruction; return instruction;
} }
MFBranchInstruction &MFProcedure::new_branch_instruction() BranchInstruction &Procedure::new_branch_instruction()
{ {
MFBranchInstruction &instruction = *allocator_.construct<MFBranchInstruction>().release(); BranchInstruction &instruction = *allocator_.construct<BranchInstruction>().release();
instruction.type_ = MFInstructionType::Branch; instruction.type_ = InstructionType::Branch;
branch_instructions_.append(&instruction); branch_instructions_.append(&instruction);
return instruction; return instruction;
} }
MFDestructInstruction &MFProcedure::new_destruct_instruction() DestructInstruction &Procedure::new_destruct_instruction()
{ {
MFDestructInstruction &instruction = *allocator_.construct<MFDestructInstruction>().release(); DestructInstruction &instruction = *allocator_.construct<DestructInstruction>().release();
instruction.type_ = MFInstructionType::Destruct; instruction.type_ = InstructionType::Destruct;
destruct_instructions_.append(&instruction); destruct_instructions_.append(&instruction);
return instruction; return instruction;
} }
MFDummyInstruction &MFProcedure::new_dummy_instruction() DummyInstruction &Procedure::new_dummy_instruction()
{ {
MFDummyInstruction &instruction = *allocator_.construct<MFDummyInstruction>().release(); DummyInstruction &instruction = *allocator_.construct<DummyInstruction>().release();
instruction.type_ = MFInstructionType::Dummy; instruction.type_ = InstructionType::Dummy;
dummy_instructions_.append(&instruction); dummy_instructions_.append(&instruction);
return instruction; return instruction;
} }
MFReturnInstruction &MFProcedure::new_return_instruction() ReturnInstruction &Procedure::new_return_instruction()
{ {
MFReturnInstruction &instruction = *allocator_.construct<MFReturnInstruction>().release(); ReturnInstruction &instruction = *allocator_.construct<ReturnInstruction>().release();
instruction.type_ = MFInstructionType::Return; instruction.type_ = InstructionType::Return;
return_instructions_.append(&instruction); return_instructions_.append(&instruction);
return instruction; return instruction;
} }
void MFProcedure::add_parameter(MFParamType::InterfaceType interface_type, MFVariable &variable) void Procedure::add_parameter(ParamType::InterfaceType interface_type, Variable &variable)
{ {
params_.append({interface_type, &variable}); params_.append({interface_type, &variable});
} }
void MFProcedure::set_entry(MFInstruction &entry) void Procedure::set_entry(Instruction &entry)
{ {
if (entry_ != nullptr) { if (entry_ != nullptr) {
entry_->prev_.remove_first_occurrence_and_reorder(MFInstructionCursor::ForEntry()); entry_->prev_.remove_first_occurrence_and_reorder(InstructionCursor::ForEntry());
} }
entry_ = &entry; entry_ = &entry;
entry_->prev_.append(MFInstructionCursor::ForEntry()); entry_->prev_.append(InstructionCursor::ForEntry());
} }
MFProcedure::~MFProcedure() Procedure::~Procedure()
{ {
for (MFCallInstruction *instruction : call_instructions_) { for (CallInstruction *instruction : call_instructions_) {
instruction->~MFCallInstruction(); instruction->~CallInstruction();
} }
for (MFBranchInstruction *instruction : branch_instructions_) { for (BranchInstruction *instruction : branch_instructions_) {
instruction->~MFBranchInstruction(); instruction->~BranchInstruction();
} }
for (MFDestructInstruction *instruction : destruct_instructions_) { for (DestructInstruction *instruction : destruct_instructions_) {
instruction->~MFDestructInstruction(); instruction->~DestructInstruction();
} }
for (MFDummyInstruction *instruction : dummy_instructions_) { for (DummyInstruction *instruction : dummy_instructions_) {
instruction->~MFDummyInstruction(); instruction->~DummyInstruction();
} }
for (MFReturnInstruction *instruction : return_instructions_) { for (ReturnInstruction *instruction : return_instructions_) {
instruction->~MFReturnInstruction(); instruction->~ReturnInstruction();
} }
for (MFVariable *variable : variables_) { for (Variable *variable : variables_) {
variable->~MFVariable(); variable->~Variable();
} }
} }
bool MFProcedure::validate() const bool Procedure::validate() const
{ {
if (entry_ == nullptr) { if (entry_ == nullptr) {
return false; return false;
@@ -280,19 +280,19 @@ bool MFProcedure::validate() const
return true; return true;
} }
bool MFProcedure::validate_all_instruction_pointers_set() const bool Procedure::validate_all_instruction_pointers_set() const
{ {
for (const MFCallInstruction *instruction : call_instructions_) { for (const CallInstruction *instruction : call_instructions_) {
if (instruction->next_ == nullptr) { if (instruction->next_ == nullptr) {
return false; return false;
} }
} }
for (const MFDestructInstruction *instruction : destruct_instructions_) { for (const DestructInstruction *instruction : destruct_instructions_) {
if (instruction->next_ == nullptr) { if (instruction->next_ == nullptr) {
return false; return false;
} }
} }
for (const MFBranchInstruction *instruction : branch_instructions_) { for (const BranchInstruction *instruction : branch_instructions_) {
if (instruction->branch_true_ == nullptr) { if (instruction->branch_true_ == nullptr) {
return false; return false;
} }
@@ -300,7 +300,7 @@ bool MFProcedure::validate_all_instruction_pointers_set() const
return false; return false;
} }
} }
for (const MFDummyInstruction *instruction : dummy_instructions_) { for (const DummyInstruction *instruction : dummy_instructions_) {
if (instruction->next_ == nullptr) { if (instruction->next_ == nullptr) {
return false; return false;
} }
@@ -308,28 +308,28 @@ bool MFProcedure::validate_all_instruction_pointers_set() const
return true; return true;
} }
bool MFProcedure::validate_all_params_provided() const bool Procedure::validate_all_params_provided() const
{ {
for (const MFCallInstruction *instruction : call_instructions_) { for (const CallInstruction *instruction : call_instructions_) {
const MultiFunction &fn = instruction->fn(); const MultiFunction &fn = instruction->fn();
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
if (param_type.category() == MFParamCategory::SingleOutput) { if (param_type.category() == ParamCategory::SingleOutput) {
/* Single outputs are optional. */ /* Single outputs are optional. */
continue; continue;
} }
const MFVariable *variable = instruction->params_[param_index]; const Variable *variable = instruction->params_[param_index];
if (variable == nullptr) { if (variable == nullptr) {
return false; return false;
} }
} }
} }
for (const MFBranchInstruction *instruction : branch_instructions_) { for (const BranchInstruction *instruction : branch_instructions_) {
if (instruction->condition_ == nullptr) { if (instruction->condition_ == nullptr) {
return false; return false;
} }
} }
for (const MFDestructInstruction *instruction : destruct_instructions_) { for (const DestructInstruction *instruction : destruct_instructions_) {
if (instruction->variable_ == nullptr) { if (instruction->variable_ == nullptr) {
return false; return false;
} }
@@ -337,13 +337,13 @@ bool MFProcedure::validate_all_params_provided() const
return true; return true;
} }
bool MFProcedure::validate_same_variables_in_one_call() const bool Procedure::validate_same_variables_in_one_call() const
{ {
for (const MFCallInstruction *instruction : call_instructions_) { for (const CallInstruction *instruction : call_instructions_) {
const MultiFunction &fn = *instruction->fn_; const MultiFunction &fn = *instruction->fn_;
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
const MFVariable *variable = instruction->params_[param_index]; const Variable *variable = instruction->params_[param_index];
if (variable == nullptr) { if (variable == nullptr) {
continue; continue;
} }
@@ -351,17 +351,17 @@ bool MFProcedure::validate_same_variables_in_one_call() const
if (other_param_index == param_index) { if (other_param_index == param_index) {
continue; continue;
} }
const MFVariable *other_variable = instruction->params_[other_param_index]; const Variable *other_variable = instruction->params_[other_param_index];
if (other_variable != variable) { if (other_variable != variable) {
continue; continue;
} }
if (ELEM(param_type.interface_type(), MFParamType::Mutable, MFParamType::Output)) { if (ELEM(param_type.interface_type(), ParamType::Mutable, ParamType::Output)) {
/* When a variable is used as mutable or output parameter, it can only be used once. */ /* When a variable is used as mutable or output parameter, it can only be used once. */
return false; return false;
} }
const MFParamType other_param_type = fn.param_type(other_param_index); const ParamType other_param_type = fn.param_type(other_param_index);
/* A variable is allowed to be used as input more than once. */ /* A variable is allowed to be used as input more than once. */
if (other_param_type.interface_type() != MFParamType::Input) { if (other_param_type.interface_type() != ParamType::Input) {
return false; return false;
} }
} }
@@ -370,9 +370,9 @@ bool MFProcedure::validate_same_variables_in_one_call() const
return true; return true;
} }
bool MFProcedure::validate_parameters() const bool Procedure::validate_parameters() const
{ {
Set<const MFVariable *> variables; Set<const Variable *> variables;
for (const MFParameter &param : params_) { for (const MFParameter &param : params_) {
/* One variable cannot be used as multiple parameters. */ /* One variable cannot be used as multiple parameters. */
if (!variables.add(param.variable)) { if (!variables.add(param.variable)) {
@@ -382,45 +382,45 @@ bool MFProcedure::validate_parameters() const
return true; return true;
} }
bool MFProcedure::validate_initialization() const bool Procedure::validate_initialization() const
{ {
/* TODO: Issue warning when it maybe wrongly initialized. */ /* TODO: Issue warning when it maybe wrongly initialized. */
for (const MFDestructInstruction *instruction : destruct_instructions_) { for (const DestructInstruction *instruction : destruct_instructions_) {
const MFVariable &variable = *instruction->variable_; const Variable &variable = *instruction->variable_;
const InitState state = this->find_initialization_state_before_instruction(*instruction, const InitState state = this->find_initialization_state_before_instruction(*instruction,
variable); variable);
if (!state.can_be_initialized) { if (!state.can_be_initialized) {
return false; return false;
} }
} }
for (const MFBranchInstruction *instruction : branch_instructions_) { for (const BranchInstruction *instruction : branch_instructions_) {
const MFVariable &variable = *instruction->condition_; const Variable &variable = *instruction->condition_;
const InitState state = this->find_initialization_state_before_instruction(*instruction, const InitState state = this->find_initialization_state_before_instruction(*instruction,
variable); variable);
if (!state.can_be_initialized) { if (!state.can_be_initialized) {
return false; return false;
} }
} }
for (const MFCallInstruction *instruction : call_instructions_) { for (const CallInstruction *instruction : call_instructions_) {
const MultiFunction &fn = *instruction->fn_; const MultiFunction &fn = *instruction->fn_;
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
/* If the parameter was an unneeded output, it could be null. */ /* If the parameter was an unneeded output, it could be null. */
if (!instruction->params_[param_index]) { if (!instruction->params_[param_index]) {
continue; continue;
} }
const MFVariable &variable = *instruction->params_[param_index]; const Variable &variable = *instruction->params_[param_index];
const InitState state = this->find_initialization_state_before_instruction(*instruction, const InitState state = this->find_initialization_state_before_instruction(*instruction,
variable); variable);
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: case ParamType::Input:
case MFParamType::Mutable: { case ParamType::Mutable: {
if (!state.can_be_initialized) { if (!state.can_be_initialized) {
return false; return false;
} }
break; break;
} }
case MFParamType::Output: { case ParamType::Output: {
if (!state.can_be_uninitialized) { if (!state.can_be_uninitialized) {
return false; return false;
} }
@@ -429,14 +429,14 @@ bool MFProcedure::validate_initialization() const
} }
} }
} }
Set<const MFVariable *> variables_that_should_be_initialized_on_return; Set<const Variable *> variables_that_should_be_initialized_on_return;
for (const MFParameter &param : params_) { for (const MFParameter &param : params_) {
if (ELEM(param.type, MFParamType::Mutable, MFParamType::Output)) { if (ELEM(param.type, ParamType::Mutable, ParamType::Output)) {
variables_that_should_be_initialized_on_return.add_new(param.variable); variables_that_should_be_initialized_on_return.add_new(param.variable);
} }
} }
for (const MFReturnInstruction *instruction : return_instructions_) { for (const ReturnInstruction *instruction : return_instructions_) {
for (const MFVariable *variable : variables_) { for (const Variable *variable : variables_) {
const InitState init_state = this->find_initialization_state_before_instruction(*instruction, const InitState init_state = this->find_initialization_state_before_instruction(*instruction,
*variable); *variable);
if (variables_that_should_be_initialized_on_return.contains(variable)) { if (variables_that_should_be_initialized_on_return.contains(variable)) {
@@ -454,8 +454,8 @@ bool MFProcedure::validate_initialization() const
return true; return true;
} }
MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction( Procedure::InitState Procedure::find_initialization_state_before_instruction(
const MFInstruction &target_instruction, const MFVariable &target_variable) const const Instruction &target_instruction, const Variable &target_variable) const
{ {
InitState state; InitState state;
@@ -463,7 +463,7 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
bool caller_initialized_variable = false; bool caller_initialized_variable = false;
for (const MFParameter &param : params_) { for (const MFParameter &param : params_) {
if (param.variable == &target_variable) { if (param.variable == &target_variable) {
if (ELEM(param.type, MFParamType::Input, MFParamType::Mutable)) { if (ELEM(param.type, ParamType::Input, ParamType::Mutable)) {
caller_initialized_variable = true; caller_initialized_variable = true;
break; break;
} }
@@ -481,30 +481,30 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
check_entry_instruction(); check_entry_instruction();
} }
Set<const MFInstruction *> checked_instructions; Set<const Instruction *> checked_instructions;
Stack<const MFInstruction *> instructions_to_check; Stack<const Instruction *> instructions_to_check;
for (const MFInstructionCursor &cursor : target_instruction.prev_) { for (const InstructionCursor &cursor : target_instruction.prev_) {
if (cursor.instruction() != nullptr) { if (cursor.instruction() != nullptr) {
instructions_to_check.push(cursor.instruction()); instructions_to_check.push(cursor.instruction());
} }
} }
while (!instructions_to_check.is_empty()) { while (!instructions_to_check.is_empty()) {
const MFInstruction &instruction = *instructions_to_check.pop(); const Instruction &instruction = *instructions_to_check.pop();
if (!checked_instructions.add(&instruction)) { if (!checked_instructions.add(&instruction)) {
/* Skip if the instruction has been checked already. */ /* Skip if the instruction has been checked already. */
continue; continue;
} }
bool state_modified = false; bool state_modified = false;
switch (instruction.type_) { switch (instruction.type_) {
case MFInstructionType::Call: { case InstructionType::Call: {
const MFCallInstruction &call_instruction = static_cast<const MFCallInstruction &>( const CallInstruction &call_instruction = static_cast<const CallInstruction &>(
instruction); instruction);
const MultiFunction &fn = *call_instruction.fn_; const MultiFunction &fn = *call_instruction.fn_;
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
if (call_instruction.params_[param_index] == &target_variable) { if (call_instruction.params_[param_index] == &target_variable) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
if (param_type.interface_type() == MFParamType::Output) { if (param_type.interface_type() == ParamType::Output) {
state.can_be_initialized = true; state.can_be_initialized = true;
state_modified = true; state_modified = true;
break; break;
@@ -513,18 +513,18 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
} }
break; break;
} }
case MFInstructionType::Destruct: { case InstructionType::Destruct: {
const MFDestructInstruction &destruct_instruction = const DestructInstruction &destruct_instruction = static_cast<const DestructInstruction &>(
static_cast<const MFDestructInstruction &>(instruction); instruction);
if (destruct_instruction.variable_ == &target_variable) { if (destruct_instruction.variable_ == &target_variable) {
state.can_be_uninitialized = true; state.can_be_uninitialized = true;
state_modified = true; state_modified = true;
} }
break; break;
} }
case MFInstructionType::Branch: case InstructionType::Branch:
case MFInstructionType::Dummy: case InstructionType::Dummy:
case MFInstructionType::Return: { case InstructionType::Return: {
/* These instruction types don't change the initialization state of variables. */ /* These instruction types don't change the initialization state of variables. */
break; break;
} }
@@ -534,7 +534,7 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
if (&instruction == entry_) { if (&instruction == entry_) {
check_entry_instruction(); check_entry_instruction();
} }
for (const MFInstructionCursor &cursor : instruction.prev_) { for (const InstructionCursor &cursor : instruction.prev_) {
if (cursor.instruction() != nullptr) { if (cursor.instruction() != nullptr) {
instructions_to_check.push(cursor.instruction()); instructions_to_check.push(cursor.instruction());
} }
@@ -545,15 +545,15 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
return state; return state;
} }
class MFProcedureDotExport { class ProcedureDotExport {
private: private:
const MFProcedure &procedure_; const Procedure &procedure_;
dot::DirectedGraph digraph_; dot::DirectedGraph digraph_;
Map<const MFInstruction *, dot::Node *> dot_nodes_by_begin_; Map<const Instruction *, dot::Node *> dot_nodes_by_begin_;
Map<const MFInstruction *, dot::Node *> dot_nodes_by_end_; Map<const Instruction *, dot::Node *> dot_nodes_by_end_;
public: public:
MFProcedureDotExport(const MFProcedure &procedure) : procedure_(procedure) ProcedureDotExport(const Procedure &procedure) : procedure_(procedure)
{ {
} }
@@ -566,7 +566,7 @@ class MFProcedureDotExport {
void create_nodes() void create_nodes()
{ {
Vector<const MFInstruction *> all_instructions; Vector<const Instruction *> all_instructions;
auto add_instructions = [&](auto instructions) { auto add_instructions = [&](auto instructions) {
all_instructions.extend(instructions.begin(), instructions.end()); all_instructions.extend(instructions.begin(), instructions.end());
}; };
@@ -576,38 +576,38 @@ class MFProcedureDotExport {
add_instructions(procedure_.dummy_instructions_); add_instructions(procedure_.dummy_instructions_);
add_instructions(procedure_.return_instructions_); add_instructions(procedure_.return_instructions_);
Set<const MFInstruction *> handled_instructions; Set<const Instruction *> handled_instructions;
for (const MFInstruction *representative : all_instructions) { for (const Instruction *representative : all_instructions) {
if (handled_instructions.contains(representative)) { if (handled_instructions.contains(representative)) {
continue; continue;
} }
Vector<const MFInstruction *> block_instructions = this->get_instructions_in_block( Vector<const Instruction *> block_instructions = this->get_instructions_in_block(
*representative); *representative);
std::stringstream ss; std::stringstream ss;
ss << "<"; ss << "<";
for (const MFInstruction *current : block_instructions) { for (const Instruction *current : block_instructions) {
handled_instructions.add_new(current); handled_instructions.add_new(current);
switch (current->type()) { switch (current->type()) {
case MFInstructionType::Call: { case InstructionType::Call: {
this->instruction_to_string(*static_cast<const MFCallInstruction *>(current), ss); this->instruction_to_string(*static_cast<const CallInstruction *>(current), ss);
break; break;
} }
case MFInstructionType::Destruct: { case InstructionType::Destruct: {
this->instruction_to_string(*static_cast<const MFDestructInstruction *>(current), ss); this->instruction_to_string(*static_cast<const DestructInstruction *>(current), ss);
break; break;
} }
case MFInstructionType::Dummy: { case InstructionType::Dummy: {
this->instruction_to_string(*static_cast<const MFDummyInstruction *>(current), ss); this->instruction_to_string(*static_cast<const DummyInstruction *>(current), ss);
break; break;
} }
case MFInstructionType::Return: { case InstructionType::Return: {
this->instruction_to_string(*static_cast<const MFReturnInstruction *>(current), ss); this->instruction_to_string(*static_cast<const ReturnInstruction *>(current), ss);
break; break;
} }
case MFInstructionType::Branch: { case InstructionType::Branch: {
this->instruction_to_string(*static_cast<const MFBranchInstruction *>(current), ss); this->instruction_to_string(*static_cast<const BranchInstruction *>(current), ss);
break; break;
} }
} }
@@ -625,7 +625,7 @@ class MFProcedureDotExport {
void create_edges() void create_edges()
{ {
auto create_edge = [&](dot::Node &from_node, auto create_edge = [&](dot::Node &from_node,
const MFInstruction *to_instruction) -> dot::DirectedEdge & { const Instruction *to_instruction) -> dot::DirectedEdge & {
if (to_instruction == nullptr) { if (to_instruction == nullptr) {
dot::Node &to_node = digraph_.new_node("missing"); dot::Node &to_node = digraph_.new_node("missing");
to_node.set_shape(dot::Attr_shape::Diamond); to_node.set_shape(dot::Attr_shape::Diamond);
@@ -636,35 +636,35 @@ class MFProcedureDotExport {
}; };
for (auto item : dot_nodes_by_end_.items()) { for (auto item : dot_nodes_by_end_.items()) {
const MFInstruction &from_instruction = *item.key; const Instruction &from_instruction = *item.key;
dot::Node &from_node = *item.value; dot::Node &from_node = *item.value;
switch (from_instruction.type()) { switch (from_instruction.type()) {
case MFInstructionType::Call: { case InstructionType::Call: {
const MFInstruction *to_instruction = const Instruction *to_instruction =
static_cast<const MFCallInstruction &>(from_instruction).next(); static_cast<const CallInstruction &>(from_instruction).next();
create_edge(from_node, to_instruction); create_edge(from_node, to_instruction);
break; break;
} }
case MFInstructionType::Destruct: { case InstructionType::Destruct: {
const MFInstruction *to_instruction = const Instruction *to_instruction =
static_cast<const MFDestructInstruction &>(from_instruction).next(); static_cast<const DestructInstruction &>(from_instruction).next();
create_edge(from_node, to_instruction); create_edge(from_node, to_instruction);
break; break;
} }
case MFInstructionType::Dummy: { case InstructionType::Dummy: {
const MFInstruction *to_instruction = const Instruction *to_instruction =
static_cast<const MFDummyInstruction &>(from_instruction).next(); static_cast<const DummyInstruction &>(from_instruction).next();
create_edge(from_node, to_instruction); create_edge(from_node, to_instruction);
break; break;
} }
case MFInstructionType::Return: { case InstructionType::Return: {
break; break;
} }
case MFInstructionType::Branch: { case InstructionType::Branch: {
const MFBranchInstruction &branch_instruction = static_cast<const MFBranchInstruction &>( const BranchInstruction &branch_instruction = static_cast<const BranchInstruction &>(
from_instruction); from_instruction);
const MFInstruction *to_true_instruction = branch_instruction.branch_true(); const Instruction *to_true_instruction = branch_instruction.branch_true();
const MFInstruction *to_false_instruction = branch_instruction.branch_false(); const Instruction *to_false_instruction = branch_instruction.branch_false();
create_edge(from_node, to_true_instruction).attributes.set("color", "#118811"); create_edge(from_node, to_true_instruction).attributes.set("color", "#118811");
create_edge(from_node, to_false_instruction).attributes.set("color", "#881111"); create_edge(from_node, to_false_instruction).attributes.set("color", "#881111");
break; break;
@@ -676,22 +676,22 @@ class MFProcedureDotExport {
create_edge(entry_node, procedure_.entry()); create_edge(entry_node, procedure_.entry());
} }
bool has_to_be_block_begin(const MFInstruction &instruction) bool has_to_be_block_begin(const Instruction &instruction)
{ {
if (instruction.prev().size() != 1) { if (instruction.prev().size() != 1) {
return true; return true;
} }
if (ELEM(instruction.prev()[0].type(), if (ELEM(instruction.prev()[0].type(),
MFInstructionCursor::Type::Branch, InstructionCursor::Type::Branch,
MFInstructionCursor::Type::Entry)) { InstructionCursor::Type::Entry)) {
return true; return true;
} }
return false; return false;
} }
const MFInstruction &get_first_instruction_in_block(const MFInstruction &representative) const Instruction &get_first_instruction_in_block(const Instruction &representative)
{ {
const MFInstruction *current = &representative; const Instruction *current = &representative;
while (!this->has_to_be_block_begin(*current)) { while (!this->has_to_be_block_begin(*current)) {
current = current->prev()[0].instruction(); current = current->prev()[0].instruction();
if (current == &representative) { if (current == &representative) {
@@ -702,25 +702,25 @@ class MFProcedureDotExport {
return *current; return *current;
} }
const MFInstruction *get_next_instruction_in_block(const MFInstruction &instruction, const Instruction *get_next_instruction_in_block(const Instruction &instruction,
const MFInstruction &block_begin) const Instruction &block_begin)
{ {
const MFInstruction *next = nullptr; const Instruction *next = nullptr;
switch (instruction.type()) { switch (instruction.type()) {
case MFInstructionType::Call: { case InstructionType::Call: {
next = static_cast<const MFCallInstruction &>(instruction).next(); next = static_cast<const CallInstruction &>(instruction).next();
break; break;
} }
case MFInstructionType::Destruct: { case InstructionType::Destruct: {
next = static_cast<const MFDestructInstruction &>(instruction).next(); next = static_cast<const DestructInstruction &>(instruction).next();
break; break;
} }
case MFInstructionType::Dummy: { case InstructionType::Dummy: {
next = static_cast<const MFDummyInstruction &>(instruction).next(); next = static_cast<const DummyInstruction &>(instruction).next();
break; break;
} }
case MFInstructionType::Return: case InstructionType::Return:
case MFInstructionType::Branch: { case InstructionType::Branch: {
break; break;
} }
} }
@@ -736,18 +736,18 @@ class MFProcedureDotExport {
return next; return next;
} }
Vector<const MFInstruction *> get_instructions_in_block(const MFInstruction &representative) Vector<const Instruction *> get_instructions_in_block(const Instruction &representative)
{ {
Vector<const MFInstruction *> instructions; Vector<const Instruction *> instructions;
const MFInstruction &begin = this->get_first_instruction_in_block(representative); const Instruction &begin = this->get_first_instruction_in_block(representative);
for (const MFInstruction *current = &begin; current != nullptr; for (const Instruction *current = &begin; current != nullptr;
current = this->get_next_instruction_in_block(*current, begin)) { current = this->get_next_instruction_in_block(*current, begin)) {
instructions.append(current); instructions.append(current);
} }
return instructions; return instructions;
} }
void variable_to_string(const MFVariable *variable, std::stringstream &ss) void variable_to_string(const Variable *variable, std::stringstream &ss)
{ {
if (variable == nullptr) { if (variable == nullptr) {
ss << "null"; ss << "null";
@@ -765,24 +765,24 @@ class MFProcedureDotExport {
ss << name; ss << name;
} }
void instruction_to_string(const MFCallInstruction &instruction, std::stringstream &ss) void instruction_to_string(const CallInstruction &instruction, std::stringstream &ss)
{ {
const MultiFunction &fn = instruction.fn(); const MultiFunction &fn = instruction.fn();
this->instruction_name_format(fn.debug_name() + ": ", ss); this->instruction_name_format(fn.debug_name() + ": ", ss);
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
const MFVariable *variable = instruction.params()[param_index]; const Variable *variable = instruction.params()[param_index];
ss << R"(<font color="grey30">)"; ss << R"(<font color="grey30">)";
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: { case ParamType::Input: {
ss << "in"; ss << "in";
break; break;
} }
case MFParamType::Mutable: { case ParamType::Mutable: {
ss << "mut"; ss << "mut";
break; break;
} }
case MFParamType::Output: { case ParamType::Output: {
ss << "out"; ss << "out";
break; break;
} }
@@ -795,24 +795,24 @@ class MFProcedureDotExport {
} }
} }
void instruction_to_string(const MFDestructInstruction &instruction, std::stringstream &ss) void instruction_to_string(const DestructInstruction &instruction, std::stringstream &ss)
{ {
instruction_name_format("Destruct ", ss); instruction_name_format("Destruct ", ss);
variable_to_string(instruction.variable(), ss); variable_to_string(instruction.variable(), ss);
} }
void instruction_to_string(const MFDummyInstruction & /*instruction*/, std::stringstream &ss) void instruction_to_string(const DummyInstruction & /*instruction*/, std::stringstream &ss)
{ {
instruction_name_format("Dummy ", ss); instruction_name_format("Dummy ", ss);
} }
void instruction_to_string(const MFReturnInstruction & /*instruction*/, std::stringstream &ss) void instruction_to_string(const ReturnInstruction & /*instruction*/, std::stringstream &ss)
{ {
instruction_name_format("Return ", ss); instruction_name_format("Return ", ss);
Vector<ConstMFParameter> outgoing_parameters; Vector<ConstMFParameter> outgoing_parameters;
for (const ConstMFParameter &param : procedure_.params()) { for (const ConstMFParameter &param : procedure_.params()) {
if (ELEM(param.type, MFParamType::Mutable, MFParamType::Output)) { if (ELEM(param.type, ParamType::Mutable, ParamType::Output)) {
outgoing_parameters.append(param); outgoing_parameters.append(param);
} }
} }
@@ -825,7 +825,7 @@ class MFProcedureDotExport {
} }
} }
void instruction_to_string(const MFBranchInstruction &instruction, std::stringstream &ss) void instruction_to_string(const BranchInstruction &instruction, std::stringstream &ss)
{ {
instruction_name_format("Branch ", ss); instruction_name_format("Branch ", ss);
variable_to_string(instruction.condition(), ss); variable_to_string(instruction.condition(), ss);
@@ -837,7 +837,7 @@ class MFProcedureDotExport {
ss << "Entry: "; ss << "Entry: ";
Vector<ConstMFParameter> incoming_parameters; Vector<ConstMFParameter> incoming_parameters;
for (const ConstMFParameter &param : procedure_.params()) { for (const ConstMFParameter &param : procedure_.params()) {
if (ELEM(param.type, MFParamType::Input, MFParamType::Mutable)) { if (ELEM(param.type, ParamType::Input, ParamType::Mutable)) {
incoming_parameters.append(param); incoming_parameters.append(param);
} }
} }
@@ -855,10 +855,10 @@ class MFProcedureDotExport {
} }
}; };
std::string MFProcedure::to_dot() const std::string Procedure::to_dot() const
{ {
MFProcedureDotExport dot_export{*this}; ProcedureDotExport dot_export{*this};
return dot_export.generate(); return dot_export.generate();
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -2,65 +2,65 @@
#include "FN_multi_function_procedure_builder.hh" #include "FN_multi_function_procedure_builder.hh"
namespace blender::fn { namespace blender::fn::multi_function {
void MFProcedureBuilder::add_destruct(MFVariable &variable) void ProcedureBuilder::add_destruct(Variable &variable)
{ {
MFDestructInstruction &instruction = procedure_->new_destruct_instruction(); DestructInstruction &instruction = procedure_->new_destruct_instruction();
instruction.set_variable(&variable); instruction.set_variable(&variable);
this->link_to_cursors(&instruction); this->link_to_cursors(&instruction);
cursors_ = {MFInstructionCursor{instruction}}; cursors_ = {InstructionCursor{instruction}};
} }
void MFProcedureBuilder::add_destruct(Span<MFVariable *> variables) void ProcedureBuilder::add_destruct(Span<Variable *> variables)
{ {
for (MFVariable *variable : variables) { for (Variable *variable : variables) {
this->add_destruct(*variable); this->add_destruct(*variable);
} }
} }
MFReturnInstruction &MFProcedureBuilder::add_return() ReturnInstruction &ProcedureBuilder::add_return()
{ {
MFReturnInstruction &instruction = procedure_->new_return_instruction(); ReturnInstruction &instruction = procedure_->new_return_instruction();
this->link_to_cursors(&instruction); this->link_to_cursors(&instruction);
cursors_ = {}; cursors_ = {};
return instruction; return instruction;
} }
MFCallInstruction &MFProcedureBuilder::add_call_with_no_variables(const MultiFunction &fn) CallInstruction &ProcedureBuilder::add_call_with_no_variables(const MultiFunction &fn)
{ {
MFCallInstruction &instruction = procedure_->new_call_instruction(fn); CallInstruction &instruction = procedure_->new_call_instruction(fn);
this->link_to_cursors(&instruction); this->link_to_cursors(&instruction);
cursors_ = {MFInstructionCursor{instruction}}; cursors_ = {InstructionCursor{instruction}};
return instruction; return instruction;
} }
MFCallInstruction &MFProcedureBuilder::add_call_with_all_variables( CallInstruction &ProcedureBuilder::add_call_with_all_variables(const MultiFunction &fn,
const MultiFunction &fn, Span<MFVariable *> param_variables) Span<Variable *> param_variables)
{ {
MFCallInstruction &instruction = this->add_call_with_no_variables(fn); CallInstruction &instruction = this->add_call_with_no_variables(fn);
instruction.set_params(param_variables); instruction.set_params(param_variables);
return instruction; return instruction;
} }
Vector<MFVariable *> MFProcedureBuilder::add_call(const MultiFunction &fn, Vector<Variable *> ProcedureBuilder::add_call(const MultiFunction &fn,
Span<MFVariable *> input_and_mutable_variables) Span<Variable *> input_and_mutable_variables)
{ {
Vector<MFVariable *> output_variables; Vector<Variable *> output_variables;
MFCallInstruction &instruction = this->add_call_with_no_variables(fn); CallInstruction &instruction = this->add_call_with_no_variables(fn);
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: case ParamType::Input:
case MFParamType::Mutable: { case ParamType::Mutable: {
MFVariable *variable = input_and_mutable_variables.first(); Variable *variable = input_and_mutable_variables.first();
instruction.set_param_variable(param_index, variable); instruction.set_param_variable(param_index, variable);
input_and_mutable_variables = input_and_mutable_variables.drop_front(1); input_and_mutable_variables = input_and_mutable_variables.drop_front(1);
break; break;
} }
case MFParamType::Output: { case ParamType::Output: {
MFVariable &variable = procedure_->new_variable(param_type.data_type(), Variable &variable = procedure_->new_variable(param_type.data_type(),
fn.param_name(param_index)); fn.param_name(param_index));
instruction.set_param_variable(param_index, &variable); instruction.set_param_variable(param_index, &variable);
output_variables.append(&variable); output_variables.append(&variable);
break; break;
@@ -72,26 +72,26 @@ Vector<MFVariable *> MFProcedureBuilder::add_call(const MultiFunction &fn,
return output_variables; return output_variables;
} }
MFProcedureBuilder::Branch MFProcedureBuilder::add_branch(MFVariable &condition) ProcedureBuilder::Branch ProcedureBuilder::add_branch(Variable &condition)
{ {
MFBranchInstruction &instruction = procedure_->new_branch_instruction(); BranchInstruction &instruction = procedure_->new_branch_instruction();
instruction.set_condition(&condition); instruction.set_condition(&condition);
this->link_to_cursors(&instruction); this->link_to_cursors(&instruction);
/* Clear cursors because this builder ends here. */ /* Clear cursors because this builder ends here. */
cursors_.clear(); cursors_.clear();
Branch branch{*procedure_, *procedure_}; Branch branch{*procedure_, *procedure_};
branch.branch_true.set_cursor(MFInstructionCursor{instruction, true}); branch.branch_true.set_cursor(InstructionCursor{instruction, true});
branch.branch_false.set_cursor(MFInstructionCursor{instruction, false}); branch.branch_false.set_cursor(InstructionCursor{instruction, false});
return branch; return branch;
} }
MFProcedureBuilder::Loop MFProcedureBuilder::add_loop() ProcedureBuilder::Loop ProcedureBuilder::add_loop()
{ {
MFDummyInstruction &loop_begin = procedure_->new_dummy_instruction(); DummyInstruction &loop_begin = procedure_->new_dummy_instruction();
MFDummyInstruction &loop_end = procedure_->new_dummy_instruction(); DummyInstruction &loop_end = procedure_->new_dummy_instruction();
this->link_to_cursors(&loop_begin); this->link_to_cursors(&loop_begin);
cursors_ = {MFInstructionCursor{loop_begin}}; cursors_ = {InstructionCursor{loop_begin}};
Loop loop; Loop loop;
loop.begin = &loop_begin; loop.begin = &loop_begin;
@@ -100,18 +100,18 @@ MFProcedureBuilder::Loop MFProcedureBuilder::add_loop()
return loop; return loop;
} }
void MFProcedureBuilder::add_loop_continue(Loop &loop) void ProcedureBuilder::add_loop_continue(Loop &loop)
{ {
this->link_to_cursors(loop.begin); this->link_to_cursors(loop.begin);
/* Clear cursors because this builder ends here. */ /* Clear cursors because this builder ends here. */
cursors_.clear(); cursors_.clear();
} }
void MFProcedureBuilder::add_loop_break(Loop &loop) void ProcedureBuilder::add_loop_break(Loop &loop)
{ {
this->link_to_cursors(loop.end); this->link_to_cursors(loop.end);
/* Clear cursors because this builder ends here. */ /* Clear cursors because this builder ends here. */
cursors_.clear(); cursors_.clear();
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -4,14 +4,14 @@
#include "BLI_stack.hh" #include "BLI_stack.hh"
namespace blender::fn { namespace blender::fn::multi_function {
MFProcedureExecutor::MFProcedureExecutor(const MFProcedure &procedure) : procedure_(procedure) ProcedureExecutor::ProcedureExecutor(const Procedure &procedure) : procedure_(procedure)
{ {
MFSignatureBuilder builder("Procedure Executor", signature_); SignatureBuilder builder("Procedure Executor", signature_);
for (const ConstMFParameter &param : procedure.params()) { for (const ConstMFParameter &param : procedure.params()) {
builder.add("Parameter", MFParamType(param.type, param.variable->data_type())); builder.add("Parameter", ParamType(param.type, param.variable->data_type()));
} }
this->set_signature(&signature_); this->set_signature(&signature_);
@@ -236,7 +236,7 @@ class ValueAllocator : NonCopyable, NonMovable {
return this->obtain<VariableValue_OneVector>(*vector_array); return this->obtain<VariableValue_OneVector>(*vector_array);
} }
void release_value(VariableValue *value, const MFDataType &data_type) void release_value(VariableValue *value, const DataType &data_type)
{ {
switch (value->type) { switch (value->type) {
case ValueType::GVArray: { case ValueType::GVArray: {
@@ -317,7 +317,7 @@ class VariableState : NonCopyable, NonMovable {
/* This a non-owning pointer to either span buffer or #GVectorArray or null. */ /* This a non-owning pointer to either span buffer or #GVectorArray or null. */
void *caller_provided_storage_ = nullptr; void *caller_provided_storage_ = nullptr;
void destruct_value(ValueAllocator &value_allocator, const MFDataType &data_type) void destruct_value(ValueAllocator &value_allocator, const DataType &data_type)
{ {
value_allocator.release_value(value_, data_type); value_allocator.release_value(value_, data_type);
value_ = nullptr; value_ = nullptr;
@@ -359,7 +359,7 @@ class VariableState : NonCopyable, NonMovable {
return tot_initialized_ == 0; return tot_initialized_ == 0;
} }
void add_as_input(MFParamsBuilder &params, IndexMask mask, const MFDataType &data_type) const void add_as_input(ParamsBuilder &params, IndexMask mask, const DataType &data_type) const
{ {
/* Sanity check to make sure that enough values are initialized. */ /* Sanity check to make sure that enough values are initialized. */
BLI_assert(mask.size() <= tot_initialized_); BLI_assert(mask.size() <= tot_initialized_);
@@ -399,7 +399,7 @@ class VariableState : NonCopyable, NonMovable {
} }
void ensure_is_mutable(IndexMask full_mask, void ensure_is_mutable(IndexMask full_mask,
const MFDataType &data_type, const DataType &data_type,
ValueAllocator &value_allocator) ValueAllocator &value_allocator)
{ {
if (value_ != nullptr && ELEM(value_->type, ValueType::Span, ValueType::GVectorArray)) { if (value_ != nullptr && ELEM(value_->type, ValueType::Span, ValueType::GVectorArray)) {
@@ -409,7 +409,7 @@ class VariableState : NonCopyable, NonMovable {
const int array_size = full_mask.min_array_size(); const int array_size = full_mask.min_array_size();
switch (data_type.category()) { switch (data_type.category()) {
case MFDataType::Single: { case DataType::Single: {
const CPPType &type = data_type.single_type(); const CPPType &type = data_type.single_type();
VariableValue_Span *new_value = nullptr; VariableValue_Span *new_value = nullptr;
if (caller_provided_storage_ == nullptr) { if (caller_provided_storage_ == nullptr) {
@@ -440,7 +440,7 @@ class VariableState : NonCopyable, NonMovable {
value_ = new_value; value_ = new_value;
break; break;
} }
case MFDataType::Vector: { case DataType::Vector: {
const CPPType &type = data_type.vector_base_type(); const CPPType &type = data_type.vector_base_type();
VariableValue_GVectorArray *new_value = nullptr; VariableValue_GVectorArray *new_value = nullptr;
if (caller_provided_storage_ == nullptr) { if (caller_provided_storage_ == nullptr) {
@@ -471,10 +471,10 @@ class VariableState : NonCopyable, NonMovable {
} }
} }
void add_as_mutable(MFParamsBuilder &params, void add_as_mutable(ParamsBuilder &params,
IndexMask mask, IndexMask mask,
IndexMask full_mask, IndexMask full_mask,
const MFDataType &data_type, const DataType &data_type,
ValueAllocator &value_allocator) ValueAllocator &value_allocator)
{ {
/* Sanity check to make sure that enough values are initialized. */ /* Sanity check to make sure that enough values are initialized. */
@@ -504,10 +504,10 @@ class VariableState : NonCopyable, NonMovable {
} }
} }
void add_as_output(MFParamsBuilder &params, void add_as_output(ParamsBuilder &params,
IndexMask mask, IndexMask mask,
IndexMask full_mask, IndexMask full_mask,
const MFDataType &data_type, const DataType &data_type,
ValueAllocator &value_allocator) ValueAllocator &value_allocator)
{ {
/* Sanity check to make sure that enough values are not initialized. */ /* Sanity check to make sure that enough values are not initialized. */
@@ -538,7 +538,7 @@ class VariableState : NonCopyable, NonMovable {
tot_initialized_ += mask.size(); tot_initialized_ += mask.size();
} }
void add_as_input__one(MFParamsBuilder &params, const MFDataType &data_type) const void add_as_input__one(ParamsBuilder &params, const DataType &data_type) const
{ {
BLI_assert(this->is_one()); BLI_assert(this->is_one());
BLI_assert(value_ != nullptr); BLI_assert(value_ != nullptr);
@@ -571,7 +571,7 @@ class VariableState : NonCopyable, NonMovable {
} }
} }
void ensure_is_mutable__one(const MFDataType &data_type, ValueAllocator &value_allocator) void ensure_is_mutable__one(const DataType &data_type, ValueAllocator &value_allocator)
{ {
BLI_assert(this->is_one()); BLI_assert(this->is_one());
if (value_ != nullptr && ELEM(value_->type, ValueType::OneSingle, ValueType::OneVector)) { if (value_ != nullptr && ELEM(value_->type, ValueType::OneSingle, ValueType::OneVector)) {
@@ -579,7 +579,7 @@ class VariableState : NonCopyable, NonMovable {
} }
switch (data_type.category()) { switch (data_type.category()) {
case MFDataType::Single: { case DataType::Single: {
const CPPType &type = data_type.single_type(); const CPPType &type = data_type.single_type();
VariableValue_OneSingle *new_value = value_allocator.obtain_OneSingle(type); VariableValue_OneSingle *new_value = value_allocator.obtain_OneSingle(type);
if (value_ != nullptr) { if (value_ != nullptr) {
@@ -600,7 +600,7 @@ class VariableState : NonCopyable, NonMovable {
value_ = new_value; value_ = new_value;
break; break;
} }
case MFDataType::Vector: { case DataType::Vector: {
const CPPType &type = data_type.vector_base_type(); const CPPType &type = data_type.vector_base_type();
VariableValue_OneVector *new_value = value_allocator.obtain_OneVector(type); VariableValue_OneVector *new_value = value_allocator.obtain_OneVector(type);
if (value_ != nullptr) { if (value_ != nullptr) {
@@ -624,8 +624,8 @@ class VariableState : NonCopyable, NonMovable {
} }
} }
void add_as_mutable__one(MFParamsBuilder &params, void add_as_mutable__one(ParamsBuilder &params,
const MFDataType &data_type, const DataType &data_type,
ValueAllocator &value_allocator) ValueAllocator &value_allocator)
{ {
BLI_assert(this->is_one()); BLI_assert(this->is_one());
@@ -653,9 +653,9 @@ class VariableState : NonCopyable, NonMovable {
} }
} }
void add_as_output__one(MFParamsBuilder &params, void add_as_output__one(ParamsBuilder &params,
IndexMask mask, IndexMask mask,
const MFDataType &data_type, const DataType &data_type,
ValueAllocator &value_allocator) ValueAllocator &value_allocator)
{ {
BLI_assert(this->is_one()); BLI_assert(this->is_one());
@@ -697,7 +697,7 @@ class VariableState : NonCopyable, NonMovable {
*/ */
bool destruct(IndexMask mask, bool destruct(IndexMask mask,
IndexMask full_mask, IndexMask full_mask,
const MFDataType &data_type, const DataType &data_type,
ValueAllocator &value_allocator) ValueAllocator &value_allocator)
{ {
BLI_assert(value_ != nullptr); BLI_assert(value_ != nullptr);
@@ -822,14 +822,14 @@ class VariableState : NonCopyable, NonMovable {
class VariableStates { class VariableStates {
private: private:
ValueAllocator value_allocator_; ValueAllocator value_allocator_;
const MFProcedure &procedure_; const Procedure &procedure_;
/** The state of every variable, indexed by #MFVariable::index_in_procedure(). */ /** The state of every variable, indexed by #Variable::index_in_procedure(). */
Array<VariableState> variable_states_; Array<VariableState> variable_states_;
IndexMask full_mask_; IndexMask full_mask_;
public: public:
VariableStates(LinearAllocator<> &linear_allocator, VariableStates(LinearAllocator<> &linear_allocator,
const MFProcedure &procedure, const Procedure &procedure,
IndexMask full_mask) IndexMask full_mask)
: value_allocator_(linear_allocator), : value_allocator_(linear_allocator),
procedure_(procedure), procedure_(procedure),
@@ -843,7 +843,7 @@ class VariableStates {
for (const int variable_i : procedure_.variables().index_range()) { for (const int variable_i : procedure_.variables().index_range()) {
VariableState &state = variable_states_[variable_i]; VariableState &state = variable_states_[variable_i];
if (state.value_ != nullptr) { if (state.value_ != nullptr) {
const MFVariable *variable = procedure_.variables()[variable_i]; const Variable *variable = procedure_.variables()[variable_i];
state.destruct_value(value_allocator_, variable->data_type()); state.destruct_value(value_allocator_, variable->data_type());
} }
} }
@@ -859,13 +859,13 @@ class VariableStates {
return full_mask_; return full_mask_;
} }
void add_initial_variable_states(const MFProcedureExecutor &fn, void add_initial_variable_states(const ProcedureExecutor &fn,
const MFProcedure &procedure, const Procedure &procedure,
MFParams &params) MFParams &params)
{ {
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
MFParamType param_type = fn.param_type(param_index); ParamType param_type = fn.param_type(param_index);
const MFVariable *variable = procedure.params()[param_index].variable; const Variable *variable = procedure.params()[param_index].variable;
auto add_state = [&](VariableValue *value, auto add_state = [&](VariableValue *value,
bool input_is_initialized, bool input_is_initialized,
@@ -880,32 +880,32 @@ class VariableStates {
}; };
switch (param_type.category()) { switch (param_type.category()) {
case MFParamCategory::SingleInput: { case ParamCategory::SingleInput: {
const GVArray &data = params.readonly_single_input(param_index); const GVArray &data = params.readonly_single_input(param_index);
add_state(value_allocator_.obtain_GVArray(data), true); add_state(value_allocator_.obtain_GVArray(data), true);
break; break;
} }
case MFParamCategory::VectorInput: { case ParamCategory::VectorInput: {
const GVVectorArray &data = params.readonly_vector_input(param_index); const GVVectorArray &data = params.readonly_vector_input(param_index);
add_state(value_allocator_.obtain_GVVectorArray(data), true); add_state(value_allocator_.obtain_GVVectorArray(data), true);
break; break;
} }
case MFParamCategory::SingleOutput: { case ParamCategory::SingleOutput: {
GMutableSpan data = params.uninitialized_single_output(param_index); GMutableSpan data = params.uninitialized_single_output(param_index);
add_state(value_allocator_.obtain_Span_not_owned(data.data()), false, data.data()); add_state(value_allocator_.obtain_Span_not_owned(data.data()), false, data.data());
break; break;
} }
case MFParamCategory::VectorOutput: { case ParamCategory::VectorOutput: {
GVectorArray &data = params.vector_output(param_index); GVectorArray &data = params.vector_output(param_index);
add_state(value_allocator_.obtain_GVectorArray_not_owned(data), false, &data); add_state(value_allocator_.obtain_GVectorArray_not_owned(data), false, &data);
break; break;
} }
case MFParamCategory::SingleMutable: { case ParamCategory::SingleMutable: {
GMutableSpan data = params.single_mutable(param_index); GMutableSpan data = params.single_mutable(param_index);
add_state(value_allocator_.obtain_Span_not_owned(data.data()), true, data.data()); add_state(value_allocator_.obtain_Span_not_owned(data.data()), true, data.data());
break; break;
} }
case MFParamCategory::VectorMutable: { case ParamCategory::VectorMutable: {
GVectorArray &data = params.vector_mutable(param_index); GVectorArray &data = params.vector_mutable(param_index);
add_state(value_allocator_.obtain_GVectorArray_not_owned(data), true, &data); add_state(value_allocator_.obtain_GVectorArray_not_owned(data), true, &data);
break; break;
@@ -915,21 +915,21 @@ class VariableStates {
} }
void add_as_param(VariableState &variable_state, void add_as_param(VariableState &variable_state,
MFParamsBuilder &params, ParamsBuilder &params,
const MFParamType &param_type, const ParamType &param_type,
const IndexMask &mask) const IndexMask &mask)
{ {
const MFDataType data_type = param_type.data_type(); const DataType data_type = param_type.data_type();
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: { case ParamType::Input: {
variable_state.add_as_input(params, mask, data_type); variable_state.add_as_input(params, mask, data_type);
break; break;
} }
case MFParamType::Mutable: { case ParamType::Mutable: {
variable_state.add_as_mutable(params, mask, full_mask_, data_type, value_allocator_); variable_state.add_as_mutable(params, mask, full_mask_, data_type, value_allocator_);
break; break;
} }
case MFParamType::Output: { case ParamType::Output: {
variable_state.add_as_output(params, mask, full_mask_, data_type, value_allocator_); variable_state.add_as_output(params, mask, full_mask_, data_type, value_allocator_);
break; break;
} }
@@ -937,28 +937,28 @@ class VariableStates {
} }
void add_as_param__one(VariableState &variable_state, void add_as_param__one(VariableState &variable_state,
MFParamsBuilder &params, ParamsBuilder &params,
const MFParamType &param_type, const ParamType &param_type,
const IndexMask &mask) const IndexMask &mask)
{ {
const MFDataType data_type = param_type.data_type(); const DataType data_type = param_type.data_type();
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: { case ParamType::Input: {
variable_state.add_as_input__one(params, data_type); variable_state.add_as_input__one(params, data_type);
break; break;
} }
case MFParamType::Mutable: { case ParamType::Mutable: {
variable_state.add_as_mutable__one(params, data_type, value_allocator_); variable_state.add_as_mutable__one(params, data_type, value_allocator_);
break; break;
} }
case MFParamType::Output: { case ParamType::Output: {
variable_state.add_as_output__one(params, mask, data_type, value_allocator_); variable_state.add_as_output__one(params, mask, data_type, value_allocator_);
break; break;
} }
} }
} }
void destruct(const MFVariable &variable, const IndexMask &mask) void destruct(const Variable &variable, const IndexMask &mask)
{ {
VariableState &variable_state = this->get_variable_state(variable); VariableState &variable_state = this->get_variable_state(variable);
if (variable_state.destruct(mask, full_mask_, variable.data_type(), value_allocator_)) { if (variable_state.destruct(mask, full_mask_, variable.data_type(), value_allocator_)) {
@@ -966,7 +966,7 @@ class VariableStates {
} }
} }
VariableState &get_variable_state(const MFVariable &variable) VariableState &get_variable_state(const Variable &variable)
{ {
const int variable_i = variable.index_in_procedure(); const int variable_i = variable.index_in_procedure();
VariableState &variable_state = variable_states_[variable_i]; VariableState &variable_state = variable_states_[variable_i];
@@ -990,12 +990,12 @@ static bool evaluate_as_one(Span<VariableState *> param_variable_states,
} }
static void gather_parameter_variable_states(const MultiFunction &fn, static void gather_parameter_variable_states(const MultiFunction &fn,
const MFCallInstruction &instruction, const CallInstruction &instruction,
VariableStates &variable_states, VariableStates &variable_states,
MutableSpan<VariableState *> r_param_variable_states) MutableSpan<VariableState *> r_param_variable_states)
{ {
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFVariable *variable = instruction.params()[param_index]; const Variable *variable = instruction.params()[param_index];
if (variable == nullptr) { if (variable == nullptr) {
r_param_variable_states[param_index] = nullptr; r_param_variable_states[param_index] = nullptr;
} }
@@ -1008,12 +1008,12 @@ static void gather_parameter_variable_states(const MultiFunction &fn,
static void fill_params__one(const MultiFunction &fn, static void fill_params__one(const MultiFunction &fn,
const IndexMask mask, const IndexMask mask,
MFParamsBuilder &params, ParamsBuilder &params,
VariableStates &variable_states, VariableStates &variable_states,
const Span<VariableState *> param_variable_states) const Span<VariableState *> param_variable_states)
{ {
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
VariableState *variable_state = param_variable_states[param_index]; VariableState *variable_state = param_variable_states[param_index];
if (variable_state == nullptr) { if (variable_state == nullptr) {
params.add_ignored_single_output(); params.add_ignored_single_output();
@@ -1026,12 +1026,12 @@ static void fill_params__one(const MultiFunction &fn,
static void fill_params(const MultiFunction &fn, static void fill_params(const MultiFunction &fn,
const IndexMask mask, const IndexMask mask,
MFParamsBuilder &params, ParamsBuilder &params,
VariableStates &variable_states, VariableStates &variable_states,
const Span<VariableState *> param_variable_states) const Span<VariableState *> param_variable_states)
{ {
for (const int param_index : fn.param_indices()) { for (const int param_index : fn.param_indices()) {
const MFParamType param_type = fn.param_type(param_index); const ParamType param_type = fn.param_type(param_index);
VariableState *variable_state = param_variable_states[param_index]; VariableState *variable_state = param_variable_states[param_index];
if (variable_state == nullptr) { if (variable_state == nullptr) {
params.add_ignored_single_output(); params.add_ignored_single_output();
@@ -1042,10 +1042,10 @@ static void fill_params(const MultiFunction &fn,
} }
} }
static void execute_call_instruction(const MFCallInstruction &instruction, static void execute_call_instruction(const CallInstruction &instruction,
const IndexMask mask, const IndexMask mask,
VariableStates &variable_states, VariableStates &variable_states,
const MFContext &context) const Context &context)
{ {
const MultiFunction &fn = instruction.fn(); const MultiFunction &fn = instruction.fn();
@@ -1056,7 +1056,7 @@ static void execute_call_instruction(const MFCallInstruction &instruction,
/* If all inputs to the function are constant, it's enough to call the function only once instead /* If all inputs to the function are constant, it's enough to call the function only once instead
* of for every index. */ * of for every index. */
if (evaluate_as_one(param_variable_states, mask, variable_states.full_mask())) { if (evaluate_as_one(param_variable_states, mask, variable_states.full_mask())) {
MFParamsBuilder params(fn, 1); ParamsBuilder params(fn, 1);
fill_params__one(fn, mask, params, variable_states, param_variable_states); fill_params__one(fn, mask, params, variable_states, param_variable_states);
try { try {
@@ -1068,7 +1068,7 @@ static void execute_call_instruction(const MFCallInstruction &instruction,
} }
} }
else { else {
MFParamsBuilder params(fn, &mask); ParamsBuilder params(fn, &mask);
fill_params(fn, mask, params, variable_states, param_variable_states); fill_params(fn, mask, params, variable_states, param_variable_states);
try { try {
@@ -1098,7 +1098,7 @@ struct InstructionIndices {
/** Contains information about the next instruction that should be executed. */ /** Contains information about the next instruction that should be executed. */
struct NextInstructionInfo { struct NextInstructionInfo {
const MFInstruction *instruction = nullptr; const Instruction *instruction = nullptr;
InstructionIndices indices; InstructionIndices indices;
IndexMask mask() const IndexMask mask() const
@@ -1123,7 +1123,7 @@ class InstructionScheduler {
public: public:
InstructionScheduler() = default; InstructionScheduler() = default;
void add_referenced_indices(const MFInstruction &instruction, IndexMask mask) void add_referenced_indices(const Instruction &instruction, IndexMask mask)
{ {
if (mask.is_empty()) { if (mask.is_empty()) {
return; return;
@@ -1134,7 +1134,7 @@ class InstructionScheduler {
next_instructions_.push({&instruction, std::move(new_indices)}); next_instructions_.push({&instruction, std::move(new_indices)});
} }
void add_owned_indices(const MFInstruction &instruction, Vector<int64_t> indices) void add_owned_indices(const Instruction &instruction, Vector<int64_t> indices)
{ {
if (indices.is_empty()) { if (indices.is_empty()) {
return; return;
@@ -1158,7 +1158,7 @@ class InstructionScheduler {
return next_instructions_.peek(); return next_instructions_.peek();
} }
void update_instruction_pointer(const MFInstruction &instruction) void update_instruction_pointer(const Instruction &instruction)
{ {
next_instructions_.peek().instruction = &instruction; next_instructions_.peek().instruction = &instruction;
} }
@@ -1169,7 +1169,7 @@ class InstructionScheduler {
} }
}; };
void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext context) const void ProcedureExecutor::call(IndexMask full_mask, MFParams params, Context context) const
{ {
BLI_assert(procedure_.validate()); BLI_assert(procedure_.validate());
@@ -1186,19 +1186,19 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
/* Loop until all indices got to a return instruction. */ /* Loop until all indices got to a return instruction. */
while (!scheduler.is_done()) { while (!scheduler.is_done()) {
const NextInstructionInfo &instr_info = scheduler.peek(); const NextInstructionInfo &instr_info = scheduler.peek();
const MFInstruction &instruction = *instr_info.instruction; const Instruction &instruction = *instr_info.instruction;
switch (instruction.type()) { switch (instruction.type()) {
case MFInstructionType::Call: { case InstructionType::Call: {
const MFCallInstruction &call_instruction = static_cast<const MFCallInstruction &>( const CallInstruction &call_instruction = static_cast<const CallInstruction &>(
instruction); instruction);
execute_call_instruction(call_instruction, instr_info.mask(), variable_states, context); execute_call_instruction(call_instruction, instr_info.mask(), variable_states, context);
scheduler.update_instruction_pointer(*call_instruction.next()); scheduler.update_instruction_pointer(*call_instruction.next());
break; break;
} }
case MFInstructionType::Branch: { case InstructionType::Branch: {
const MFBranchInstruction &branch_instruction = static_cast<const MFBranchInstruction &>( const BranchInstruction &branch_instruction = static_cast<const BranchInstruction &>(
instruction); instruction);
const MFVariable *condition_var = branch_instruction.condition(); const Variable *condition_var = branch_instruction.condition();
VariableState &variable_state = variable_states.get_variable_state(*condition_var); VariableState &variable_state = variable_states.get_variable_state(*condition_var);
IndicesSplitVectors new_indices; IndicesSplitVectors new_indices;
@@ -1208,21 +1208,21 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
scheduler.add_owned_indices(*branch_instruction.branch_true(), new_indices[true]); scheduler.add_owned_indices(*branch_instruction.branch_true(), new_indices[true]);
break; break;
} }
case MFInstructionType::Destruct: { case InstructionType::Destruct: {
const MFDestructInstruction &destruct_instruction = const DestructInstruction &destruct_instruction = static_cast<const DestructInstruction &>(
static_cast<const MFDestructInstruction &>(instruction); instruction);
const MFVariable *variable = destruct_instruction.variable(); const Variable *variable = destruct_instruction.variable();
variable_states.destruct(*variable, instr_info.mask()); variable_states.destruct(*variable, instr_info.mask());
scheduler.update_instruction_pointer(*destruct_instruction.next()); scheduler.update_instruction_pointer(*destruct_instruction.next());
break; break;
} }
case MFInstructionType::Dummy: { case InstructionType::Dummy: {
const MFDummyInstruction &dummy_instruction = static_cast<const MFDummyInstruction &>( const DummyInstruction &dummy_instruction = static_cast<const DummyInstruction &>(
instruction); instruction);
scheduler.update_instruction_pointer(*dummy_instruction.next()); scheduler.update_instruction_pointer(*dummy_instruction.next());
break; break;
} }
case MFInstructionType::Return: { case InstructionType::Return: {
/* Don't insert the indices back into the scheduler. */ /* Don't insert the indices back into the scheduler. */
scheduler.pop(); scheduler.pop();
break; break;
@@ -1231,17 +1231,17 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
} }
for (const int param_index : this->param_indices()) { for (const int param_index : this->param_indices()) {
const MFParamType param_type = this->param_type(param_index); const ParamType param_type = this->param_type(param_index);
const MFVariable *variable = procedure_.params()[param_index].variable; const Variable *variable = procedure_.params()[param_index].variable;
VariableState &variable_state = variable_states.get_variable_state(*variable); VariableState &variable_state = variable_states.get_variable_state(*variable);
switch (param_type.interface_type()) { switch (param_type.interface_type()) {
case MFParamType::Input: { case ParamType::Input: {
/* Input variables must be destructed in the end. */ /* Input variables must be destructed in the end. */
BLI_assert(variable_state.is_fully_uninitialized(full_mask)); BLI_assert(variable_state.is_fully_uninitialized(full_mask));
break; break;
} }
case MFParamType::Mutable: case ParamType::Mutable:
case MFParamType::Output: { case ParamType::Output: {
/* Mutable and output variables must be initialized in the end. */ /* Mutable and output variables must be initialized in the end. */
BLI_assert(variable_state.is_fully_initialized(full_mask)); BLI_assert(variable_state.is_fully_initialized(full_mask));
/* Make sure that the data is in the memory provided by the caller. */ /* Make sure that the data is in the memory provided by the caller. */
@@ -1253,7 +1253,7 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
} }
} }
MultiFunction::ExecutionHints MFProcedureExecutor::get_execution_hints() const MultiFunction::ExecutionHints ProcedureExecutor::get_execution_hints() const
{ {
ExecutionHints hints; ExecutionHints hints;
hints.allocates_array = true; hints.allocates_array = true;
@@ -1261,4 +1261,4 @@ MultiFunction::ExecutionHints MFProcedureExecutor::get_execution_hints() const
return hints; return hints;
} }
} // namespace blender::fn } // namespace blender::fn::multi_function

View File

@@ -2,20 +2,19 @@
#include "FN_multi_function_procedure_optimization.hh" #include "FN_multi_function_procedure_optimization.hh"
namespace blender::fn::procedure_optimization { namespace blender::fn::multi_function::procedure_optimization {
void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr) void move_destructs_up(Procedure &procedure, Instruction &block_end_instr)
{ {
/* A mapping from a variable to its destruct instruction. */ /* A mapping from a variable to its destruct instruction. */
Map<MFVariable *, MFDestructInstruction *> destruct_instructions; Map<Variable *, DestructInstruction *> destruct_instructions;
MFInstruction *current_instr = &block_end_instr; Instruction *current_instr = &block_end_instr;
while (true) { while (true) {
MFInstructionType instr_type = current_instr->type(); InstructionType instr_type = current_instr->type();
switch (instr_type) { switch (instr_type) {
case MFInstructionType::Destruct: { case InstructionType::Destruct: {
MFDestructInstruction &destruct_instr = static_cast<MFDestructInstruction &>( DestructInstruction &destruct_instr = static_cast<DestructInstruction &>(*current_instr);
*current_instr); Variable *variable = destruct_instr.variable();
MFVariable *variable = destruct_instr.variable();
if (variable == nullptr) { if (variable == nullptr) {
continue; continue;
} }
@@ -24,31 +23,31 @@ void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr)
destruct_instructions.add(variable, &destruct_instr); destruct_instructions.add(variable, &destruct_instr);
break; break;
} }
case MFInstructionType::Call: { case InstructionType::Call: {
MFCallInstruction &call_instr = static_cast<MFCallInstruction &>(*current_instr); CallInstruction &call_instr = static_cast<CallInstruction &>(*current_instr);
/* For each variable, place the corresponding remembered destruct instruction right after /* For each variable, place the corresponding remembered destruct instruction right after
* this call instruction. */ * this call instruction. */
for (MFVariable *variable : call_instr.params()) { for (Variable *variable : call_instr.params()) {
if (variable == nullptr) { if (variable == nullptr) {
continue; continue;
} }
MFDestructInstruction *destruct_instr = destruct_instructions.pop_default(variable, DestructInstruction *destruct_instr = destruct_instructions.pop_default(variable,
nullptr); nullptr);
if (destruct_instr == nullptr) { if (destruct_instr == nullptr) {
continue; continue;
} }
/* Unlink destruct instruction from previous position. */ /* Unlink destruct instruction from previous position. */
MFInstruction *after_destruct_instr = destruct_instr->next(); Instruction *after_destruct_instr = destruct_instr->next();
while (!destruct_instr->prev().is_empty()) { while (!destruct_instr->prev().is_empty()) {
/* Do a copy of the cursor here, because `destruct_instr->prev()` changes when /* Do a copy of the cursor here, because `destruct_instr->prev()` changes when
* #set_next is called below. */ * #set_next is called below. */
const MFInstructionCursor cursor = destruct_instr->prev()[0]; const InstructionCursor cursor = destruct_instr->prev()[0];
cursor.set_next(procedure, after_destruct_instr); cursor.set_next(procedure, after_destruct_instr);
} }
/* Insert destruct instruction in new position. */ /* Insert destruct instruction in new position. */
MFInstruction *next_instr = call_instr.next(); Instruction *next_instr = call_instr.next();
call_instr.set_next(destruct_instr); call_instr.set_next(destruct_instr);
destruct_instr->set_next(next_instr); destruct_instr->set_next(next_instr);
} }
@@ -59,12 +58,12 @@ void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr)
} }
} }
const Span<MFInstructionCursor> prev_cursors = current_instr->prev(); const Span<InstructionCursor> prev_cursors = current_instr->prev();
if (prev_cursors.size() != 1) { if (prev_cursors.size() != 1) {
/* Stop when there is some branching before this instruction. */ /* Stop when there is some branching before this instruction. */
break; break;
} }
const MFInstructionCursor &prev_cursor = prev_cursors[0]; const InstructionCursor &prev_cursor = prev_cursors[0];
current_instr = prev_cursor.instruction(); current_instr = prev_cursor.instruction();
if (current_instr == nullptr) { if (current_instr == nullptr) {
/* Stop when there is no previous instruction. E.g. when this is the first instruction. */ /* Stop when there is no previous instruction. E.g. when this is the first instruction. */
@@ -73,4 +72,4 @@ void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr)
} }
} }
} // namespace blender::fn::procedure_optimization } // namespace blender::fn::multi_function::procedure_optimization

View File

@@ -13,7 +13,7 @@ TEST(field, ConstantFunction)
{ {
/* TODO: Figure out how to not use another "FieldOperation(" inside of std::make_shared. */ /* TODO: Figure out how to not use another "FieldOperation(" inside of std::make_shared. */
GField constant_field{std::make_shared<FieldOperation>( GField constant_field{std::make_shared<FieldOperation>(
FieldOperation(std::make_unique<CustomMF_Constant<int>>(10), {})), FieldOperation(std::make_unique<mf::CustomMF_Constant<int>>(10), {})),
0}; 0};
Array<int> result(4); Array<int> result(4);
@@ -104,7 +104,7 @@ TEST(field, InputAndFunction)
{ {
GField index_field{std::make_shared<IndexFieldInput>()}; GField index_field{std::make_shared<IndexFieldInput>()};
auto add_fn = build_mf::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; }); auto add_fn = mf::build::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; });
GField output_field{ GField output_field{
std::make_shared<FieldOperation>(FieldOperation(add_fn, {index_field, index_field})), 0}; std::make_shared<FieldOperation>(FieldOperation(add_fn, {index_field, index_field})), 0};
@@ -127,11 +127,11 @@ TEST(field, TwoFunctions)
{ {
GField index_field{std::make_shared<IndexFieldInput>()}; GField index_field{std::make_shared<IndexFieldInput>()};
auto add_fn = build_mf::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; }); auto add_fn = mf::build::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; });
GField add_field{ GField add_field{
std::make_shared<FieldOperation>(FieldOperation(add_fn, {index_field, index_field})), 0}; std::make_shared<FieldOperation>(FieldOperation(add_fn, {index_field, index_field})), 0};
auto add_10_fn = build_mf::SI1_SO<int, int>("add_10", [](int a) { return a + 10; }); auto add_10_fn = mf::build::SI1_SO<int, int>("add_10", [](int a) { return a + 10; });
GField result_field{std::make_shared<FieldOperation>(FieldOperation(add_10_fn, {add_field})), 0}; GField result_field{std::make_shared<FieldOperation>(FieldOperation(add_10_fn, {add_field})), 0};
Array<int> result(10); Array<int> result(10);
@@ -149,14 +149,14 @@ TEST(field, TwoFunctions)
EXPECT_EQ(result[8], 26); EXPECT_EQ(result[8], 26);
} }
class TwoOutputFunction : public MultiFunction { class TwoOutputFunction : public mf::MultiFunction {
private: private:
MFSignature signature_; mf::Signature signature_;
public: public:
TwoOutputFunction() TwoOutputFunction()
{ {
MFSignatureBuilder builder{"Two Outputs", signature_}; mf::SignatureBuilder builder{"Two Outputs", signature_};
builder.single_input<int>("In1"); builder.single_input<int>("In1");
builder.single_input<int>("In2"); builder.single_input<int>("In2");
builder.single_output<int>("Add"); builder.single_output<int>("Add");
@@ -164,7 +164,7 @@ class TwoOutputFunction : public MultiFunction {
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<int> &in1 = params.readonly_single_input<int>(0, "In1"); const VArray<int> &in1 = params.readonly_single_input<int>(0, "In1");
const VArray<int> &in2 = params.readonly_single_input<int>(1, "In2"); const VArray<int> &in2 = params.readonly_single_input<int>(1, "In2");
@@ -223,7 +223,7 @@ TEST(field, TwoFunctionsTwoOutputs)
Field<int> result_field_1{fn, 0}; Field<int> result_field_1{fn, 0};
Field<int> intermediate_field{fn, 1}; Field<int> intermediate_field{fn, 1};
auto add_10_fn = build_mf::SI1_SO<int, int>("add_10", [](int a) { return a + 10; }); auto add_10_fn = mf::build::SI1_SO<int, int>("add_10", [](int a) { return a + 10; });
Field<int> result_field_2{ Field<int> result_field_2{
std::make_shared<FieldOperation>(FieldOperation(add_10_fn, {intermediate_field})), 0}; std::make_shared<FieldOperation>(FieldOperation(add_10_fn, {intermediate_field})), 0};
@@ -248,7 +248,7 @@ TEST(field, TwoFunctionsTwoOutputs)
TEST(field, SameFieldTwice) TEST(field, SameFieldTwice)
{ {
GField constant_field{ GField constant_field{
std::make_shared<FieldOperation>(std::make_unique<CustomMF_Constant<int>>(10)), 0}; std::make_shared<FieldOperation>(std::make_unique<mf::CustomMF_Constant<int>>(10)), 0};
FieldContext field_context; FieldContext field_context;
IndexMask mask{IndexRange(2)}; IndexMask mask{IndexRange(2)};
@@ -267,7 +267,7 @@ TEST(field, SameFieldTwice)
TEST(field, IgnoredOutput) TEST(field, IgnoredOutput)
{ {
static OptionalOutputsFunction fn; static mf::tests::OptionalOutputsFunction fn;
Field<int> field{std::make_shared<FieldOperation>(fn), 0}; Field<int> field{std::make_shared<FieldOperation>(fn), 0};
FieldContext field_context; FieldContext field_context;

View File

@@ -7,7 +7,7 @@
#include "FN_multi_function_procedure_executor.hh" #include "FN_multi_function_procedure_executor.hh"
#include "FN_multi_function_test_common.hh" #include "FN_multi_function_test_common.hh"
namespace blender::fn::tests { namespace blender::fn::multi_function::tests {
TEST(multi_function_procedure, ConstantOutput) TEST(multi_function_procedure, ConstantOutput)
{ {
@@ -19,10 +19,10 @@ TEST(multi_function_procedure, ConstantOutput)
*/ */
CustomMF_Constant<int> constant_fn{5}; CustomMF_Constant<int> constant_fn{5};
auto add_fn = build_mf::SI2_SO<int, int, int>("Add", [](int a, int b) { return a + b; }); auto add_fn = build::SI2_SO<int, int, int>("Add", [](int a, int b) { return a + b; });
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
auto [var1] = builder.add_call<1>(constant_fn); auto [var1] = builder.add_call<1>(constant_fn);
auto [var2] = builder.add_call<1>(add_fn, {var1, var1}); auto [var2] = builder.add_call<1>(add_fn, {var1, var1});
@@ -32,10 +32,10 @@ TEST(multi_function_procedure, ConstantOutput)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor executor{procedure}; ProcedureExecutor executor{procedure};
MFParamsBuilder params{executor, 2}; ParamsBuilder params{executor, 2};
MFContextBuilder context; ContextBuilder context;
Array<int> output_array(2); Array<int> output_array(2);
params.add_uninitialized_single_output(output_array.as_mutable_span()); params.add_uninitialized_single_output(output_array.as_mutable_span());
@@ -56,14 +56,14 @@ TEST(multi_function_procedure, SimpleTest)
* } * }
*/ */
auto add_fn = fn::build_mf::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; }); auto add_fn = mf::build::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; });
auto add_10_fn = fn::build_mf::SM<int>("add_10", [](int &a) { a += 10; }); auto add_10_fn = mf::build::SM<int>("add_10", [](int &a) { a += 10; });
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
MFVariable *var1 = &builder.add_single_input_parameter<int>(); Variable *var1 = &builder.add_single_input_parameter<int>();
MFVariable *var2 = &builder.add_single_input_parameter<int>(); Variable *var2 = &builder.add_single_input_parameter<int>();
auto [var3] = builder.add_call<1>(add_fn, {var1, var2}); auto [var3] = builder.add_call<1>(add_fn, {var1, var2});
auto [var4] = builder.add_call<1>(add_fn, {var2, var3}); auto [var4] = builder.add_call<1>(add_fn, {var2, var3});
builder.add_call(add_10_fn, {var4}); builder.add_call(add_10_fn, {var4});
@@ -73,10 +73,10 @@ TEST(multi_function_procedure, SimpleTest)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor executor{procedure}; ProcedureExecutor executor{procedure};
MFParamsBuilder params{executor, 3}; ParamsBuilder params{executor, 3};
MFContextBuilder context; ContextBuilder context;
Array<int> input_array = {1, 2, 3}; Array<int> input_array = {1, 2, 3};
params.add_readonly_single_input(input_array.as_span()); params.add_readonly_single_input(input_array.as_span());
@@ -106,16 +106,16 @@ TEST(multi_function_procedure, BranchTest)
* } * }
*/ */
auto add_10_fn = build_mf::SM<int>("add_10", [](int &a) { a += 10; }); auto add_10_fn = build::SM<int>("add_10", [](int &a) { a += 10; });
auto add_100_fn = build_mf::SM<int>("add_100", [](int &a) { a += 100; }); auto add_100_fn = build::SM<int>("add_100", [](int &a) { a += 100; });
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
MFVariable *var1 = &builder.add_single_mutable_parameter<int>(); Variable *var1 = &builder.add_single_mutable_parameter<int>();
MFVariable *var2 = &builder.add_single_input_parameter<bool>(); Variable *var2 = &builder.add_single_input_parameter<bool>();
MFProcedureBuilder::Branch branch = builder.add_branch(*var2); ProcedureBuilder::Branch branch = builder.add_branch(*var2);
branch.branch_false.add_call(add_10_fn, {var1}); branch.branch_false.add_call(add_10_fn, {var1});
branch.branch_true.add_call(add_100_fn, {var1}); branch.branch_true.add_call(add_100_fn, {var1});
builder.set_cursor_after_branch(branch); builder.set_cursor_after_branch(branch);
@@ -125,8 +125,8 @@ TEST(multi_function_procedure, BranchTest)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor procedure_fn{procedure}; ProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params(procedure_fn, 5); ParamsBuilder params(procedure_fn, 5);
Array<int> values_a = {1, 5, 3, 6, 2}; Array<int> values_a = {1, 5, 3, 6, 2};
Array<bool> values_cond = {true, false, true, true, false}; Array<bool> values_cond = {true, false, true, true, false};
@@ -134,7 +134,7 @@ TEST(multi_function_procedure, BranchTest)
params.add_single_mutable(values_a.as_mutable_span()); params.add_single_mutable(values_a.as_mutable_span());
params.add_readonly_single_input(values_cond.as_span()); params.add_readonly_single_input(values_cond.as_span());
MFContextBuilder context; ContextBuilder context;
procedure_fn.call({1, 2, 3, 4}, params, context); procedure_fn.call({1, 2, 3, 4}, params, context);
EXPECT_EQ(values_a[0], 1); EXPECT_EQ(values_a[0], 1);
@@ -153,28 +153,28 @@ TEST(multi_function_procedure, EvaluateOne)
*/ */
int tot_evaluations = 0; int tot_evaluations = 0;
const auto add_10_fn = fn::build_mf::SI1_SO<int, int>("add_10", [&](int a) { const auto add_10_fn = mf::build::SI1_SO<int, int>("add_10", [&](int a) {
tot_evaluations++; tot_evaluations++;
return a + 10; return a + 10;
}); });
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
MFVariable *var1 = &builder.add_single_input_parameter<int>(); Variable *var1 = &builder.add_single_input_parameter<int>();
auto [var2] = builder.add_call<1>(add_10_fn, {var1}); auto [var2] = builder.add_call<1>(add_10_fn, {var1});
builder.add_destruct(*var1); builder.add_destruct(*var1);
builder.add_return(); builder.add_return();
builder.add_output_parameter(*var2); builder.add_output_parameter(*var2);
MFProcedureExecutor procedure_fn{procedure}; ProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5}; ParamsBuilder params{procedure_fn, 5};
Array<int> values_out = {1, 2, 3, 4, 5}; Array<int> values_out = {1, 2, 3, 4, 5};
params.add_readonly_single_input_value(1); params.add_readonly_single_input_value(1);
params.add_uninitialized_single_output(values_out.as_mutable_span()); params.add_uninitialized_single_output(values_out.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
procedure_fn.call({0, 1, 3, 4}, params, context); procedure_fn.call({0, 1, 3, 4}, params, context);
EXPECT_EQ(values_out[0], 11); EXPECT_EQ(values_out[0], 11);
@@ -205,25 +205,25 @@ TEST(multi_function_procedure, SimpleLoop)
CustomMF_Constant<int> const_1_fn{1}; CustomMF_Constant<int> const_1_fn{1};
CustomMF_Constant<int> const_0_fn{0}; CustomMF_Constant<int> const_0_fn{0};
auto greater_or_equal_fn = fn::build_mf::SI2_SO<int, int, bool>( auto greater_or_equal_fn = mf::build::SI2_SO<int, int, bool>(
"greater or equal", [](int a, int b) { return a >= b; }); "greater or equal", [](int a, int b) { return a >= b; });
auto double_fn = build_mf::SM<int>("double", [](int &a) { a *= 2; }); auto double_fn = build::SM<int>("double", [](int &a) { a *= 2; });
auto add_1000_fn = build_mf::SM<int>("add 1000", [](int &a) { a += 1000; }); auto add_1000_fn = build::SM<int>("add 1000", [](int &a) { a += 1000; });
auto add_1_fn = build_mf::SM<int>("add 1", [](int &a) { a += 1; }); auto add_1_fn = build::SM<int>("add 1", [](int &a) { a += 1; });
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
MFVariable *var_count = &builder.add_single_input_parameter<int>("count"); Variable *var_count = &builder.add_single_input_parameter<int>("count");
auto [var_out] = builder.add_call<1>(const_1_fn); auto [var_out] = builder.add_call<1>(const_1_fn);
var_out->set_name("out"); var_out->set_name("out");
auto [var_index] = builder.add_call<1>(const_0_fn); auto [var_index] = builder.add_call<1>(const_0_fn);
var_index->set_name("index"); var_index->set_name("index");
MFProcedureBuilder::Loop loop = builder.add_loop(); ProcedureBuilder::Loop loop = builder.add_loop();
auto [var_condition] = builder.add_call<1>(greater_or_equal_fn, {var_index, var_count}); auto [var_condition] = builder.add_call<1>(greater_or_equal_fn, {var_index, var_count});
var_condition->set_name("condition"); var_condition->set_name("condition");
MFProcedureBuilder::Branch branch = builder.add_branch(*var_condition); ProcedureBuilder::Branch branch = builder.add_branch(*var_condition);
branch.branch_true.add_destruct(*var_condition); branch.branch_true.add_destruct(*var_condition);
branch.branch_true.add_loop_break(loop); branch.branch_true.add_loop_break(loop);
branch.branch_false.add_destruct(*var_condition); branch.branch_false.add_destruct(*var_condition);
@@ -239,8 +239,8 @@ TEST(multi_function_procedure, SimpleLoop)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor procedure_fn{procedure}; ProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5}; ParamsBuilder params{procedure_fn, 5};
Array<int> counts = {4, 3, 7, 6, 4}; Array<int> counts = {4, 3, 7, 6, 4};
Array<int> results(5, -1); Array<int> results(5, -1);
@@ -248,7 +248,7 @@ TEST(multi_function_procedure, SimpleLoop)
params.add_readonly_single_input(counts.as_span()); params.add_readonly_single_input(counts.as_span());
params.add_uninitialized_single_output(results.as_mutable_span()); params.add_uninitialized_single_output(results.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
procedure_fn.call({0, 1, 3, 4}, params, context); procedure_fn.call({0, 1, 3, 4}, params, context);
EXPECT_EQ(results[0], 1016); EXPECT_EQ(results[0], 1016);
@@ -277,11 +277,11 @@ TEST(multi_function_procedure, Vectors)
SumVectorFunction sum_elements_fn; SumVectorFunction sum_elements_fn;
CustomMF_Constant<int> constant_5_fn{5}; CustomMF_Constant<int> constant_5_fn{5};
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
MFVariable *var_v1 = &builder.add_input_parameter(MFDataType::ForVector<int>()); Variable *var_v1 = &builder.add_input_parameter(DataType::ForVector<int>());
MFVariable *var_v2 = &builder.add_parameter(MFParamType::ForMutableVector(CPPType::get<int>())); Variable *var_v2 = &builder.add_parameter(ParamType::ForMutableVector(CPPType::get<int>()));
builder.add_call(extend_fn, {var_v1, var_v2}); builder.add_call(extend_fn, {var_v1, var_v2});
auto [var_constant] = builder.add_call<1>(constant_5_fn); auto [var_constant] = builder.add_call<1>(constant_5_fn);
builder.add_call(append_fn, {var_v2, var_constant}); builder.add_call(append_fn, {var_v2, var_constant});
@@ -295,8 +295,8 @@ TEST(multi_function_procedure, Vectors)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor procedure_fn{procedure}; ProcedureExecutor procedure_fn{procedure};
MFParamsBuilder params{procedure_fn, 5}; ParamsBuilder params{procedure_fn, 5};
Array<int> v1 = {5, 2, 3}; Array<int> v1 = {5, 2, 3};
GVectorArray v2{CPPType::get<int>(), 5}; GVectorArray v2{CPPType::get<int>(), 5};
@@ -310,7 +310,7 @@ TEST(multi_function_procedure, Vectors)
params.add_vector_mutable(v2); params.add_vector_mutable(v2);
params.add_vector_output(v3); params.add_vector_output(v3);
MFContextBuilder context; ContextBuilder context;
procedure_fn.call({0, 1, 3, 4}, params, context); procedure_fn.call({0, 1, 3, 4}, params, context);
EXPECT_EQ(v2[0].size(), 6); EXPECT_EQ(v2[0].size(), 6);
@@ -338,12 +338,12 @@ TEST(multi_function_procedure, BufferReuse)
* } * }
*/ */
auto add_10_fn = build_mf::SI1_SO<int, int>("add 10", [](int a) { return a + 10; }); auto add_10_fn = build::SI1_SO<int, int>("add 10", [](int a) { return a + 10; });
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
MFVariable *var_a = &builder.add_single_input_parameter<int>(); Variable *var_a = &builder.add_single_input_parameter<int>();
auto [var_b] = builder.add_call<1>(add_10_fn, {var_a}); auto [var_b] = builder.add_call<1>(add_10_fn, {var_a});
builder.add_destruct(*var_a); builder.add_destruct(*var_a);
auto [var_c] = builder.add_call<1>(add_10_fn, {var_b}); auto [var_c] = builder.add_call<1>(add_10_fn, {var_b});
@@ -359,16 +359,16 @@ TEST(multi_function_procedure, BufferReuse)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor procedure_fn{procedure}; ProcedureExecutor procedure_fn{procedure};
Array<int> inputs = {4, 1, 6, 2, 3}; Array<int> inputs = {4, 1, 6, 2, 3};
Array<int> results(5, -1); Array<int> results(5, -1);
MFParamsBuilder params{procedure_fn, 5}; ParamsBuilder params{procedure_fn, 5};
params.add_readonly_single_input(inputs.as_span()); params.add_readonly_single_input(inputs.as_span());
params.add_uninitialized_single_output(results.as_mutable_span()); params.add_uninitialized_single_output(results.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
procedure_fn.call({0, 2, 3, 4}, params, context); procedure_fn.call({0, 2, 3, 4}, params, context);
EXPECT_EQ(results[0], 54); EXPECT_EQ(results[0], 54);
@@ -380,12 +380,12 @@ TEST(multi_function_procedure, BufferReuse)
TEST(multi_function_procedure, OutputBufferReplaced) TEST(multi_function_procedure, OutputBufferReplaced)
{ {
MFProcedure procedure; Procedure procedure;
MFProcedureBuilder builder{procedure}; ProcedureBuilder builder{procedure};
const int output_value = 42; const int output_value = 42;
CustomMF_GenericConstant constant_fn(CPPType::get<int>(), &output_value, false); CustomMF_GenericConstant constant_fn(CPPType::get<int>(), &output_value, false);
MFVariable &var_o = procedure.new_variable(MFDataType::ForSingle<int>()); Variable &var_o = procedure.new_variable(DataType::ForSingle<int>());
builder.add_output_parameter(var_o); builder.add_output_parameter(var_o);
builder.add_call_with_all_variables(constant_fn, {&var_o}); builder.add_call_with_all_variables(constant_fn, {&var_o});
builder.add_destruct(var_o); builder.add_destruct(var_o);
@@ -394,13 +394,13 @@ TEST(multi_function_procedure, OutputBufferReplaced)
EXPECT_TRUE(procedure.validate()); EXPECT_TRUE(procedure.validate());
MFProcedureExecutor procedure_fn{procedure}; ProcedureExecutor procedure_fn{procedure};
Array<int> output(3, 0); Array<int> output(3, 0);
fn::MFParamsBuilder params(procedure_fn, output.size()); mf::ParamsBuilder params(procedure_fn, output.size());
params.add_uninitialized_single_output(output.as_mutable_span()); params.add_uninitialized_single_output(output.as_mutable_span());
fn::MFContextBuilder context; mf::ContextBuilder context;
procedure_fn.call(IndexMask(output.size()), params, context); procedure_fn.call(IndexMask(output.size()), params, context);
EXPECT_EQ(output[0], output_value); EXPECT_EQ(output[0], output_value);
@@ -408,4 +408,4 @@ TEST(multi_function_procedure, OutputBufferReplaced)
EXPECT_EQ(output[2], output_value); EXPECT_EQ(output[2], output_value);
} }
} // namespace blender::fn::tests } // namespace blender::fn::multi_function::tests

View File

@@ -6,28 +6,28 @@
#include "FN_multi_function_builder.hh" #include "FN_multi_function_builder.hh"
#include "FN_multi_function_test_common.hh" #include "FN_multi_function_test_common.hh"
namespace blender::fn::tests { namespace blender::fn::multi_function::tests {
namespace { namespace {
class AddFunction : public MultiFunction { class AddFunction : public MultiFunction {
public: public:
AddFunction() AddFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder("Add", signature); SignatureBuilder builder("Add", signature);
builder.single_input<int>("A"); builder.single_input<int>("A");
builder.single_input<int>("B"); builder.single_input<int>("B");
builder.single_output<int>("Result"); builder.single_output<int>("Result");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
const VArray<int> &a = params.readonly_single_input<int>(0, "A"); const VArray<int> &a = params.readonly_single_input<int>(0, "A");
const VArray<int> &b = params.readonly_single_input<int>(1, "B"); const VArray<int> &b = params.readonly_single_input<int>(1, "B");
@@ -47,12 +47,12 @@ TEST(multi_function, AddFunction)
Array<int> input2 = {10, 20, 30}; Array<int> input2 = {10, 20, 30};
Array<int> output(3, -1); Array<int> output(3, -1);
MFParamsBuilder params(fn, 3); ParamsBuilder params(fn, 3);
params.add_readonly_single_input(input1.as_span()); params.add_readonly_single_input(input1.as_span());
params.add_readonly_single_input(input2.as_span()); params.add_readonly_single_input(input2.as_span());
params.add_uninitialized_single_output(output.as_mutable_span()); params.add_uninitialized_single_output(output.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
fn.call({0, 2}, params, context); fn.call({0, 2}, params, context);
@@ -74,11 +74,11 @@ TEST(multi_function, AddPrefixFunction)
std::string prefix = "AB"; std::string prefix = "AB";
MFParamsBuilder params(fn, strings.size()); ParamsBuilder params(fn, strings.size());
params.add_readonly_single_input(&prefix); params.add_readonly_single_input(&prefix);
params.add_single_mutable(strings.as_mutable_span()); params.add_single_mutable(strings.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
fn.call({0, 2, 3}, params, context); fn.call({0, 2, 3}, params, context);
@@ -96,11 +96,11 @@ TEST(multi_function, CreateRangeFunction)
GVectorArray_TypedMutableRef<int> ranges_ref{ranges}; GVectorArray_TypedMutableRef<int> ranges_ref{ranges};
Array<int> sizes = {3, 0, 6, 1, 4}; Array<int> sizes = {3, 0, 6, 1, 4};
MFParamsBuilder params(fn, ranges.size()); ParamsBuilder params(fn, ranges.size());
params.add_readonly_single_input(sizes.as_span()); params.add_readonly_single_input(sizes.as_span());
params.add_vector_output(ranges); params.add_vector_output(ranges);
MFContextBuilder context; ContextBuilder context;
fn.call({0, 1, 2, 3}, params, context); fn.call({0, 1, 2, 3}, params, context);
@@ -128,11 +128,11 @@ TEST(multi_function, GenericAppendFunction)
vectors_ref.append(2, 6); vectors_ref.append(2, 6);
Array<int> values = {5, 7, 3, 1}; Array<int> values = {5, 7, 3, 1};
MFParamsBuilder params(fn, vectors.size()); ParamsBuilder params(fn, vectors.size());
params.add_vector_mutable(vectors); params.add_vector_mutable(vectors);
params.add_readonly_single_input(values.as_span()); params.add_readonly_single_input(values.as_span());
MFContextBuilder context; ContextBuilder context;
fn.call(IndexRange(vectors.size()), params, context); fn.call(IndexRange(vectors.size()), params, context);
@@ -156,10 +156,10 @@ TEST(multi_function, CustomMF_Constant)
Array<int> outputs(4, 0); Array<int> outputs(4, 0);
MFParamsBuilder params(fn, outputs.size()); ParamsBuilder params(fn, outputs.size());
params.add_uninitialized_single_output(outputs.as_mutable_span()); params.add_uninitialized_single_output(outputs.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
fn.call({0, 2, 3}, params, context); fn.call({0, 2, 3}, params, context);
@@ -176,10 +176,10 @@ TEST(multi_function, CustomMF_GenericConstant)
Array<int> outputs(4, 0); Array<int> outputs(4, 0);
MFParamsBuilder params(fn, outputs.size()); ParamsBuilder params(fn, outputs.size());
params.add_uninitialized_single_output(outputs.as_mutable_span()); params.add_uninitialized_single_output(outputs.as_mutable_span());
MFContextBuilder context; ContextBuilder context;
fn.call({0, 1, 2}, params, context); fn.call({0, 1, 2}, params, context);
@@ -197,10 +197,10 @@ TEST(multi_function, CustomMF_GenericConstantArray)
GVectorArray vector_array{CPPType::get<int32_t>(), 4}; GVectorArray vector_array{CPPType::get<int32_t>(), 4};
GVectorArray_TypedMutableRef<int> vector_array_ref{vector_array}; GVectorArray_TypedMutableRef<int> vector_array_ref{vector_array};
MFParamsBuilder params(fn, vector_array.size()); ParamsBuilder params(fn, vector_array.size());
params.add_vector_output(vector_array); params.add_vector_output(vector_array);
MFContextBuilder context; ContextBuilder context;
fn.call({1, 2, 3}, params, context); fn.call({1, 2, 3}, params, context);
@@ -220,20 +220,20 @@ TEST(multi_function, IgnoredOutputs)
{ {
OptionalOutputsFunction fn; OptionalOutputsFunction fn;
{ {
MFParamsBuilder params(fn, 10); ParamsBuilder params(fn, 10);
params.add_ignored_single_output("Out 1"); params.add_ignored_single_output("Out 1");
params.add_ignored_single_output("Out 2"); params.add_ignored_single_output("Out 2");
MFContextBuilder context; ContextBuilder context;
fn.call(IndexRange(10), params, context); fn.call(IndexRange(10), params, context);
} }
{ {
Array<int> results_1(10); Array<int> results_1(10);
Array<std::string> results_2(10, NoInitialization()); Array<std::string> results_2(10, NoInitialization());
MFParamsBuilder params(fn, 10); ParamsBuilder params(fn, 10);
params.add_uninitialized_single_output(results_1.as_mutable_span(), "Out 1"); params.add_uninitialized_single_output(results_1.as_mutable_span(), "Out 1");
params.add_uninitialized_single_output(results_2.as_mutable_span(), "Out 2"); params.add_uninitialized_single_output(results_2.as_mutable_span(), "Out 2");
MFContextBuilder context; ContextBuilder context;
fn.call(IndexRange(10), params, context); fn.call(IndexRange(10), params, context);
EXPECT_EQ(results_1[0], 5); EXPECT_EQ(results_1[0], 5);
@@ -244,4 +244,4 @@ TEST(multi_function, IgnoredOutputs)
} }
} // namespace } // namespace
} // namespace blender::fn::tests } // namespace blender::fn::multi_function::tests

View File

@@ -2,26 +2,26 @@
#include "FN_multi_function.hh" #include "FN_multi_function.hh"
namespace blender::fn::tests { namespace blender::fn::multi_function::tests {
class AddPrefixFunction : public MultiFunction { class AddPrefixFunction : public MultiFunction {
public: public:
AddPrefixFunction() AddPrefixFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder{"Add Prefix", signature}; SignatureBuilder builder{"Add Prefix", signature};
builder.single_input<std::string>("Prefix"); builder.single_input<std::string>("Prefix");
builder.single_mutable<std::string>("Strings"); builder.single_mutable<std::string>("Strings");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
const VArray<std::string> &prefixes = params.readonly_single_input<std::string>(0, "Prefix"); const VArray<std::string> &prefixes = params.readonly_single_input<std::string>(0, "Prefix");
MutableSpan<std::string> strings = params.single_mutable<std::string>(1, "Strings"); MutableSpan<std::string> strings = params.single_mutable<std::string>(1, "Strings");
@@ -36,20 +36,20 @@ class CreateRangeFunction : public MultiFunction {
public: public:
CreateRangeFunction() CreateRangeFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder{"Create Range", signature}; SignatureBuilder builder{"Create Range", signature};
builder.single_input<int>("Size"); builder.single_input<int>("Size");
builder.vector_output<int>("Range"); builder.vector_output<int>("Range");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
const VArray<int> &sizes = params.readonly_single_input<int>(0, "Size"); const VArray<int> &sizes = params.readonly_single_input<int>(0, "Size");
GVectorArray &ranges = params.vector_output(1, "Range"); GVectorArray &ranges = params.vector_output(1, "Range");
@@ -65,18 +65,18 @@ class CreateRangeFunction : public MultiFunction {
class GenericAppendFunction : public MultiFunction { class GenericAppendFunction : public MultiFunction {
private: private:
MFSignature signature_; Signature signature_;
public: public:
GenericAppendFunction(const CPPType &type) GenericAppendFunction(const CPPType &type)
{ {
MFSignatureBuilder builder{"Append", signature_}; SignatureBuilder builder{"Append", signature_};
builder.vector_mutable("Vector", type); builder.vector_mutable("Vector", type);
builder.single_input("Value", type); builder.single_input("Value", type);
this->set_signature(&signature_); this->set_signature(&signature_);
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
GVectorArray &vectors = params.vector_mutable(0, "Vector"); GVectorArray &vectors = params.vector_mutable(0, "Vector");
const GVArray &values = params.readonly_single_input(1, "Value"); const GVArray &values = params.readonly_single_input(1, "Value");
@@ -94,20 +94,20 @@ class ConcatVectorsFunction : public MultiFunction {
public: public:
ConcatVectorsFunction() ConcatVectorsFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder{"Concat Vectors", signature}; SignatureBuilder builder{"Concat Vectors", signature};
builder.vector_mutable<int>("A"); builder.vector_mutable<int>("A");
builder.vector_input<int>("B"); builder.vector_input<int>("B");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
GVectorArray &a = params.vector_mutable(0); GVectorArray &a = params.vector_mutable(0);
const GVVectorArray &b = params.readonly_vector_input(1); const GVVectorArray &b = params.readonly_vector_input(1);
@@ -119,20 +119,20 @@ class AppendFunction : public MultiFunction {
public: public:
AppendFunction() AppendFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder{"Append", signature}; SignatureBuilder builder{"Append", signature};
builder.vector_mutable<int>("Vector"); builder.vector_mutable<int>("Vector");
builder.single_input<int>("Value"); builder.single_input<int>("Value");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
GVectorArray_TypedMutableRef<int> vectors = params.vector_mutable<int>(0); GVectorArray_TypedMutableRef<int> vectors = params.vector_mutable<int>(0);
const VArray<int> &values = params.readonly_single_input<int>(1); const VArray<int> &values = params.readonly_single_input<int>(1);
@@ -147,20 +147,20 @@ class SumVectorFunction : public MultiFunction {
public: public:
SumVectorFunction() SumVectorFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder{"Sum Vectors", signature}; SignatureBuilder builder{"Sum Vectors", signature};
builder.vector_input<int>("Vector"); builder.vector_input<int>("Vector");
builder.single_output<int>("Sum"); builder.single_output<int>("Sum");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
const VVectorArray<int> &vectors = params.readonly_vector_input<int>(0); const VVectorArray<int> &vectors = params.readonly_vector_input<int>(0);
MutableSpan<int> sums = params.uninitialized_single_output<int>(1); MutableSpan<int> sums = params.uninitialized_single_output<int>(1);
@@ -179,20 +179,20 @@ class OptionalOutputsFunction : public MultiFunction {
public: public:
OptionalOutputsFunction() OptionalOutputsFunction()
{ {
static MFSignature signature = create_signature(); static Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static MFSignature create_signature() static Signature create_signature()
{ {
MFSignature signature; Signature signature;
MFSignatureBuilder builder{"Optional Outputs", signature}; SignatureBuilder builder{"Optional Outputs", signature};
builder.single_output<int>("Out 1"); builder.single_output<int>("Out 1");
builder.single_output<std::string>("Out 2"); builder.single_output<std::string>("Out 2");
return signature; return signature;
} }
void call(IndexMask mask, MFParams params, MFContext /*context*/) const override void call(IndexMask mask, MFParams params, Context /*context*/) const override
{ {
if (params.single_output_is_required(0, "Out 1")) { if (params.single_output_is_required(0, "Out 1")) {
MutableSpan<int> values = params.uninitialized_single_output<int>(0, "Out 1"); MutableSpan<int> values = params.uninitialized_single_output<int>(0, "Out 1");
@@ -205,4 +205,4 @@ class OptionalOutputsFunction : public MultiFunction {
} }
}; };
} // namespace blender::fn::tests } // namespace blender::fn::multi_function::tests

View File

@@ -17,10 +17,10 @@ namespace blender::geometry {
static fn::Field<int> get_count_input_max_one(const fn::Field<int> &count_field) static fn::Field<int> get_count_input_max_one(const fn::Field<int> &count_field)
{ {
static auto max_one_fn = fn::build_mf::SI1_SO<int, int>( static auto max_one_fn = mf::build::SI1_SO<int, int>(
"Clamp Above One", "Clamp Above One",
[](int value) { return std::max(1, value); }, [](int value) { return std::max(1, value); },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
auto clamp_op = std::make_shared<fn::FieldOperation>( auto clamp_op = std::make_shared<fn::FieldOperation>(
fn::FieldOperation(max_one_fn, {count_field})); fn::FieldOperation(max_one_fn, {count_field}));
@@ -29,7 +29,7 @@ static fn::Field<int> get_count_input_max_one(const fn::Field<int> &count_field)
static fn::Field<int> get_count_input_from_length(const fn::Field<float> &length_field) static fn::Field<int> get_count_input_from_length(const fn::Field<float> &length_field)
{ {
static auto get_count_fn = fn::build_mf::SI2_SO<float, float, int>( static auto get_count_fn = mf::build::SI2_SO<float, float, int>(
"Length Input to Count", "Length Input to Count",
[](const float curve_length, const float sample_length) { [](const float curve_length, const float sample_length) {
/* Find the number of sampled segments by dividing the total length by /* Find the number of sampled segments by dividing the total length by
@@ -37,7 +37,7 @@ static fn::Field<int> get_count_input_from_length(const fn::Field<float> &length
const int count = int(curve_length / sample_length) + 1; const int count = int(curve_length / sample_length) + 1;
return std::max(1, count); return std::max(1, count);
}, },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
auto get_count_op = std::make_shared<fn::FieldOperation>(fn::FieldOperation( auto get_count_op = std::make_shared<fn::FieldOperation>(fn::FieldOperation(
get_count_fn, get_count_fn,

View File

@@ -125,17 +125,16 @@ using blender::fn::ValueOrFieldCPPType;
using blender::nodes::FieldInferencingInterface; using blender::nodes::FieldInferencingInterface;
using blender::nodes::GeoNodeExecParams; using blender::nodes::GeoNodeExecParams;
using blender::nodes::InputSocketFieldType; using blender::nodes::InputSocketFieldType;
using blender::nodes::geo_eval_log::GeoModifierLog;
using blender::threading::EnumerableThreadSpecific;
using namespace blender::fn::multi_function_types;
using blender::nodes::geo_eval_log::GeometryAttributeInfo; using blender::nodes::geo_eval_log::GeometryAttributeInfo;
using blender::nodes::geo_eval_log::GeometryInfoLog; using blender::nodes::geo_eval_log::GeometryInfoLog;
using blender::nodes::geo_eval_log::GeoModifierLog;
using blender::nodes::geo_eval_log::GeoNodeLog; using blender::nodes::geo_eval_log::GeoNodeLog;
using blender::nodes::geo_eval_log::GeoTreeLog; using blender::nodes::geo_eval_log::GeoTreeLog;
using blender::nodes::geo_eval_log::NamedAttributeUsage; using blender::nodes::geo_eval_log::NamedAttributeUsage;
using blender::nodes::geo_eval_log::NodeWarning; using blender::nodes::geo_eval_log::NodeWarning;
using blender::nodes::geo_eval_log::NodeWarningType; using blender::nodes::geo_eval_log::NodeWarningType;
using blender::nodes::geo_eval_log::ValueLog; using blender::nodes::geo_eval_log::ValueLog;
using blender::threading::EnumerableThreadSpecific;
static void initData(ModifierData *md) static void initData(ModifierData *md)
{ {

View File

@@ -31,8 +31,8 @@ struct Depsgraph;
namespace blender::nodes { namespace blender::nodes {
namespace lf = fn::lazy_function;
using lf::LazyFunction; using lf::LazyFunction;
using mf::MultiFunction;
/** /**
* Data that is passed into geometry nodes evaluation from the modifier. * Data that is passed into geometry nodes evaluation from the modifier.

View File

@@ -51,8 +51,8 @@ inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&cal
return false; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); static auto exec_preset_slow = mf::build::exec_presets::Materialized();
/* This is just an utility function to keep the individual cases smaller. */ /* This is just an utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); static auto exec_preset_slow = mf::build::exec_presets::Materialized();
/* This is just an utility function to keep the individual cases smaller. */ /* This is just an utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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) { switch (operation) {
case NODE_MATH_MULTIPLY_ADD: case NODE_MATH_MULTIPLY_ADD:
return dispatch(fn::build_mf::exec_presets::AllSpanOrSingle(), return dispatch(mf::build::exec_presets::AllSpanOrSingle(),
[](float a, float b, float c) { return a * b + c; }); [](float a, float b, float c) { return a * b + c; });
case NODE_MATH_COMPARE: case NODE_MATH_COMPARE:
return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(), return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
[](float a, float b, float c) -> float { [](float a, float b, float c) -> float {
return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f; return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
}); });
case NODE_MATH_SMOOTH_MIN: case NODE_MATH_SMOOTH_MIN:
return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(), return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
[](float a, float b, float c) { return smoothminf(a, b, c); }); [](float a, float b, float c) { return smoothminf(a, b, c); });
case NODE_MATH_SMOOTH_MAX: case NODE_MATH_SMOOTH_MAX:
return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(), return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0, 1>(),
[](float a, float b, float c) { return -smoothminf(-a, -b, c); }); [](float a, float b, float c) { return -smoothminf(-a, -b, c); });
case NODE_MATH_WRAP: case NODE_MATH_WRAP:
return dispatch(fn::build_mf::exec_presets::SomeSpanOrSingle<0>(), return dispatch(mf::build::exec_presets::SomeSpanOrSingle<0>(),
[](float a, float b, float c) { return wrapf(a, b, c); }); [](float a, float b, float c) { return wrapf(a, b, c); });
} }
return false; return false;
@@ -214,8 +214,8 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl3(const NodeVectorMathOperation
return false; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); static auto exec_preset_slow = mf::build::exec_presets::Materialized();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); static auto exec_preset_slow = mf::build::exec_presets::Materialized();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); static auto exec_preset_slow = mf::build::exec_presets::Materialized();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { 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; return false;
} }
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized(); static auto exec_preset_slow = mf::build::exec_presets::Materialized();
/* This is just a utility function to keep the individual cases smaller. */ /* This is just a utility function to keep the individual cases smaller. */
auto dispatch = [&](auto exec_preset, auto math_function) -> bool { auto dispatch = [&](auto exec_preset, auto math_function) -> bool {

View File

@@ -8,8 +8,6 @@
namespace blender::nodes { namespace blender::nodes {
using namespace fn::multi_function_types;
class NodeMultiFunctions; class NodeMultiFunctions;
/** /**
@@ -19,8 +17,8 @@ class NodeMultiFunctionBuilder : NonCopyable, NonMovable {
private: private:
const bNode &node_; const bNode &node_;
const bNodeTree &tree_; const bNodeTree &tree_;
std::shared_ptr<MultiFunction> owned_built_fn_; std::shared_ptr<mf::MultiFunction> owned_built_fn_;
const MultiFunction *built_fn_ = nullptr; const mf::MultiFunction *built_fn_ = nullptr;
friend NodeMultiFunctions; friend NodeMultiFunctions;
@@ -31,8 +29,8 @@ class NodeMultiFunctionBuilder : NonCopyable, NonMovable {
* Assign a multi-function for the current node. The input and output parameters of the function * Assign a multi-function for the current node. The input and output parameters of the function
* have to match the available sockets in the node. * have to match the available sockets in the node.
*/ */
void set_matching_fn(const MultiFunction *fn); void set_matching_fn(const mf::MultiFunction *fn);
void set_matching_fn(const MultiFunction &fn); void set_matching_fn(const mf::MultiFunction &fn);
/** /**
* Utility method for creating and assigning a multi-function when it can't have a static * Utility method for creating and assigning a multi-function when it can't have a static
@@ -50,8 +48,8 @@ class NodeMultiFunctionBuilder : NonCopyable, NonMovable {
class NodeMultiFunctions { class NodeMultiFunctions {
public: public:
struct Item { struct Item {
const MultiFunction *fn = nullptr; const mf::MultiFunction *fn = nullptr;
std::shared_ptr<MultiFunction> owned_fn; std::shared_ptr<mf::MultiFunction> owned_fn;
}; };
private: private:
@@ -82,12 +80,12 @@ inline const bNodeTree &NodeMultiFunctionBuilder::tree()
return tree_; return tree_;
} }
inline void NodeMultiFunctionBuilder::set_matching_fn(const MultiFunction *fn) inline void NodeMultiFunctionBuilder::set_matching_fn(const mf::MultiFunction *fn)
{ {
built_fn_ = fn; built_fn_ = fn;
} }
inline void NodeMultiFunctionBuilder::set_matching_fn(const MultiFunction &fn) inline void NodeMultiFunctionBuilder::set_matching_fn(const mf::MultiFunction &fn)
{ {
built_fn_ = &fn; built_fn_ = &fn;
} }

View File

@@ -133,7 +133,7 @@ static void align_rotations_fixed_pivot(IndexMask mask,
}); });
} }
class MF_AlignEulerToVector : public fn::MultiFunction { class MF_AlignEulerToVector : public mf::MultiFunction {
private: private:
int main_axis_mode_; int main_axis_mode_;
int pivot_axis_mode_; int pivot_axis_mode_;
@@ -142,14 +142,14 @@ class MF_AlignEulerToVector : public fn::MultiFunction {
MF_AlignEulerToVector(int main_axis_mode, int pivot_axis_mode) MF_AlignEulerToVector(int main_axis_mode, int pivot_axis_mode)
: main_axis_mode_(main_axis_mode), pivot_axis_mode_(pivot_axis_mode) : main_axis_mode_(main_axis_mode), pivot_axis_mode_(pivot_axis_mode)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Align Euler to Vector", signature}; mf::SignatureBuilder builder{"Align Euler to Vector", signature};
builder.single_input<float3>("Rotation"); builder.single_input<float3>("Rotation");
builder.single_input<float>("Factor"); builder.single_input<float>("Factor");
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -158,7 +158,7 @@ class MF_AlignEulerToVector : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &input_rotations = params.readonly_single_input<float3>(0, "Rotation"); const VArray<float3> &input_rotations = params.readonly_single_input<float3>(0, "Rotation");
const VArray<float> &factors = params.readonly_single_input<float>(1, "Factor"); const VArray<float> &factors = params.readonly_single_input<float>(1, "Factor");

View File

@@ -65,26 +65,26 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
} }
} }
static const fn::MultiFunction *get_multi_function(const bNode &bnode) static const mf::MultiFunction *get_multi_function(const bNode &bnode)
{ {
static auto exec_preset = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
static auto and_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto and_fn = mf::build::SI2_SO<bool, bool, bool>(
"And", [](bool a, bool b) { return a && b; }, exec_preset); "And", [](bool a, bool b) { return a && b; }, exec_preset);
static auto or_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto or_fn = mf::build::SI2_SO<bool, bool, bool>(
"Or", [](bool a, bool b) { return a || b; }, exec_preset); "Or", [](bool a, bool b) { return a || b; }, exec_preset);
static auto not_fn = fn::build_mf::SI1_SO<bool, bool>( static auto not_fn = mf::build::SI1_SO<bool, bool>(
"Not", [](bool a) { return !a; }, exec_preset); "Not", [](bool a) { return !a; }, exec_preset);
static auto nand_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto nand_fn = mf::build::SI2_SO<bool, bool, bool>(
"Not And", [](bool a, bool b) { return !(a && b); }, exec_preset); "Not And", [](bool a, bool b) { return !(a && b); }, exec_preset);
static auto nor_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto nor_fn = mf::build::SI2_SO<bool, bool, bool>(
"Nor", [](bool a, bool b) { return !(a || b); }, exec_preset); "Nor", [](bool a, bool b) { return !(a || b); }, exec_preset);
static auto xnor_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto xnor_fn = mf::build::SI2_SO<bool, bool, bool>(
"Equal", [](bool a, bool b) { return a == b; }, exec_preset); "Equal", [](bool a, bool b) { return a == b; }, exec_preset);
static auto xor_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto xor_fn = mf::build::SI2_SO<bool, bool, bool>(
"Not Equal", [](bool a, bool b) { return a != b; }, exec_preset); "Not Equal", [](bool a, bool b) { return a != b; }, exec_preset);
static auto imply_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto imply_fn = mf::build::SI2_SO<bool, bool, bool>(
"Imply", [](bool a, bool b) { return !a || b; }, exec_preset); "Imply", [](bool a, bool b) { return !a || b; }, exec_preset);
static auto nimply_fn = fn::build_mf::SI2_SO<bool, bool, bool>( static auto nimply_fn = mf::build::SI2_SO<bool, bool, bool>(
"Subtract", [](bool a, bool b) { return a && !b; }, exec_preset); "Subtract", [](bool a, bool b) { return a && !b; }, exec_preset);
switch (bnode.custom1) { switch (bnode.custom1) {
@@ -114,7 +114,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -49,20 +49,20 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = data; node->storage = data;
} }
static const fn::MultiFunction *get_multi_function(const bNode &bnode) static const mf::MultiFunction *get_multi_function(const bNode &bnode)
{ {
const NodeCombSepColor &storage = node_storage(bnode); const NodeCombSepColor &storage = node_storage(bnode);
static auto rgba_fn = fn::build_mf::SI4_SO<float, float, float, float, ColorGeometry4f>( static auto rgba_fn = mf::build::SI4_SO<float, float, float, float, ColorGeometry4f>(
"RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); }); "RGB", [](float r, float g, float b, float a) { return ColorGeometry4f(r, g, b, a); });
static auto hsva_fn = fn::build_mf::SI4_SO<float, float, float, float, ColorGeometry4f>( static auto hsva_fn = mf::build::SI4_SO<float, float, float, float, ColorGeometry4f>(
"HSV", [](float h, float s, float v, float a) { "HSV", [](float h, float s, float v, float a) {
ColorGeometry4f r_color; ColorGeometry4f r_color;
hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b); hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b);
r_color.a = a; r_color.a = a;
return r_color; return r_color;
}); });
static auto hsla_fn = fn::build_mf::SI4_SO<float, float, float, float, ColorGeometry4f>( static auto hsla_fn = mf::build::SI4_SO<float, float, float, float, ColorGeometry4f>(
"HSL", [](float h, float s, float l, float a) { "HSL", [](float h, float s, float l, float a) {
ColorGeometry4f color; ColorGeometry4f color;
hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b); hsl_to_rgb(h, s, l, &color.r, &color.g, &color.b);
@@ -85,7 +85,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -164,45 +164,45 @@ static float component_average(float3 a)
return (a.x + a.y + a.z) / 3.0f; return (a.x + a.y + a.z) / 3.0f;
} }
static const fn::MultiFunction *get_multi_function(const bNode &node) static const mf::MultiFunction *get_multi_function(const bNode &node)
{ {
const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage; const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage;
static auto exec_preset_all = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset_all = mf::build::exec_presets::AllSpanOrSingle();
static auto exec_preset_first_two = fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>(); static auto exec_preset_first_two = mf::build::exec_presets::SomeSpanOrSingle<0, 1>();
switch (data->data_type) { switch (data->data_type) {
case SOCK_FLOAT: case SOCK_FLOAT:
switch (data->operation) { switch (data->operation) {
case NODE_COMPARE_LESS_THAN: { case NODE_COMPARE_LESS_THAN: {
static auto fn = fn::build_mf::SI2_SO<float, float, bool>( static auto fn = mf::build::SI2_SO<float, float, bool>(
"Less Than", [](float a, float b) { return a < b; }, exec_preset_all); "Less Than", [](float a, float b) { return a < b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_LESS_EQUAL: { case NODE_COMPARE_LESS_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<float, float, bool>( static auto fn = mf::build::SI2_SO<float, float, bool>(
"Less Equal", [](float a, float b) { return a <= b; }, exec_preset_all); "Less Equal", [](float a, float b) { return a <= b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_GREATER_THAN: { case NODE_COMPARE_GREATER_THAN: {
static auto fn = fn::build_mf::SI2_SO<float, float, bool>( static auto fn = mf::build::SI2_SO<float, float, bool>(
"Greater Than", [](float a, float b) { return a > b; }, exec_preset_all); "Greater Than", [](float a, float b) { return a > b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_GREATER_EQUAL: { case NODE_COMPARE_GREATER_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<float, float, bool>( static auto fn = mf::build::SI2_SO<float, float, bool>(
"Greater Equal", [](float a, float b) { return a >= b; }, exec_preset_all); "Greater Equal", [](float a, float b) { return a >= b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_EQUAL: { case NODE_COMPARE_EQUAL: {
static auto fn = fn::build_mf::SI3_SO<float, float, float, bool>( static auto fn = mf::build::SI3_SO<float, float, float, bool>(
"Equal", "Equal",
[](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; }, [](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_NOT_EQUAL: case NODE_COMPARE_NOT_EQUAL:
static auto fn = fn::build_mf::SI3_SO<float, float, float, bool>( static auto fn = mf::build::SI3_SO<float, float, float, bool>(
"Not Equal", "Not Equal",
[](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; }, [](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; },
exec_preset_first_two); exec_preset_first_two);
@@ -212,32 +212,32 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case SOCK_INT: case SOCK_INT:
switch (data->operation) { switch (data->operation) {
case NODE_COMPARE_LESS_THAN: { case NODE_COMPARE_LESS_THAN: {
static auto fn = fn::build_mf::SI2_SO<int, int, bool>( static auto fn = mf::build::SI2_SO<int, int, bool>(
"Less Than", [](int a, int b) { return a < b; }, exec_preset_all); "Less Than", [](int a, int b) { return a < b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_LESS_EQUAL: { case NODE_COMPARE_LESS_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<int, int, bool>( static auto fn = mf::build::SI2_SO<int, int, bool>(
"Less Equal", [](int a, int b) { return a <= b; }, exec_preset_all); "Less Equal", [](int a, int b) { return a <= b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_GREATER_THAN: { case NODE_COMPARE_GREATER_THAN: {
static auto fn = fn::build_mf::SI2_SO<int, int, bool>( static auto fn = mf::build::SI2_SO<int, int, bool>(
"Greater Than", [](int a, int b) { return a > b; }, exec_preset_all); "Greater Than", [](int a, int b) { return a > b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_GREATER_EQUAL: { case NODE_COMPARE_GREATER_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<int, int, bool>( static auto fn = mf::build::SI2_SO<int, int, bool>(
"Greater Equal", [](int a, int b) { return a >= b; }, exec_preset_all); "Greater Equal", [](int a, int b) { return a >= b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_EQUAL: { case NODE_COMPARE_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<int, int, bool>( static auto fn = mf::build::SI2_SO<int, int, bool>(
"Equal", [](int a, int b) { return a == b; }, exec_preset_all); "Equal", [](int a, int b) { return a == b; }, exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_NOT_EQUAL: { case NODE_COMPARE_NOT_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<int, int, bool>( static auto fn = mf::build::SI2_SO<int, int, bool>(
"Not Equal", [](int a, int b) { return a != b; }, exec_preset_all); "Not Equal", [](int a, int b) { return a != b; }, exec_preset_all);
return &fn; return &fn;
} }
@@ -248,35 +248,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_COMPARE_LESS_THAN: case NODE_COMPARE_LESS_THAN:
switch (data->mode) { switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: { case NODE_COMPARE_MODE_AVERAGE: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Less Than - Average", "Less Than - Average",
[](float3 a, float3 b) { return component_average(a) < component_average(b); }, [](float3 a, float3 b) { return component_average(a) < component_average(b); },
exec_preset_all); exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DOT_PRODUCT: { case NODE_COMPARE_MODE_DOT_PRODUCT: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Less Than - Dot Product", "Less Than - Dot Product",
[](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; }, [](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DIRECTION: { case NODE_COMPARE_MODE_DIRECTION: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Less Than - Direction", "Less Than - Direction",
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; }, [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_ELEMENT: { case NODE_COMPARE_MODE_ELEMENT: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Less Than - Element-wise", "Less Than - Element-wise",
[](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; }, [](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; return &fn;
} }
case NODE_COMPARE_MODE_LENGTH: { case NODE_COMPARE_MODE_LENGTH: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Less Than - Length", "Less Than - Length",
[](float3 a, float3 b) { return math::length(a) < math::length(b); }, [](float3 a, float3 b) { return math::length(a) < math::length(b); },
exec_preset_all); exec_preset_all);
@@ -287,35 +287,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_COMPARE_LESS_EQUAL: case NODE_COMPARE_LESS_EQUAL:
switch (data->mode) { switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: { case NODE_COMPARE_MODE_AVERAGE: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Less Equal - Average", "Less Equal - Average",
[](float3 a, float3 b) { return component_average(a) <= component_average(b); }, [](float3 a, float3 b) { return component_average(a) <= component_average(b); },
exec_preset_all); exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DOT_PRODUCT: { case NODE_COMPARE_MODE_DOT_PRODUCT: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Less Equal - Dot Product", "Less Equal - Dot Product",
[](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; }, [](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DIRECTION: { case NODE_COMPARE_MODE_DIRECTION: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Less Equal - Direction", "Less Equal - Direction",
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; }, [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_ELEMENT: { case NODE_COMPARE_MODE_ELEMENT: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Less Equal - Element-wise", "Less Equal - Element-wise",
[](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; }, [](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; return &fn;
} }
case NODE_COMPARE_MODE_LENGTH: { case NODE_COMPARE_MODE_LENGTH: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Less Equal - Length", "Less Equal - Length",
[](float3 a, float3 b) { return math::length(a) <= math::length(b); }, [](float3 a, float3 b) { return math::length(a) <= math::length(b); },
exec_preset_all); exec_preset_all);
@@ -326,35 +326,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_COMPARE_GREATER_THAN: case NODE_COMPARE_GREATER_THAN:
switch (data->mode) { switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: { case NODE_COMPARE_MODE_AVERAGE: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Greater Than - Average", "Greater Than - Average",
[](float3 a, float3 b) { return component_average(a) > component_average(b); }, [](float3 a, float3 b) { return component_average(a) > component_average(b); },
exec_preset_all); exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DOT_PRODUCT: { case NODE_COMPARE_MODE_DOT_PRODUCT: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Greater Than - Dot Product", "Greater Than - Dot Product",
[](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; }, [](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DIRECTION: { case NODE_COMPARE_MODE_DIRECTION: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Greater Than - Direction", "Greater Than - Direction",
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; }, [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_ELEMENT: { case NODE_COMPARE_MODE_ELEMENT: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Greater Than - Element-wise", "Greater Than - Element-wise",
[](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; }, [](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; return &fn;
} }
case NODE_COMPARE_MODE_LENGTH: { case NODE_COMPARE_MODE_LENGTH: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Greater Than - Length", "Greater Than - Length",
[](float3 a, float3 b) { return math::length(a) > math::length(b); }, [](float3 a, float3 b) { return math::length(a) > math::length(b); },
exec_preset_all); exec_preset_all);
@@ -365,35 +365,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_COMPARE_GREATER_EQUAL: case NODE_COMPARE_GREATER_EQUAL:
switch (data->mode) { switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: { case NODE_COMPARE_MODE_AVERAGE: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Greater Equal - Average", "Greater Equal - Average",
[](float3 a, float3 b) { return component_average(a) >= component_average(b); }, [](float3 a, float3 b) { return component_average(a) >= component_average(b); },
exec_preset_all); exec_preset_all);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DOT_PRODUCT: { case NODE_COMPARE_MODE_DOT_PRODUCT: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Greater Equal - Dot Product", "Greater Equal - Dot Product",
[](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; }, [](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DIRECTION: { case NODE_COMPARE_MODE_DIRECTION: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Greater Equal - Direction", "Greater Equal - Direction",
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; }, [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; },
exec_preset_first_two); exec_preset_first_two);
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_ELEMENT: { case NODE_COMPARE_MODE_ELEMENT: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Greater Equal - Element-wise", "Greater Equal - Element-wise",
[](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; }, [](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; return &fn;
} }
case NODE_COMPARE_MODE_LENGTH: { case NODE_COMPARE_MODE_LENGTH: {
static auto fn = fn::build_mf::SI2_SO<float3, float3, bool>( static auto fn = mf::build::SI2_SO<float3, float3, bool>(
"Greater Equal - Length", "Greater Equal - Length",
[](float3 a, float3 b) { return math::length(a) >= math::length(b); }, [](float3 a, float3 b) { return math::length(a) >= math::length(b); },
exec_preset_all); exec_preset_all);
@@ -404,7 +404,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_COMPARE_EQUAL: case NODE_COMPARE_EQUAL:
switch (data->mode) { switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: { case NODE_COMPARE_MODE_AVERAGE: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Equal - Average", "Equal - Average",
[](float3 a, float3 b, float epsilon) { [](float3 a, float3 b, float epsilon) {
return abs(component_average(a) - component_average(b)) <= epsilon; return abs(component_average(a) - component_average(b)) <= epsilon;
@@ -413,7 +413,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DOT_PRODUCT: { case NODE_COMPARE_MODE_DOT_PRODUCT: {
static auto fn = fn::build_mf::SI4_SO<float3, float3, float, float, bool>( static auto fn = mf::build::SI4_SO<float3, float3, float, float, bool>(
"Equal - Dot Product", "Equal - Dot Product",
[](float3 a, float3 b, float comp, float epsilon) { [](float3 a, float3 b, float comp, float epsilon) {
return abs(math::dot(a, b) - comp) <= epsilon; return abs(math::dot(a, b) - comp) <= epsilon;
@@ -422,7 +422,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DIRECTION: { case NODE_COMPARE_MODE_DIRECTION: {
static auto fn = fn::build_mf::SI4_SO<float3, float3, float, float, bool>( static auto fn = mf::build::SI4_SO<float3, float3, float, float, bool>(
"Equal - Direction", "Equal - Direction",
[](float3 a, float3 b, float angle, float epsilon) { [](float3 a, float3 b, float angle, float epsilon) {
return abs(angle_v3v3(a, b) - angle) <= epsilon; return abs(angle_v3v3(a, b) - angle) <= epsilon;
@@ -431,7 +431,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_ELEMENT: { case NODE_COMPARE_MODE_ELEMENT: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Equal - Element-wise", "Equal - Element-wise",
[](float3 a, float3 b, float epsilon) { [](float3 a, float3 b, float epsilon) {
return abs(a.x - b.x) <= epsilon && abs(a.y - b.y) <= epsilon && return abs(a.x - b.x) <= epsilon && abs(a.y - b.y) <= epsilon &&
@@ -441,7 +441,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_LENGTH: { case NODE_COMPARE_MODE_LENGTH: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Equal - Length", "Equal - Length",
[](float3 a, float3 b, float epsilon) { [](float3 a, float3 b, float epsilon) {
return abs(math::length(a) - math::length(b)) <= epsilon; return abs(math::length(a) - math::length(b)) <= epsilon;
@@ -454,7 +454,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_COMPARE_NOT_EQUAL: case NODE_COMPARE_NOT_EQUAL:
switch (data->mode) { switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: { case NODE_COMPARE_MODE_AVERAGE: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Not Equal - Average", "Not Equal - Average",
[](float3 a, float3 b, float epsilon) { [](float3 a, float3 b, float epsilon) {
return abs(component_average(a) - component_average(b)) > epsilon; return abs(component_average(a) - component_average(b)) > epsilon;
@@ -463,7 +463,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DOT_PRODUCT: { case NODE_COMPARE_MODE_DOT_PRODUCT: {
static auto fn = fn::build_mf::SI4_SO<float3, float3, float, float, bool>( static auto fn = mf::build::SI4_SO<float3, float3, float, float, bool>(
"Not Equal - Dot Product", "Not Equal - Dot Product",
[](float3 a, float3 b, float comp, float epsilon) { [](float3 a, float3 b, float comp, float epsilon) {
return abs(math::dot(a, b) - comp) >= epsilon; return abs(math::dot(a, b) - comp) >= epsilon;
@@ -472,7 +472,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_DIRECTION: { case NODE_COMPARE_MODE_DIRECTION: {
static auto fn = fn::build_mf::SI4_SO<float3, float3, float, float, bool>( static auto fn = mf::build::SI4_SO<float3, float3, float, float, bool>(
"Not Equal - Direction", "Not Equal - Direction",
[](float3 a, float3 b, float angle, float epsilon) { [](float3 a, float3 b, float angle, float epsilon) {
return abs(angle_v3v3(a, b) - angle) > epsilon; return abs(angle_v3v3(a, b) - angle) > epsilon;
@@ -481,7 +481,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_ELEMENT: { case NODE_COMPARE_MODE_ELEMENT: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Not Equal - Element-wise", "Not Equal - Element-wise",
[](float3 a, float3 b, float epsilon) { [](float3 a, float3 b, float epsilon) {
return abs(a.x - b.x) > epsilon || abs(a.y - b.y) > epsilon || return abs(a.x - b.x) > epsilon || abs(a.y - b.y) > epsilon ||
@@ -491,7 +491,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_MODE_LENGTH: { case NODE_COMPARE_MODE_LENGTH: {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, bool>( static auto fn = mf::build::SI3_SO<float3, float3, float, bool>(
"Not Equal - Length", "Not Equal - Length",
[](float3 a, float3 b, float epsilon) { [](float3 a, float3 b, float epsilon) {
return abs(math::length(a) - math::length(b)) > epsilon; return abs(math::length(a) - math::length(b)) > epsilon;
@@ -506,7 +506,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case SOCK_RGBA: case SOCK_RGBA:
switch (data->operation) { switch (data->operation) {
case NODE_COMPARE_EQUAL: { case NODE_COMPARE_EQUAL: {
static auto fn = fn::build_mf::SI3_SO<ColorGeometry4f, ColorGeometry4f, float, bool>( static auto fn = mf::build::SI3_SO<ColorGeometry4f, ColorGeometry4f, float, bool>(
"Equal", "Equal",
[](ColorGeometry4f a, ColorGeometry4f b, float epsilon) { [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
return abs(a.r - b.r) <= epsilon && abs(a.g - b.g) <= epsilon && return abs(a.r - b.r) <= epsilon && abs(a.g - b.g) <= epsilon &&
@@ -516,7 +516,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_NOT_EQUAL: { case NODE_COMPARE_NOT_EQUAL: {
static auto fn = fn::build_mf::SI3_SO<ColorGeometry4f, ColorGeometry4f, float, bool>( static auto fn = mf::build::SI3_SO<ColorGeometry4f, ColorGeometry4f, float, bool>(
"Not Equal", "Not Equal",
[](ColorGeometry4f a, ColorGeometry4f b, float epsilon) { [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
return abs(a.r - b.r) > epsilon || abs(a.g - b.g) > epsilon || return abs(a.r - b.r) > epsilon || abs(a.g - b.g) > epsilon ||
@@ -526,7 +526,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_COLOR_BRIGHTER: { case NODE_COMPARE_COLOR_BRIGHTER: {
static auto fn = fn::build_mf::SI2_SO<ColorGeometry4f, ColorGeometry4f, bool>( static auto fn = mf::build::SI2_SO<ColorGeometry4f, ColorGeometry4f, bool>(
"Brighter", "Brighter",
[](ColorGeometry4f a, ColorGeometry4f b) { [](ColorGeometry4f a, ColorGeometry4f b) {
return rgb_to_grayscale(a) > rgb_to_grayscale(b); return rgb_to_grayscale(a) > rgb_to_grayscale(b);
@@ -535,7 +535,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
return &fn; return &fn;
} }
case NODE_COMPARE_COLOR_DARKER: { case NODE_COMPARE_COLOR_DARKER: {
static auto fn = fn::build_mf::SI2_SO<ColorGeometry4f, ColorGeometry4f, bool>( static auto fn = mf::build::SI2_SO<ColorGeometry4f, ColorGeometry4f, bool>(
"Darker", "Darker",
[](ColorGeometry4f a, ColorGeometry4f b) { [](ColorGeometry4f a, ColorGeometry4f b) {
return rgb_to_grayscale(a) < rgb_to_grayscale(b); return rgb_to_grayscale(a) < rgb_to_grayscale(b);
@@ -548,12 +548,12 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case SOCK_STRING: case SOCK_STRING:
switch (data->operation) { switch (data->operation) {
case NODE_COMPARE_EQUAL: { case NODE_COMPARE_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<std::string, std::string, bool>( static auto fn = mf::build::SI2_SO<std::string, std::string, bool>(
"Equal", [](std::string a, std::string b) { return a == b; }); "Equal", [](std::string a, std::string b) { return a == b; });
return &fn; return &fn;
} }
case NODE_COMPARE_NOT_EQUAL: { case NODE_COMPARE_NOT_EQUAL: {
static auto fn = fn::build_mf::SI2_SO<std::string, std::string, bool>( static auto fn = mf::build::SI2_SO<std::string, std::string, bool>(
"Not Equal", [](std::string a, std::string b) { return a != b; }); "Not Equal", [](std::string a, std::string b) { return a != b; });
return &fn; return &fn;
} }
@@ -565,7 +565,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -36,16 +36,16 @@ static void node_label(const bNodeTree * /*tree*/, const bNode *node, char *labe
BLI_strncpy(label, IFACE_(name), maxlen); BLI_strncpy(label, IFACE_(name), maxlen);
} }
static const fn::MultiFunction *get_multi_function(const bNode &bnode) static const mf::MultiFunction *get_multi_function(const bNode &bnode)
{ {
static auto exec_preset = fn::build_mf::exec_presets::AllSpanOrSingle(); static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
static auto round_fn = fn::build_mf::SI1_SO<float, int>( static auto round_fn = mf::build::SI1_SO<float, int>(
"Round", [](float a) { return int(round(a)); }, exec_preset); "Round", [](float a) { return int(round(a)); }, exec_preset);
static auto floor_fn = fn::build_mf::SI1_SO<float, int>( static auto floor_fn = mf::build::SI1_SO<float, int>(
"Floor", [](float a) { return int(floor(a)); }, exec_preset); "Floor", [](float a) { return int(floor(a)); }, exec_preset);
static auto ceil_fn = fn::build_mf::SI1_SO<float, int>( static auto ceil_fn = mf::build::SI1_SO<float, int>(
"Ceiling", [](float a) { return int(ceil(a)); }, exec_preset); "Ceiling", [](float a) { return int(ceil(a)); }, exec_preset);
static auto trunc_fn = fn::build_mf::SI1_SO<float, int>( static auto trunc_fn = mf::build::SI1_SO<float, int>(
"Truncate", [](float a) { return int(trunc(a)); }, exec_preset); "Truncate", [](float a) { return int(trunc(a)); }, exec_preset);
switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) { switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) {
@@ -65,7 +65,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -24,7 +24,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const bNode &bnode = builder.node(); const bNode &bnode = builder.node();
NodeInputBool *node_storage = static_cast<NodeInputBool *>(bnode.storage); NodeInputBool *node_storage = static_cast<NodeInputBool *>(bnode.storage);
builder.construct_and_set_matching_fn<fn::CustomMF_Constant<bool>>(node_storage->boolean); builder.construct_and_set_matching_fn<mf::CustomMF_Constant<bool>>(node_storage->boolean);
} }
static void node_init(bNodeTree * /*tree*/, bNode *node) static void node_init(bNodeTree * /*tree*/, bNode *node)

View File

@@ -25,7 +25,7 @@ static void node_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &
const bNode &bnode = builder.node(); const bNode &bnode = builder.node();
NodeInputColor *node_storage = static_cast<NodeInputColor *>(bnode.storage); NodeInputColor *node_storage = static_cast<NodeInputColor *>(bnode.storage);
blender::ColorGeometry4f color = (ColorGeometry4f)node_storage->color; blender::ColorGeometry4f color = (ColorGeometry4f)node_storage->color;
builder.construct_and_set_matching_fn<blender::fn::CustomMF_Constant<ColorGeometry4f>>(color); builder.construct_and_set_matching_fn<blender::mf::CustomMF_Constant<ColorGeometry4f>>(color);
} }
static void node_init(bNodeTree * /*tree*/, bNode *node) static void node_init(bNodeTree * /*tree*/, bNode *node)

View File

@@ -24,7 +24,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const bNode &bnode = builder.node(); const bNode &bnode = builder.node();
NodeInputInt *node_storage = static_cast<NodeInputInt *>(bnode.storage); NodeInputInt *node_storage = static_cast<NodeInputInt *>(bnode.storage);
builder.construct_and_set_matching_fn<fn::CustomMF_Constant<int>>(node_storage->integer); builder.construct_and_set_matching_fn<mf::CustomMF_Constant<int>>(node_storage->integer);
} }
static void node_init(bNodeTree * /*tree*/, bNode *node) static void node_init(bNodeTree * /*tree*/, bNode *node)

View File

@@ -10,24 +10,24 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_output<decl::String>(N_("Tab")); b.add_output<decl::String>(N_("Tab"));
} }
class MF_SpecialCharacters : public fn::MultiFunction { class MF_SpecialCharacters : public mf::MultiFunction {
public: public:
MF_SpecialCharacters() MF_SpecialCharacters()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Special Characters", signature}; mf::SignatureBuilder builder{"Special Characters", signature};
builder.single_output<std::string>("Line Break"); builder.single_output<std::string>("Line Break");
builder.single_output<std::string>("Tab"); builder.single_output<std::string>("Tab");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
MutableSpan<std::string> lb = params.uninitialized_single_output<std::string>(0, "Line Break"); MutableSpan<std::string> lb = params.uninitialized_single_output<std::string>(0, "Line Break");
MutableSpan<std::string> tab = params.uninitialized_single_output<std::string>(1, "Tab"); MutableSpan<std::string> tab = params.uninitialized_single_output<std::string>(1, "Tab");

View File

@@ -23,7 +23,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
const bNode &bnode = builder.node(); const bNode &bnode = builder.node();
NodeInputString *node_storage = static_cast<NodeInputString *>(bnode.storage); NodeInputString *node_storage = static_cast<NodeInputString *>(bnode.storage);
std::string string = std::string((node_storage->string) ? node_storage->string : ""); std::string string = std::string((node_storage->string) ? node_storage->string : "");
builder.construct_and_set_matching_fn<fn::CustomMF_Constant<std::string>>(std::move(string)); builder.construct_and_set_matching_fn<mf::CustomMF_Constant<std::string>>(std::move(string));
} }
static void node_init(bNodeTree * /*tree*/, bNode *node) static void node_init(bNodeTree * /*tree*/, bNode *node)

View File

@@ -25,7 +25,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
const bNode &bnode = builder.node(); const bNode &bnode = builder.node();
NodeInputVector *node_storage = static_cast<NodeInputVector *>(bnode.storage); NodeInputVector *node_storage = static_cast<NodeInputVector *>(bnode.storage);
float3 vector(node_storage->vector); float3 vector(node_storage->vector);
builder.construct_and_set_matching_fn<fn::CustomMF_Constant<float3>>(vector); builder.construct_and_set_matching_fn<mf::CustomMF_Constant<float3>>(vector);
} }
static void node_init(bNodeTree * /*tree*/, bNode *node) static void node_init(bNodeTree * /*tree*/, bNode *node)

View File

@@ -141,7 +141,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
switch (data_type) { switch (data_type) {
case CD_PROP_FLOAT3: { case CD_PROP_FLOAT3: {
static auto fn = fn::build_mf::SI4_SO<float3, float3, int, int, float3>( static auto fn = mf::build::SI4_SO<float3, float3, int, int, float3>(
"Random Vector", "Random Vector",
[](float3 min_value, float3 max_value, int id, int seed) -> float3 { [](float3 min_value, float3 max_value, int id, int seed) -> float3 {
const float x = noise::hash_to_float(seed, id, 0); const float x = noise::hash_to_float(seed, id, 0);
@@ -149,23 +149,23 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
const float z = noise::hash_to_float(seed, id, 2); const float z = noise::hash_to_float(seed, id, 2);
return float3(x, y, z) * (max_value - min_value) + min_value; return float3(x, y, z) * (max_value - min_value) + min_value;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<2>()); mf::build::exec_presets::SomeSpanOrSingle<2>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }
case CD_PROP_FLOAT: { case CD_PROP_FLOAT: {
static auto fn = fn::build_mf::SI4_SO<float, float, int, int, float>( static auto fn = mf::build::SI4_SO<float, float, int, int, float>(
"Random Float", "Random Float",
[](float min_value, float max_value, int id, int seed) -> float { [](float min_value, float max_value, int id, int seed) -> float {
const float value = noise::hash_to_float(seed, id); const float value = noise::hash_to_float(seed, id);
return value * (max_value - min_value) + min_value; return value * (max_value - min_value) + min_value;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<2>()); mf::build::exec_presets::SomeSpanOrSingle<2>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }
case CD_PROP_INT32: { case CD_PROP_INT32: {
static auto fn = fn::build_mf::SI4_SO<int, int, int, int, int>( static auto fn = mf::build::SI4_SO<int, int, int, int, int>(
"Random Int", "Random Int",
[](int min_value, int max_value, int id, int seed) -> int { [](int min_value, int max_value, int id, int seed) -> int {
const float value = noise::hash_to_float(id, seed); const float value = noise::hash_to_float(id, seed);
@@ -173,17 +173,17 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
* distribution for the first and last values (See T93591). */ * distribution for the first and last values (See T93591). */
return floor(value * (max_value + 1 - min_value) + min_value); return floor(value * (max_value + 1 - min_value) + min_value);
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<2>()); mf::build::exec_presets::SomeSpanOrSingle<2>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }
case CD_PROP_BOOL: { case CD_PROP_BOOL: {
static auto fn = fn::build_mf::SI3_SO<float, int, int, bool>( static auto fn = mf::build::SI3_SO<float, int, int, bool>(
"Random Bool", "Random Bool",
[](float probability, int id, int seed) -> bool { [](float probability, int id, int seed) -> bool {
return noise::hash_to_float(id, seed) <= probability; return noise::hash_to_float(id, seed) <= probability;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<1>()); mf::build::exec_presets::SomeSpanOrSingle<1>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }

View File

@@ -30,12 +30,10 @@ static std::string replace_all(const StringRefNull str,
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto substring_fn = static auto substring_fn = mf::build::SI3_SO<std::string, std::string, std::string, std::string>(
fn::build_mf::SI3_SO<std::string, std::string, std::string, std::string>( "Replace", [](const std::string &str, const std::string &find, const std::string &replace) {
"Replace", return replace_all(str, find, 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); builder.set_matching_fn(&substring_fn);
} }

View File

@@ -52,9 +52,9 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
} }
static const fn::MultiFunction *get_multi_function(const bNode &bnode) static const mf::MultiFunction *get_multi_function(const bNode &bnode)
{ {
static auto obj_euler_rot = fn::build_mf::SI2_SO<float3, float3, float3>( static auto obj_euler_rot = mf::build::SI2_SO<float3, float3, float3>(
"Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) { "Rotate Euler by Euler/Object", [](const float3 &input, const float3 &rotation) {
float input_mat[3][3]; float input_mat[3][3];
eul_to_mat3(input_mat, input); eul_to_mat3(input_mat, input);
@@ -66,7 +66,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
mat3_to_eul(result, mat_res); mat3_to_eul(result, mat_res);
return result; return result;
}); });
static auto obj_AA_rot = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto obj_AA_rot = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate Euler by AxisAngle/Object", "Rotate Euler by AxisAngle/Object",
[](const float3 &input, const float3 &axis, float angle) { [](const float3 &input, const float3 &axis, float angle) {
float input_mat[3][3]; float input_mat[3][3];
@@ -79,7 +79,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
mat3_to_eul(result, mat_res); mat3_to_eul(result, mat_res);
return result; return result;
}); });
static auto local_euler_rot = fn::build_mf::SI2_SO<float3, float3, float3>( static auto local_euler_rot = mf::build::SI2_SO<float3, float3, float3>(
"Rotate Euler by Euler/Local", [](const float3 &input, const float3 &rotation) { "Rotate Euler by Euler/Local", [](const float3 &input, const float3 &rotation) {
float input_mat[3][3]; float input_mat[3][3];
eul_to_mat3(input_mat, input); eul_to_mat3(input_mat, input);
@@ -91,7 +91,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
mat3_to_eul(result, mat_res); mat3_to_eul(result, mat_res);
return result; return result;
}); });
static auto local_AA_rot = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto local_AA_rot = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate Euler by AxisAngle/Local", [](const float3 &input, const float3 &axis, float angle) { "Rotate Euler by AxisAngle/Local", [](const float3 &input, const float3 &axis, float angle) {
float input_mat[3][3]; float input_mat[3][3];
eul_to_mat3(input_mat, input); eul_to_mat3(input_mat, input);
@@ -107,12 +107,12 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
short space = bnode.custom2; short space = bnode.custom2;
if (type == FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE) { if (type == FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE) {
return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ?
static_cast<const MultiFunction *>(&obj_AA_rot) : static_cast<const mf::MultiFunction *>(&obj_AA_rot) :
&local_AA_rot; &local_AA_rot;
} }
if (type == FN_NODE_ROTATE_EULER_TYPE_EULER) { if (type == FN_NODE_ROTATE_EULER_TYPE_EULER) {
return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ? return space == FN_NODE_ROTATE_EULER_SPACE_OBJECT ?
static_cast<const MultiFunction *>(&obj_euler_rot) : static_cast<const mf::MultiFunction *>(&obj_euler_rot) :
&local_euler_rot; &local_euler_rot;
} }
BLI_assert_unreachable(); BLI_assert_unreachable();
@@ -121,7 +121,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -37,18 +37,18 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = data; node->storage = data;
} }
class SeparateRGBAFunction : public fn::MultiFunction { class SeparateRGBAFunction : public mf::MultiFunction {
public: public:
SeparateRGBAFunction() SeparateRGBAFunction()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Separate Color", signature}; mf::SignatureBuilder builder{"Separate Color", signature};
builder.single_input<ColorGeometry4f>("Color"); builder.single_input<ColorGeometry4f>("Color");
builder.single_output<float>("Red"); builder.single_output<float>("Red");
builder.single_output<float>("Green"); builder.single_output<float>("Green");
@@ -57,7 +57,7 @@ class SeparateRGBAFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0, const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
"Color"); "Color");
@@ -99,18 +99,18 @@ class SeparateRGBAFunction : public fn::MultiFunction {
} }
}; };
class SeparateHSVAFunction : public fn::MultiFunction { class SeparateHSVAFunction : public mf::MultiFunction {
public: public:
SeparateHSVAFunction() SeparateHSVAFunction()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Separate Color", signature}; mf::SignatureBuilder builder{"Separate Color", signature};
builder.single_input<ColorGeometry4f>("Color"); builder.single_input<ColorGeometry4f>("Color");
builder.single_output<float>("Hue"); builder.single_output<float>("Hue");
builder.single_output<float>("Saturation"); builder.single_output<float>("Saturation");
@@ -119,7 +119,7 @@ class SeparateHSVAFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0, const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
"Color"); "Color");
@@ -140,18 +140,18 @@ class SeparateHSVAFunction : public fn::MultiFunction {
} }
}; };
class SeparateHSLAFunction : public fn::MultiFunction { class SeparateHSLAFunction : public mf::MultiFunction {
public: public:
SeparateHSLAFunction() SeparateHSLAFunction()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Separate Color", signature}; mf::SignatureBuilder builder{"Separate Color", signature};
builder.single_input<ColorGeometry4f>("Color"); builder.single_input<ColorGeometry4f>("Color");
builder.single_output<float>("Hue"); builder.single_output<float>("Hue");
builder.single_output<float>("Saturation"); builder.single_output<float>("Saturation");
@@ -160,7 +160,7 @@ class SeparateHSLAFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0, const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
"Color"); "Color");

View File

@@ -16,7 +16,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto slice_fn = fn::build_mf::SI3_SO<std::string, int, int, std::string>( static auto slice_fn = mf::build::SI3_SO<std::string, int, int, std::string>(
"Slice", [](const std::string &str, int a, int b) { "Slice", [](const std::string &str, int a, int b) {
const int len = BLI_strlen_utf8(str.c_str()); 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 start = BLI_str_utf8_offset_from_index(str.c_str(), std::clamp(a, 0, len));

View File

@@ -16,7 +16,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto str_len_fn = fn::build_mf::SI1_SO<std::string, int>( static auto str_len_fn = mf::build::SI1_SO<std::string, int>(
"String Length", [](const std::string &a) { return BLI_strlen_utf8(a.c_str()); }); "String Length", [](const std::string &a) { return BLI_strlen_utf8(a.c_str()); });
builder.set_matching_fn(&str_len_fn); builder.set_matching_fn(&str_len_fn);
} }

View File

@@ -14,7 +14,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder) static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto to_str_fn = fn::build_mf::SI2_SO<float, int, std::string>( static auto to_str_fn = mf::build::SI2_SO<float, int, std::string>(
"Value To String", [](float a, int b) { "Value To String", [](float a, int b) {
std::stringstream stream; std::stringstream stream;
stream << std::fixed << std::setprecision(std::max(0, b)) << a; stream << std::fixed << std::setprecision(std::max(0, b)) << a;

View File

@@ -201,7 +201,7 @@ static void sample_indices_and_factors_to_compressed(const Span<float> accumulat
* Given an array of accumulated lengths, find the segment indices that * Given an array of accumulated lengths, find the segment indices that
* sample lengths lie on, and how far along the segment they are. * sample lengths lie on, and how far along the segment they are.
*/ */
class SampleFloatSegmentsFunction : public fn::MultiFunction { class SampleFloatSegmentsFunction : public mf::MultiFunction {
private: private:
Array<float> accumulated_lengths_; Array<float> accumulated_lengths_;
GeometryNodeCurveSampleMode length_mode_; GeometryNodeCurveSampleMode length_mode_;
@@ -211,14 +211,14 @@ class SampleFloatSegmentsFunction : public fn::MultiFunction {
const GeometryNodeCurveSampleMode length_mode) const GeometryNodeCurveSampleMode length_mode)
: accumulated_lengths_(std::move(accumulated_lengths)), length_mode_(length_mode) : accumulated_lengths_(std::move(accumulated_lengths)), length_mode_(length_mode)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample Curve Index", signature}; mf::SignatureBuilder builder{"Sample Curve Index", signature};
builder.single_input<float>("Length"); builder.single_input<float>("Length");
builder.single_output<int>("Curve Index"); builder.single_output<int>("Curve Index");
@@ -226,7 +226,7 @@ class SampleFloatSegmentsFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArraySpan<float> lengths = params.readonly_single_input<float>(0, "Length"); const VArraySpan<float> lengths = params.readonly_single_input<float>(0, "Length");
MutableSpan<int> indices = params.uninitialized_single_output<int>(1, "Curve Index"); MutableSpan<int> indices = params.uninitialized_single_output<int>(1, "Curve Index");
@@ -238,7 +238,7 @@ class SampleFloatSegmentsFunction : public fn::MultiFunction {
} }
}; };
class SampleCurveFunction : public fn::MultiFunction { class SampleCurveFunction : public mf::MultiFunction {
private: private:
/** /**
* The function holds a geometry set instead of curves or a curve component reference in order * The function holds a geometry set instead of curves or a curve component reference in order
@@ -249,7 +249,7 @@ class SampleCurveFunction : public fn::MultiFunction {
GField src_field_; GField src_field_;
GeometryNodeCurveSampleMode length_mode_; GeometryNodeCurveSampleMode length_mode_;
fn::MFSignature signature_; mf::Signature signature_;
std::optional<bke::CurvesFieldContext> source_context_; std::optional<bke::CurvesFieldContext> source_context_;
std::unique_ptr<FieldEvaluator> source_evaluator_; std::unique_ptr<FieldEvaluator> source_evaluator_;
@@ -266,10 +266,10 @@ class SampleCurveFunction : public fn::MultiFunction {
this->evaluate_source(); this->evaluate_source();
} }
fn::MFSignature create_signature() mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample Curve", signature}; mf::SignatureBuilder builder{"Sample Curve", signature};
builder.single_input<int>("Curve Index"); builder.single_input<int>("Curve Index");
builder.single_input<float>("Length"); builder.single_input<float>("Length");
builder.single_output<float3>("Position"); builder.single_output<float3>("Position");
@@ -279,7 +279,7 @@ class SampleCurveFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
MutableSpan<float3> sampled_positions = params.uninitialized_single_output_if_required<float3>( MutableSpan<float3> sampled_positions = params.uninitialized_single_output_if_required<float3>(
2, "Position"); 2, "Position");

View File

@@ -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 /* 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. */ * can take care of the multiplication and to simplify each extrude function. */
static auto multiply_fn = fn::build_mf::SI2_SO<float3, float, float3>( static auto multiply_fn = mf::build::SI2_SO<float3, float, float3>(
"Scale", "Scale",
[](const float3 &offset, const float scale) { return offset * scale; }, [](const float3 &offset, const float scale) { return offset * scale; },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
std::shared_ptr<FieldOperation> multiply_op = std::make_shared<FieldOperation>( std::shared_ptr<FieldOperation> multiply_op = std::make_shared<FieldOperation>(
FieldOperation(multiply_fn, {std::move(offset_field), std::move(scale_field)})); FieldOperation(multiply_fn, {std::move(offset_field), std::move(scale_field)}));
const Field<float3> final_offset{std::move(multiply_op)}; const Field<float3> final_offset{std::move(multiply_op)};

View File

@@ -45,7 +45,7 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->storage = tex; node->storage = tex;
} }
class ImageFieldsFunction : public fn::MultiFunction { class ImageFieldsFunction : public mf::MultiFunction {
private: private:
const int8_t interpolation_; const int8_t interpolation_;
const int8_t extension_; const int8_t extension_;
@@ -64,7 +64,7 @@ class ImageFieldsFunction : public fn::MultiFunction {
image_(image), image_(image),
image_user_(image_user) image_user_(image_user)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
image_buffer_ = BKE_image_acquire_ibuf(&image_, &image_user_, &image_lock_); image_buffer_ = BKE_image_acquire_ibuf(&image_, &image_user_, &image_lock_);
@@ -91,10 +91,10 @@ class ImageFieldsFunction : public fn::MultiFunction {
BKE_image_release_ibuf(&image_, image_buffer_, image_lock_); BKE_image_release_ibuf(&image_, image_buffer_, image_lock_);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"ImageFunction", signature}; mf::SignatureBuilder builder{"ImageFunction", signature};
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_output<ColorGeometry4f>("Color"); builder.single_output<ColorGeometry4f>("Color");
builder.single_output<float>("Alpha"); builder.single_output<float>("Alpha");
@@ -319,7 +319,7 @@ class ImageFieldsFunction : public fn::MultiFunction {
} }
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "Vector"); const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "Vector");
MutableSpan<ColorGeometry4f> r_color = params.uninitialized_single_output<ColorGeometry4f>( MutableSpan<ColorGeometry4f> r_color = params.uninitialized_single_output<ColorGeometry4f>(

View File

@@ -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. /* Use another multi-function operation to make sure the input radius is greater than zero.
* TODO: Use mutable multi-function once that is supported. */ * TODO: Use mutable multi-function once that is supported. */
static auto max_zero_fn = fn::build_mf::SI1_SO<float, float>( static auto max_zero_fn = mf::build::SI1_SO<float, float>(
__func__, __func__,
[](float value) { return std::max(0.0f, value); }, [](float value) { return std::max(0.0f, value); },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
auto max_zero_op = std::make_shared<FieldOperation>( auto max_zero_op = std::make_shared<FieldOperation>(
FieldOperation(max_zero_fn, {std::move(radius)})); FieldOperation(max_zero_fn, {std::move(radius)}));
Field<float> positive_radius(std::move(max_zero_op), 0); Field<float> positive_radius(std::move(max_zero_op), 0);

View File

@@ -129,7 +129,7 @@ static bool calculate_pointcloud_proximity(const VArray<float3> &positions,
return true; return true;
} }
class ProximityFunction : public fn::MultiFunction { class ProximityFunction : public mf::MultiFunction {
private: private:
GeometrySet target_; GeometrySet target_;
GeometryNodeProximityTargetType type_; GeometryNodeProximityTargetType type_;
@@ -138,21 +138,21 @@ class ProximityFunction : public fn::MultiFunction {
ProximityFunction(GeometrySet target, GeometryNodeProximityTargetType type) ProximityFunction(GeometrySet target, GeometryNodeProximityTargetType type)
: target_(std::move(target)), type_(type) : target_(std::move(target)), type_(type)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Geometry Proximity", signature}; mf::SignatureBuilder builder{"Geometry Proximity", signature};
builder.single_input<float3>("Source Position"); builder.single_input<float3>("Source Position");
builder.single_output<float3>("Position"); builder.single_output<float3>("Position");
builder.single_output<float>("Distance"); builder.single_output<float>("Distance");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &src_positions = params.readonly_single_input<float3>(0, const VArray<float3> &src_positions = params.readonly_single_input<float3>(0,
"Source Position"); "Source Position");

View File

@@ -202,7 +202,7 @@ static void raycast_to_mesh(IndexMask mask,
} }
} }
class RaycastFunction : public fn::MultiFunction { class RaycastFunction : public mf::MultiFunction {
private: private:
GeometrySet target_; GeometrySet target_;
GeometryNodeRaycastMapMode mapping_; GeometryNodeRaycastMapMode mapping_;
@@ -217,7 +217,7 @@ class RaycastFunction : public fn::MultiFunction {
* the field inputs for better performance. */ * the field inputs for better performance. */
const eAttrDomain domain_ = ATTR_DOMAIN_CORNER; const eAttrDomain domain_ = ATTR_DOMAIN_CORNER;
fn::MFSignature signature_; mf::Signature signature_;
public: public:
RaycastFunction(GeometrySet target, GField src_field, GeometryNodeRaycastMapMode mapping) RaycastFunction(GeometrySet target, GField src_field, GeometryNodeRaycastMapMode mapping)
@@ -229,10 +229,10 @@ class RaycastFunction : public fn::MultiFunction {
this->set_signature(&signature_); this->set_signature(&signature_);
} }
fn::MFSignature create_signature() mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Geometry Proximity", signature}; mf::SignatureBuilder builder{"Geometry Proximity", signature};
builder.single_input<float3>("Source Position"); builder.single_input<float3>("Source Position");
builder.single_input<float3>("Ray Direction"); builder.single_input<float3>("Ray Direction");
builder.single_input<float>("Ray Length"); builder.single_input<float>("Ray Length");
@@ -246,7 +246,7 @@ class RaycastFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
/* Hit positions are always necessary for retrieving the attribute from the target if that /* Hit positions are always necessary for retrieving the attribute from the target if that
* output is required, so always retrieve a span from the evaluator in that case (it's * output is required, so always retrieve a span from the evaluator in that case (it's

View File

@@ -176,13 +176,13 @@ void copy_with_clamped_indices(const VArray<T> &src,
* instance geometry set in the source. A future optimization could be removing that limitation * instance geometry set in the source. A future optimization could be removing that limitation
* internally. * internally.
*/ */
class SampleIndexFunction : public fn::MultiFunction { class SampleIndexFunction : public mf::MultiFunction {
GeometrySet src_geometry_; GeometrySet src_geometry_;
GField src_field_; GField src_field_;
eAttrDomain domain_; eAttrDomain domain_;
bool clamp_; bool clamp_;
fn::MFSignature signature_; mf::Signature signature_;
std::optional<bke::GeometryFieldContext> geometry_context_; std::optional<bke::GeometryFieldContext> geometry_context_;
std::unique_ptr<FieldEvaluator> evaluator_; std::unique_ptr<FieldEvaluator> evaluator_;
@@ -206,10 +206,10 @@ class SampleIndexFunction : public fn::MultiFunction {
this->evaluate_field(); this->evaluate_field();
} }
fn::MFSignature create_signature() mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample Index", signature}; mf::SignatureBuilder builder{"Sample Index", signature};
builder.single_input<int>("Index"); builder.single_input<int>("Index");
builder.single_output("Value", src_field_.cpp_type()); builder.single_output("Value", src_field_.cpp_type());
return signature; return signature;
@@ -229,7 +229,7 @@ class SampleIndexFunction : public fn::MultiFunction {
src_data_ = &evaluator_->get_evaluated(0); src_data_ = &evaluator_->get_evaluated(0);
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<int> &indices = params.readonly_single_input<int>(0, "Index"); const VArray<int> &indices = params.readonly_single_input<int>(0, "Index");
GMutableSpan dst = params.uninitialized_single_output(1, "Value"); GMutableSpan dst = params.uninitialized_single_output(1, "Value");

View File

@@ -232,13 +232,13 @@ static const GeometryComponent *find_source_component(const GeometrySet &geometr
return nullptr; return nullptr;
} }
class SampleNearestFunction : public fn::MultiFunction { class SampleNearestFunction : public mf::MultiFunction {
GeometrySet source_; GeometrySet source_;
eAttrDomain domain_; eAttrDomain domain_;
const GeometryComponent *src_component_; const GeometryComponent *src_component_;
fn::MFSignature signature_; mf::Signature signature_;
public: public:
SampleNearestFunction(GeometrySet geometry, eAttrDomain domain) SampleNearestFunction(GeometrySet geometry, eAttrDomain domain)
@@ -251,16 +251,16 @@ class SampleNearestFunction : public fn::MultiFunction {
this->src_component_ = find_source_component(source_, domain_); this->src_component_ = find_source_component(source_, domain_);
} }
fn::MFSignature create_signature() mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample Nearest", signature}; mf::SignatureBuilder builder{"Sample Nearest", signature};
builder.single_input<float3>("Position"); builder.single_input<float3>("Position");
builder.single_output<int>("Index"); builder.single_output<int>("Index");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position"); const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position");
MutableSpan<int> indices = params.uninitialized_single_output<int>(1, "Index"); MutableSpan<int> indices = params.uninitialized_single_output<int>(1, "Index");

View File

@@ -116,7 +116,7 @@ static void get_closest_mesh_looptris(const Mesh &mesh,
* function could be called many times, calculate the data from the source geometry once and store * function could be called many times, calculate the data from the source geometry once and store
* it for later. * it for later.
*/ */
class SampleNearestSurfaceFunction : public fn::MultiFunction { class SampleNearestSurfaceFunction : public mf::MultiFunction {
GeometrySet source_; GeometrySet source_;
GField src_field_; GField src_field_;
@@ -128,7 +128,7 @@ class SampleNearestSurfaceFunction : public fn::MultiFunction {
*/ */
eAttrDomain domain_ = ATTR_DOMAIN_CORNER; eAttrDomain domain_ = ATTR_DOMAIN_CORNER;
fn::MFSignature signature_; mf::Signature signature_;
std::optional<bke::MeshFieldContext> source_context_; std::optional<bke::MeshFieldContext> source_context_;
std::unique_ptr<FieldEvaluator> source_evaluator_; std::unique_ptr<FieldEvaluator> source_evaluator_;
@@ -144,16 +144,16 @@ class SampleNearestSurfaceFunction : public fn::MultiFunction {
this->evaluate_source_field(); this->evaluate_source_field();
} }
fn::MFSignature create_signature() mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample Nearest Surface", signature}; mf::SignatureBuilder builder{"Sample Nearest Surface", signature};
builder.single_input<float3>("Position"); builder.single_input<float3>("Position");
builder.single_output("Value", src_field_.cpp_type()); builder.single_output("Value", src_field_.cpp_type());
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position"); const VArray<float3> &positions = params.readonly_single_input<float3>(0, "Position");
GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Value"); GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Value");

View File

@@ -105,7 +105,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
} }
} }
class SampleMeshBarycentricFunction : public fn::MultiFunction { class SampleMeshBarycentricFunction : public mf::MultiFunction {
GeometrySet source_; GeometrySet source_;
GField src_field_; GField src_field_;
@@ -116,7 +116,7 @@ class SampleMeshBarycentricFunction : public fn::MultiFunction {
*/ */
eAttrDomain domain_ = ATTR_DOMAIN_CORNER; eAttrDomain domain_ = ATTR_DOMAIN_CORNER;
fn::MFSignature signature_; mf::Signature signature_;
std::optional<bke::MeshFieldContext> source_context_; std::optional<bke::MeshFieldContext> source_context_;
std::unique_ptr<FieldEvaluator> source_evaluator_; std::unique_ptr<FieldEvaluator> source_evaluator_;
@@ -134,17 +134,17 @@ class SampleMeshBarycentricFunction : public fn::MultiFunction {
this->evaluate_source(); this->evaluate_source();
} }
fn::MFSignature create_signature() mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample Barycentric Triangles", signature}; mf::SignatureBuilder builder{"Sample Barycentric Triangles", signature};
builder.single_input<int>("Triangle Index"); builder.single_input<int>("Triangle Index");
builder.single_input<float3>("Barycentric Weight"); builder.single_input<float3>("Barycentric Weight");
builder.single_output("Value", src_field_.cpp_type()); builder.single_output("Value", src_field_.cpp_type());
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArraySpan<int> triangle_indices = params.readonly_single_input<int>(0, const VArraySpan<int> triangle_indices = params.readonly_single_input<int>(0,
"Triangle Index"); "Triangle Index");
@@ -185,7 +185,7 @@ class SampleMeshBarycentricFunction : public fn::MultiFunction {
} }
}; };
class ReverseUVSampleFunction : public fn::MultiFunction { class ReverseUVSampleFunction : public mf::MultiFunction {
GeometrySet source_; GeometrySet source_;
Field<float2> src_uv_map_field_; Field<float2> src_uv_map_field_;
@@ -200,15 +200,15 @@ class ReverseUVSampleFunction : public fn::MultiFunction {
: source_(std::move(geometry)), src_uv_map_field_(std::move(src_uv_map_field)) : source_(std::move(geometry)), src_uv_map_field_(std::move(src_uv_map_field))
{ {
source_.ensure_owns_direct_data(); source_.ensure_owns_direct_data();
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
this->evaluate_source(); this->evaluate_source();
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Sample UV Surface", signature}; mf::SignatureBuilder builder{"Sample UV Surface", signature};
builder.single_input<float2>("Sample UV"); builder.single_input<float2>("Sample UV");
builder.single_output<bool>("Is Valid"); builder.single_output<bool>("Is Valid");
builder.single_output<int>("Triangle Index"); builder.single_output<int>("Triangle Index");
@@ -216,7 +216,7 @@ class ReverseUVSampleFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArraySpan<float2> sample_uvs = params.readonly_single_input<float2>(0, "Sample UV"); const VArraySpan<float2> sample_uvs = params.readonly_single_input<float2>(0, "Sample UV");
MutableSpan<bool> is_valid = params.uninitialized_single_output_if_required<bool>(1, MutableSpan<bool> is_valid = params.uninitialized_single_output_if_required<bool>(1,

View File

@@ -171,7 +171,7 @@ template<typename T> void switch_fields(GeoNodeExecParams &params, const StringR
Field<T> falses_field = params.extract_input<Field<T>>(name_false); Field<T> falses_field = params.extract_input<Field<T>>(name_false);
Field<T> trues_field = params.extract_input<Field<T>>(name_true); Field<T> trues_field = params.extract_input<Field<T>>(name_true);
static auto switch_fn = fn::build_mf::SI3_SO<bool, T, T, T>( static auto switch_fn = mf::build::SI3_SO<bool, T, T, T>(
"Switch", [](bool condition, const T &false_value, const T &true_value) { "Switch", [](bool condition, const T &false_value, const T &true_value) {
return condition ? true_value : false_value; return condition ? true_value : false_value;
}); });

View File

@@ -37,7 +37,6 @@ namespace blender::nodes {
using fn::ValueOrField; using fn::ValueOrField;
using fn::ValueOrFieldCPPType; using fn::ValueOrFieldCPPType;
using namespace fn::multi_function_types;
static const CPPType *get_socket_cpp_type(const bNodeSocketType &typeinfo) static const CPPType *get_socket_cpp_type(const bNodeSocketType &typeinfo)
{ {
@@ -353,8 +352,8 @@ static void execute_multi_function_on_value_or_field(
} }
else { else {
/* In this case, the multi-function is evaluated directly. */ /* In this case, the multi-function is evaluated directly. */
MFParamsBuilder params{fn, 1}; mf::ParamsBuilder params{fn, 1};
MFContextBuilder context; mf::ContextBuilder context;
for (const int i : input_types.index_range()) { for (const int i : input_types.index_range()) {
const ValueOrFieldCPPType &type = *input_types[i]; const ValueOrFieldCPPType &type = *input_types[i];
@@ -445,7 +444,7 @@ class LazyFunctionForMutedNode : public LazyFunction {
if (from_type != nullptr && to_type != nullptr) { if (from_type != nullptr && to_type != nullptr) {
if (conversions.is_convertible(from_type->value, to_type->value)) { if (conversions.is_convertible(from_type->value, to_type->value)) {
const MultiFunction &multi_fn = *conversions.get_conversion_multi_function( const MultiFunction &multi_fn = *conversions.get_conversion_multi_function(
MFDataType::ForSingle(from_type->value), MFDataType::ForSingle(to_type->value)); mf::DataType::ForSingle(from_type->value), mf::DataType::ForSingle(to_type->value));
execute_multi_function_on_value_or_field( execute_multi_function_on_value_or_field(
multi_fn, {}, {from_type}, {to_type}, {input_value}, {output_value}); multi_fn, {}, {from_type}, {to_type}, {input_value}, {output_value});
} }
@@ -1676,8 +1675,8 @@ struct GeometryNodesLazyFunctionGraphBuilder {
if (from_field_type != nullptr && to_field_type != nullptr) { if (from_field_type != nullptr && to_field_type != nullptr) {
if (conversions_->is_convertible(from_field_type->value, to_field_type->value)) { if (conversions_->is_convertible(from_field_type->value, to_field_type->value)) {
const MultiFunction &multi_fn = *conversions_->get_conversion_multi_function( const MultiFunction &multi_fn = *conversions_->get_conversion_multi_function(
MFDataType::ForSingle(from_field_type->value), mf::DataType::ForSingle(from_field_type->value),
MFDataType::ForSingle(to_field_type->value)); mf::DataType::ForSingle(to_field_type->value));
auto fn = std::make_unique<LazyFunctionForMultiFunctionConversion>( auto fn = std::make_unique<LazyFunctionForMultiFunctionConversion>(
multi_fn, *from_field_type, *to_field_type); multi_fn, *from_field_type, *to_field_type);
lf::Node &conversion_node = lf_graph_->add_function(*fn); lf::Node &conversion_node = lf_graph_->add_function(*fn);

View File

@@ -44,10 +44,10 @@ static int gpu_shader_clamp(GPUMaterial *mat,
static void sh_node_clamp_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_clamp_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto minmax_fn = fn::build_mf::SI3_SO<float, float, float, float>( static auto minmax_fn = mf::build::SI3_SO<float, float, float, float>(
"Clamp (Min Max)", "Clamp (Min Max)",
[](float value, float min, float max) { return std::min(std::max(value, min), max); }); [](float value, float min, float max) { return std::min(std::max(value, min), max); });
static auto range_fn = fn::build_mf::SI3_SO<float, float, float, float>( static auto range_fn = mf::build::SI3_SO<float, float, float, float>(
"Clamp (Range)", [](float value, float a, float b) { "Clamp (Range)", [](float value, float a, float b) {
if (a < b) { if (a < b) {
return clamp_f(value, a, b); return clamp_f(value, a, b);

View File

@@ -87,28 +87,28 @@ static int gpu_shader_valtorgb(GPUMaterial *mat,
return GPU_stack_link(mat, node, "valtorgb", in, out, tex, GPU_constant(&layer)); return GPU_stack_link(mat, node, "valtorgb", in, out, tex, GPU_constant(&layer));
} }
class ColorBandFunction : public fn::MultiFunction { class ColorBandFunction : public mf::MultiFunction {
private: private:
const ColorBand &color_band_; const ColorBand &color_band_;
public: public:
ColorBandFunction(const ColorBand &color_band) : color_band_(color_band) ColorBandFunction(const ColorBand &color_band) : color_band_(color_band)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Color Band", signature}; mf::SignatureBuilder builder{"Color Band", signature};
builder.single_input<float>("Value"); builder.single_input<float>("Value");
builder.single_output<ColorGeometry4f>("Color"); builder.single_output<ColorGeometry4f>("Color");
builder.single_output<float>("Alpha"); builder.single_output<float>("Alpha");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float> &values = params.readonly_single_input<float>(0, "Value"); const VArray<float> &values = params.readonly_single_input<float>(0, "Value");
MutableSpan<ColorGeometry4f> colors = params.uninitialized_single_output<ColorGeometry4f>( MutableSpan<ColorGeometry4f> colors = params.uninitialized_single_output<ColorGeometry4f>(

View File

@@ -63,28 +63,28 @@ static int gpu_shader_curve_vec(GPUMaterial *mat,
GPU_uniform(end_slopes)); GPU_uniform(end_slopes));
} }
class CurveVecFunction : public fn::MultiFunction { class CurveVecFunction : public mf::MultiFunction {
private: private:
const CurveMapping &cumap_; const CurveMapping &cumap_;
public: public:
CurveVecFunction(const CurveMapping &cumap) : cumap_(cumap) CurveVecFunction(const CurveMapping &cumap) : cumap_(cumap)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Curve Vec", signature}; mf::SignatureBuilder builder{"Curve Vec", signature};
builder.single_input<float>("Fac"); builder.single_input<float>("Fac");
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_output<float3>("Vector"); builder.single_output<float3>("Vector");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac"); const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
const VArray<float3> &vec_in = params.readonly_single_input<float3>(1, "Vector"); const VArray<float3> &vec_in = params.readonly_single_input<float3>(1, "Vector");
@@ -209,28 +209,28 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat,
GPU_uniform(end_slopes)); GPU_uniform(end_slopes));
} }
class CurveRGBFunction : public fn::MultiFunction { class CurveRGBFunction : public mf::MultiFunction {
private: private:
const CurveMapping &cumap_; const CurveMapping &cumap_;
public: public:
CurveRGBFunction(const CurveMapping &cumap) : cumap_(cumap) CurveRGBFunction(const CurveMapping &cumap) : cumap_(cumap)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Curve RGB", signature}; mf::SignatureBuilder builder{"Curve RGB", signature};
builder.single_input<float>("Fac"); builder.single_input<float>("Fac");
builder.single_input<ColorGeometry4f>("Color"); builder.single_input<ColorGeometry4f>("Color");
builder.single_output<ColorGeometry4f>("Color"); builder.single_output<ColorGeometry4f>("Color");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac"); const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
const VArray<ColorGeometry4f> &col_in = params.readonly_single_input<ColorGeometry4f>(1, const VArray<ColorGeometry4f> &col_in = params.readonly_single_input<ColorGeometry4f>(1,
@@ -332,28 +332,28 @@ static int gpu_shader_curve_float(GPUMaterial *mat,
GPU_uniform(end_slopes)); GPU_uniform(end_slopes));
} }
class CurveFloatFunction : public fn::MultiFunction { class CurveFloatFunction : public mf::MultiFunction {
private: private:
const CurveMapping &cumap_; const CurveMapping &cumap_;
public: public:
CurveFloatFunction(const CurveMapping &cumap) : cumap_(cumap) CurveFloatFunction(const CurveMapping &cumap) : cumap_(cumap)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Curve Float", signature}; mf::SignatureBuilder builder{"Curve Float", signature};
builder.single_input<float>("Factor"); builder.single_input<float>("Factor");
builder.single_input<float>("Value"); builder.single_input<float>("Value");
builder.single_output<float>("Value"); builder.single_output<float>("Value");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor"); const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
const VArray<float> &val_in = params.readonly_single_input<float>(1, "Value"); const VArray<float> &val_in = params.readonly_single_input<float>(1, "Value");

View File

@@ -233,7 +233,7 @@ static float3 clamp_range(const float3 value, const float3 min, const float3 max
template<bool Clamp> static auto build_float_linear() template<bool Clamp> static auto build_float_linear()
{ {
return fn::build_mf::SI5_SO<float, float, float, float, float, float>( return mf::build::SI5_SO<float, float, float, float, float, float>(
Clamp ? "Map Range (clamped)" : "Map Range (unclamped)", Clamp ? "Map Range (clamped)" : "Map Range (unclamped)",
[](float value, float from_min, float from_max, float to_min, float to_max) -> float { [](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); const float factor = safe_divide(value - from_min, from_max - from_min);
@@ -243,12 +243,12 @@ template<bool Clamp> static auto build_float_linear()
} }
return result; return result;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
} }
template<bool Clamp> static auto build_float_stepped() template<bool Clamp> static auto build_float_stepped()
{ {
return fn::build_mf::SI6_SO<float, float, float, float, float, float, float>( return mf::build::SI6_SO<float, float, float, float, float, float, float>(
Clamp ? "Map Range Stepped (clamped)" : "Map Range Stepped (unclamped)", 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 value, float from_min, float from_max, float to_min, float to_max, float steps)
-> float { -> float {
@@ -260,12 +260,12 @@ template<bool Clamp> static auto build_float_stepped()
} }
return result; return result;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
} }
template<bool Clamp> static auto build_vector_linear() template<bool Clamp> static auto build_vector_linear()
{ {
return fn::build_mf::SI5_SO<float3, float3, float3, float3, float3, float3>( return mf::build::SI5_SO<float3, float3, float3, float3, float3, float3>(
Clamp ? "Vector Map Range (clamped)" : "Vector Map Range (unclamped)", Clamp ? "Vector Map Range (clamped)" : "Vector Map Range (unclamped)",
[](const float3 &value, [](const float3 &value,
const float3 &from_min, const float3 &from_min,
@@ -279,12 +279,12 @@ template<bool Clamp> static auto build_vector_linear()
} }
return result; return result;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
} }
template<bool Clamp> static auto build_vector_stepped() template<bool Clamp> static auto build_vector_stepped()
{ {
return fn::build_mf::SI6_SO<float3, float3, float3, float3, float3, float3, float3>( return mf::build::SI6_SO<float3, float3, float3, float3, float3, float3, float3>(
Clamp ? "Vector Map Range Stepped (clamped)" : "Vector Map Range Stepped (unclamped)", Clamp ? "Vector Map Range Stepped (clamped)" : "Vector Map Range Stepped (unclamped)",
[](const float3 &value, [](const float3 &value,
const float3 &from_min, const float3 &from_min,
@@ -300,7 +300,7 @@ template<bool Clamp> static auto build_vector_stepped()
} }
return result; return result;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
} }
static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &builder)
@@ -335,7 +335,7 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
break; break;
} }
case NODE_MAP_RANGE_SMOOTHSTEP: { case NODE_MAP_RANGE_SMOOTHSTEP: {
static auto fn = fn::build_mf::SI5_SO<float3, float3, float3, float3, float3, float3>( static auto fn = mf::build::SI5_SO<float3, float3, float3, float3, float3, float3>(
"Vector Map Range Smoothstep", "Vector Map Range Smoothstep",
[](const float3 &value, [](const float3 &value,
const float3 &from_min, const float3 &from_min,
@@ -347,12 +347,12 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
factor = (float3(3.0f) - 2.0f * factor) * (factor * factor); factor = (float3(3.0f) - 2.0f * factor) * (factor * factor);
return factor * (to_max - to_min) + to_min; return factor * (to_max - to_min) + to_min;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }
case NODE_MAP_RANGE_SMOOTHERSTEP: { case NODE_MAP_RANGE_SMOOTHERSTEP: {
static auto fn = fn::build_mf::SI5_SO<float3, float3, float3, float3, float3, float3>( static auto fn = mf::build::SI5_SO<float3, float3, float3, float3, float3, float3>(
"Vector Map Range Smootherstep", "Vector Map Range Smootherstep",
[](const float3 &value, [](const float3 &value,
const float3 &from_min, const float3 &from_min,
@@ -364,7 +364,7 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f);
return factor * (to_max - to_min) + to_min; return factor * (to_max - to_min) + to_min;
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }
@@ -397,7 +397,7 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
break; break;
} }
case NODE_MAP_RANGE_SMOOTHSTEP: { case NODE_MAP_RANGE_SMOOTHSTEP: {
static auto fn = fn::build_mf::SI5_SO<float, float, float, float, float, float>( static auto fn = mf::build::SI5_SO<float, float, float, float, float, float>(
"Map Range Smoothstep", "Map Range Smoothstep",
[](float value, float from_min, float from_max, float to_min, float to_max) [](float value, float from_min, float from_max, float to_min, float to_max)
-> float { -> float {
@@ -406,12 +406,12 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
factor = (3.0f - 2.0f * factor) * (factor * factor); factor = (3.0f - 2.0f * factor) * (factor * factor);
return to_min + factor * (to_max - to_min); return to_min + factor * (to_max - to_min);
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }
case NODE_MAP_RANGE_SMOOTHERSTEP: { case NODE_MAP_RANGE_SMOOTHERSTEP: {
static auto fn = fn::build_mf::SI5_SO<float, float, float, float, float, float>( static auto fn = mf::build::SI5_SO<float, float, float, float, float, float>(
"Map Range Smoothstep", "Map Range Smoothstep",
[](float value, float from_min, float from_max, float to_min, float to_max) [](float value, float from_min, float from_max, float to_min, float to_max)
-> float { -> float {
@@ -420,7 +420,7 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f); factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f);
return to_min + factor * (to_max - to_min); return to_min + factor * (to_max - to_min);
}, },
fn::build_mf::exec_presets::SomeSpanOrSingle<0>()); mf::build::exec_presets::SomeSpanOrSingle<0>());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
break; break;
} }

View File

@@ -102,14 +102,14 @@ static int gpu_shader_math(GPUMaterial *mat,
return 0; return 0;
} }
static const fn::MultiFunction *get_base_multi_function(const bNode &node) static const mf::MultiFunction *get_base_multi_function(const bNode &node)
{ {
const int mode = node.custom1; const int mode = node.custom1;
const fn::MultiFunction *base_fn = nullptr; const mf::MultiFunction *base_fn = nullptr;
try_dispatch_float_math_fl_to_fl( try_dispatch_float_math_fl_to_fl(
mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) { mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI1_SO<float, float>( static auto fn = mf::build::SI1_SO<float, float>(
info.title_case_name.c_str(), function, devi_fn); info.title_case_name.c_str(), function, devi_fn);
base_fn = &fn; base_fn = &fn;
}); });
@@ -119,7 +119,7 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node)
try_dispatch_float_math_fl_fl_to_fl( try_dispatch_float_math_fl_fl_to_fl(
mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) { mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI2_SO<float, float, float>( static auto fn = mf::build::SI2_SO<float, float, float>(
info.title_case_name.c_str(), function, devi_fn); info.title_case_name.c_str(), function, devi_fn);
base_fn = &fn; base_fn = &fn;
}); });
@@ -129,7 +129,7 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node)
try_dispatch_float_math_fl_fl_fl_to_fl( try_dispatch_float_math_fl_fl_fl_to_fl(
mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) { mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI3_SO<float, float, float, float>( static auto fn = mf::build::SI3_SO<float, float, float, float>(
info.title_case_name.c_str(), function, devi_fn); info.title_case_name.c_str(), function, devi_fn);
base_fn = &fn; base_fn = &fn;
}); });
@@ -140,17 +140,17 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node)
return nullptr; return nullptr;
} }
class ClampWrapperFunction : public fn::MultiFunction { class ClampWrapperFunction : public mf::MultiFunction {
private: private:
const fn::MultiFunction &fn_; const mf::MultiFunction &fn_;
public: public:
ClampWrapperFunction(const fn::MultiFunction &fn) : fn_(fn) ClampWrapperFunction(const mf::MultiFunction &fn) : fn_(fn)
{ {
this->set_signature(&fn.signature()); this->set_signature(&fn.signature());
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext context) const override void call(IndexMask mask, mf::MFParams params, mf::Context context) const override
{ {
fn_.call(mask, params, context); fn_.call(mask, params, context);
@@ -168,7 +168,7 @@ class ClampWrapperFunction : public fn::MultiFunction {
static void sh_node_math_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_math_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *base_function = get_base_multi_function(builder.node()); const mf::MultiFunction *base_function = get_base_multi_function(builder.node());
const bool clamp_output = builder.node().custom2 != 0; const bool clamp_output = builder.node().custom2 != 0;
if (clamp_output) { if (clamp_output) {

View File

@@ -351,7 +351,7 @@ static int gpu_shader_mix(GPUMaterial *mat,
return ret; return ret;
} }
class MixColorFunction : public fn::MultiFunction { class MixColorFunction : public mf::MultiFunction {
private: private:
const bool clamp_factor_; const bool clamp_factor_;
const bool clamp_result_; const bool clamp_result_;
@@ -361,14 +361,14 @@ class MixColorFunction : public fn::MultiFunction {
MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type) MixColorFunction(const bool clamp_factor, const bool clamp_result, const int blend_type)
: clamp_factor_(clamp_factor), clamp_result_(clamp_result), blend_type_(blend_type) : clamp_factor_(clamp_factor), clamp_result_(clamp_result), blend_type_(blend_type)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"MixColor", signature}; mf::SignatureBuilder builder{"MixColor", signature};
builder.single_input<float>("Factor"); builder.single_input<float>("Factor");
builder.single_input<ColorGeometry4f>("A"); builder.single_input<ColorGeometry4f>("A");
builder.single_input<ColorGeometry4f>("B"); builder.single_input<ColorGeometry4f>("B");
@@ -376,7 +376,7 @@ class MixColorFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor"); const VArray<float> &fac = params.readonly_single_input<float>(0, "Factor");
const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, "A"); const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, "A");
@@ -405,7 +405,7 @@ class MixColorFunction : public fn::MultiFunction {
} }
}; };
static const fn::MultiFunction *get_multi_function(const bNode &node) static const mf::MultiFunction *get_multi_function(const bNode &node)
{ {
const NodeShaderMix *data = (NodeShaderMix *)node.storage; const NodeShaderMix *data = (NodeShaderMix *)node.storage;
bool uniform_factor = data->factor_mode == NODE_MIX_MODE_UNIFORM; bool uniform_factor = data->factor_mode == NODE_MIX_MODE_UNIFORM;
@@ -413,14 +413,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
switch (data->data_type) { switch (data->data_type) {
case SOCK_FLOAT: { case SOCK_FLOAT: {
if (clamp_factor) { if (clamp_factor) {
static auto fn = fn::build_mf::SI3_SO<float, float, float, float>( static auto fn = mf::build::SI3_SO<float, float, float, float>(
"Clamp Mix Float", [](float t, const float a, const float b) { "Clamp Mix Float", [](float t, const float a, const float b) {
return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f)); return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
}); });
return &fn; return &fn;
} }
else { else {
static auto fn = fn::build_mf::SI3_SO<float, float, float, float>( static auto fn = mf::build::SI3_SO<float, float, float, float>(
"Mix Float", [](const float t, const float a, const float b) { "Mix Float", [](const float t, const float a, const float b) {
return math::interpolate(a, b, t); return math::interpolate(a, b, t);
}); });
@@ -430,14 +430,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case SOCK_VECTOR: { case SOCK_VECTOR: {
if (clamp_factor) { if (clamp_factor) {
if (uniform_factor) { if (uniform_factor) {
static auto fn = fn::build_mf::SI3_SO<float, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float, float3, float3, float3>(
"Clamp Mix Vector", [](const float t, const float3 a, const float3 b) { "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 math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
}); });
return &fn; return &fn;
} }
else { else {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
"Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) { "Clamp Mix Vector Non Uniform", [](float3 t, const float3 a, const float3 b) {
t = math::clamp(t, 0.0f, 1.0f); t = math::clamp(t, 0.0f, 1.0f);
return a * (float3(1.0f) - t) + b * t; return a * (float3(1.0f) - t) + b * t;
@@ -447,14 +447,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
} }
else { else {
if (uniform_factor) { if (uniform_factor) {
static auto fn = fn::build_mf::SI3_SO<float, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float, float3, float3, float3>(
"Mix Vector", [](const float t, const float3 a, const float3 b) { "Mix Vector", [](const float t, const float3 a, const float3 b) {
return math::interpolate(a, b, t); return math::interpolate(a, b, t);
}); });
return &fn; return &fn;
} }
else { else {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
"Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) { "Mix Vector Non Uniform", [](const float3 t, const float3 a, const float3 b) {
return a * (float3(1.0f) - t) + b * t; return a * (float3(1.0f) - t) + b * t;
}); });
@@ -476,7 +476,7 @@ static void sh_node_mix_build_multi_function(NodeMultiFunctionBuilder &builder)
storage.clamp_factor, storage.clamp_result, storage.blend_type); storage.clamp_factor, storage.clamp_result, storage.blend_type);
} }
else { else {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }
} }

View File

@@ -91,7 +91,7 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat,
return ret; return ret;
} }
class MixRGBFunction : public fn::MultiFunction { class MixRGBFunction : public mf::MultiFunction {
private: private:
bool clamp_; bool clamp_;
int type_; int type_;
@@ -99,14 +99,14 @@ class MixRGBFunction : public fn::MultiFunction {
public: public:
MixRGBFunction(bool clamp, int type) : clamp_(clamp), type_(type) MixRGBFunction(bool clamp, int type) : clamp_(clamp), type_(type)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"MixRGB", signature}; mf::SignatureBuilder builder{"MixRGB", signature};
builder.single_input<float>("Fac"); builder.single_input<float>("Fac");
builder.single_input<ColorGeometry4f>("Color1"); builder.single_input<ColorGeometry4f>("Color1");
builder.single_input<ColorGeometry4f>("Color2"); builder.single_input<ColorGeometry4f>("Color2");
@@ -114,7 +114,7 @@ class MixRGBFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac"); const VArray<float> &fac = params.readonly_single_input<float>(0, "Fac");
const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1, const VArray<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1,

View File

@@ -27,18 +27,18 @@ static int gpu_shader_seprgb(GPUMaterial *mat,
return GPU_stack_link(mat, node, "separate_rgb", in, out); return GPU_stack_link(mat, node, "separate_rgb", in, out);
} }
class SeparateRGBFunction : public fn::MultiFunction { class SeparateRGBFunction : public mf::MultiFunction {
public: public:
SeparateRGBFunction() SeparateRGBFunction()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Separate RGB", signature}; mf::SignatureBuilder builder{"Separate RGB", signature};
builder.single_input<ColorGeometry4f>("Color"); builder.single_input<ColorGeometry4f>("Color");
builder.single_output<float>("R"); builder.single_output<float>("R");
builder.single_output<float>("G"); builder.single_output<float>("G");
@@ -46,7 +46,7 @@ class SeparateRGBFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0, const VArray<ColorGeometry4f> &colors = params.readonly_single_input<ColorGeometry4f>(0,
"Color"); "Color");
@@ -109,7 +109,7 @@ static int gpu_shader_combrgb(GPUMaterial *mat,
static void sh_node_combrgb_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_combrgb_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto fn = fn::build_mf::SI3_SO<float, float, float, ColorGeometry4f>( static auto fn = mf::build::SI3_SO<float, float, float, ColorGeometry4f>(
"Combine RGB", [](float r, float g, float b) { return ColorGeometry4f(r, g, b, 1.0f); }); "Combine RGB", [](float r, float g, float b) { return ColorGeometry4f(r, g, b, 1.0f); });
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -27,18 +27,18 @@ static int gpu_shader_sepxyz(GPUMaterial *mat,
return GPU_stack_link(mat, node, "separate_xyz", in, out); return GPU_stack_link(mat, node, "separate_xyz", in, out);
} }
class MF_SeparateXYZ : public fn::MultiFunction { class MF_SeparateXYZ : public mf::MultiFunction {
public: public:
MF_SeparateXYZ() MF_SeparateXYZ()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Separate XYZ", signature}; mf::SignatureBuilder builder{"Separate XYZ", signature};
builder.single_input<float3>("XYZ"); builder.single_input<float3>("XYZ");
builder.single_output<float>("X"); builder.single_output<float>("X");
builder.single_output<float>("Y"); builder.single_output<float>("Y");
@@ -46,7 +46,7 @@ class MF_SeparateXYZ : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "XYZ"); const VArray<float3> &vectors = params.readonly_single_input<float3>(0, "XYZ");
MutableSpan<float> xs = params.uninitialized_single_output_if_required<float>(1, "X"); MutableSpan<float> xs = params.uninitialized_single_output_if_required<float>(1, "X");
@@ -126,10 +126,10 @@ static int gpu_shader_combxyz(GPUMaterial *mat,
static void sh_node_combxyz_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_combxyz_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
static auto fn = fn::build_mf::SI3_SO<float, float, float, float3>( static auto fn = mf::build::SI3_SO<float, float, float, float3>(
"Combine Vector", "Combine Vector",
[](float x, float y, float z) { return float3(x, y, z); }, [](float x, float y, float z) { return float3(x, y, z); },
fn::build_mf::exec_presets::AllSpanOrSingle()); mf::build::exec_presets::AllSpanOrSingle());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -108,7 +108,7 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat,
GPU_constant(&squash_freq)); GPU_constant(&squash_freq));
} }
class BrickFunction : public fn::MultiFunction { class BrickFunction : public mf::MultiFunction {
private: private:
const float offset_; const float offset_;
const int offset_freq_; const int offset_freq_;
@@ -122,14 +122,14 @@ class BrickFunction : public fn::MultiFunction {
const int squash_freq) const int squash_freq)
: offset_(offset), offset_freq_(offset_freq), squash_(squash), squash_freq_(squash_freq) : offset_(offset), offset_freq_(offset_freq), squash_(squash), squash_freq_(squash_freq)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"BrickTexture", signature}; mf::SignatureBuilder builder{"BrickTexture", signature};
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_input<ColorGeometry4f>("Color1"); builder.single_input<ColorGeometry4f>("Color1");
builder.single_input<ColorGeometry4f>("Color2"); builder.single_input<ColorGeometry4f>("Color2");
@@ -204,7 +204,7 @@ class BrickFunction : public fn::MultiFunction {
return float2(tint, mortar); return float2(tint, mortar);
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
const VArray<ColorGeometry4f> &color1_values = params.readonly_single_input<ColorGeometry4f>( const VArray<ColorGeometry4f> &color1_values = params.readonly_single_input<ColorGeometry4f>(

View File

@@ -44,18 +44,18 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_tex_checker", in, out); return GPU_stack_link(mat, node, "node_tex_checker", in, out);
} }
class NodeTexChecker : public fn::MultiFunction { class NodeTexChecker : public mf::MultiFunction {
public: public:
NodeTexChecker() NodeTexChecker()
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Checker", signature}; mf::SignatureBuilder builder{"Checker", signature};
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_input<ColorGeometry4f>("Color1"); builder.single_input<ColorGeometry4f>("Color1");
builder.single_input<ColorGeometry4f>("Color2"); builder.single_input<ColorGeometry4f>("Color2");
@@ -65,7 +65,7 @@ class NodeTexChecker : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
const VArray<ColorGeometry4f> &color1 = params.readonly_single_input<ColorGeometry4f>( const VArray<ColorGeometry4f> &color1 = params.readonly_single_input<ColorGeometry4f>(

View File

@@ -47,28 +47,28 @@ static int node_shader_gpu_tex_gradient(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_tex_gradient", in, out, GPU_constant(&gradient_type)); return GPU_stack_link(mat, node, "node_tex_gradient", in, out, GPU_constant(&gradient_type));
} }
class GradientFunction : public fn::MultiFunction { class GradientFunction : public mf::MultiFunction {
private: private:
int gradient_type_; int gradient_type_;
public: public:
GradientFunction(int gradient_type) : gradient_type_(gradient_type) GradientFunction(int gradient_type) : gradient_type_(gradient_type)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"GradientFunction", signature}; mf::SignatureBuilder builder{"GradientFunction", signature};
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_output<ColorGeometry4f>("Color"); builder.single_output<ColorGeometry4f>("Color");
builder.single_output<float>("Fac"); builder.single_output<float>("Fac");
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");

View File

@@ -48,21 +48,21 @@ static int node_shader_gpu_tex_magic(GPUMaterial *mat,
return GPU_stack_link(mat, node, "node_tex_magic", in, out, GPU_constant(&depth)); return GPU_stack_link(mat, node, "node_tex_magic", in, out, GPU_constant(&depth));
} }
class MagicFunction : public fn::MultiFunction { class MagicFunction : public mf::MultiFunction {
private: private:
int depth_; int depth_;
public: public:
MagicFunction(int depth) : depth_(depth) MagicFunction(int depth) : depth_(depth)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"MagicFunction", signature}; mf::SignatureBuilder builder{"MagicFunction", signature};
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_input<float>("Scale"); builder.single_input<float>("Scale");
builder.single_input<float>("Distortion"); builder.single_input<float>("Distortion");
@@ -71,7 +71,7 @@ class MagicFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale"); const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale");

View File

@@ -125,7 +125,7 @@ static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node)
node_sock_label(outFacSock, "Height"); node_sock_label(outFacSock, "Height");
} }
class MusgraveFunction : public fn::MultiFunction { class MusgraveFunction : public mf::MultiFunction {
private: private:
const int dimensions_; const int dimensions_;
const int musgrave_type_; const int musgrave_type_;
@@ -136,7 +136,7 @@ class MusgraveFunction : public fn::MultiFunction {
{ {
BLI_assert(dimensions >= 1 && dimensions <= 4); BLI_assert(dimensions >= 1 && dimensions <= 4);
BLI_assert(musgrave_type >= 0 && musgrave_type <= 4); BLI_assert(musgrave_type >= 0 && musgrave_type <= 4);
static std::array<fn::MFSignature, 20> signatures{ static std::array<mf::Signature, 20> signatures{
create_signature(1, SHD_MUSGRAVE_MULTIFRACTAL), create_signature(1, SHD_MUSGRAVE_MULTIFRACTAL),
create_signature(2, SHD_MUSGRAVE_MULTIFRACTAL), create_signature(2, SHD_MUSGRAVE_MULTIFRACTAL),
create_signature(3, SHD_MUSGRAVE_MULTIFRACTAL), create_signature(3, SHD_MUSGRAVE_MULTIFRACTAL),
@@ -165,10 +165,10 @@ class MusgraveFunction : public fn::MultiFunction {
this->set_signature(&signatures[dimensions + musgrave_type * 4 - 1]); this->set_signature(&signatures[dimensions + musgrave_type * 4 - 1]);
} }
static fn::MFSignature create_signature(const int dimensions, const int musgrave_type) static mf::Signature create_signature(const int dimensions, const int musgrave_type)
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Musgrave", signature}; mf::SignatureBuilder builder{"Musgrave", signature};
if (ELEM(dimensions, 2, 3, 4)) { if (ELEM(dimensions, 2, 3, 4)) {
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -195,7 +195,7 @@ class MusgraveFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
auto get_vector = [&](int param_index) -> VArray<float3> { auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector"); return params.readonly_single_input<float3>(param_index, "Vector");

View File

@@ -81,7 +81,7 @@ static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node)
nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4); nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4);
} }
class NoiseFunction : public fn::MultiFunction { class NoiseFunction : public mf::MultiFunction {
private: private:
int dimensions_; int dimensions_;
@@ -89,7 +89,7 @@ class NoiseFunction : public fn::MultiFunction {
NoiseFunction(int dimensions) : dimensions_(dimensions) NoiseFunction(int dimensions) : dimensions_(dimensions)
{ {
BLI_assert(dimensions >= 1 && dimensions <= 4); BLI_assert(dimensions >= 1 && dimensions <= 4);
static std::array<fn::MFSignature, 4> signatures{ static std::array<mf::Signature, 4> signatures{
create_signature(1), create_signature(1),
create_signature(2), create_signature(2),
create_signature(3), create_signature(3),
@@ -98,10 +98,10 @@ class NoiseFunction : public fn::MultiFunction {
this->set_signature(&signatures[dimensions - 1]); this->set_signature(&signatures[dimensions - 1]);
} }
static fn::MFSignature create_signature(int dimensions) static mf::Signature create_signature(int dimensions)
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"Noise", signature}; mf::SignatureBuilder builder{"Noise", signature};
if (ELEM(dimensions, 2, 3, 4)) { if (ELEM(dimensions, 2, 3, 4)) {
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -121,7 +121,7 @@ class NoiseFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4); int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4);
const VArray<float> &scale = params.readonly_single_input<float>(param++, "Scale"); const VArray<float> &scale = params.readonly_single_input<float>(param++, "Scale");

View File

@@ -179,9 +179,9 @@ static void node_shader_update_tex_voronoi(bNodeTree *ntree, bNode *node)
nodeSetSocketAvailability(ntree, outRadiusSock, storage.feature == SHD_VORONOI_N_SPHERE_RADIUS); nodeSetSocketAvailability(ntree, outRadiusSock, storage.feature == SHD_VORONOI_N_SPHERE_RADIUS);
} }
static MultiFunction::ExecutionHints voronoi_execution_hints{50, false}; static mf::MultiFunction::ExecutionHints voronoi_execution_hints{50, false};
class VoronoiMinowskiFunction : public fn::MultiFunction { class VoronoiMinowskiFunction : public mf::MultiFunction {
private: private:
int dimensions_; int dimensions_;
int feature_; int feature_;
@@ -191,7 +191,7 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
{ {
BLI_assert(dimensions >= 2 && dimensions <= 4); BLI_assert(dimensions >= 2 && dimensions <= 4);
BLI_assert(feature >= 0 && feature <= 2); BLI_assert(feature >= 0 && feature <= 2);
static std::array<fn::MFSignature, 9> signatures{ static std::array<mf::Signature, 9> signatures{
create_signature(2, SHD_VORONOI_F1), create_signature(2, SHD_VORONOI_F1),
create_signature(3, SHD_VORONOI_F1), create_signature(3, SHD_VORONOI_F1),
create_signature(4, SHD_VORONOI_F1), create_signature(4, SHD_VORONOI_F1),
@@ -207,10 +207,10 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
this->set_signature(&signatures[(dimensions - 1) + feature * 3 - 1]); this->set_signature(&signatures[(dimensions - 1) + feature * 3 - 1]);
} }
static fn::MFSignature create_signature(int dimensions, int feature) static mf::Signature create_signature(int dimensions, int feature)
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"voronoi_minowski", signature}; mf::SignatureBuilder builder{"voronoi_minowski", signature};
if (ELEM(dimensions, 2, 3, 4)) { if (ELEM(dimensions, 2, 3, 4)) {
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -237,7 +237,7 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
auto get_vector = [&](int param_index) -> VArray<float3> { auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector"); return params.readonly_single_input<float3>(param_index, "Vector");
@@ -614,7 +614,7 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
} }
}; };
class VoronoiMetricFunction : public fn::MultiFunction { class VoronoiMetricFunction : public mf::MultiFunction {
private: private:
int dimensions_; int dimensions_;
int feature_; int feature_;
@@ -626,7 +626,7 @@ class VoronoiMetricFunction : public fn::MultiFunction {
{ {
BLI_assert(dimensions >= 1 && dimensions <= 4); BLI_assert(dimensions >= 1 && dimensions <= 4);
BLI_assert(feature >= 0 && feature <= 4); BLI_assert(feature >= 0 && feature <= 4);
static std::array<fn::MFSignature, 12> signatures{ static std::array<mf::Signature, 12> signatures{
create_signature(1, SHD_VORONOI_F1), create_signature(1, SHD_VORONOI_F1),
create_signature(2, SHD_VORONOI_F1), create_signature(2, SHD_VORONOI_F1),
create_signature(3, SHD_VORONOI_F1), create_signature(3, SHD_VORONOI_F1),
@@ -645,10 +645,10 @@ class VoronoiMetricFunction : public fn::MultiFunction {
this->set_signature(&signatures[dimensions + feature * 4 - 1]); this->set_signature(&signatures[dimensions + feature * 4 - 1]);
} }
static fn::MFSignature create_signature(int dimensions, int feature) static mf::Signature create_signature(int dimensions, int feature)
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"voronoi_metric", signature}; mf::SignatureBuilder builder{"voronoi_metric", signature};
if (ELEM(dimensions, 2, 3, 4)) { if (ELEM(dimensions, 2, 3, 4)) {
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -674,7 +674,7 @@ class VoronoiMetricFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
auto get_vector = [&](int param_index) -> VArray<float3> { auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector"); return params.readonly_single_input<float3>(param_index, "Vector");
@@ -1134,7 +1134,7 @@ class VoronoiMetricFunction : public fn::MultiFunction {
} }
}; };
class VoronoiEdgeFunction : public fn::MultiFunction { class VoronoiEdgeFunction : public mf::MultiFunction {
private: private:
int dimensions_; int dimensions_;
int feature_; int feature_;
@@ -1144,7 +1144,7 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
{ {
BLI_assert(dimensions >= 1 && dimensions <= 4); BLI_assert(dimensions >= 1 && dimensions <= 4);
BLI_assert(feature >= 3 && feature <= 4); BLI_assert(feature >= 3 && feature <= 4);
static std::array<fn::MFSignature, 8> signatures{ static std::array<mf::Signature, 8> signatures{
create_signature(1, SHD_VORONOI_DISTANCE_TO_EDGE), create_signature(1, SHD_VORONOI_DISTANCE_TO_EDGE),
create_signature(2, SHD_VORONOI_DISTANCE_TO_EDGE), create_signature(2, SHD_VORONOI_DISTANCE_TO_EDGE),
create_signature(3, SHD_VORONOI_DISTANCE_TO_EDGE), create_signature(3, SHD_VORONOI_DISTANCE_TO_EDGE),
@@ -1158,10 +1158,10 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
this->set_signature(&signatures[dimensions + (feature - 3) * 4 - 1]); this->set_signature(&signatures[dimensions + (feature - 3) * 4 - 1]);
} }
static fn::MFSignature create_signature(int dimensions, int feature) static mf::Signature create_signature(int dimensions, int feature)
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"voronoi_edge", signature}; mf::SignatureBuilder builder{"voronoi_edge", signature};
if (ELEM(dimensions, 2, 3, 4)) { if (ELEM(dimensions, 2, 3, 4)) {
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -1182,7 +1182,7 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
auto get_vector = [&](int param_index) -> VArray<float3> { auto get_vector = [&](int param_index) -> VArray<float3> {
return params.readonly_single_input<float3>(param_index, "Vector"); return params.readonly_single_input<float3>(param_index, "Vector");

View File

@@ -80,7 +80,7 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat,
GPU_constant(&wave_profile)); GPU_constant(&wave_profile));
} }
class WaveFunction : public fn::MultiFunction { class WaveFunction : public mf::MultiFunction {
private: private:
int wave_type_; int wave_type_;
int bands_direction_; int bands_direction_;
@@ -94,14 +94,14 @@ class WaveFunction : public fn::MultiFunction {
rings_direction_(rings_direction), rings_direction_(rings_direction),
wave_profile_(wave_profile) wave_profile_(wave_profile)
{ {
static fn::MFSignature signature = create_signature(); static mf::Signature signature = create_signature();
this->set_signature(&signature); this->set_signature(&signature);
} }
static fn::MFSignature create_signature() static mf::Signature create_signature()
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"MagicFunction", signature}; mf::SignatureBuilder builder{"MagicFunction", signature};
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
builder.single_input<float>("Scale"); builder.single_input<float>("Scale");
builder.single_input<float>("Distortion"); builder.single_input<float>("Distortion");
@@ -114,7 +114,7 @@ class WaveFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector"); const VArray<float3> &vector = params.readonly_single_input<float3>(0, "Vector");
const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale"); const VArray<float> &scale = params.readonly_single_input<float>(1, "Scale");

View File

@@ -63,7 +63,7 @@ static void node_shader_update_tex_white_noise(bNodeTree *ntree, bNode *node)
nodeSetSocketAvailability(ntree, sockW, node->custom1 == 1 || node->custom1 == 4); nodeSetSocketAvailability(ntree, sockW, node->custom1 == 1 || node->custom1 == 4);
} }
class WhiteNoiseFunction : public fn::MultiFunction { class WhiteNoiseFunction : public mf::MultiFunction {
private: private:
int dimensions_; int dimensions_;
@@ -71,7 +71,7 @@ class WhiteNoiseFunction : public fn::MultiFunction {
WhiteNoiseFunction(int dimensions) : dimensions_(dimensions) WhiteNoiseFunction(int dimensions) : dimensions_(dimensions)
{ {
BLI_assert(dimensions >= 1 && dimensions <= 4); BLI_assert(dimensions >= 1 && dimensions <= 4);
static std::array<fn::MFSignature, 4> signatures{ static std::array<mf::Signature, 4> signatures{
create_signature(1), create_signature(1),
create_signature(2), create_signature(2),
create_signature(3), create_signature(3),
@@ -80,10 +80,10 @@ class WhiteNoiseFunction : public fn::MultiFunction {
this->set_signature(&signatures[dimensions - 1]); this->set_signature(&signatures[dimensions - 1]);
} }
static fn::MFSignature create_signature(int dimensions) static mf::Signature create_signature(int dimensions)
{ {
fn::MFSignature signature; mf::Signature signature;
fn::MFSignatureBuilder builder{"WhiteNoise", signature}; mf::SignatureBuilder builder{"WhiteNoise", signature};
if (ELEM(dimensions, 2, 3, 4)) { if (ELEM(dimensions, 2, 3, 4)) {
builder.single_input<float3>("Vector"); builder.single_input<float3>("Vector");
@@ -98,7 +98,7 @@ class WhiteNoiseFunction : public fn::MultiFunction {
return signature; return signature;
} }
void call(IndexMask mask, fn::MFParams params, fn::MFContext /*context*/) const override void call(IndexMask mask, mf::MFParams params, mf::Context /*context*/) const override
{ {
int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4); int param = ELEM(dimensions_, 2, 3, 4) + ELEM(dimensions_, 1, 4);

View File

@@ -29,7 +29,7 @@ static void sh_node_value_build_multi_function(NodeMultiFunctionBuilder &builder
{ {
const bNodeSocket *bsocket = (bNodeSocket *)builder.node().outputs.first; const bNodeSocket *bsocket = (bNodeSocket *)builder.node().outputs.first;
const bNodeSocketValueFloat *value = (const bNodeSocketValueFloat *)bsocket->default_value; const bNodeSocketValueFloat *value = (const bNodeSocketValueFloat *)bsocket->default_value;
builder.construct_and_set_matching_fn<fn::CustomMF_Constant<float>>(value->value); builder.construct_and_set_matching_fn<mf::CustomMF_Constant<float>>(value->value);
} }
} // namespace blender::nodes::node_shader_value_cc } // namespace blender::nodes::node_shader_value_cc

View File

@@ -225,15 +225,15 @@ static void node_shader_update_vector_math(bNodeTree *ntree, bNode *node)
} }
} }
static const fn::MultiFunction *get_multi_function(const bNode &node) static const mf::MultiFunction *get_multi_function(const bNode &node)
{ {
NodeVectorMathOperation operation = NodeVectorMathOperation(node.custom1); NodeVectorMathOperation operation = NodeVectorMathOperation(node.custom1);
const fn::MultiFunction *multi_fn = nullptr; const mf::MultiFunction *multi_fn = nullptr;
try_dispatch_float_math_fl3_fl3_to_fl3( try_dispatch_float_math_fl3_fl3_to_fl3(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI2_SO<float3, float3, float3>( static auto fn = mf::build::SI2_SO<float3, float3, float3>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -243,7 +243,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
try_dispatch_float_math_fl3_fl3_fl3_to_fl3( try_dispatch_float_math_fl3_fl3_fl3_to_fl3(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -253,7 +253,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
try_dispatch_float_math_fl3_fl3_fl_to_fl3( try_dispatch_float_math_fl3_fl3_fl_to_fl3(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -263,7 +263,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
try_dispatch_float_math_fl3_fl3_to_fl( try_dispatch_float_math_fl3_fl3_to_fl(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI2_SO<float3, float3, float>( static auto fn = mf::build::SI2_SO<float3, float3, float>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -273,7 +273,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
try_dispatch_float_math_fl3_fl_to_fl3( try_dispatch_float_math_fl3_fl_to_fl3(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI2_SO<float3, float, float3>( static auto fn = mf::build::SI2_SO<float3, float, float3>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -283,7 +283,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
try_dispatch_float_math_fl3_to_fl3( try_dispatch_float_math_fl3_to_fl3(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI1_SO<float3, float3>( static auto fn = mf::build::SI1_SO<float3, float3>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -293,7 +293,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
try_dispatch_float_math_fl3_to_fl( try_dispatch_float_math_fl3_to_fl(
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) { operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static auto fn = fn::build_mf::SI1_SO<float3, float>( static auto fn = mf::build::SI1_SO<float3, float>(
info.title_case_name.c_str(), function, exec_preset); info.title_case_name.c_str(), function, exec_preset);
multi_fn = &fn; multi_fn = &fn;
}); });
@@ -306,7 +306,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
static void sh_node_vector_math_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_vector_math_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }

View File

@@ -96,7 +96,7 @@ static float3 sh_node_vector_rotate_euler(const float3 &vector,
return result + center; return result + center;
} }
static const fn::MultiFunction *get_multi_function(const bNode &node) static const mf::MultiFunction *get_multi_function(const bNode &node)
{ {
bool invert = node.custom2; bool invert = node.custom2;
const int mode = node.custom1; const int mode = node.custom1;
@@ -104,14 +104,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
switch (mode) { switch (mode) {
case NODE_VECTOR_ROTATE_TYPE_AXIS: { case NODE_VECTOR_ROTATE_TYPE_AXIS: {
if (invert) { if (invert) {
static auto fn = fn::build_mf::SI4_SO<float3, float3, float3, float, float3>( static auto fn = mf::build::SI4_SO<float3, float3, float3, float, float3>(
"Rotate Axis", "Rotate Axis",
[](const float3 &in, const float3 &center, const float3 &axis, float angle) { [](const float3 &in, const float3 &center, const float3 &axis, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle); return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}); });
return &fn; return &fn;
} }
static auto fn = fn::build_mf::SI4_SO<float3, float3, float3, float, float3>( static auto fn = mf::build::SI4_SO<float3, float3, float3, float, float3>(
"Rotate Axis", "Rotate Axis",
[](const float3 &in, const float3 &center, const float3 &axis, float angle) { [](const float3 &in, const float3 &center, const float3 &axis, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle); return sh_node_vector_rotate_around_axis(in, center, axis, angle);
@@ -121,13 +121,13 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_VECTOR_ROTATE_TYPE_AXIS_X: { case NODE_VECTOR_ROTATE_TYPE_AXIS_X: {
float3 axis = float3(1.0f, 0.0f, 0.0f); float3 axis = float3(1.0f, 0.0f, 0.0f);
if (invert) { if (invert) {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate X-Axis", [=](const float3 &in, const float3 &center, float angle) { "Rotate X-Axis", [=](const float3 &in, const float3 &center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle); return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}); });
return &fn; return &fn;
} }
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate X-Axis", [=](const float3 &in, const float3 &center, float angle) { "Rotate X-Axis", [=](const float3 &in, const float3 &center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle); return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}); });
@@ -136,13 +136,13 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: { case NODE_VECTOR_ROTATE_TYPE_AXIS_Y: {
float3 axis = float3(0.0f, 1.0f, 0.0f); float3 axis = float3(0.0f, 1.0f, 0.0f);
if (invert) { if (invert) {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate Y-Axis", [=](const float3 &in, const float3 &center, float angle) { "Rotate Y-Axis", [=](const float3 &in, const float3 &center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle); return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}); });
return &fn; return &fn;
} }
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate Y-Axis", [=](const float3 &in, const float3 &center, float angle) { "Rotate Y-Axis", [=](const float3 &in, const float3 &center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle); return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}); });
@@ -151,13 +151,13 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: { case NODE_VECTOR_ROTATE_TYPE_AXIS_Z: {
float3 axis = float3(0.0f, 0.0f, 1.0f); float3 axis = float3(0.0f, 0.0f, 1.0f);
if (invert) { if (invert) {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate Z-Axis", [=](const float3 &in, const float3 &center, float angle) { "Rotate Z-Axis", [=](const float3 &in, const float3 &center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, -angle); return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
}); });
return &fn; return &fn;
} }
static auto fn = fn::build_mf::SI3_SO<float3, float3, float, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float, float3>(
"Rotate Z-Axis", [=](const float3 &in, const float3 &center, float angle) { "Rotate Z-Axis", [=](const float3 &in, const float3 &center, float angle) {
return sh_node_vector_rotate_around_axis(in, center, axis, angle); return sh_node_vector_rotate_around_axis(in, center, axis, angle);
}); });
@@ -165,13 +165,13 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
} }
case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: { case NODE_VECTOR_ROTATE_TYPE_EULER_XYZ: {
if (invert) { if (invert) {
static auto fn = fn::build_mf::SI3_SO<float3, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
"Rotate Euler", [](const float3 &in, const float3 &center, const float3 &rotation) { "Rotate Euler", [](const float3 &in, const float3 &center, const float3 &rotation) {
return sh_node_vector_rotate_euler(in, center, rotation, true); return sh_node_vector_rotate_euler(in, center, rotation, true);
}); });
return &fn; return &fn;
} }
static auto fn = fn::build_mf::SI3_SO<float3, float3, float3, float3>( static auto fn = mf::build::SI3_SO<float3, float3, float3, float3>(
"Rotate Euler", [](const float3 &in, const float3 &center, const float3 &rotation) { "Rotate Euler", [](const float3 &in, const float3 &center, const float3 &rotation) {
return sh_node_vector_rotate_euler(in, center, rotation, false); return sh_node_vector_rotate_euler(in, center, rotation, false);
}); });
@@ -185,7 +185,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
static void sh_node_vector_rotate_build_multi_function(NodeMultiFunctionBuilder &builder) static void sh_node_vector_rotate_build_multi_function(NodeMultiFunctionBuilder &builder)
{ {
const fn::MultiFunction *fn = get_multi_function(builder.node()); const mf::MultiFunction *fn = get_multi_function(builder.node());
builder.set_matching_fn(fn); builder.set_matching_fn(fn);
} }