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:
@@ -17,7 +17,9 @@
|
||||
struct Mesh;
|
||||
struct PointCloud;
|
||||
namespace blender::fn {
|
||||
namespace multi_function {
|
||||
class MultiFunction;
|
||||
}
|
||||
class GField;
|
||||
} // namespace blender::fn
|
||||
|
||||
@@ -174,7 +176,7 @@ struct AttributeValidator {
|
||||
/**
|
||||
* Single input, single output function that corrects attribute values if necessary.
|
||||
*/
|
||||
const fn::MultiFunction *function;
|
||||
const fn::multi_function::MultiFunction *function;
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
|
@@ -107,9 +107,6 @@ class GeoNodeExecParams;
|
||||
class NodeDeclarationBuilder;
|
||||
class GatherLinkSearchOpParams;
|
||||
} // namespace nodes
|
||||
namespace fn {
|
||||
class MFDataType;
|
||||
} // namespace fn
|
||||
namespace realtime_compositor {
|
||||
class Context;
|
||||
class NodeOperation;
|
||||
|
@@ -8,19 +8,19 @@
|
||||
namespace blender::bke {
|
||||
|
||||
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_uninitialized)(const void *src, void *dst);
|
||||
};
|
||||
|
||||
class DataTypeConversions {
|
||||
private:
|
||||
Map<std::pair<fn::MFDataType, fn::MFDataType>, ConversionFunctions> conversions_;
|
||||
Map<std::pair<mf::DataType, mf::DataType>, ConversionFunctions> conversions_;
|
||||
|
||||
public:
|
||||
void add(fn::MFDataType from_type,
|
||||
fn::MFDataType to_type,
|
||||
const fn::MultiFunction &fn,
|
||||
void add(mf::DataType from_type,
|
||||
mf::DataType to_type,
|
||||
const mf::MultiFunction &fn,
|
||||
void (*convert_single_to_initialized)(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});
|
||||
}
|
||||
|
||||
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});
|
||||
}
|
||||
|
||||
const ConversionFunctions *get_conversion_functions(const CPPType &from, const CPPType &to) const
|
||||
{
|
||||
return this->get_conversion_functions(fn::MFDataType::ForSingle(from),
|
||||
fn::MFDataType::ForSingle(to));
|
||||
return this->get_conversion_functions(mf::DataType::ForSingle(from),
|
||||
mf::DataType::ForSingle(to));
|
||||
}
|
||||
|
||||
const fn::MultiFunction *get_conversion_multi_function(fn::MFDataType from,
|
||||
fn::MFDataType to) const
|
||||
const mf::MultiFunction *get_conversion_multi_function(mf::DataType from, mf::DataType to) const
|
||||
{
|
||||
const ConversionFunctions *functions = this->get_conversion_functions(from, to);
|
||||
return functions ? functions->multi_function : nullptr;
|
||||
@@ -49,7 +48,7 @@ class DataTypeConversions {
|
||||
bool is_convertible(const CPPType &from_type, const CPPType &to_type) const
|
||||
{
|
||||
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,
|
||||
|
@@ -440,12 +440,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
|
||||
make_array_write_attribute<float3>,
|
||||
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",
|
||||
[](int8_t value) {
|
||||
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",
|
||||
ATTR_DOMAIN_POINT,
|
||||
CD_PROP_INT8,
|
||||
@@ -484,10 +484,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
|
||||
make_array_write_attribute<float>,
|
||||
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",
|
||||
[](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",
|
||||
ATTR_DOMAIN_CURVE,
|
||||
CD_PROP_INT8,
|
||||
@@ -501,12 +501,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
|
||||
tag_component_topology_changed,
|
||||
AttributeValidator{&nurbs_order_clamp});
|
||||
|
||||
static const 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",
|
||||
[](int8_t value) {
|
||||
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",
|
||||
ATTR_DOMAIN_CURVE,
|
||||
CD_PROP_INT8,
|
||||
@@ -520,12 +520,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
|
||||
tag_component_normals_changed,
|
||||
AttributeValidator{&normal_mode_clamp});
|
||||
|
||||
static const 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",
|
||||
[](int8_t value) {
|
||||
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",
|
||||
ATTR_DOMAIN_CURVE,
|
||||
CD_PROP_INT8,
|
||||
@@ -539,12 +539,12 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
|
||||
tag_component_topology_changed,
|
||||
AttributeValidator{&knots_mode_clamp});
|
||||
|
||||
static const 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",
|
||||
[](int8_t value) {
|
||||
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",
|
||||
ATTR_DOMAIN_CURVE,
|
||||
CD_PROP_INT8,
|
||||
@@ -558,10 +558,10 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
|
||||
tag_component_curve_types_changed,
|
||||
AttributeValidator{&curve_type_clamp});
|
||||
|
||||
static const auto resolution_clamp = fn::build_mf::SI1_SO<int, int>(
|
||||
static const auto resolution_clamp = mf::build::SI1_SO<int, int>(
|
||||
"Resolution Validate",
|
||||
[](int value) { return std::max<int>(value, 1); },
|
||||
fn::build_mf::exec_presets::AllSpanOrSingle());
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
static BuiltinCustomDataLayerProvider resolution("resolution",
|
||||
ATTR_DOMAIN_CURVE,
|
||||
CD_PROP_INT32,
|
||||
|
@@ -1264,13 +1264,13 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
|
||||
make_array_write_attribute<int>,
|
||||
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",
|
||||
[](int value) {
|
||||
/* 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());
|
||||
},
|
||||
fn::build_mf::exec_presets::AllSpanOrSingle());
|
||||
mf::build::exec_presets::AllSpanOrSingle());
|
||||
static BuiltinCustomDataLayerProvider material_index("material_index",
|
||||
ATTR_DOMAIN_FACE,
|
||||
CD_PROP_INT32,
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
using fn::MFDataType;
|
||||
using mf::DataType;
|
||||
|
||||
template<typename From, typename To, To (*ConversionF)(const From &)>
|
||||
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 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(),
|
||||
/* Use lambda instead of passing #ConversionF directly, because otherwise the compiler won't
|
||||
* inline the function. */
|
||||
[](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) {
|
||||
*(To *)dst = ConversionF(*(const From *)src);
|
||||
};
|
||||
static auto convert_single_to_uninitialized = [](const void *src, void *dst) {
|
||||
new (dst) To(ConversionF(*(const From *)src));
|
||||
};
|
||||
conversions.add(fn::MFDataType::ForSingle<From>(),
|
||||
fn::MFDataType::ForSingle<To>(),
|
||||
conversions.add(mf::DataType::ForSingle<From>(),
|
||||
mf::DataType::ForSingle<To>(),
|
||||
multi_function,
|
||||
convert_single_to_initialized,
|
||||
convert_single_to_uninitialized);
|
||||
@@ -361,26 +361,26 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type,
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
functions->convert_single_to_uninitialized(from_value, to_value);
|
||||
}
|
||||
|
||||
static void call_convert_to_uninitialized_fn(const GVArray &from,
|
||||
const fn::MultiFunction &fn,
|
||||
const mf::MultiFunction &fn,
|
||||
const IndexMask mask,
|
||||
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_uninitialized_single_output(to);
|
||||
fn::MFContextBuilder context;
|
||||
mf::ContextBuilder context;
|
||||
fn.call_auto(mask, params, context);
|
||||
}
|
||||
|
||||
static void call_convert_to_uninitialized_fn(const GVArray &from,
|
||||
const fn::MultiFunction &fn,
|
||||
const mf::MultiFunction &fn,
|
||||
GMutableSpan 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(this->is_convertible(from_type, to_type));
|
||||
|
||||
const fn::MultiFunction *fn = this->get_conversion_multi_function(
|
||||
MFDataType::ForSingle(from_type), MFDataType::ForSingle(to_type));
|
||||
const mf::MultiFunction *fn = this->get_conversion_multi_function(DataType::ForSingle(from_type),
|
||||
DataType::ForSingle(to_type));
|
||||
|
||||
to_type.destruct_n(to_span.data(), to_span.size());
|
||||
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)) {
|
||||
return {};
|
||||
}
|
||||
const fn::MultiFunction &fn = *this->get_conversion_multi_function(
|
||||
fn::MFDataType::ForSingle(from_type), fn::MFDataType::ForSingle(to_type));
|
||||
const mf::MultiFunction &fn = *this->get_conversion_multi_function(
|
||||
mf::DataType::ForSingle(from_type), mf::DataType::ForSingle(to_type));
|
||||
return {std::make_shared<fn::FieldOperation>(fn, Vector<fn::GField>{std::move(field)})};
|
||||
}
|
||||
|
||||
|
@@ -212,28 +212,28 @@ class FieldOperation : public FieldNode {
|
||||
* The multi-function used by this node. It is optionally owned.
|
||||
* Multi-functions with mutable or vector parameters are not supported currently.
|
||||
*/
|
||||
std::shared_ptr<const MultiFunction> owned_function_;
|
||||
const MultiFunction *function_;
|
||||
std::shared_ptr<const mf::MultiFunction> owned_function_;
|
||||
const mf::MultiFunction *function_;
|
||||
|
||||
/** Inputs to the operation. */
|
||||
blender::Vector<GField> inputs_;
|
||||
|
||||
public:
|
||||
FieldOperation(std::shared_ptr<const MultiFunction> function, Vector<GField> inputs = {});
|
||||
FieldOperation(const MultiFunction &function, Vector<GField> inputs = {});
|
||||
FieldOperation(std::shared_ptr<const mf::MultiFunction> function, Vector<GField> inputs = {});
|
||||
FieldOperation(const mf::MultiFunction &function, Vector<GField> inputs = {});
|
||||
~FieldOperation();
|
||||
|
||||
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;
|
||||
|
||||
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 = {})
|
||||
{
|
||||
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 = {})
|
||||
{
|
||||
return std::make_shared<FieldOperation>(FieldOperation(function, inputs));
|
||||
@@ -640,7 +640,7 @@ inline Span<GField> FieldOperation::inputs() const
|
||||
return inputs_;
|
||||
}
|
||||
|
||||
inline const MultiFunction &FieldOperation::multi_function() const
|
||||
inline const mf::MultiFunction &FieldOperation::multi_function() const
|
||||
{
|
||||
return *function_;
|
||||
}
|
||||
@@ -649,7 +649,7 @@ inline const CPPType &FieldOperation::output_cpp_type(int output_index) const
|
||||
{
|
||||
int output_counter = 0;
|
||||
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 (output_counter == output_index) {
|
||||
return param_type.data_type().single_type();
|
||||
|
@@ -470,3 +470,7 @@ inline void Params::assert_valid_thread() const
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::fn::lazy_function
|
||||
|
||||
namespace blender {
|
||||
namespace lf = fn::lazy_function;
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* arrays are not owned by MFParams.
|
||||
* - `IndexMask`: An array of indices indicating which indices in the provided arrays should be
|
||||
* 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:
|
||||
* 1. Create a new subclass of MultiFunction.
|
||||
@@ -35,11 +35,11 @@
|
||||
#include "FN_multi_function_context.hh"
|
||||
#include "FN_multi_function_params.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
class MultiFunction {
|
||||
private:
|
||||
const MFSignature *signature_ref_ = nullptr;
|
||||
const Signature *signature_ref_ = nullptr;
|
||||
|
||||
public:
|
||||
virtual ~MultiFunction()
|
||||
@@ -52,8 +52,8 @@ class MultiFunction {
|
||||
* - Automatic index mask offsetting to avoid large temporary intermediate arrays that are mostly
|
||||
* unused.
|
||||
*/
|
||||
void call_auto(IndexMask mask, MFParams params, MFContext context) const;
|
||||
virtual void call(IndexMask mask, MFParams params, MFContext context) const = 0;
|
||||
void call_auto(IndexMask mask, MFParams params, Context context) const;
|
||||
virtual void call(IndexMask mask, MFParams params, Context context) const = 0;
|
||||
|
||||
virtual uint64_t hash() const
|
||||
{
|
||||
@@ -75,7 +75,7 @@ class MultiFunction {
|
||||
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;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ class MultiFunction {
|
||||
|
||||
virtual std::string debug_name() const;
|
||||
|
||||
const MFSignature &signature() const
|
||||
const Signature &signature() const
|
||||
{
|
||||
BLI_assert(signature_ref_ != nullptr);
|
||||
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
|
||||
* signature lives as long as the multi function. It is ok to embed the signature into the child
|
||||
* 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. */
|
||||
BLI_assert(signature != nullptr);
|
||||
@@ -138,25 +138,18 @@ class MultiFunction {
|
||||
virtual ExecutionHints get_execution_hints() const;
|
||||
};
|
||||
|
||||
inline MFParamsBuilder::MFParamsBuilder(const MultiFunction &fn, int64_t mask_size)
|
||||
: MFParamsBuilder(fn.signature(), IndexMask(mask_size))
|
||||
inline ParamsBuilder::ParamsBuilder(const MultiFunction &fn, int64_t mask_size)
|
||||
: ParamsBuilder(fn.signature(), IndexMask(mask_size))
|
||||
{
|
||||
}
|
||||
|
||||
inline MFParamsBuilder::MFParamsBuilder(const MultiFunction &fn, const IndexMask *mask)
|
||||
: MFParamsBuilder(fn.signature(), *mask)
|
||||
inline ParamsBuilder::ParamsBuilder(const MultiFunction &fn, const IndexMask *mask)
|
||||
: ParamsBuilder(fn.signature(), *mask)
|
||||
{
|
||||
}
|
||||
|
||||
namespace multi_function_types {
|
||||
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::multi_function
|
||||
|
||||
} // namespace blender::fn
|
||||
namespace blender {
|
||||
namespace mf = fn::multi_function;
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
#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
|
||||
@@ -66,13 +66,13 @@ struct AllSpanOrSingle {
|
||||
return std::make_tuple(IndexMaskDevirtualizer<true, true>{mask}, [&]() {
|
||||
typedef ParamTags ParamTag;
|
||||
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);
|
||||
return GVArrayDevirtualizer<T, true, true>{varray_impl};
|
||||
}
|
||||
else if constexpr (ELEM(ParamTag::category,
|
||||
MFParamCategory::SingleOutput,
|
||||
MFParamCategory::SingleMutable)) {
|
||||
ParamCategory::SingleOutput,
|
||||
ParamCategory::SingleMutable)) {
|
||||
T *ptr = std::get<I>(loaded_params);
|
||||
return BasicDevirtualizer<T *>{ptr};
|
||||
}
|
||||
@@ -99,14 +99,14 @@ template<size_t... Indices> struct SomeSpanOrSingle {
|
||||
typedef ParamTags ParamTag;
|
||||
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>();
|
||||
const GVArrayImpl &varray_impl = *std::get<I>(loaded_params);
|
||||
return GVArrayDevirtualizer<T, true, UseSpan>{varray_impl};
|
||||
}
|
||||
else if constexpr (ELEM(ParamTag::category,
|
||||
MFParamCategory::SingleOutput,
|
||||
MFParamCategory::SingleMutable)) {
|
||||
ParamCategory::SingleOutput,
|
||||
ParamCategory::SingleMutable)) {
|
||||
T *ptr = std::get<I>(loaded_params);
|
||||
return BasicDevirtualizer<T *>{ptr};
|
||||
}
|
||||
@@ -135,16 +135,16 @@ void execute_array(TypeSequence<ParamTags...> /*param_tags*/,
|
||||
for (const int64_t i : mask) {
|
||||
element_fn([&]() -> decltype(auto) {
|
||||
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. */
|
||||
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
|
||||
* reference, because the pointer points to uninitialized memory. */
|
||||
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. */
|
||||
return args[i];
|
||||
}
|
||||
@@ -180,13 +180,13 @@ void execute_materialized_impl(TypeSequence<ParamTags...> /*param_tags*/,
|
||||
const int64_t out_i = out_mask[i];
|
||||
element_fn([&]() -> decltype(auto) {
|
||||
using ParamTag = ParamTags;
|
||||
if constexpr (ParamTag::category == MFParamCategory::SingleInput) {
|
||||
if constexpr (ParamTag::category == ParamCategory::SingleInput) {
|
||||
return chunks[in_i];
|
||||
}
|
||||
else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) {
|
||||
else if constexpr (ParamTag::category == ParamCategory::SingleOutput) {
|
||||
return chunks + out_i;
|
||||
}
|
||||
else if constexpr (ParamTag::category == MFParamCategory::SingleMutable) {
|
||||
else if constexpr (ParamTag::category == ParamCategory::SingleMutable) {
|
||||
return chunks[out_i];
|
||||
}
|
||||
}()...);
|
||||
@@ -230,7 +230,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
|
||||
typedef ParamTags ParamTag;
|
||||
typedef typename ParamTag::base_type T;
|
||||
[[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 CommonVArrayInfo common_info = varray_impl.common_info();
|
||||
if (common_info.type == CommonVArrayInfo::Type::Single) {
|
||||
@@ -269,7 +269,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
|
||||
using ParamTag = ParamTags;
|
||||
using T = typename ParamTag::base_type;
|
||||
[[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) {
|
||||
/* The single value has been filled into a buffer already reused for every chunk. */
|
||||
return Span<T>(std::get<I>(buffers));
|
||||
@@ -296,8 +296,8 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
|
||||
}
|
||||
}
|
||||
else if constexpr (ELEM(ParamTag::category,
|
||||
MFParamCategory::SingleOutput,
|
||||
MFParamCategory::SingleMutable)) {
|
||||
ParamCategory::SingleOutput,
|
||||
ParamCategory::SingleMutable)) {
|
||||
/* For outputs, just pass a pointer. This is important so that `__restrict` works. */
|
||||
return std::get<I>(loaded_params);
|
||||
}
|
||||
@@ -310,7 +310,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
|
||||
typedef ParamTags ParamTag;
|
||||
typedef typename ParamTag::base_type T;
|
||||
[[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) {
|
||||
T *in_chunk = std::get<I>(buffers_owner).ptr();
|
||||
destruct_n(in_chunk, chunk_size);
|
||||
@@ -327,7 +327,7 @@ void execute_materialized(TypeSequence<ParamTags...> /* param_tags */,
|
||||
typedef ParamTags ParamTag;
|
||||
typedef typename ParamTag::base_type T;
|
||||
[[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) {
|
||||
MutableSpan<T> in_chunk = std::get<I>(buffers);
|
||||
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 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();
|
||||
}
|
||||
else if constexpr (ParamTag::category == MFParamCategory::SingleOutput) {
|
||||
else if constexpr (ParamTag::category == ParamCategory::SingleOutput) {
|
||||
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());
|
||||
}
|
||||
}()...);
|
||||
@@ -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. */
|
||||
typedef ParamTags ParamTag;
|
||||
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);
|
||||
return GVArray(&varray_impl).typed<T>();
|
||||
}
|
||||
else if constexpr (ELEM(ParamTag::category,
|
||||
MFParamCategory::SingleOutput,
|
||||
MFParamCategory::SingleMutable)) {
|
||||
ParamCategory::SingleOutput,
|
||||
ParamCategory::SingleMutable)) {
|
||||
T *ptr = std::get<I>(loaded_params);
|
||||
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 {
|
||||
private:
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
CallFn call_fn_;
|
||||
|
||||
public:
|
||||
CustomMF(const char *name, CallFn call_fn, TypeSequence<ParamTags...> /*param_tags*/)
|
||||
: 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. */
|
||||
([&] { builder.add(ParamTags(), ""); }(), ...);
|
||||
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);
|
||||
}
|
||||
@@ -463,8 +463,8 @@ inline auto build_multi_function_with_n_inputs_one_output(const char *name,
|
||||
const ExecPreset exec_preset,
|
||||
TypeSequence<In...> /*in_types*/)
|
||||
{
|
||||
constexpr auto param_tags = TypeSequence<MFParamTag<MFParamCategory::SingleInput, In>...,
|
||||
MFParamTag<MFParamCategory::SingleOutput, Out>>();
|
||||
constexpr auto param_tags = TypeSequence<MFParamTag<ParamCategory::SingleInput, In>...,
|
||||
MFParamTag<ParamCategory::SingleOutput, Out>>();
|
||||
auto call_fn = build_multi_function_call_from_element_fn(
|
||||
[element_fn](const In &...in, Out *out) { new (out) Out(element_fn(in...)); },
|
||||
exec_preset,
|
||||
@@ -573,15 +573,15 @@ inline auto SM(const char *name,
|
||||
const ElementFn element_fn,
|
||||
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(
|
||||
element_fn, exec_preset, 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
|
||||
@@ -592,7 +592,7 @@ class CustomMF_GenericConstant : public MultiFunction {
|
||||
private:
|
||||
const CPPType &type_;
|
||||
const void *value_;
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
bool owns_value_;
|
||||
|
||||
template<typename T> friend class CustomMF_Constant;
|
||||
@@ -600,7 +600,7 @@ class CustomMF_GenericConstant : public MultiFunction {
|
||||
public:
|
||||
CustomMF_GenericConstant(const CPPType &type, const void *value, bool make_value_copy);
|
||||
~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;
|
||||
bool equals(const MultiFunction &other) const override;
|
||||
};
|
||||
@@ -612,11 +612,11 @@ class CustomMF_GenericConstant : public MultiFunction {
|
||||
class CustomMF_GenericConstantArray : public MultiFunction {
|
||||
private:
|
||||
GSpan array_;
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
|
||||
public:
|
||||
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 {
|
||||
private:
|
||||
T value_;
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
|
||||
public:
|
||||
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");
|
||||
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);
|
||||
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 {
|
||||
private:
|
||||
int output_amount_;
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
|
||||
public:
|
||||
CustomMF_DefaultOutput(Span<MFDataType> input_types, Span<MFDataType> output_types);
|
||||
void call(IndexMask mask, MFParams params, MFContext context) const override;
|
||||
CustomMF_DefaultOutput(Span<DataType> input_types, Span<DataType> output_types);
|
||||
void call(IndexMask mask, MFParams params, Context context) const override;
|
||||
};
|
||||
|
||||
class CustomMF_GenericCopy : public MultiFunction {
|
||||
private:
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
|
||||
public:
|
||||
CustomMF_GenericCopy(MFDataType data_type);
|
||||
void call(IndexMask mask, MFParams params, MFContext context) const override;
|
||||
CustomMF_GenericCopy(DataType data_type);
|
||||
void call(IndexMask mask, MFParams params, Context context) const override;
|
||||
};
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -5,7 +5,7 @@
|
||||
/** \file
|
||||
* \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:
|
||||
* - Pass debug information up and down the function call stack.
|
||||
* - Pass reusable memory buffers to sub-functions to increase performance.
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
#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:
|
||||
MFContext(MFContextBuilder & /*builder*/)
|
||||
Context(ContextBuilder & /*builder*/)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -5,16 +5,16 @@
|
||||
/** \file
|
||||
* \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
|
||||
* is possible when necessary.
|
||||
*/
|
||||
|
||||
#include "BLI_cpp_type.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
class MFDataType {
|
||||
class DataType {
|
||||
public:
|
||||
enum Category {
|
||||
Single,
|
||||
@@ -25,31 +25,31 @@ class MFDataType {
|
||||
Category category_;
|
||||
const CPPType *type_;
|
||||
|
||||
MFDataType(Category category, const CPPType &type) : category_(category), type_(&type)
|
||||
DataType(Category category, const CPPType &type) : category_(category), type_(&type)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
@@ -79,8 +79,8 @@ class MFDataType {
|
||||
return *type_;
|
||||
}
|
||||
|
||||
friend bool operator==(const MFDataType &a, const MFDataType &b);
|
||||
friend bool operator!=(const MFDataType &a, const MFDataType &b);
|
||||
friend bool operator==(const DataType &a, const DataType &b);
|
||||
friend bool operator!=(const DataType &a, const DataType &b);
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
inline bool operator!=(const MFDataType &a, const MFDataType &b)
|
||||
inline bool operator!=(const DataType &a, const DataType &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -14,15 +14,15 @@
|
||||
* - 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "FN_multi_function_data_type.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
enum class MFParamCategory {
|
||||
enum class ParamCategory {
|
||||
SingleInput,
|
||||
VectorInput,
|
||||
SingleOutput,
|
||||
@@ -31,12 +31,12 @@ enum class MFParamCategory {
|
||||
VectorMutable,
|
||||
};
|
||||
|
||||
template<MFParamCategory Category, typename T> struct MFParamTag {
|
||||
static constexpr MFParamCategory category = Category;
|
||||
template<ParamCategory Category, typename T> struct MFParamTag {
|
||||
static constexpr ParamCategory category = Category;
|
||||
using base_type = T;
|
||||
};
|
||||
|
||||
class MFParamType {
|
||||
class ParamType {
|
||||
public:
|
||||
enum InterfaceType {
|
||||
Input,
|
||||
@@ -46,45 +46,45 @@ class MFParamType {
|
||||
|
||||
private:
|
||||
InterfaceType interface_type_;
|
||||
MFDataType data_type_;
|
||||
DataType data_type_;
|
||||
|
||||
public:
|
||||
MFParamType(InterfaceType interface_type, MFDataType data_type)
|
||||
ParamType(InterfaceType interface_type, DataType 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_;
|
||||
}
|
||||
@@ -94,34 +94,34 @@ class MFParamType {
|
||||
return interface_type_;
|
||||
}
|
||||
|
||||
MFParamCategory category() const
|
||||
ParamCategory category() const
|
||||
{
|
||||
switch (data_type_.category()) {
|
||||
case MFDataType::Single: {
|
||||
case DataType::Single: {
|
||||
switch (interface_type_) {
|
||||
case Input:
|
||||
return MFParamCategory::SingleInput;
|
||||
return ParamCategory::SingleInput;
|
||||
case Output:
|
||||
return MFParamCategory::SingleOutput;
|
||||
return ParamCategory::SingleOutput;
|
||||
case Mutable:
|
||||
return MFParamCategory::SingleMutable;
|
||||
return ParamCategory::SingleMutable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFDataType::Vector: {
|
||||
case DataType::Vector: {
|
||||
switch (interface_type_) {
|
||||
case Input:
|
||||
return MFParamCategory::VectorInput;
|
||||
return ParamCategory::VectorInput;
|
||||
case Output:
|
||||
return MFParamCategory::VectorOutput;
|
||||
return ParamCategory::VectorOutput;
|
||||
case Mutable:
|
||||
return MFParamCategory::VectorMutable;
|
||||
return ParamCategory::VectorMutable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return MFParamCategory::SingleInput;
|
||||
return ParamCategory::SingleInput;
|
||||
}
|
||||
|
||||
bool is_input_or_mutable() const
|
||||
@@ -139,18 +139,18 @@ class MFParamType {
|
||||
return interface_type_ == Output;
|
||||
}
|
||||
|
||||
friend bool operator==(const MFParamType &a, const MFParamType &b);
|
||||
friend bool operator!=(const MFParamType &a, const MFParamType &b);
|
||||
friend bool operator==(const ParamType &a, const ParamType &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_;
|
||||
}
|
||||
|
||||
inline bool operator!=(const MFParamType &a, const MFParamType &b)
|
||||
inline bool operator!=(const ParamType &a, const ParamType &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -5,9 +5,9 @@
|
||||
/** \file
|
||||
* \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.
|
||||
*/
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
|
||||
#include "FN_multi_function_signature.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
class MFParamsBuilder {
|
||||
class ParamsBuilder {
|
||||
private:
|
||||
ResourceScope scope_;
|
||||
const MFSignature *signature_;
|
||||
const Signature *signature_;
|
||||
IndexMask mask_;
|
||||
int64_t min_array_size_;
|
||||
Vector<std::variant<GVArray, GMutableSpan, const GVVectorArray *, GVectorArray *>>
|
||||
@@ -37,23 +37,23 @@ class MFParamsBuilder {
|
||||
|
||||
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())
|
||||
{
|
||||
actual_params_.reserve(signature.params.size());
|
||||
}
|
||||
|
||||
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
|
||||
* 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 = "")
|
||||
{
|
||||
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>,
|
||||
varray_tag::single{},
|
||||
CPPType::get<T>(),
|
||||
@@ -62,7 +62,7 @@ class MFParamsBuilder {
|
||||
}
|
||||
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>,
|
||||
varray_tag::single_ref{},
|
||||
CPPType::get<T>(),
|
||||
@@ -71,13 +71,13 @@ class MFParamsBuilder {
|
||||
}
|
||||
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_);
|
||||
actual_params_.append_unchecked_as(std::in_place_type<GVArray>, varray_tag::span{}, span);
|
||||
}
|
||||
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>,
|
||||
varray_tag::single_ref{},
|
||||
*value.type(),
|
||||
@@ -86,7 +86,7 @@ class MFParamsBuilder {
|
||||
}
|
||||
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_);
|
||||
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 = "")
|
||||
{
|
||||
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_);
|
||||
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 = "")
|
||||
{
|
||||
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_);
|
||||
actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
|
||||
}
|
||||
@@ -124,8 +124,8 @@ class MFParamsBuilder {
|
||||
{
|
||||
this->assert_current_param_name(expected_name);
|
||||
const int param_index = this->current_param_index();
|
||||
const MFParamType ¶m_type = signature_->params[param_index].type;
|
||||
BLI_assert(param_type.category() == MFParamCategory::SingleOutput);
|
||||
const ParamType ¶m_type = signature_->params[param_index].type;
|
||||
BLI_assert(param_type.category() == ParamCategory::SingleOutput);
|
||||
const CPPType &type = param_type.data_type().single_type();
|
||||
/* An empty span indicates that this is ignored. */
|
||||
const GMutableSpan dummy_span{type};
|
||||
@@ -134,7 +134,7 @@ class MFParamsBuilder {
|
||||
|
||||
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);
|
||||
BLI_assert(vector_array.size() >= min_array_size_);
|
||||
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 = "")
|
||||
{
|
||||
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_);
|
||||
actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
|
||||
}
|
||||
|
||||
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);
|
||||
BLI_assert(vector_array.size() >= min_array_size_);
|
||||
actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
|
||||
@@ -158,16 +158,16 @@ class MFParamsBuilder {
|
||||
GMutableSpan computed_array(int param_index)
|
||||
{
|
||||
BLI_assert(ELEM(signature_->params[param_index].type.category(),
|
||||
MFParamCategory::SingleOutput,
|
||||
MFParamCategory::SingleMutable));
|
||||
ParamCategory::SingleOutput,
|
||||
ParamCategory::SingleMutable));
|
||||
return *std::get_if<GMutableSpan>(&actual_params_[param_index]);
|
||||
}
|
||||
|
||||
GVectorArray &computed_vector_array(int param_index)
|
||||
{
|
||||
BLI_assert(ELEM(signature_->params[param_index].type.category(),
|
||||
MFParamCategory::VectorOutput,
|
||||
MFParamCategory::VectorMutable));
|
||||
ParamCategory::VectorOutput,
|
||||
ParamCategory::VectorMutable));
|
||||
return **std::get_if<GVectorArray *>(&actual_params_[param_index]);
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ class MFParamsBuilder {
|
||||
}
|
||||
|
||||
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);
|
||||
#ifdef DEBUG
|
||||
@@ -188,7 +188,7 @@ class MFParamsBuilder {
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
@@ -214,10 +214,10 @@ class MFParamsBuilder {
|
||||
|
||||
class MFParams {
|
||||
private:
|
||||
MFParamsBuilder *builder_;
|
||||
ParamsBuilder *builder_;
|
||||
|
||||
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 = "")
|
||||
{
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ class MFParams {
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ class MFParams {
|
||||
}
|
||||
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]);
|
||||
if (!span.is_empty()) {
|
||||
return span;
|
||||
@@ -272,7 +272,7 @@ class MFParams {
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ class MFParams {
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ class MFParams {
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ class MFParams {
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -316,12 +316,12 @@ class MFParams {
|
||||
}
|
||||
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]);
|
||||
}
|
||||
|
||||
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);
|
||||
#ifdef DEBUG
|
||||
@@ -332,7 +332,7 @@ class MFParams {
|
||||
#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);
|
||||
#ifdef DEBUG
|
||||
@@ -346,4 +346,4 @@ class MFParams {
|
||||
GMutableSpan ensure_dummy_single_output(int param_index);
|
||||
};
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -8,19 +8,19 @@
|
||||
|
||||
#include "FN_multi_function.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
class MFVariable;
|
||||
class MFInstruction;
|
||||
class MFCallInstruction;
|
||||
class MFBranchInstruction;
|
||||
class MFDestructInstruction;
|
||||
class MFDummyInstruction;
|
||||
class MFReturnInstruction;
|
||||
class MFProcedure;
|
||||
class Variable;
|
||||
class Instruction;
|
||||
class CallInstruction;
|
||||
class BranchInstruction;
|
||||
class DestructInstruction;
|
||||
class DummyInstruction;
|
||||
class ReturnInstruction;
|
||||
class Procedure;
|
||||
|
||||
/** Every instruction has exactly one of these types. */
|
||||
enum class MFInstructionType {
|
||||
enum class InstructionType {
|
||||
Call,
|
||||
Branch,
|
||||
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.
|
||||
*/
|
||||
class MFInstructionCursor {
|
||||
class InstructionCursor {
|
||||
public:
|
||||
enum Type {
|
||||
None,
|
||||
@@ -45,33 +45,33 @@ class MFInstructionCursor {
|
||||
|
||||
private:
|
||||
Type type_ = None;
|
||||
MFInstruction *instruction_ = nullptr;
|
||||
Instruction *instruction_ = nullptr;
|
||||
/* Only used when it is a branch instruction. */
|
||||
bool branch_output_ = false;
|
||||
|
||||
public:
|
||||
MFInstructionCursor() = default;
|
||||
MFInstructionCursor(MFCallInstruction &instruction);
|
||||
MFInstructionCursor(MFDestructInstruction &instruction);
|
||||
MFInstructionCursor(MFBranchInstruction &instruction, bool branch_output);
|
||||
MFInstructionCursor(MFDummyInstruction &instruction);
|
||||
InstructionCursor() = default;
|
||||
InstructionCursor(CallInstruction &instruction);
|
||||
InstructionCursor(DestructInstruction &instruction);
|
||||
InstructionCursor(BranchInstruction &instruction, bool branch_output);
|
||||
InstructionCursor(DummyInstruction &instruction);
|
||||
|
||||
static MFInstructionCursor ForEntry();
|
||||
static InstructionCursor ForEntry();
|
||||
|
||||
MFInstruction *next(MFProcedure &procedure) const;
|
||||
void set_next(MFProcedure &procedure, MFInstruction *new_instruction) const;
|
||||
Instruction *next(Procedure &procedure) const;
|
||||
void set_next(Procedure &procedure, Instruction *new_instruction) const;
|
||||
|
||||
MFInstruction *instruction() const;
|
||||
Instruction *instruction() 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_ &&
|
||||
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);
|
||||
}
|
||||
@@ -82,21 +82,21 @@ class MFInstructionCursor {
|
||||
* either uninitialized or contains a value for every index (remember, a multi-function procedure
|
||||
* is always evaluated for many indices at the same time).
|
||||
*/
|
||||
class MFVariable : NonCopyable, NonMovable {
|
||||
class Variable : NonCopyable, NonMovable {
|
||||
private:
|
||||
MFDataType data_type_;
|
||||
Vector<MFInstruction *> users_;
|
||||
DataType data_type_;
|
||||
Vector<Instruction *> users_;
|
||||
std::string name_;
|
||||
int index_in_graph_;
|
||||
|
||||
friend MFProcedure;
|
||||
friend MFCallInstruction;
|
||||
friend MFBranchInstruction;
|
||||
friend MFDestructInstruction;
|
||||
friend Procedure;
|
||||
friend CallInstruction;
|
||||
friend BranchInstruction;
|
||||
friend DestructInstruction;
|
||||
|
||||
public:
|
||||
MFDataType data_type() const;
|
||||
Span<MFInstruction *> users();
|
||||
DataType data_type() const;
|
||||
Span<Instruction *> users();
|
||||
|
||||
StringRefNull name() const;
|
||||
void set_name(std::string name);
|
||||
@@ -105,78 +105,78 @@ class MFVariable : NonCopyable, NonMovable {
|
||||
};
|
||||
|
||||
/** Base class for all instruction types. */
|
||||
class MFInstruction : NonCopyable, NonMovable {
|
||||
class Instruction : NonCopyable, NonMovable {
|
||||
protected:
|
||||
MFInstructionType type_;
|
||||
Vector<MFInstructionCursor> prev_;
|
||||
InstructionType type_;
|
||||
Vector<InstructionCursor> prev_;
|
||||
|
||||
friend MFProcedure;
|
||||
friend MFCallInstruction;
|
||||
friend MFBranchInstruction;
|
||||
friend MFDestructInstruction;
|
||||
friend MFDummyInstruction;
|
||||
friend MFReturnInstruction;
|
||||
friend Procedure;
|
||||
friend CallInstruction;
|
||||
friend BranchInstruction;
|
||||
friend DestructInstruction;
|
||||
friend DummyInstruction;
|
||||
friend ReturnInstruction;
|
||||
|
||||
public:
|
||||
MFInstructionType type() const;
|
||||
InstructionType type() const;
|
||||
|
||||
/**
|
||||
* Other instructions that come before this instruction. There can be multiple previous
|
||||
* 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 the variables whose data will be passed into the multi-function.
|
||||
*/
|
||||
class MFCallInstruction : public MFInstruction {
|
||||
class CallInstruction : public Instruction {
|
||||
private:
|
||||
const MultiFunction *fn_ = nullptr;
|
||||
MFInstruction *next_ = nullptr;
|
||||
MutableSpan<MFVariable *> params_;
|
||||
Instruction *next_ = nullptr;
|
||||
MutableSpan<Variable *> params_;
|
||||
|
||||
friend MFProcedure;
|
||||
friend Procedure;
|
||||
|
||||
public:
|
||||
const MultiFunction &fn() const;
|
||||
|
||||
MFInstruction *next();
|
||||
const MFInstruction *next() const;
|
||||
void set_next(MFInstruction *instruction);
|
||||
Instruction *next();
|
||||
const Instruction *next() const;
|
||||
void set_next(Instruction *instruction);
|
||||
|
||||
void set_param_variable(int param_index, MFVariable *variable);
|
||||
void set_params(Span<MFVariable *> variables);
|
||||
void set_param_variable(int param_index, Variable *variable);
|
||||
void set_params(Span<Variable *> variables);
|
||||
|
||||
Span<MFVariable *> params();
|
||||
Span<const MFVariable *> params() const;
|
||||
Span<Variable *> params();
|
||||
Span<const Variable *> params() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
class MFBranchInstruction : public MFInstruction {
|
||||
class BranchInstruction : public Instruction {
|
||||
private:
|
||||
MFVariable *condition_ = nullptr;
|
||||
MFInstruction *branch_true_ = nullptr;
|
||||
MFInstruction *branch_false_ = nullptr;
|
||||
Variable *condition_ = nullptr;
|
||||
Instruction *branch_true_ = nullptr;
|
||||
Instruction *branch_false_ = nullptr;
|
||||
|
||||
friend MFProcedure;
|
||||
friend Procedure;
|
||||
|
||||
public:
|
||||
MFVariable *condition();
|
||||
const MFVariable *condition() const;
|
||||
void set_condition(MFVariable *variable);
|
||||
Variable *condition();
|
||||
const Variable *condition() const;
|
||||
void set_condition(Variable *variable);
|
||||
|
||||
MFInstruction *branch_true();
|
||||
const MFInstruction *branch_true() const;
|
||||
void set_branch_true(MFInstruction *instruction);
|
||||
Instruction *branch_true();
|
||||
const Instruction *branch_true() const;
|
||||
void set_branch_true(Instruction *instruction);
|
||||
|
||||
MFInstruction *branch_false();
|
||||
const MFInstruction *branch_false() const;
|
||||
void set_branch_false(MFInstruction *instruction);
|
||||
Instruction *branch_false();
|
||||
const Instruction *branch_false() const;
|
||||
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
|
||||
* might help with memory buffer reuse, which decreases memory-usage and increases performance.
|
||||
*/
|
||||
class MFDestructInstruction : public MFInstruction {
|
||||
class DestructInstruction : public Instruction {
|
||||
private:
|
||||
MFVariable *variable_ = nullptr;
|
||||
MFInstruction *next_ = nullptr;
|
||||
Variable *variable_ = nullptr;
|
||||
Instruction *next_ = nullptr;
|
||||
|
||||
friend MFProcedure;
|
||||
friend Procedure;
|
||||
|
||||
public:
|
||||
MFVariable *variable();
|
||||
const MFVariable *variable() const;
|
||||
void set_variable(MFVariable *variable);
|
||||
Variable *variable();
|
||||
const Variable *variable() const;
|
||||
void set_variable(Variable *variable);
|
||||
|
||||
MFInstruction *next();
|
||||
const MFInstruction *next() const;
|
||||
void set_next(MFInstruction *instruction);
|
||||
Instruction *next();
|
||||
const Instruction *next() const;
|
||||
void set_next(Instruction *instruction);
|
||||
};
|
||||
|
||||
/**
|
||||
* This instruction does nothing, it just exists to building a procedure simpler in some cases.
|
||||
*/
|
||||
class MFDummyInstruction : public MFInstruction {
|
||||
class DummyInstruction : public Instruction {
|
||||
private:
|
||||
MFInstruction *next_ = nullptr;
|
||||
Instruction *next_ = nullptr;
|
||||
|
||||
friend MFProcedure;
|
||||
friend Procedure;
|
||||
|
||||
public:
|
||||
MFInstruction *next();
|
||||
const MFInstruction *next() const;
|
||||
void set_next(MFInstruction *instruction);
|
||||
Instruction *next();
|
||||
const Instruction *next() const;
|
||||
void set_next(Instruction *instruction);
|
||||
};
|
||||
|
||||
/**
|
||||
* This instruction ends the procedure.
|
||||
*/
|
||||
class MFReturnInstruction : public MFInstruction {
|
||||
class ReturnInstruction : public Instruction {
|
||||
};
|
||||
|
||||
/**
|
||||
* Inputs and outputs of the entire procedure network.
|
||||
*/
|
||||
struct MFParameter {
|
||||
MFParamType::InterfaceType type;
|
||||
MFVariable *variable;
|
||||
ParamType::InterfaceType type;
|
||||
Variable *variable;
|
||||
};
|
||||
|
||||
struct ConstMFParameter {
|
||||
MFParamType::InterfaceType type;
|
||||
const MFVariable *variable;
|
||||
ParamType::InterfaceType type;
|
||||
const Variable *variable;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -241,46 +241,46 @@ struct ConstMFParameter {
|
||||
* variables and instructions that operate on those variables. Branching and looping within the
|
||||
* 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.
|
||||
*/
|
||||
class MFProcedure : NonCopyable, NonMovable {
|
||||
class Procedure : NonCopyable, NonMovable {
|
||||
private:
|
||||
LinearAllocator<> allocator_;
|
||||
Vector<MFCallInstruction *> call_instructions_;
|
||||
Vector<MFBranchInstruction *> branch_instructions_;
|
||||
Vector<MFDestructInstruction *> destruct_instructions_;
|
||||
Vector<MFDummyInstruction *> dummy_instructions_;
|
||||
Vector<MFReturnInstruction *> return_instructions_;
|
||||
Vector<MFVariable *> variables_;
|
||||
Vector<CallInstruction *> call_instructions_;
|
||||
Vector<BranchInstruction *> branch_instructions_;
|
||||
Vector<DestructInstruction *> destruct_instructions_;
|
||||
Vector<DummyInstruction *> dummy_instructions_;
|
||||
Vector<ReturnInstruction *> return_instructions_;
|
||||
Vector<Variable *> variables_;
|
||||
Vector<MFParameter> params_;
|
||||
Vector<destruct_ptr<MultiFunction>> owned_functions_;
|
||||
MFInstruction *entry_ = nullptr;
|
||||
Instruction *entry_ = nullptr;
|
||||
|
||||
friend class MFProcedureDotExport;
|
||||
friend class ProcedureDotExport;
|
||||
|
||||
public:
|
||||
MFProcedure() = default;
|
||||
~MFProcedure();
|
||||
Procedure() = default;
|
||||
~Procedure();
|
||||
|
||||
MFVariable &new_variable(MFDataType data_type, std::string name = "");
|
||||
MFCallInstruction &new_call_instruction(const MultiFunction &fn);
|
||||
MFBranchInstruction &new_branch_instruction();
|
||||
MFDestructInstruction &new_destruct_instruction();
|
||||
MFDummyInstruction &new_dummy_instruction();
|
||||
MFReturnInstruction &new_return_instruction();
|
||||
Variable &new_variable(DataType data_type, std::string name = "");
|
||||
CallInstruction &new_call_instruction(const MultiFunction &fn);
|
||||
BranchInstruction &new_branch_instruction();
|
||||
DestructInstruction &new_destruct_instruction();
|
||||
DummyInstruction &new_dummy_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;
|
||||
|
||||
template<typename T, typename... Args> const MultiFunction &construct_function(Args &&...args);
|
||||
|
||||
MFInstruction *entry();
|
||||
const MFInstruction *entry() const;
|
||||
void set_entry(MFInstruction &entry);
|
||||
Instruction *entry();
|
||||
const Instruction *entry() const;
|
||||
void set_entry(Instruction &entry);
|
||||
|
||||
Span<MFVariable *> variables();
|
||||
Span<const MFVariable *> variables() const;
|
||||
Span<Variable *> variables();
|
||||
Span<const Variable *> variables() const;
|
||||
|
||||
std::string to_dot() const;
|
||||
|
||||
@@ -298,59 +298,49 @@ class MFProcedure : NonCopyable, NonMovable {
|
||||
bool can_be_uninitialized = false;
|
||||
};
|
||||
|
||||
InitState find_initialization_state_before_instruction(const MFInstruction &target_instruction,
|
||||
const MFVariable &variable) const;
|
||||
InitState find_initialization_state_before_instruction(const Instruction &target_instruction,
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
inline MFInstructionCursor::MFInstructionCursor(MFDestructInstruction &instruction)
|
||||
inline InstructionCursor::InstructionCursor(DestructInstruction &instruction)
|
||||
: type_(Destruct), instruction_(&instruction)
|
||||
{
|
||||
}
|
||||
|
||||
inline MFInstructionCursor::MFInstructionCursor(MFBranchInstruction &instruction,
|
||||
bool branch_output)
|
||||
inline InstructionCursor::InstructionCursor(BranchInstruction &instruction, bool branch_output)
|
||||
: type_(Branch), instruction_(&instruction), branch_output_(branch_output)
|
||||
{
|
||||
}
|
||||
|
||||
inline MFInstructionCursor::MFInstructionCursor(MFDummyInstruction &instruction)
|
||||
inline InstructionCursor::InstructionCursor(DummyInstruction &instruction)
|
||||
: type_(Dummy), instruction_(&instruction)
|
||||
{
|
||||
}
|
||||
|
||||
inline MFInstructionCursor MFInstructionCursor::ForEntry()
|
||||
inline InstructionCursor InstructionCursor::ForEntry()
|
||||
{
|
||||
MFInstructionCursor cursor;
|
||||
InstructionCursor cursor;
|
||||
cursor.type_ = Type::Entry;
|
||||
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
|
||||
* version of #MFInstructionCursor. */
|
||||
* version of #InstructionCursor. */
|
||||
return instruction_;
|
||||
}
|
||||
|
||||
inline MFInstructionCursor::Type MFInstructionCursor::type() const
|
||||
inline InstructionCursor::Type InstructionCursor::type() const
|
||||
{
|
||||
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_;
|
||||
}
|
||||
|
||||
inline Span<MFInstruction *> MFVariable::users()
|
||||
inline Span<Instruction *> Variable::users()
|
||||
{
|
||||
return users_;
|
||||
}
|
||||
|
||||
inline StringRefNull MFVariable::name() const
|
||||
inline StringRefNull Variable::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
inline int MFVariable::index_in_procedure() const
|
||||
inline int Variable::index_in_procedure() const
|
||||
{
|
||||
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_;
|
||||
}
|
||||
|
||||
inline Span<MFInstructionCursor> MFInstruction::prev() const
|
||||
inline Span<InstructionCursor> Instruction::prev() const
|
||||
{
|
||||
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_;
|
||||
}
|
||||
|
||||
inline MFInstruction *MFCallInstruction::next()
|
||||
inline Instruction *CallInstruction::next()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
inline const MFInstruction *MFCallInstruction::next() const
|
||||
inline const Instruction *CallInstruction::next() const
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
inline Span<MFVariable *> MFCallInstruction::params()
|
||||
inline Span<Variable *> CallInstruction::params()
|
||||
{
|
||||
return params_;
|
||||
}
|
||||
|
||||
inline Span<const MFVariable *> MFCallInstruction::params() const
|
||||
inline Span<const Variable *> CallInstruction::params() const
|
||||
{
|
||||
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_;
|
||||
}
|
||||
|
||||
inline const MFVariable *MFBranchInstruction::condition() const
|
||||
inline const Variable *BranchInstruction::condition() const
|
||||
{
|
||||
return condition_;
|
||||
}
|
||||
|
||||
inline MFInstruction *MFBranchInstruction::branch_true()
|
||||
inline Instruction *BranchInstruction::branch_true()
|
||||
{
|
||||
return branch_true_;
|
||||
}
|
||||
|
||||
inline const MFInstruction *MFBranchInstruction::branch_true() const
|
||||
inline const Instruction *BranchInstruction::branch_true() const
|
||||
{
|
||||
return branch_true_;
|
||||
}
|
||||
|
||||
inline MFInstruction *MFBranchInstruction::branch_false()
|
||||
inline Instruction *BranchInstruction::branch_false()
|
||||
{
|
||||
return branch_false_;
|
||||
}
|
||||
|
||||
inline const MFInstruction *MFBranchInstruction::branch_false() const
|
||||
inline const Instruction *BranchInstruction::branch_false() const
|
||||
{
|
||||
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_;
|
||||
}
|
||||
|
||||
inline const MFVariable *MFDestructInstruction::variable() const
|
||||
inline const Variable *DestructInstruction::variable() const
|
||||
{
|
||||
return variable_;
|
||||
}
|
||||
|
||||
inline MFInstruction *MFDestructInstruction::next()
|
||||
inline Instruction *DestructInstruction::next()
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
|
||||
inline const MFInstruction *MFDestructInstruction::next() const
|
||||
inline const Instruction *DestructInstruction::next() const
|
||||
{
|
||||
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_;
|
||||
}
|
||||
|
||||
inline const MFInstruction *MFDummyInstruction::next() const
|
||||
inline const Instruction *DummyInstruction::next() const
|
||||
{
|
||||
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));
|
||||
return params_.as_span().cast<ConstMFParameter>();
|
||||
}
|
||||
|
||||
inline MFInstruction *MFProcedure::entry()
|
||||
inline Instruction *Procedure::entry()
|
||||
{
|
||||
return entry_;
|
||||
}
|
||||
|
||||
inline const MFInstruction *MFProcedure::entry() const
|
||||
inline const Instruction *Procedure::entry() const
|
||||
{
|
||||
return entry_;
|
||||
}
|
||||
|
||||
inline Span<MFVariable *> MFProcedure::variables()
|
||||
inline Span<Variable *> Procedure::variables()
|
||||
{
|
||||
return variables_;
|
||||
}
|
||||
|
||||
inline Span<const MFVariable *> MFProcedure::variables() const
|
||||
inline Span<const Variable *> Procedure::variables() const
|
||||
{
|
||||
return variables_;
|
||||
}
|
||||
|
||||
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)...);
|
||||
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
|
||||
|
@@ -8,182 +8,181 @@
|
||||
|
||||
#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:
|
||||
/** Procedure that is being build. */
|
||||
MFProcedure *procedure_ = nullptr;
|
||||
Procedure *procedure_ = nullptr;
|
||||
/** Cursors where the next instruction should be inserted. */
|
||||
Vector<MFInstructionCursor> cursors_;
|
||||
Vector<InstructionCursor> cursors_;
|
||||
|
||||
public:
|
||||
struct Branch;
|
||||
struct Loop;
|
||||
|
||||
MFProcedureBuilder(MFProcedure &procedure,
|
||||
MFInstructionCursor initial_cursor = MFInstructionCursor::ForEntry());
|
||||
ProcedureBuilder(Procedure &procedure,
|
||||
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(Span<MFInstructionCursor> cursors);
|
||||
void set_cursor(Span<MFProcedureBuilder *> builders);
|
||||
void set_cursor(const InstructionCursor &cursor);
|
||||
void set_cursor(Span<InstructionCursor> cursors);
|
||||
void set_cursor(Span<ProcedureBuilder *> builders);
|
||||
void set_cursor_after_branch(Branch &branch);
|
||||
void set_cursor_after_loop(Loop &loop);
|
||||
|
||||
void add_destruct(MFVariable &variable);
|
||||
void add_destruct(Span<MFVariable *> variables);
|
||||
void add_destruct(Variable &variable);
|
||||
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();
|
||||
void add_loop_continue(Loop &loop);
|
||||
void add_loop_break(Loop &loop);
|
||||
|
||||
MFCallInstruction &add_call_with_no_variables(const MultiFunction &fn);
|
||||
MFCallInstruction &add_call_with_all_variables(const MultiFunction &fn,
|
||||
Span<MFVariable *> param_variables);
|
||||
CallInstruction &add_call_with_no_variables(const MultiFunction &fn);
|
||||
CallInstruction &add_call_with_all_variables(const MultiFunction &fn,
|
||||
Span<Variable *> param_variables);
|
||||
|
||||
Vector<MFVariable *> add_call(const MultiFunction &fn,
|
||||
Span<MFVariable *> input_and_mutable_variables = {});
|
||||
Vector<Variable *> add_call(const MultiFunction &fn,
|
||||
Span<Variable *> input_and_mutable_variables = {});
|
||||
|
||||
template<int OutputN>
|
||||
std::array<MFVariable *, OutputN> add_call(const MultiFunction &fn,
|
||||
Span<MFVariable *> input_and_mutable_variables = {});
|
||||
std::array<Variable *, OutputN> add_call(const MultiFunction &fn,
|
||||
Span<Variable *> input_and_mutable_variables = {});
|
||||
|
||||
void add_parameter(MFParamType::InterfaceType interface_type, MFVariable &variable);
|
||||
MFVariable &add_parameter(MFParamType param_type, std::string name = "");
|
||||
void add_parameter(ParamType::InterfaceType interface_type, Variable &variable);
|
||||
Variable &add_parameter(ParamType param_type, std::string name = "");
|
||||
|
||||
MFVariable &add_input_parameter(MFDataType data_type, std::string name = "");
|
||||
template<typename T> MFVariable &add_single_input_parameter(std::string name = "");
|
||||
template<typename T> MFVariable &add_single_mutable_parameter(std::string name = "");
|
||||
Variable &add_input_parameter(DataType data_type, std::string name = "");
|
||||
template<typename T> Variable &add_single_input_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:
|
||||
void link_to_cursors(MFInstruction *instruction);
|
||||
void link_to_cursors(Instruction *instruction);
|
||||
};
|
||||
|
||||
struct MFProcedureBuilder::Branch {
|
||||
MFProcedureBuilder branch_true;
|
||||
MFProcedureBuilder branch_false;
|
||||
struct ProcedureBuilder::Branch {
|
||||
ProcedureBuilder branch_true;
|
||||
ProcedureBuilder branch_false;
|
||||
};
|
||||
|
||||
struct MFProcedureBuilder::Loop {
|
||||
MFInstruction *begin = nullptr;
|
||||
MFDummyInstruction *end = nullptr;
|
||||
struct ProcedureBuilder::Loop {
|
||||
Instruction *begin = nullptr;
|
||||
DummyInstruction *end = nullptr;
|
||||
};
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* MFProcedureBuilder inline methods.
|
||||
* ProcedureBuilder inline methods.
|
||||
*/
|
||||
|
||||
inline MFProcedureBuilder::MFProcedureBuilder(Branch &branch)
|
||||
: MFProcedureBuilder(*branch.branch_true.procedure_)
|
||||
inline ProcedureBuilder::ProcedureBuilder(Branch &branch)
|
||||
: ProcedureBuilder(*branch.branch_true.procedure_)
|
||||
{
|
||||
this->set_cursor_after_branch(branch);
|
||||
}
|
||||
|
||||
inline MFProcedureBuilder::MFProcedureBuilder(MFProcedure &procedure,
|
||||
MFInstructionCursor initial_cursor)
|
||||
inline ProcedureBuilder::ProcedureBuilder(Procedure &procedure, InstructionCursor initial_cursor)
|
||||
: procedure_(&procedure), cursors_({initial_cursor})
|
||||
{
|
||||
}
|
||||
|
||||
inline MFProcedureBuilder::MFProcedureBuilder(Span<MFProcedureBuilder *> builders)
|
||||
: MFProcedureBuilder(*builders[0]->procedure_)
|
||||
inline ProcedureBuilder::ProcedureBuilder(Span<ProcedureBuilder *> builders)
|
||||
: ProcedureBuilder(*builders[0]->procedure_)
|
||||
{
|
||||
this->set_cursor(builders);
|
||||
}
|
||||
|
||||
inline void MFProcedureBuilder::set_cursor(const MFInstructionCursor &cursor)
|
||||
inline void ProcedureBuilder::set_cursor(const InstructionCursor &cursor)
|
||||
{
|
||||
cursors_ = {cursor};
|
||||
}
|
||||
|
||||
inline void MFProcedureBuilder::set_cursor(Span<MFInstructionCursor> cursors)
|
||||
inline void ProcedureBuilder::set_cursor(Span<InstructionCursor> 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});
|
||||
}
|
||||
|
||||
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();
|
||||
for (MFProcedureBuilder *builder : builders) {
|
||||
for (ProcedureBuilder *builder : builders) {
|
||||
cursors_.extend(builder->cursors_);
|
||||
}
|
||||
}
|
||||
|
||||
template<int OutputN>
|
||||
inline std::array<MFVariable *, OutputN> MFProcedureBuilder::add_call(
|
||||
const MultiFunction &fn, Span<MFVariable *> input_and_mutable_variables)
|
||||
inline std::array<Variable *, OutputN> ProcedureBuilder::add_call(
|
||||
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);
|
||||
|
||||
std::array<MFVariable *, OutputN> output_array;
|
||||
std::array<Variable *, OutputN> output_array;
|
||||
initialized_copy_n(output_variables.data(), OutputN, output_array.data());
|
||||
return output_array;
|
||||
}
|
||||
|
||||
inline void MFProcedureBuilder::add_parameter(MFParamType::InterfaceType interface_type,
|
||||
MFVariable &variable)
|
||||
inline void ProcedureBuilder::add_parameter(ParamType::InterfaceType interface_type,
|
||||
Variable &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);
|
||||
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>
|
||||
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>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -8,21 +8,21 @@
|
||||
|
||||
#include "FN_multi_function_procedure.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
/** A multi-function that executes a procedure internally. */
|
||||
class MFProcedureExecutor : public MultiFunction {
|
||||
class ProcedureExecutor : public MultiFunction {
|
||||
private:
|
||||
MFSignature signature_;
|
||||
const MFProcedure &procedure_;
|
||||
Signature signature_;
|
||||
const Procedure &procedure_;
|
||||
|
||||
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:
|
||||
ExecutionHints get_execution_hints() const override;
|
||||
};
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -5,11 +5,11 @@
|
||||
/** \file
|
||||
* \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.
|
||||
*
|
||||
* 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.
|
||||
* - 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
|
||||
@@ -23,10 +23,10 @@
|
||||
|
||||
#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
|
||||
* 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
|
||||
@@ -42,6 +42,6 @@ namespace blender::fn::procedure_optimization {
|
||||
* \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.
|
||||
*/
|
||||
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
|
||||
|
@@ -6,18 +6,18 @@
|
||||
* \ingroup fn
|
||||
*
|
||||
* 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 "BLI_vector.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
struct MFSignature {
|
||||
struct Signature {
|
||||
struct ParamInfo {
|
||||
MFParamType type;
|
||||
ParamType type;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
@@ -32,12 +32,12 @@ struct MFSignature {
|
||||
Vector<ParamInfo> params;
|
||||
};
|
||||
|
||||
class MFSignatureBuilder {
|
||||
class SignatureBuilder {
|
||||
private:
|
||||
MFSignature &signature_;
|
||||
Signature &signature_;
|
||||
|
||||
public:
|
||||
MFSignatureBuilder(const char *function_name, MFSignature &signature_to_build)
|
||||
SignatureBuilder(const char *function_name, Signature &signature_to_build)
|
||||
: signature_(signature_to_build)
|
||||
{
|
||||
signature_.function_name = function_name;
|
||||
@@ -51,7 +51,7 @@ class MFSignatureBuilder {
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -59,11 +59,11 @@ class MFSignatureBuilder {
|
||||
}
|
||||
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 */
|
||||
@@ -74,7 +74,7 @@ class MFSignatureBuilder {
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -82,11 +82,11 @@ class MFSignatureBuilder {
|
||||
}
|
||||
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 */
|
||||
@@ -97,7 +97,7 @@ class MFSignatureBuilder {
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -105,48 +105,48 @@ class MFSignatureBuilder {
|
||||
}
|
||||
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 ¶m_type)
|
||||
void add(const char *name, const ParamType ¶m_type)
|
||||
{
|
||||
switch (param_type.interface_type()) {
|
||||
case MFParamType::Input:
|
||||
case ParamType::Input:
|
||||
this->input(name, param_type.data_type());
|
||||
break;
|
||||
case MFParamType::Mutable:
|
||||
case ParamType::Mutable:
|
||||
this->mutable_(name, param_type.data_type());
|
||||
break;
|
||||
case MFParamType::Output:
|
||||
case ParamType::Output:
|
||||
this->output(name, param_type.data_type());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<MFParamCategory Category, typename T>
|
||||
template<ParamCategory Category, typename T>
|
||||
void add(MFParamTag<Category, T> /* tag */, const char *name)
|
||||
{
|
||||
switch (Category) {
|
||||
case MFParamCategory::SingleInput:
|
||||
case ParamCategory::SingleInput:
|
||||
this->single_input<T>(name);
|
||||
return;
|
||||
case MFParamCategory::VectorInput:
|
||||
case ParamCategory::VectorInput:
|
||||
this->vector_input<T>(name);
|
||||
return;
|
||||
case MFParamCategory::SingleOutput:
|
||||
case ParamCategory::SingleOutput:
|
||||
this->single_output<T>(name);
|
||||
return;
|
||||
case MFParamCategory::VectorOutput:
|
||||
case ParamCategory::VectorOutput:
|
||||
this->vector_output<T>(name);
|
||||
return;
|
||||
case MFParamCategory::SingleMutable:
|
||||
case ParamCategory::SingleMutable:
|
||||
this->single_mutable<T>(name);
|
||||
return;
|
||||
case MFParamCategory::VectorMutable:
|
||||
case ParamCategory::VectorMutable:
|
||||
this->vector_mutable<T>(name);
|
||||
return;
|
||||
}
|
||||
@@ -154,4 +154,4 @@ class MFSignatureBuilder {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -142,19 +142,19 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info,
|
||||
/**
|
||||
* 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,
|
||||
const FieldTreeInfo &field_tree_info,
|
||||
Span<GFieldRef> output_fields)
|
||||
{
|
||||
MFProcedureBuilder builder{procedure};
|
||||
mf::ProcedureBuilder builder{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. */
|
||||
for (const FieldInput &field_input : field_tree_info.deduplicated_field_inputs) {
|
||||
MFVariable &variable = builder.add_input_parameter(
|
||||
MFDataType::ForSingle(field_input.cpp_type()), field_input.debug_name());
|
||||
mf::Variable &variable = builder.add_input_parameter(
|
||||
mf::DataType::ForSingle(field_input.cpp_type()), field_input.debug_name());
|
||||
variable_by_field.add_new({field_input, 0}, &variable);
|
||||
}
|
||||
|
||||
@@ -196,20 +196,20 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
|
||||
else {
|
||||
/* All inputs variables are ready, now gather all variables that are used by the
|
||||
* function and call it. */
|
||||
const MultiFunction &multi_function = operation_node.multi_function();
|
||||
Vector<MFVariable *> variables(multi_function.param_amount());
|
||||
const mf::MultiFunction &multi_function = operation_node.multi_function();
|
||||
Vector<mf::Variable *> variables(multi_function.param_amount());
|
||||
|
||||
int param_input_index = 0;
|
||||
int param_output_index = 0;
|
||||
for (const int param_index : multi_function.param_indices()) {
|
||||
const MFParamType param_type = multi_function.param_type(param_index);
|
||||
const MFParamType::InterfaceType interface_type = param_type.interface_type();
|
||||
if (interface_type == MFParamType::Input) {
|
||||
const mf::ParamType param_type = multi_function.param_type(param_index);
|
||||
const mf::ParamType::InterfaceType interface_type = param_type.interface_type();
|
||||
if (interface_type == mf::ParamType::Input) {
|
||||
const GField &input_field = operation_inputs[param_input_index];
|
||||
variables[param_index] = variable_by_field.lookup(input_field);
|
||||
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 bool output_is_ignored =
|
||||
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 {
|
||||
/* 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;
|
||||
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: {
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@@ -247,13 +247,14 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
|
||||
}
|
||||
|
||||
/* Add output parameters to the procedure. */
|
||||
Set<MFVariable *> already_output_variables;
|
||||
Set<mf::Variable *> already_output_variables;
|
||||
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)) {
|
||||
/* One variable can be output at most once. To output the same value twice, we have to make
|
||||
* a copy first. */
|
||||
const MultiFunction ©_fn = scope.construct<CustomMF_GenericCopy>(variable->data_type());
|
||||
const mf::MultiFunction ©_fn = scope.construct<mf::CustomMF_GenericCopy>(
|
||||
variable->data_type());
|
||||
variable = builder.add_call<1>(copy_fn, {variable})[0];
|
||||
}
|
||||
builder.add_output_parameter(*variable);
|
||||
@@ -264,13 +265,13 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
|
||||
variable_by_field.remove(field);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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";
|
||||
BLI_assert(procedure.validate());
|
||||
@@ -366,13 +367,13 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
|
||||
/* Evaluate varying fields if necessary. */
|
||||
if (!varying_fields_to_evaluate.is_empty()) {
|
||||
/* Build the procedure for those fields. */
|
||||
MFProcedure procedure;
|
||||
mf::Procedure procedure;
|
||||
build_multi_function_procedure_for_fields(
|
||||
procedure, scope, field_tree_info, varying_fields_to_evaluate);
|
||||
MFProcedureExecutor procedure_executor{procedure};
|
||||
mf::ProcedureExecutor procedure_executor{procedure};
|
||||
|
||||
MFParamsBuilder mf_params{procedure_executor, &mask};
|
||||
MFContextBuilder mf_context;
|
||||
mf::ParamsBuilder mf_params{procedure_executor, &mask};
|
||||
mf::ContextBuilder mf_context;
|
||||
|
||||
/* Provide inputs to the procedure executor. */
|
||||
for (const GVArray &varray : field_context_inputs) {
|
||||
@@ -418,12 +419,12 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
|
||||
/* Evaluate constant fields if necessary. */
|
||||
if (!constant_fields_to_evaluate.is_empty()) {
|
||||
/* Build the procedure for those fields. */
|
||||
MFProcedure procedure;
|
||||
mf::Procedure procedure;
|
||||
build_multi_function_procedure_for_fields(
|
||||
procedure, scope, field_tree_info, constant_fields_to_evaluate);
|
||||
MFProcedureExecutor procedure_executor{procedure};
|
||||
MFParamsBuilder mf_params{procedure_executor, 1};
|
||||
MFContextBuilder mf_context;
|
||||
mf::ProcedureExecutor procedure_executor{procedure};
|
||||
mf::ParamsBuilder mf_params{procedure_executor, 1};
|
||||
mf::ContextBuilder mf_context;
|
||||
|
||||
/* Provide inputs to the procedure executor. */
|
||||
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)
|
||||
{
|
||||
static auto not_fn = build_mf::SI1_SO<bool, bool>(
|
||||
"Not", [](bool a) { return !a; }, build_mf::exec_presets::AllSpanOrSingle());
|
||||
static auto not_fn = mf::build::SI1_SO<bool, bool>(
|
||||
"Not", [](bool a) { return !a; }, mf::build::exec_presets::AllSpanOrSingle());
|
||||
auto not_op = std::make_shared<FieldOperation>(FieldOperation(not_fn, {field}));
|
||||
return Field<bool>(not_op);
|
||||
}
|
||||
@@ -597,7 +598,7 @@ void FieldNode::for_each_field_input_recursive(FunctionRef<void(const FieldInput
|
||||
/** \name #FieldOperation
|
||||
* \{ */
|
||||
|
||||
FieldOperation::FieldOperation(std::shared_ptr<const MultiFunction> function,
|
||||
FieldOperation::FieldOperation(std::shared_ptr<const mf::MultiFunction> function,
|
||||
Vector<GField> 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;
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
field_inputs_ = combine_field_inputs(inputs_);
|
||||
|
@@ -5,7 +5,7 @@
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
using ExecutionHints = MultiFunction::ExecutionHints;
|
||||
|
||||
@@ -22,10 +22,10 @@ ExecutionHints MultiFunction::get_execution_hints() const
|
||||
static bool supports_threading_by_slicing_params(const MultiFunction &fn)
|
||||
{
|
||||
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(),
|
||||
MFParamType::InterfaceType::Mutable,
|
||||
MFParamType::InterfaceType::Output)) {
|
||||
ParamType::InterfaceType::Mutable,
|
||||
ParamType::InterfaceType::Output)) {
|
||||
if (param_type.data_type().is_vector()) {
|
||||
return false;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ static int64_t compute_grain_size(const ExecutionHints &hints, const IndexMask m
|
||||
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()) {
|
||||
return;
|
||||
@@ -90,24 +90,24 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
|
||||
Vector<int64_t> 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. */
|
||||
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()) {
|
||||
case MFParamCategory::SingleInput: {
|
||||
case ParamCategory::SingleInput: {
|
||||
const GVArray &varray = params.readonly_single_input(param_index);
|
||||
offset_params.add_readonly_single_input(varray.slice(input_slice_range));
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::SingleMutable: {
|
||||
case ParamCategory::SingleMutable: {
|
||||
const GMutableSpan span = params.single_mutable(param_index);
|
||||
const GMutableSpan sliced_span = span.slice(input_slice_range);
|
||||
offset_params.add_single_mutable(sliced_span);
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::SingleOutput: {
|
||||
case ParamCategory::SingleOutput: {
|
||||
const GMutableSpan span = params.uninitialized_single_output_if_required(param_index);
|
||||
if (span.is_empty()) {
|
||||
offset_params.add_ignored_single_output();
|
||||
@@ -118,9 +118,9 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::VectorInput:
|
||||
case MFParamCategory::VectorMutable:
|
||||
case MFParamCategory::VectorOutput: {
|
||||
case ParamCategory::VectorInput:
|
||||
case ParamCategory::VectorMutable:
|
||||
case ParamCategory::VectorOutput: {
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
@@ -136,4 +136,4 @@ std::string MultiFunction::debug_name() const
|
||||
return signature_ref_->function_name;
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "BLI_hash.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
|
||||
const void *value,
|
||||
@@ -18,7 +18,7 @@ CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
|
||||
}
|
||||
value_ = value;
|
||||
|
||||
MFSignatureBuilder builder{"Constant", signature_};
|
||||
SignatureBuilder builder{"Constant", signature_};
|
||||
builder.single_output("Value", type);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
const CPPType &type = array.type();
|
||||
MFSignatureBuilder builder{"Constant Vector", signature_};
|
||||
SignatureBuilder builder{"Constant Vector", signature_};
|
||||
builder.vector_output("Value", type);
|
||||
this->set_signature(&signature_);
|
||||
}
|
||||
|
||||
void CustomMF_GenericConstantArray::call(IndexMask mask,
|
||||
MFParams params,
|
||||
MFContext /*context*/) const
|
||||
Context /*context*/) const
|
||||
{
|
||||
GVectorArray &vectors = params.vector_output(0);
|
||||
for (int64_t i : mask) {
|
||||
@@ -72,23 +72,23 @@ void CustomMF_GenericConstantArray::call(IndexMask mask,
|
||||
}
|
||||
}
|
||||
|
||||
CustomMF_DefaultOutput::CustomMF_DefaultOutput(Span<MFDataType> input_types,
|
||||
Span<MFDataType> output_types)
|
||||
CustomMF_DefaultOutput::CustomMF_DefaultOutput(Span<DataType> input_types,
|
||||
Span<DataType> output_types)
|
||||
: output_amount_(output_types.size())
|
||||
{
|
||||
MFSignatureBuilder builder{"Default Output", signature_};
|
||||
for (MFDataType data_type : input_types) {
|
||||
SignatureBuilder builder{"Default Output", signature_};
|
||||
for (DataType data_type : input_types) {
|
||||
builder.input("Input", data_type);
|
||||
}
|
||||
for (MFDataType data_type : output_types) {
|
||||
for (DataType data_type : output_types) {
|
||||
builder.output("Output", data_type);
|
||||
}
|
||||
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()) {
|
||||
MFParamType param_type = this->param_type(param_index);
|
||||
ParamType param_type = this->param_type(param_index);
|
||||
if (!param_type.is_output()) {
|
||||
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.output("Output", data_type);
|
||||
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()) {
|
||||
case MFDataType::Single: {
|
||||
case DataType::Single: {
|
||||
const GVArray &inputs = params.readonly_single_input(0, "Input");
|
||||
GMutableSpan outputs = params.uninitialized_single_output(1, "Output");
|
||||
inputs.materialize_to_uninitialized(mask, outputs.data());
|
||||
break;
|
||||
}
|
||||
case MFDataType::Vector: {
|
||||
case DataType::Vector: {
|
||||
const GVVectorArray &inputs = params.readonly_vector_input(0, "Input");
|
||||
GVectorArray &outputs = params.vector_output(1, "Output");
|
||||
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
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "FN_multi_function_params.hh"
|
||||
|
||||
namespace blender::fn {
|
||||
namespace blender::fn::multi_function {
|
||||
|
||||
GMutableSpan MFParams::ensure_dummy_single_output(int param_index)
|
||||
{
|
||||
@@ -27,4 +27,4 @@ GMutableSpan MFParams::ensure_dummy_single_output(int param_index)
|
||||
return span;
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -5,9 +5,9 @@
|
||||
#include "BLI_dot_export.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_) {
|
||||
case Type::None: {
|
||||
@@ -18,11 +18,11 @@ void MFInstructionCursor::set_next(MFProcedure &procedure, MFInstruction *new_in
|
||||
break;
|
||||
}
|
||||
case Type::Call: {
|
||||
static_cast<MFCallInstruction *>(instruction_)->set_next(new_instruction);
|
||||
static_cast<CallInstruction *>(instruction_)->set_next(new_instruction);
|
||||
break;
|
||||
}
|
||||
case Type::Branch: {
|
||||
MFBranchInstruction &branch_instruction = *static_cast<MFBranchInstruction *>(instruction_);
|
||||
BranchInstruction &branch_instruction = *static_cast<BranchInstruction *>(instruction_);
|
||||
if (branch_output_) {
|
||||
branch_instruction.set_branch_true(new_instruction);
|
||||
}
|
||||
@@ -32,17 +32,17 @@ void MFInstructionCursor::set_next(MFProcedure &procedure, MFInstruction *new_in
|
||||
break;
|
||||
}
|
||||
case Type::Destruct: {
|
||||
static_cast<MFDestructInstruction *>(instruction_)->set_next(new_instruction);
|
||||
static_cast<DestructInstruction *>(instruction_)->set_next(new_instruction);
|
||||
break;
|
||||
}
|
||||
case Type::Dummy: {
|
||||
static_cast<MFDummyInstruction *>(instruction_)->set_next(new_instruction);
|
||||
static_cast<DummyInstruction *>(instruction_)->set_next(new_instruction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MFInstruction *MFInstructionCursor::next(MFProcedure &procedure) const
|
||||
Instruction *InstructionCursor::next(Procedure &procedure) const
|
||||
{
|
||||
switch (type_) {
|
||||
case Type::None:
|
||||
@@ -50,28 +50,28 @@ MFInstruction *MFInstructionCursor::next(MFProcedure &procedure) const
|
||||
case Type::Entry:
|
||||
return procedure.entry();
|
||||
case Type::Call:
|
||||
return static_cast<MFCallInstruction *>(instruction_)->next();
|
||||
return static_cast<CallInstruction *>(instruction_)->next();
|
||||
case Type::Branch: {
|
||||
MFBranchInstruction &branch_instruction = *static_cast<MFBranchInstruction *>(instruction_);
|
||||
BranchInstruction &branch_instruction = *static_cast<BranchInstruction *>(instruction_);
|
||||
if (branch_output_) {
|
||||
return branch_instruction.branch_true();
|
||||
}
|
||||
return branch_instruction.branch_false();
|
||||
}
|
||||
case Type::Destruct:
|
||||
return static_cast<MFDestructInstruction *>(instruction_)->next();
|
||||
return static_cast<DestructInstruction *>(instruction_)->next();
|
||||
case Type::Dummy:
|
||||
return static_cast<MFDummyInstruction *>(instruction_)->next();
|
||||
return static_cast<DummyInstruction *>(instruction_)->next();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MFVariable::set_name(std::string name)
|
||||
void Variable::set_name(std::string name)
|
||||
{
|
||||
name_ = std::move(name);
|
||||
}
|
||||
|
||||
void MFCallInstruction::set_next(MFInstruction *instruction)
|
||||
void CallInstruction::set_next(Instruction *instruction)
|
||||
{
|
||||
if (next_ != nullptr) {
|
||||
next_->prev_.remove_first_occurrence_and_reorder(*this);
|
||||
@@ -82,7 +82,7 @@ void MFCallInstruction::set_next(MFInstruction *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) {
|
||||
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;
|
||||
}
|
||||
|
||||
void MFCallInstruction::set_params(Span<MFVariable *> variables)
|
||||
void CallInstruction::set_params(Span<Variable *> variables)
|
||||
{
|
||||
BLI_assert(variables.size() == params_.size());
|
||||
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) {
|
||||
condition_->users_.remove_first_occurrence_and_reorder(this);
|
||||
@@ -113,7 +113,7 @@ void MFBranchInstruction::set_condition(MFVariable *variable)
|
||||
condition_ = variable;
|
||||
}
|
||||
|
||||
void MFBranchInstruction::set_branch_true(MFInstruction *instruction)
|
||||
void BranchInstruction::set_branch_true(Instruction *instruction)
|
||||
{
|
||||
if (branch_true_ != nullptr) {
|
||||
branch_true_->prev_.remove_first_occurrence_and_reorder({*this, true});
|
||||
@@ -124,7 +124,7 @@ void MFBranchInstruction::set_branch_true(MFInstruction *instruction)
|
||||
branch_true_ = instruction;
|
||||
}
|
||||
|
||||
void MFBranchInstruction::set_branch_false(MFInstruction *instruction)
|
||||
void BranchInstruction::set_branch_false(Instruction *instruction)
|
||||
{
|
||||
if (branch_false_ != nullptr) {
|
||||
branch_false_->prev_.remove_first_occurrence_and_reorder({*this, false});
|
||||
@@ -135,7 +135,7 @@ void MFBranchInstruction::set_branch_false(MFInstruction *instruction)
|
||||
branch_false_ = instruction;
|
||||
}
|
||||
|
||||
void MFDestructInstruction::set_variable(MFVariable *variable)
|
||||
void DestructInstruction::set_variable(Variable *variable)
|
||||
{
|
||||
if (variable_ != nullptr) {
|
||||
variable_->users_.remove_first_occurrence_and_reorder(this);
|
||||
@@ -146,7 +146,7 @@ void MFDestructInstruction::set_variable(MFVariable *variable)
|
||||
variable_ = variable;
|
||||
}
|
||||
|
||||
void MFDestructInstruction::set_next(MFInstruction *instruction)
|
||||
void DestructInstruction::set_next(Instruction *instruction)
|
||||
{
|
||||
if (next_ != nullptr) {
|
||||
next_->prev_.remove_first_occurrence_and_reorder(*this);
|
||||
@@ -157,7 +157,7 @@ void MFDestructInstruction::set_next(MFInstruction *instruction)
|
||||
next_ = instruction;
|
||||
}
|
||||
|
||||
void MFDummyInstruction::set_next(MFInstruction *instruction)
|
||||
void DummyInstruction::set_next(Instruction *instruction)
|
||||
{
|
||||
if (next_ != nullptr) {
|
||||
next_->prev_.remove_first_occurrence_and_reorder(*this);
|
||||
@@ -168,9 +168,9 @@ void MFDummyInstruction::set_next(MFInstruction *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.data_type_ = data_type;
|
||||
variable.index_in_graph_ = variables_.size();
|
||||
@@ -178,86 +178,86 @@ MFVariable &MFProcedure::new_variable(MFDataType data_type, std::string name)
|
||||
return variable;
|
||||
}
|
||||
|
||||
MFCallInstruction &MFProcedure::new_call_instruction(const MultiFunction &fn)
|
||||
CallInstruction &Procedure::new_call_instruction(const MultiFunction &fn)
|
||||
{
|
||||
MFCallInstruction &instruction = *allocator_.construct<MFCallInstruction>().release();
|
||||
instruction.type_ = MFInstructionType::Call;
|
||||
CallInstruction &instruction = *allocator_.construct<CallInstruction>().release();
|
||||
instruction.type_ = InstructionType::Call;
|
||||
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);
|
||||
call_instructions_.append(&instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
MFBranchInstruction &MFProcedure::new_branch_instruction()
|
||||
BranchInstruction &Procedure::new_branch_instruction()
|
||||
{
|
||||
MFBranchInstruction &instruction = *allocator_.construct<MFBranchInstruction>().release();
|
||||
instruction.type_ = MFInstructionType::Branch;
|
||||
BranchInstruction &instruction = *allocator_.construct<BranchInstruction>().release();
|
||||
instruction.type_ = InstructionType::Branch;
|
||||
branch_instructions_.append(&instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
MFDestructInstruction &MFProcedure::new_destruct_instruction()
|
||||
DestructInstruction &Procedure::new_destruct_instruction()
|
||||
{
|
||||
MFDestructInstruction &instruction = *allocator_.construct<MFDestructInstruction>().release();
|
||||
instruction.type_ = MFInstructionType::Destruct;
|
||||
DestructInstruction &instruction = *allocator_.construct<DestructInstruction>().release();
|
||||
instruction.type_ = InstructionType::Destruct;
|
||||
destruct_instructions_.append(&instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
MFDummyInstruction &MFProcedure::new_dummy_instruction()
|
||||
DummyInstruction &Procedure::new_dummy_instruction()
|
||||
{
|
||||
MFDummyInstruction &instruction = *allocator_.construct<MFDummyInstruction>().release();
|
||||
instruction.type_ = MFInstructionType::Dummy;
|
||||
DummyInstruction &instruction = *allocator_.construct<DummyInstruction>().release();
|
||||
instruction.type_ = InstructionType::Dummy;
|
||||
dummy_instructions_.append(&instruction);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
MFReturnInstruction &MFProcedure::new_return_instruction()
|
||||
ReturnInstruction &Procedure::new_return_instruction()
|
||||
{
|
||||
MFReturnInstruction &instruction = *allocator_.construct<MFReturnInstruction>().release();
|
||||
instruction.type_ = MFInstructionType::Return;
|
||||
ReturnInstruction &instruction = *allocator_.construct<ReturnInstruction>().release();
|
||||
instruction.type_ = InstructionType::Return;
|
||||
return_instructions_.append(&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});
|
||||
}
|
||||
|
||||
void MFProcedure::set_entry(MFInstruction &entry)
|
||||
void Procedure::set_entry(Instruction &entry)
|
||||
{
|
||||
if (entry_ != nullptr) {
|
||||
entry_->prev_.remove_first_occurrence_and_reorder(MFInstructionCursor::ForEntry());
|
||||
entry_->prev_.remove_first_occurrence_and_reorder(InstructionCursor::ForEntry());
|
||||
}
|
||||
entry_ = &entry;
|
||||
entry_->prev_.append(MFInstructionCursor::ForEntry());
|
||||
entry_->prev_.append(InstructionCursor::ForEntry());
|
||||
}
|
||||
|
||||
MFProcedure::~MFProcedure()
|
||||
Procedure::~Procedure()
|
||||
{
|
||||
for (MFCallInstruction *instruction : call_instructions_) {
|
||||
instruction->~MFCallInstruction();
|
||||
for (CallInstruction *instruction : call_instructions_) {
|
||||
instruction->~CallInstruction();
|
||||
}
|
||||
for (MFBranchInstruction *instruction : branch_instructions_) {
|
||||
instruction->~MFBranchInstruction();
|
||||
for (BranchInstruction *instruction : branch_instructions_) {
|
||||
instruction->~BranchInstruction();
|
||||
}
|
||||
for (MFDestructInstruction *instruction : destruct_instructions_) {
|
||||
instruction->~MFDestructInstruction();
|
||||
for (DestructInstruction *instruction : destruct_instructions_) {
|
||||
instruction->~DestructInstruction();
|
||||
}
|
||||
for (MFDummyInstruction *instruction : dummy_instructions_) {
|
||||
instruction->~MFDummyInstruction();
|
||||
for (DummyInstruction *instruction : dummy_instructions_) {
|
||||
instruction->~DummyInstruction();
|
||||
}
|
||||
for (MFReturnInstruction *instruction : return_instructions_) {
|
||||
instruction->~MFReturnInstruction();
|
||||
for (ReturnInstruction *instruction : return_instructions_) {
|
||||
instruction->~ReturnInstruction();
|
||||
}
|
||||
for (MFVariable *variable : variables_) {
|
||||
variable->~MFVariable();
|
||||
for (Variable *variable : variables_) {
|
||||
variable->~Variable();
|
||||
}
|
||||
}
|
||||
|
||||
bool MFProcedure::validate() const
|
||||
bool Procedure::validate() const
|
||||
{
|
||||
if (entry_ == nullptr) {
|
||||
return false;
|
||||
@@ -280,19 +280,19 @@ bool MFProcedure::validate() const
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const MFDestructInstruction *instruction : destruct_instructions_) {
|
||||
for (const DestructInstruction *instruction : destruct_instructions_) {
|
||||
if (instruction->next_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const MFBranchInstruction *instruction : branch_instructions_) {
|
||||
for (const BranchInstruction *instruction : branch_instructions_) {
|
||||
if (instruction->branch_true_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -300,7 +300,7 @@ bool MFProcedure::validate_all_instruction_pointers_set() const
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const MFDummyInstruction *instruction : dummy_instructions_) {
|
||||
for (const DummyInstruction *instruction : dummy_instructions_) {
|
||||
if (instruction->next_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -308,28 +308,28 @@ bool MFProcedure::validate_all_instruction_pointers_set() const
|
||||
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();
|
||||
for (const int param_index : fn.param_indices()) {
|
||||
const MFParamType param_type = fn.param_type(param_index);
|
||||
if (param_type.category() == MFParamCategory::SingleOutput) {
|
||||
const ParamType param_type = fn.param_type(param_index);
|
||||
if (param_type.category() == ParamCategory::SingleOutput) {
|
||||
/* Single outputs are optional. */
|
||||
continue;
|
||||
}
|
||||
const MFVariable *variable = instruction->params_[param_index];
|
||||
const Variable *variable = instruction->params_[param_index];
|
||||
if (variable == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const MFBranchInstruction *instruction : branch_instructions_) {
|
||||
for (const BranchInstruction *instruction : branch_instructions_) {
|
||||
if (instruction->condition_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const MFDestructInstruction *instruction : destruct_instructions_) {
|
||||
for (const DestructInstruction *instruction : destruct_instructions_) {
|
||||
if (instruction->variable_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -337,13 +337,13 @@ bool MFProcedure::validate_all_params_provided() const
|
||||
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_;
|
||||
for (const int param_index : fn.param_indices()) {
|
||||
const MFParamType param_type = fn.param_type(param_index);
|
||||
const MFVariable *variable = instruction->params_[param_index];
|
||||
const ParamType param_type = fn.param_type(param_index);
|
||||
const Variable *variable = instruction->params_[param_index];
|
||||
if (variable == nullptr) {
|
||||
continue;
|
||||
}
|
||||
@@ -351,17 +351,17 @@ bool MFProcedure::validate_same_variables_in_one_call() const
|
||||
if (other_param_index == param_index) {
|
||||
continue;
|
||||
}
|
||||
const MFVariable *other_variable = instruction->params_[other_param_index];
|
||||
const Variable *other_variable = instruction->params_[other_param_index];
|
||||
if (other_variable != variable) {
|
||||
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. */
|
||||
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. */
|
||||
if (other_param_type.interface_type() != MFParamType::Input) {
|
||||
if (other_param_type.interface_type() != ParamType::Input) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -370,9 +370,9 @@ bool MFProcedure::validate_same_variables_in_one_call() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MFProcedure::validate_parameters() const
|
||||
bool Procedure::validate_parameters() const
|
||||
{
|
||||
Set<const MFVariable *> variables;
|
||||
Set<const Variable *> variables;
|
||||
for (const MFParameter ¶m : params_) {
|
||||
/* One variable cannot be used as multiple parameters. */
|
||||
if (!variables.add(param.variable)) {
|
||||
@@ -382,45 +382,45 @@ bool MFProcedure::validate_parameters() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MFProcedure::validate_initialization() const
|
||||
bool Procedure::validate_initialization() const
|
||||
{
|
||||
/* TODO: Issue warning when it maybe wrongly initialized. */
|
||||
for (const MFDestructInstruction *instruction : destruct_instructions_) {
|
||||
const MFVariable &variable = *instruction->variable_;
|
||||
for (const DestructInstruction *instruction : destruct_instructions_) {
|
||||
const Variable &variable = *instruction->variable_;
|
||||
const InitState state = this->find_initialization_state_before_instruction(*instruction,
|
||||
variable);
|
||||
if (!state.can_be_initialized) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const MFBranchInstruction *instruction : branch_instructions_) {
|
||||
const MFVariable &variable = *instruction->condition_;
|
||||
for (const BranchInstruction *instruction : branch_instructions_) {
|
||||
const Variable &variable = *instruction->condition_;
|
||||
const InitState state = this->find_initialization_state_before_instruction(*instruction,
|
||||
variable);
|
||||
if (!state.can_be_initialized) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (const MFCallInstruction *instruction : call_instructions_) {
|
||||
for (const CallInstruction *instruction : call_instructions_) {
|
||||
const MultiFunction &fn = *instruction->fn_;
|
||||
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 (!instruction->params_[param_index]) {
|
||||
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,
|
||||
variable);
|
||||
switch (param_type.interface_type()) {
|
||||
case MFParamType::Input:
|
||||
case MFParamType::Mutable: {
|
||||
case ParamType::Input:
|
||||
case ParamType::Mutable: {
|
||||
if (!state.can_be_initialized) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFParamType::Output: {
|
||||
case ParamType::Output: {
|
||||
if (!state.can_be_uninitialized) {
|
||||
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 ¶m : 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);
|
||||
}
|
||||
}
|
||||
for (const MFReturnInstruction *instruction : return_instructions_) {
|
||||
for (const MFVariable *variable : variables_) {
|
||||
for (const ReturnInstruction *instruction : return_instructions_) {
|
||||
for (const Variable *variable : variables_) {
|
||||
const InitState init_state = this->find_initialization_state_before_instruction(*instruction,
|
||||
*variable);
|
||||
if (variables_that_should_be_initialized_on_return.contains(variable)) {
|
||||
@@ -454,8 +454,8 @@ bool MFProcedure::validate_initialization() const
|
||||
return true;
|
||||
}
|
||||
|
||||
MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction(
|
||||
const MFInstruction &target_instruction, const MFVariable &target_variable) const
|
||||
Procedure::InitState Procedure::find_initialization_state_before_instruction(
|
||||
const Instruction &target_instruction, const Variable &target_variable) const
|
||||
{
|
||||
InitState state;
|
||||
|
||||
@@ -463,7 +463,7 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
|
||||
bool caller_initialized_variable = false;
|
||||
for (const MFParameter ¶m : params_) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@@ -481,30 +481,30 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
|
||||
check_entry_instruction();
|
||||
}
|
||||
|
||||
Set<const MFInstruction *> checked_instructions;
|
||||
Stack<const MFInstruction *> instructions_to_check;
|
||||
for (const MFInstructionCursor &cursor : target_instruction.prev_) {
|
||||
Set<const Instruction *> checked_instructions;
|
||||
Stack<const Instruction *> instructions_to_check;
|
||||
for (const InstructionCursor &cursor : target_instruction.prev_) {
|
||||
if (cursor.instruction() != nullptr) {
|
||||
instructions_to_check.push(cursor.instruction());
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
/* Skip if the instruction has been checked already. */
|
||||
continue;
|
||||
}
|
||||
bool state_modified = false;
|
||||
switch (instruction.type_) {
|
||||
case MFInstructionType::Call: {
|
||||
const MFCallInstruction &call_instruction = static_cast<const MFCallInstruction &>(
|
||||
case InstructionType::Call: {
|
||||
const CallInstruction &call_instruction = static_cast<const CallInstruction &>(
|
||||
instruction);
|
||||
const MultiFunction &fn = *call_instruction.fn_;
|
||||
for (const int param_index : fn.param_indices()) {
|
||||
if (call_instruction.params_[param_index] == &target_variable) {
|
||||
const MFParamType param_type = fn.param_type(param_index);
|
||||
if (param_type.interface_type() == MFParamType::Output) {
|
||||
const ParamType param_type = fn.param_type(param_index);
|
||||
if (param_type.interface_type() == ParamType::Output) {
|
||||
state.can_be_initialized = true;
|
||||
state_modified = true;
|
||||
break;
|
||||
@@ -513,18 +513,18 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Destruct: {
|
||||
const MFDestructInstruction &destruct_instruction =
|
||||
static_cast<const MFDestructInstruction &>(instruction);
|
||||
case InstructionType::Destruct: {
|
||||
const DestructInstruction &destruct_instruction = static_cast<const DestructInstruction &>(
|
||||
instruction);
|
||||
if (destruct_instruction.variable_ == &target_variable) {
|
||||
state.can_be_uninitialized = true;
|
||||
state_modified = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Branch:
|
||||
case MFInstructionType::Dummy:
|
||||
case MFInstructionType::Return: {
|
||||
case InstructionType::Branch:
|
||||
case InstructionType::Dummy:
|
||||
case InstructionType::Return: {
|
||||
/* These instruction types don't change the initialization state of variables. */
|
||||
break;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
|
||||
if (&instruction == entry_) {
|
||||
check_entry_instruction();
|
||||
}
|
||||
for (const MFInstructionCursor &cursor : instruction.prev_) {
|
||||
for (const InstructionCursor &cursor : instruction.prev_) {
|
||||
if (cursor.instruction() != nullptr) {
|
||||
instructions_to_check.push(cursor.instruction());
|
||||
}
|
||||
@@ -545,15 +545,15 @@ MFProcedure::InitState MFProcedure::find_initialization_state_before_instruction
|
||||
return state;
|
||||
}
|
||||
|
||||
class MFProcedureDotExport {
|
||||
class ProcedureDotExport {
|
||||
private:
|
||||
const MFProcedure &procedure_;
|
||||
const Procedure &procedure_;
|
||||
dot::DirectedGraph digraph_;
|
||||
Map<const MFInstruction *, dot::Node *> dot_nodes_by_begin_;
|
||||
Map<const MFInstruction *, dot::Node *> dot_nodes_by_end_;
|
||||
Map<const Instruction *, dot::Node *> dot_nodes_by_begin_;
|
||||
Map<const Instruction *, dot::Node *> dot_nodes_by_end_;
|
||||
|
||||
public:
|
||||
MFProcedureDotExport(const MFProcedure &procedure) : procedure_(procedure)
|
||||
ProcedureDotExport(const Procedure &procedure) : procedure_(procedure)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -566,7 +566,7 @@ class MFProcedureDotExport {
|
||||
|
||||
void create_nodes()
|
||||
{
|
||||
Vector<const MFInstruction *> all_instructions;
|
||||
Vector<const Instruction *> all_instructions;
|
||||
auto add_instructions = [&](auto instructions) {
|
||||
all_instructions.extend(instructions.begin(), instructions.end());
|
||||
};
|
||||
@@ -576,38 +576,38 @@ class MFProcedureDotExport {
|
||||
add_instructions(procedure_.dummy_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)) {
|
||||
continue;
|
||||
}
|
||||
Vector<const MFInstruction *> block_instructions = this->get_instructions_in_block(
|
||||
Vector<const Instruction *> block_instructions = this->get_instructions_in_block(
|
||||
*representative);
|
||||
std::stringstream ss;
|
||||
ss << "<";
|
||||
|
||||
for (const MFInstruction *current : block_instructions) {
|
||||
for (const Instruction *current : block_instructions) {
|
||||
handled_instructions.add_new(current);
|
||||
switch (current->type()) {
|
||||
case MFInstructionType::Call: {
|
||||
this->instruction_to_string(*static_cast<const MFCallInstruction *>(current), ss);
|
||||
case InstructionType::Call: {
|
||||
this->instruction_to_string(*static_cast<const CallInstruction *>(current), ss);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Destruct: {
|
||||
this->instruction_to_string(*static_cast<const MFDestructInstruction *>(current), ss);
|
||||
case InstructionType::Destruct: {
|
||||
this->instruction_to_string(*static_cast<const DestructInstruction *>(current), ss);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Dummy: {
|
||||
this->instruction_to_string(*static_cast<const MFDummyInstruction *>(current), ss);
|
||||
case InstructionType::Dummy: {
|
||||
this->instruction_to_string(*static_cast<const DummyInstruction *>(current), ss);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Return: {
|
||||
this->instruction_to_string(*static_cast<const MFReturnInstruction *>(current), ss);
|
||||
case InstructionType::Return: {
|
||||
this->instruction_to_string(*static_cast<const ReturnInstruction *>(current), ss);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Branch: {
|
||||
this->instruction_to_string(*static_cast<const MFBranchInstruction *>(current), ss);
|
||||
case InstructionType::Branch: {
|
||||
this->instruction_to_string(*static_cast<const BranchInstruction *>(current), ss);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -625,7 +625,7 @@ class MFProcedureDotExport {
|
||||
void create_edges()
|
||||
{
|
||||
auto create_edge = [&](dot::Node &from_node,
|
||||
const MFInstruction *to_instruction) -> dot::DirectedEdge & {
|
||||
const Instruction *to_instruction) -> dot::DirectedEdge & {
|
||||
if (to_instruction == nullptr) {
|
||||
dot::Node &to_node = digraph_.new_node("missing");
|
||||
to_node.set_shape(dot::Attr_shape::Diamond);
|
||||
@@ -636,35 +636,35 @@ class MFProcedureDotExport {
|
||||
};
|
||||
|
||||
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;
|
||||
switch (from_instruction.type()) {
|
||||
case MFInstructionType::Call: {
|
||||
const MFInstruction *to_instruction =
|
||||
static_cast<const MFCallInstruction &>(from_instruction).next();
|
||||
case InstructionType::Call: {
|
||||
const Instruction *to_instruction =
|
||||
static_cast<const CallInstruction &>(from_instruction).next();
|
||||
create_edge(from_node, to_instruction);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Destruct: {
|
||||
const MFInstruction *to_instruction =
|
||||
static_cast<const MFDestructInstruction &>(from_instruction).next();
|
||||
case InstructionType::Destruct: {
|
||||
const Instruction *to_instruction =
|
||||
static_cast<const DestructInstruction &>(from_instruction).next();
|
||||
create_edge(from_node, to_instruction);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Dummy: {
|
||||
const MFInstruction *to_instruction =
|
||||
static_cast<const MFDummyInstruction &>(from_instruction).next();
|
||||
case InstructionType::Dummy: {
|
||||
const Instruction *to_instruction =
|
||||
static_cast<const DummyInstruction &>(from_instruction).next();
|
||||
create_edge(from_node, to_instruction);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Return: {
|
||||
case InstructionType::Return: {
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Branch: {
|
||||
const MFBranchInstruction &branch_instruction = static_cast<const MFBranchInstruction &>(
|
||||
case InstructionType::Branch: {
|
||||
const BranchInstruction &branch_instruction = static_cast<const BranchInstruction &>(
|
||||
from_instruction);
|
||||
const MFInstruction *to_true_instruction = branch_instruction.branch_true();
|
||||
const MFInstruction *to_false_instruction = branch_instruction.branch_false();
|
||||
const Instruction *to_true_instruction = branch_instruction.branch_true();
|
||||
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_false_instruction).attributes.set("color", "#881111");
|
||||
break;
|
||||
@@ -676,22 +676,22 @@ class MFProcedureDotExport {
|
||||
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) {
|
||||
return true;
|
||||
}
|
||||
if (ELEM(instruction.prev()[0].type(),
|
||||
MFInstructionCursor::Type::Branch,
|
||||
MFInstructionCursor::Type::Entry)) {
|
||||
InstructionCursor::Type::Branch,
|
||||
InstructionCursor::Type::Entry)) {
|
||||
return true;
|
||||
}
|
||||
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)) {
|
||||
current = current->prev()[0].instruction();
|
||||
if (current == &representative) {
|
||||
@@ -702,25 +702,25 @@ class MFProcedureDotExport {
|
||||
return *current;
|
||||
}
|
||||
|
||||
const MFInstruction *get_next_instruction_in_block(const MFInstruction &instruction,
|
||||
const MFInstruction &block_begin)
|
||||
const Instruction *get_next_instruction_in_block(const Instruction &instruction,
|
||||
const Instruction &block_begin)
|
||||
{
|
||||
const MFInstruction *next = nullptr;
|
||||
const Instruction *next = nullptr;
|
||||
switch (instruction.type()) {
|
||||
case MFInstructionType::Call: {
|
||||
next = static_cast<const MFCallInstruction &>(instruction).next();
|
||||
case InstructionType::Call: {
|
||||
next = static_cast<const CallInstruction &>(instruction).next();
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Destruct: {
|
||||
next = static_cast<const MFDestructInstruction &>(instruction).next();
|
||||
case InstructionType::Destruct: {
|
||||
next = static_cast<const DestructInstruction &>(instruction).next();
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Dummy: {
|
||||
next = static_cast<const MFDummyInstruction &>(instruction).next();
|
||||
case InstructionType::Dummy: {
|
||||
next = static_cast<const DummyInstruction &>(instruction).next();
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Return:
|
||||
case MFInstructionType::Branch: {
|
||||
case InstructionType::Return:
|
||||
case InstructionType::Branch: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -736,18 +736,18 @@ class MFProcedureDotExport {
|
||||
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;
|
||||
const MFInstruction &begin = this->get_first_instruction_in_block(representative);
|
||||
for (const MFInstruction *current = &begin; current != nullptr;
|
||||
Vector<const Instruction *> instructions;
|
||||
const Instruction &begin = this->get_first_instruction_in_block(representative);
|
||||
for (const Instruction *current = &begin; current != nullptr;
|
||||
current = this->get_next_instruction_in_block(*current, begin)) {
|
||||
instructions.append(current);
|
||||
}
|
||||
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) {
|
||||
ss << "null";
|
||||
@@ -765,24 +765,24 @@ class MFProcedureDotExport {
|
||||
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();
|
||||
this->instruction_name_format(fn.debug_name() + ": ", ss);
|
||||
for (const int param_index : fn.param_indices()) {
|
||||
const MFParamType param_type = fn.param_type(param_index);
|
||||
const MFVariable *variable = instruction.params()[param_index];
|
||||
const ParamType param_type = fn.param_type(param_index);
|
||||
const Variable *variable = instruction.params()[param_index];
|
||||
ss << R"(<font color="grey30">)";
|
||||
switch (param_type.interface_type()) {
|
||||
case MFParamType::Input: {
|
||||
case ParamType::Input: {
|
||||
ss << "in";
|
||||
break;
|
||||
}
|
||||
case MFParamType::Mutable: {
|
||||
case ParamType::Mutable: {
|
||||
ss << "mut";
|
||||
break;
|
||||
}
|
||||
case MFParamType::Output: {
|
||||
case ParamType::Output: {
|
||||
ss << "out";
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Vector<ConstMFParameter> outgoing_parameters;
|
||||
for (const ConstMFParameter ¶m : procedure_.params()) {
|
||||
if (ELEM(param.type, MFParamType::Mutable, MFParamType::Output)) {
|
||||
if (ELEM(param.type, ParamType::Mutable, ParamType::Output)) {
|
||||
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);
|
||||
variable_to_string(instruction.condition(), ss);
|
||||
@@ -837,7 +837,7 @@ class MFProcedureDotExport {
|
||||
ss << "Entry: ";
|
||||
Vector<ConstMFParameter> incoming_parameters;
|
||||
for (const ConstMFParameter ¶m : procedure_.params()) {
|
||||
if (ELEM(param.type, MFParamType::Input, MFParamType::Mutable)) {
|
||||
if (ELEM(param.type, ParamType::Input, ParamType::Mutable)) {
|
||||
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();
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -2,64 +2,64 @@
|
||||
|
||||
#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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
cursors_ = {};
|
||||
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);
|
||||
cursors_ = {MFInstructionCursor{instruction}};
|
||||
cursors_ = {InstructionCursor{instruction}};
|
||||
return instruction;
|
||||
}
|
||||
|
||||
MFCallInstruction &MFProcedureBuilder::add_call_with_all_variables(
|
||||
const MultiFunction &fn, Span<MFVariable *> param_variables)
|
||||
CallInstruction &ProcedureBuilder::add_call_with_all_variables(const MultiFunction &fn,
|
||||
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);
|
||||
return instruction;
|
||||
}
|
||||
|
||||
Vector<MFVariable *> MFProcedureBuilder::add_call(const MultiFunction &fn,
|
||||
Span<MFVariable *> input_and_mutable_variables)
|
||||
Vector<Variable *> ProcedureBuilder::add_call(const MultiFunction &fn,
|
||||
Span<Variable *> input_and_mutable_variables)
|
||||
{
|
||||
Vector<MFVariable *> output_variables;
|
||||
MFCallInstruction &instruction = this->add_call_with_no_variables(fn);
|
||||
Vector<Variable *> output_variables;
|
||||
CallInstruction &instruction = this->add_call_with_no_variables(fn);
|
||||
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()) {
|
||||
case MFParamType::Input:
|
||||
case MFParamType::Mutable: {
|
||||
MFVariable *variable = input_and_mutable_variables.first();
|
||||
case ParamType::Input:
|
||||
case ParamType::Mutable: {
|
||||
Variable *variable = input_and_mutable_variables.first();
|
||||
instruction.set_param_variable(param_index, variable);
|
||||
input_and_mutable_variables = input_and_mutable_variables.drop_front(1);
|
||||
break;
|
||||
}
|
||||
case MFParamType::Output: {
|
||||
MFVariable &variable = procedure_->new_variable(param_type.data_type(),
|
||||
case ParamType::Output: {
|
||||
Variable &variable = procedure_->new_variable(param_type.data_type(),
|
||||
fn.param_name(param_index));
|
||||
instruction.set_param_variable(param_index, &variable);
|
||||
output_variables.append(&variable);
|
||||
@@ -72,26 +72,26 @@ Vector<MFVariable *> MFProcedureBuilder::add_call(const MultiFunction &fn,
|
||||
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);
|
||||
this->link_to_cursors(&instruction);
|
||||
/* Clear cursors because this builder ends here. */
|
||||
cursors_.clear();
|
||||
|
||||
Branch branch{*procedure_, *procedure_};
|
||||
branch.branch_true.set_cursor(MFInstructionCursor{instruction, true});
|
||||
branch.branch_false.set_cursor(MFInstructionCursor{instruction, false});
|
||||
branch.branch_true.set_cursor(InstructionCursor{instruction, true});
|
||||
branch.branch_false.set_cursor(InstructionCursor{instruction, false});
|
||||
return branch;
|
||||
}
|
||||
|
||||
MFProcedureBuilder::Loop MFProcedureBuilder::add_loop()
|
||||
ProcedureBuilder::Loop ProcedureBuilder::add_loop()
|
||||
{
|
||||
MFDummyInstruction &loop_begin = procedure_->new_dummy_instruction();
|
||||
MFDummyInstruction &loop_end = procedure_->new_dummy_instruction();
|
||||
DummyInstruction &loop_begin = procedure_->new_dummy_instruction();
|
||||
DummyInstruction &loop_end = procedure_->new_dummy_instruction();
|
||||
this->link_to_cursors(&loop_begin);
|
||||
cursors_ = {MFInstructionCursor{loop_begin}};
|
||||
cursors_ = {InstructionCursor{loop_begin}};
|
||||
|
||||
Loop loop;
|
||||
loop.begin = &loop_begin;
|
||||
@@ -100,18 +100,18 @@ MFProcedureBuilder::Loop MFProcedureBuilder::add_loop()
|
||||
return loop;
|
||||
}
|
||||
|
||||
void MFProcedureBuilder::add_loop_continue(Loop &loop)
|
||||
void ProcedureBuilder::add_loop_continue(Loop &loop)
|
||||
{
|
||||
this->link_to_cursors(loop.begin);
|
||||
/* Clear cursors because this builder ends here. */
|
||||
cursors_.clear();
|
||||
}
|
||||
|
||||
void MFProcedureBuilder::add_loop_break(Loop &loop)
|
||||
void ProcedureBuilder::add_loop_break(Loop &loop)
|
||||
{
|
||||
this->link_to_cursors(loop.end);
|
||||
/* Clear cursors because this builder ends here. */
|
||||
cursors_.clear();
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -4,14 +4,14 @@
|
||||
|
||||
#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 ¶m : 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_);
|
||||
@@ -236,7 +236,7 @@ class ValueAllocator : NonCopyable, NonMovable {
|
||||
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) {
|
||||
case ValueType::GVArray: {
|
||||
@@ -317,7 +317,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
/* This a non-owning pointer to either span buffer or #GVectorArray or null. */
|
||||
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_ = nullptr;
|
||||
@@ -359,7 +359,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
return tot_initialized_ == 0;
|
||||
}
|
||||
|
||||
void add_as_input(MFParamsBuilder ¶ms, IndexMask mask, const MFDataType &data_type) const
|
||||
void add_as_input(ParamsBuilder ¶ms, IndexMask mask, const DataType &data_type) const
|
||||
{
|
||||
/* Sanity check to make sure that enough values are initialized. */
|
||||
BLI_assert(mask.size() <= tot_initialized_);
|
||||
@@ -399,7 +399,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
}
|
||||
|
||||
void ensure_is_mutable(IndexMask full_mask,
|
||||
const MFDataType &data_type,
|
||||
const DataType &data_type,
|
||||
ValueAllocator &value_allocator)
|
||||
{
|
||||
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();
|
||||
|
||||
switch (data_type.category()) {
|
||||
case MFDataType::Single: {
|
||||
case DataType::Single: {
|
||||
const CPPType &type = data_type.single_type();
|
||||
VariableValue_Span *new_value = nullptr;
|
||||
if (caller_provided_storage_ == nullptr) {
|
||||
@@ -440,7 +440,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
value_ = new_value;
|
||||
break;
|
||||
}
|
||||
case MFDataType::Vector: {
|
||||
case DataType::Vector: {
|
||||
const CPPType &type = data_type.vector_base_type();
|
||||
VariableValue_GVectorArray *new_value = nullptr;
|
||||
if (caller_provided_storage_ == nullptr) {
|
||||
@@ -471,10 +471,10 @@ class VariableState : NonCopyable, NonMovable {
|
||||
}
|
||||
}
|
||||
|
||||
void add_as_mutable(MFParamsBuilder ¶ms,
|
||||
void add_as_mutable(ParamsBuilder ¶ms,
|
||||
IndexMask mask,
|
||||
IndexMask full_mask,
|
||||
const MFDataType &data_type,
|
||||
const DataType &data_type,
|
||||
ValueAllocator &value_allocator)
|
||||
{
|
||||
/* Sanity check to make sure that enough values are initialized. */
|
||||
@@ -504,10 +504,10 @@ class VariableState : NonCopyable, NonMovable {
|
||||
}
|
||||
}
|
||||
|
||||
void add_as_output(MFParamsBuilder ¶ms,
|
||||
void add_as_output(ParamsBuilder ¶ms,
|
||||
IndexMask mask,
|
||||
IndexMask full_mask,
|
||||
const MFDataType &data_type,
|
||||
const DataType &data_type,
|
||||
ValueAllocator &value_allocator)
|
||||
{
|
||||
/* Sanity check to make sure that enough values are not initialized. */
|
||||
@@ -538,7 +538,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
tot_initialized_ += mask.size();
|
||||
}
|
||||
|
||||
void add_as_input__one(MFParamsBuilder ¶ms, const MFDataType &data_type) const
|
||||
void add_as_input__one(ParamsBuilder ¶ms, const DataType &data_type) const
|
||||
{
|
||||
BLI_assert(this->is_one());
|
||||
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());
|
||||
if (value_ != nullptr && ELEM(value_->type, ValueType::OneSingle, ValueType::OneVector)) {
|
||||
@@ -579,7 +579,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
}
|
||||
|
||||
switch (data_type.category()) {
|
||||
case MFDataType::Single: {
|
||||
case DataType::Single: {
|
||||
const CPPType &type = data_type.single_type();
|
||||
VariableValue_OneSingle *new_value = value_allocator.obtain_OneSingle(type);
|
||||
if (value_ != nullptr) {
|
||||
@@ -600,7 +600,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
value_ = new_value;
|
||||
break;
|
||||
}
|
||||
case MFDataType::Vector: {
|
||||
case DataType::Vector: {
|
||||
const CPPType &type = data_type.vector_base_type();
|
||||
VariableValue_OneVector *new_value = value_allocator.obtain_OneVector(type);
|
||||
if (value_ != nullptr) {
|
||||
@@ -624,8 +624,8 @@ class VariableState : NonCopyable, NonMovable {
|
||||
}
|
||||
}
|
||||
|
||||
void add_as_mutable__one(MFParamsBuilder ¶ms,
|
||||
const MFDataType &data_type,
|
||||
void add_as_mutable__one(ParamsBuilder ¶ms,
|
||||
const DataType &data_type,
|
||||
ValueAllocator &value_allocator)
|
||||
{
|
||||
BLI_assert(this->is_one());
|
||||
@@ -653,9 +653,9 @@ class VariableState : NonCopyable, NonMovable {
|
||||
}
|
||||
}
|
||||
|
||||
void add_as_output__one(MFParamsBuilder ¶ms,
|
||||
void add_as_output__one(ParamsBuilder ¶ms,
|
||||
IndexMask mask,
|
||||
const MFDataType &data_type,
|
||||
const DataType &data_type,
|
||||
ValueAllocator &value_allocator)
|
||||
{
|
||||
BLI_assert(this->is_one());
|
||||
@@ -697,7 +697,7 @@ class VariableState : NonCopyable, NonMovable {
|
||||
*/
|
||||
bool destruct(IndexMask mask,
|
||||
IndexMask full_mask,
|
||||
const MFDataType &data_type,
|
||||
const DataType &data_type,
|
||||
ValueAllocator &value_allocator)
|
||||
{
|
||||
BLI_assert(value_ != nullptr);
|
||||
@@ -822,14 +822,14 @@ class VariableState : NonCopyable, NonMovable {
|
||||
class VariableStates {
|
||||
private:
|
||||
ValueAllocator value_allocator_;
|
||||
const MFProcedure &procedure_;
|
||||
/** The state of every variable, indexed by #MFVariable::index_in_procedure(). */
|
||||
const Procedure &procedure_;
|
||||
/** The state of every variable, indexed by #Variable::index_in_procedure(). */
|
||||
Array<VariableState> variable_states_;
|
||||
IndexMask full_mask_;
|
||||
|
||||
public:
|
||||
VariableStates(LinearAllocator<> &linear_allocator,
|
||||
const MFProcedure &procedure,
|
||||
const Procedure &procedure,
|
||||
IndexMask full_mask)
|
||||
: value_allocator_(linear_allocator),
|
||||
procedure_(procedure),
|
||||
@@ -843,7 +843,7 @@ class VariableStates {
|
||||
for (const int variable_i : procedure_.variables().index_range()) {
|
||||
VariableState &state = variable_states_[variable_i];
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -859,13 +859,13 @@ class VariableStates {
|
||||
return full_mask_;
|
||||
}
|
||||
|
||||
void add_initial_variable_states(const MFProcedureExecutor &fn,
|
||||
const MFProcedure &procedure,
|
||||
void add_initial_variable_states(const ProcedureExecutor &fn,
|
||||
const Procedure &procedure,
|
||||
MFParams ¶ms)
|
||||
{
|
||||
for (const int param_index : fn.param_indices()) {
|
||||
MFParamType param_type = fn.param_type(param_index);
|
||||
const MFVariable *variable = procedure.params()[param_index].variable;
|
||||
ParamType param_type = fn.param_type(param_index);
|
||||
const Variable *variable = procedure.params()[param_index].variable;
|
||||
|
||||
auto add_state = [&](VariableValue *value,
|
||||
bool input_is_initialized,
|
||||
@@ -880,32 +880,32 @@ class VariableStates {
|
||||
};
|
||||
|
||||
switch (param_type.category()) {
|
||||
case MFParamCategory::SingleInput: {
|
||||
case ParamCategory::SingleInput: {
|
||||
const GVArray &data = params.readonly_single_input(param_index);
|
||||
add_state(value_allocator_.obtain_GVArray(data), true);
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::VectorInput: {
|
||||
case ParamCategory::VectorInput: {
|
||||
const GVVectorArray &data = params.readonly_vector_input(param_index);
|
||||
add_state(value_allocator_.obtain_GVVectorArray(data), true);
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::SingleOutput: {
|
||||
case ParamCategory::SingleOutput: {
|
||||
GMutableSpan data = params.uninitialized_single_output(param_index);
|
||||
add_state(value_allocator_.obtain_Span_not_owned(data.data()), false, data.data());
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::VectorOutput: {
|
||||
case ParamCategory::VectorOutput: {
|
||||
GVectorArray &data = params.vector_output(param_index);
|
||||
add_state(value_allocator_.obtain_GVectorArray_not_owned(data), false, &data);
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::SingleMutable: {
|
||||
case ParamCategory::SingleMutable: {
|
||||
GMutableSpan data = params.single_mutable(param_index);
|
||||
add_state(value_allocator_.obtain_Span_not_owned(data.data()), true, data.data());
|
||||
break;
|
||||
}
|
||||
case MFParamCategory::VectorMutable: {
|
||||
case ParamCategory::VectorMutable: {
|
||||
GVectorArray &data = params.vector_mutable(param_index);
|
||||
add_state(value_allocator_.obtain_GVectorArray_not_owned(data), true, &data);
|
||||
break;
|
||||
@@ -915,21 +915,21 @@ class VariableStates {
|
||||
}
|
||||
|
||||
void add_as_param(VariableState &variable_state,
|
||||
MFParamsBuilder ¶ms,
|
||||
const MFParamType ¶m_type,
|
||||
ParamsBuilder ¶ms,
|
||||
const ParamType ¶m_type,
|
||||
const IndexMask &mask)
|
||||
{
|
||||
const MFDataType data_type = param_type.data_type();
|
||||
const DataType data_type = param_type.data_type();
|
||||
switch (param_type.interface_type()) {
|
||||
case MFParamType::Input: {
|
||||
case ParamType::Input: {
|
||||
variable_state.add_as_input(params, mask, data_type);
|
||||
break;
|
||||
}
|
||||
case MFParamType::Mutable: {
|
||||
case ParamType::Mutable: {
|
||||
variable_state.add_as_mutable(params, mask, full_mask_, data_type, value_allocator_);
|
||||
break;
|
||||
}
|
||||
case MFParamType::Output: {
|
||||
case ParamType::Output: {
|
||||
variable_state.add_as_output(params, mask, full_mask_, data_type, value_allocator_);
|
||||
break;
|
||||
}
|
||||
@@ -937,28 +937,28 @@ class VariableStates {
|
||||
}
|
||||
|
||||
void add_as_param__one(VariableState &variable_state,
|
||||
MFParamsBuilder ¶ms,
|
||||
const MFParamType ¶m_type,
|
||||
ParamsBuilder ¶ms,
|
||||
const ParamType ¶m_type,
|
||||
const IndexMask &mask)
|
||||
{
|
||||
const MFDataType data_type = param_type.data_type();
|
||||
const DataType data_type = param_type.data_type();
|
||||
switch (param_type.interface_type()) {
|
||||
case MFParamType::Input: {
|
||||
case ParamType::Input: {
|
||||
variable_state.add_as_input__one(params, data_type);
|
||||
break;
|
||||
}
|
||||
case MFParamType::Mutable: {
|
||||
case ParamType::Mutable: {
|
||||
variable_state.add_as_mutable__one(params, data_type, value_allocator_);
|
||||
break;
|
||||
}
|
||||
case MFParamType::Output: {
|
||||
case ParamType::Output: {
|
||||
variable_state.add_as_output__one(params, mask, data_type, value_allocator_);
|
||||
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);
|
||||
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();
|
||||
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,
|
||||
const MFCallInstruction &instruction,
|
||||
const CallInstruction &instruction,
|
||||
VariableStates &variable_states,
|
||||
MutableSpan<VariableState *> r_param_variable_states)
|
||||
{
|
||||
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) {
|
||||
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,
|
||||
const IndexMask mask,
|
||||
MFParamsBuilder ¶ms,
|
||||
ParamsBuilder ¶ms,
|
||||
VariableStates &variable_states,
|
||||
const Span<VariableState *> param_variable_states)
|
||||
{
|
||||
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];
|
||||
if (variable_state == nullptr) {
|
||||
params.add_ignored_single_output();
|
||||
@@ -1026,12 +1026,12 @@ static void fill_params__one(const MultiFunction &fn,
|
||||
|
||||
static void fill_params(const MultiFunction &fn,
|
||||
const IndexMask mask,
|
||||
MFParamsBuilder ¶ms,
|
||||
ParamsBuilder ¶ms,
|
||||
VariableStates &variable_states,
|
||||
const Span<VariableState *> param_variable_states)
|
||||
{
|
||||
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];
|
||||
if (variable_state == nullptr) {
|
||||
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,
|
||||
VariableStates &variable_states,
|
||||
const MFContext &context)
|
||||
const Context &context)
|
||||
{
|
||||
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
|
||||
* of for every index. */
|
||||
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);
|
||||
|
||||
try {
|
||||
@@ -1068,7 +1068,7 @@ static void execute_call_instruction(const MFCallInstruction &instruction,
|
||||
}
|
||||
}
|
||||
else {
|
||||
MFParamsBuilder params(fn, &mask);
|
||||
ParamsBuilder params(fn, &mask);
|
||||
fill_params(fn, mask, params, variable_states, param_variable_states);
|
||||
|
||||
try {
|
||||
@@ -1098,7 +1098,7 @@ struct InstructionIndices {
|
||||
|
||||
/** Contains information about the next instruction that should be executed. */
|
||||
struct NextInstructionInfo {
|
||||
const MFInstruction *instruction = nullptr;
|
||||
const Instruction *instruction = nullptr;
|
||||
InstructionIndices indices;
|
||||
|
||||
IndexMask mask() const
|
||||
@@ -1123,7 +1123,7 @@ class InstructionScheduler {
|
||||
public:
|
||||
InstructionScheduler() = default;
|
||||
|
||||
void add_referenced_indices(const MFInstruction &instruction, IndexMask mask)
|
||||
void add_referenced_indices(const Instruction &instruction, IndexMask mask)
|
||||
{
|
||||
if (mask.is_empty()) {
|
||||
return;
|
||||
@@ -1134,7 +1134,7 @@ class InstructionScheduler {
|
||||
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()) {
|
||||
return;
|
||||
@@ -1158,7 +1158,7 @@ class InstructionScheduler {
|
||||
return next_instructions_.peek();
|
||||
}
|
||||
|
||||
void update_instruction_pointer(const MFInstruction &instruction)
|
||||
void update_instruction_pointer(const 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());
|
||||
|
||||
@@ -1186,19 +1186,19 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
|
||||
/* Loop until all indices got to a return instruction. */
|
||||
while (!scheduler.is_done()) {
|
||||
const NextInstructionInfo &instr_info = scheduler.peek();
|
||||
const MFInstruction &instruction = *instr_info.instruction;
|
||||
const Instruction &instruction = *instr_info.instruction;
|
||||
switch (instruction.type()) {
|
||||
case MFInstructionType::Call: {
|
||||
const MFCallInstruction &call_instruction = static_cast<const MFCallInstruction &>(
|
||||
case InstructionType::Call: {
|
||||
const CallInstruction &call_instruction = static_cast<const CallInstruction &>(
|
||||
instruction);
|
||||
execute_call_instruction(call_instruction, instr_info.mask(), variable_states, context);
|
||||
scheduler.update_instruction_pointer(*call_instruction.next());
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Branch: {
|
||||
const MFBranchInstruction &branch_instruction = static_cast<const MFBranchInstruction &>(
|
||||
case InstructionType::Branch: {
|
||||
const BranchInstruction &branch_instruction = static_cast<const BranchInstruction &>(
|
||||
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);
|
||||
|
||||
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]);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Destruct: {
|
||||
const MFDestructInstruction &destruct_instruction =
|
||||
static_cast<const MFDestructInstruction &>(instruction);
|
||||
const MFVariable *variable = destruct_instruction.variable();
|
||||
case InstructionType::Destruct: {
|
||||
const DestructInstruction &destruct_instruction = static_cast<const DestructInstruction &>(
|
||||
instruction);
|
||||
const Variable *variable = destruct_instruction.variable();
|
||||
variable_states.destruct(*variable, instr_info.mask());
|
||||
scheduler.update_instruction_pointer(*destruct_instruction.next());
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Dummy: {
|
||||
const MFDummyInstruction &dummy_instruction = static_cast<const MFDummyInstruction &>(
|
||||
case InstructionType::Dummy: {
|
||||
const DummyInstruction &dummy_instruction = static_cast<const DummyInstruction &>(
|
||||
instruction);
|
||||
scheduler.update_instruction_pointer(*dummy_instruction.next());
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Return: {
|
||||
case InstructionType::Return: {
|
||||
/* Don't insert the indices back into the scheduler. */
|
||||
scheduler.pop();
|
||||
break;
|
||||
@@ -1231,17 +1231,17 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
|
||||
}
|
||||
|
||||
for (const int param_index : this->param_indices()) {
|
||||
const MFParamType param_type = this->param_type(param_index);
|
||||
const MFVariable *variable = procedure_.params()[param_index].variable;
|
||||
const ParamType param_type = this->param_type(param_index);
|
||||
const Variable *variable = procedure_.params()[param_index].variable;
|
||||
VariableState &variable_state = variable_states.get_variable_state(*variable);
|
||||
switch (param_type.interface_type()) {
|
||||
case MFParamType::Input: {
|
||||
case ParamType::Input: {
|
||||
/* Input variables must be destructed in the end. */
|
||||
BLI_assert(variable_state.is_fully_uninitialized(full_mask));
|
||||
break;
|
||||
}
|
||||
case MFParamType::Mutable:
|
||||
case MFParamType::Output: {
|
||||
case ParamType::Mutable:
|
||||
case ParamType::Output: {
|
||||
/* Mutable and output variables must be initialized in the end. */
|
||||
BLI_assert(variable_state.is_fully_initialized(full_mask));
|
||||
/* 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;
|
||||
hints.allocates_array = true;
|
||||
@@ -1261,4 +1261,4 @@ MultiFunction::ExecutionHints MFProcedureExecutor::get_execution_hints() const
|
||||
return hints;
|
||||
}
|
||||
|
||||
} // namespace blender::fn
|
||||
} // namespace blender::fn::multi_function
|
||||
|
@@ -2,20 +2,19 @@
|
||||
|
||||
#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. */
|
||||
Map<MFVariable *, MFDestructInstruction *> destruct_instructions;
|
||||
MFInstruction *current_instr = &block_end_instr;
|
||||
Map<Variable *, DestructInstruction *> destruct_instructions;
|
||||
Instruction *current_instr = &block_end_instr;
|
||||
while (true) {
|
||||
MFInstructionType instr_type = current_instr->type();
|
||||
InstructionType instr_type = current_instr->type();
|
||||
switch (instr_type) {
|
||||
case MFInstructionType::Destruct: {
|
||||
MFDestructInstruction &destruct_instr = static_cast<MFDestructInstruction &>(
|
||||
*current_instr);
|
||||
MFVariable *variable = destruct_instr.variable();
|
||||
case InstructionType::Destruct: {
|
||||
DestructInstruction &destruct_instr = static_cast<DestructInstruction &>(*current_instr);
|
||||
Variable *variable = destruct_instr.variable();
|
||||
if (variable == nullptr) {
|
||||
continue;
|
||||
}
|
||||
@@ -24,31 +23,31 @@ void move_destructs_up(MFProcedure &procedure, MFInstruction &block_end_instr)
|
||||
destruct_instructions.add(variable, &destruct_instr);
|
||||
break;
|
||||
}
|
||||
case MFInstructionType::Call: {
|
||||
MFCallInstruction &call_instr = static_cast<MFCallInstruction &>(*current_instr);
|
||||
case InstructionType::Call: {
|
||||
CallInstruction &call_instr = static_cast<CallInstruction &>(*current_instr);
|
||||
/* For each variable, place the corresponding remembered destruct instruction right after
|
||||
* this call instruction. */
|
||||
for (MFVariable *variable : call_instr.params()) {
|
||||
for (Variable *variable : call_instr.params()) {
|
||||
if (variable == nullptr) {
|
||||
continue;
|
||||
}
|
||||
MFDestructInstruction *destruct_instr = destruct_instructions.pop_default(variable,
|
||||
DestructInstruction *destruct_instr = destruct_instructions.pop_default(variable,
|
||||
nullptr);
|
||||
if (destruct_instr == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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()) {
|
||||
/* Do a copy of the cursor here, because `destruct_instr->prev()` changes when
|
||||
* #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);
|
||||
}
|
||||
|
||||
/* Insert destruct instruction in new position. */
|
||||
MFInstruction *next_instr = call_instr.next();
|
||||
Instruction *next_instr = call_instr.next();
|
||||
call_instr.set_next(destruct_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) {
|
||||
/* Stop when there is some branching before this instruction. */
|
||||
break;
|
||||
}
|
||||
const MFInstructionCursor &prev_cursor = prev_cursors[0];
|
||||
const InstructionCursor &prev_cursor = prev_cursors[0];
|
||||
current_instr = prev_cursor.instruction();
|
||||
if (current_instr == nullptr) {
|
||||
/* 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
|
||||
|
@@ -13,7 +13,7 @@ TEST(field, ConstantFunction)
|
||||
{
|
||||
/* TODO: Figure out how to not use another "FieldOperation(" inside of std::make_shared. */
|
||||
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};
|
||||
|
||||
Array<int> result(4);
|
||||
@@ -104,7 +104,7 @@ TEST(field, InputAndFunction)
|
||||
{
|
||||
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{
|
||||
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>()};
|
||||
|
||||
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{
|
||||
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};
|
||||
|
||||
Array<int> result(10);
|
||||
@@ -149,14 +149,14 @@ TEST(field, TwoFunctions)
|
||||
EXPECT_EQ(result[8], 26);
|
||||
}
|
||||
|
||||
class TwoOutputFunction : public MultiFunction {
|
||||
class TwoOutputFunction : public mf::MultiFunction {
|
||||
private:
|
||||
MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
public:
|
||||
TwoOutputFunction()
|
||||
{
|
||||
MFSignatureBuilder builder{"Two Outputs", signature_};
|
||||
mf::SignatureBuilder builder{"Two Outputs", signature_};
|
||||
builder.single_input<int>("In1");
|
||||
builder.single_input<int>("In2");
|
||||
builder.single_output<int>("Add");
|
||||
@@ -164,7 +164,7 @@ class TwoOutputFunction : public MultiFunction {
|
||||
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> &in2 = params.readonly_single_input<int>(1, "In2");
|
||||
@@ -223,7 +223,7 @@ TEST(field, TwoFunctionsTwoOutputs)
|
||||
Field<int> result_field_1{fn, 0};
|
||||
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{
|
||||
std::make_shared<FieldOperation>(FieldOperation(add_10_fn, {intermediate_field})), 0};
|
||||
|
||||
@@ -248,7 +248,7 @@ TEST(field, TwoFunctionsTwoOutputs)
|
||||
TEST(field, SameFieldTwice)
|
||||
{
|
||||
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;
|
||||
IndexMask mask{IndexRange(2)};
|
||||
@@ -267,7 +267,7 @@ TEST(field, SameFieldTwice)
|
||||
|
||||
TEST(field, IgnoredOutput)
|
||||
{
|
||||
static OptionalOutputsFunction fn;
|
||||
static mf::tests::OptionalOutputsFunction fn;
|
||||
Field<int> field{std::make_shared<FieldOperation>(fn), 0};
|
||||
|
||||
FieldContext field_context;
|
||||
|
@@ -7,7 +7,7 @@
|
||||
#include "FN_multi_function_procedure_executor.hh"
|
||||
#include "FN_multi_function_test_common.hh"
|
||||
|
||||
namespace blender::fn::tests {
|
||||
namespace blender::fn::multi_function::tests {
|
||||
|
||||
TEST(multi_function_procedure, ConstantOutput)
|
||||
{
|
||||
@@ -19,10 +19,10 @@ TEST(multi_function_procedure, ConstantOutput)
|
||||
*/
|
||||
|
||||
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;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure procedure;
|
||||
ProcedureBuilder builder{procedure};
|
||||
|
||||
auto [var1] = builder.add_call<1>(constant_fn);
|
||||
auto [var2] = builder.add_call<1>(add_fn, {var1, var1});
|
||||
@@ -32,10 +32,10 @@ TEST(multi_function_procedure, ConstantOutput)
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor executor{procedure};
|
||||
ProcedureExecutor executor{procedure};
|
||||
|
||||
MFParamsBuilder params{executor, 2};
|
||||
MFContextBuilder context;
|
||||
ParamsBuilder params{executor, 2};
|
||||
ContextBuilder context;
|
||||
|
||||
Array<int> output_array(2);
|
||||
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_10_fn = fn::build_mf::SM<int>("add_10", [](int &a) { a += 10; });
|
||||
auto add_fn = mf::build::SI2_SO<int, int, int>("add", [](int a, int b) { return a + b; });
|
||||
auto add_10_fn = mf::build::SM<int>("add_10", [](int &a) { a += 10; });
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure procedure;
|
||||
ProcedureBuilder builder{procedure};
|
||||
|
||||
MFVariable *var1 = &builder.add_single_input_parameter<int>();
|
||||
MFVariable *var2 = &builder.add_single_input_parameter<int>();
|
||||
Variable *var1 = &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 [var4] = builder.add_call<1>(add_fn, {var2, var3});
|
||||
builder.add_call(add_10_fn, {var4});
|
||||
@@ -73,10 +73,10 @@ TEST(multi_function_procedure, SimpleTest)
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor executor{procedure};
|
||||
ProcedureExecutor executor{procedure};
|
||||
|
||||
MFParamsBuilder params{executor, 3};
|
||||
MFContextBuilder context;
|
||||
ParamsBuilder params{executor, 3};
|
||||
ContextBuilder context;
|
||||
|
||||
Array<int> input_array = {1, 2, 3};
|
||||
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_100_fn = build_mf::SM<int>("add_100", [](int &a) { a += 100; });
|
||||
auto add_10_fn = build::SM<int>("add_10", [](int &a) { a += 10; });
|
||||
auto add_100_fn = build::SM<int>("add_100", [](int &a) { a += 100; });
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure procedure;
|
||||
ProcedureBuilder builder{procedure};
|
||||
|
||||
MFVariable *var1 = &builder.add_single_mutable_parameter<int>();
|
||||
MFVariable *var2 = &builder.add_single_input_parameter<bool>();
|
||||
Variable *var1 = &builder.add_single_mutable_parameter<int>();
|
||||
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_true.add_call(add_100_fn, {var1});
|
||||
builder.set_cursor_after_branch(branch);
|
||||
@@ -125,8 +125,8 @@ TEST(multi_function_procedure, BranchTest)
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
MFParamsBuilder params(procedure_fn, 5);
|
||||
ProcedureExecutor procedure_fn{procedure};
|
||||
ParamsBuilder params(procedure_fn, 5);
|
||||
|
||||
Array<int> values_a = {1, 5, 3, 6, 2};
|
||||
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_readonly_single_input(values_cond.as_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
procedure_fn.call({1, 2, 3, 4}, params, context);
|
||||
|
||||
EXPECT_EQ(values_a[0], 1);
|
||||
@@ -153,28 +153,28 @@ TEST(multi_function_procedure, EvaluateOne)
|
||||
*/
|
||||
|
||||
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++;
|
||||
return a + 10;
|
||||
});
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure 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});
|
||||
builder.add_destruct(*var1);
|
||||
builder.add_return();
|
||||
builder.add_output_parameter(*var2);
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
MFParamsBuilder params{procedure_fn, 5};
|
||||
ProcedureExecutor procedure_fn{procedure};
|
||||
ParamsBuilder params{procedure_fn, 5};
|
||||
|
||||
Array<int> values_out = {1, 2, 3, 4, 5};
|
||||
params.add_readonly_single_input_value(1);
|
||||
params.add_uninitialized_single_output(values_out.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
procedure_fn.call({0, 1, 3, 4}, params, context);
|
||||
|
||||
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_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; });
|
||||
auto double_fn = build_mf::SM<int>("double", [](int &a) { a *= 2; });
|
||||
auto add_1000_fn = build_mf::SM<int>("add 1000", [](int &a) { a += 1000; });
|
||||
auto add_1_fn = build_mf::SM<int>("add 1", [](int &a) { a += 1; });
|
||||
auto double_fn = build::SM<int>("double", [](int &a) { a *= 2; });
|
||||
auto add_1000_fn = build::SM<int>("add 1000", [](int &a) { a += 1000; });
|
||||
auto add_1_fn = build::SM<int>("add 1", [](int &a) { a += 1; });
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure 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);
|
||||
var_out->set_name("out");
|
||||
auto [var_index] = builder.add_call<1>(const_0_fn);
|
||||
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});
|
||||
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_loop_break(loop);
|
||||
branch.branch_false.add_destruct(*var_condition);
|
||||
@@ -239,8 +239,8 @@ TEST(multi_function_procedure, SimpleLoop)
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
MFParamsBuilder params{procedure_fn, 5};
|
||||
ProcedureExecutor procedure_fn{procedure};
|
||||
ParamsBuilder params{procedure_fn, 5};
|
||||
|
||||
Array<int> counts = {4, 3, 7, 6, 4};
|
||||
Array<int> results(5, -1);
|
||||
@@ -248,7 +248,7 @@ TEST(multi_function_procedure, SimpleLoop)
|
||||
params.add_readonly_single_input(counts.as_span());
|
||||
params.add_uninitialized_single_output(results.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
procedure_fn.call({0, 1, 3, 4}, params, context);
|
||||
|
||||
EXPECT_EQ(results[0], 1016);
|
||||
@@ -277,11 +277,11 @@ TEST(multi_function_procedure, Vectors)
|
||||
SumVectorFunction sum_elements_fn;
|
||||
CustomMF_Constant<int> constant_5_fn{5};
|
||||
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure procedure;
|
||||
ProcedureBuilder builder{procedure};
|
||||
|
||||
MFVariable *var_v1 = &builder.add_input_parameter(MFDataType::ForVector<int>());
|
||||
MFVariable *var_v2 = &builder.add_parameter(MFParamType::ForMutableVector(CPPType::get<int>()));
|
||||
Variable *var_v1 = &builder.add_input_parameter(DataType::ForVector<int>());
|
||||
Variable *var_v2 = &builder.add_parameter(ParamType::ForMutableVector(CPPType::get<int>()));
|
||||
builder.add_call(extend_fn, {var_v1, var_v2});
|
||||
auto [var_constant] = builder.add_call<1>(constant_5_fn);
|
||||
builder.add_call(append_fn, {var_v2, var_constant});
|
||||
@@ -295,8 +295,8 @@ TEST(multi_function_procedure, Vectors)
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
MFParamsBuilder params{procedure_fn, 5};
|
||||
ProcedureExecutor procedure_fn{procedure};
|
||||
ParamsBuilder params{procedure_fn, 5};
|
||||
|
||||
Array<int> v1 = {5, 2, 3};
|
||||
GVectorArray v2{CPPType::get<int>(), 5};
|
||||
@@ -310,7 +310,7 @@ TEST(multi_function_procedure, Vectors)
|
||||
params.add_vector_mutable(v2);
|
||||
params.add_vector_output(v3);
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
procedure_fn.call({0, 1, 3, 4}, params, context);
|
||||
|
||||
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;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure 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});
|
||||
builder.add_destruct(*var_a);
|
||||
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());
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
ProcedureExecutor procedure_fn{procedure};
|
||||
|
||||
Array<int> inputs = {4, 1, 6, 2, 3};
|
||||
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_uninitialized_single_output(results.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
procedure_fn.call({0, 2, 3, 4}, params, context);
|
||||
|
||||
EXPECT_EQ(results[0], 54);
|
||||
@@ -380,12 +380,12 @@ TEST(multi_function_procedure, BufferReuse)
|
||||
|
||||
TEST(multi_function_procedure, OutputBufferReplaced)
|
||||
{
|
||||
MFProcedure procedure;
|
||||
MFProcedureBuilder builder{procedure};
|
||||
Procedure procedure;
|
||||
ProcedureBuilder builder{procedure};
|
||||
|
||||
const int output_value = 42;
|
||||
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_call_with_all_variables(constant_fn, {&var_o});
|
||||
builder.add_destruct(var_o);
|
||||
@@ -394,13 +394,13 @@ TEST(multi_function_procedure, OutputBufferReplaced)
|
||||
|
||||
EXPECT_TRUE(procedure.validate());
|
||||
|
||||
MFProcedureExecutor procedure_fn{procedure};
|
||||
ProcedureExecutor procedure_fn{procedure};
|
||||
|
||||
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());
|
||||
|
||||
fn::MFContextBuilder context;
|
||||
mf::ContextBuilder context;
|
||||
procedure_fn.call(IndexMask(output.size()), params, context);
|
||||
|
||||
EXPECT_EQ(output[0], output_value);
|
||||
@@ -408,4 +408,4 @@ TEST(multi_function_procedure, OutputBufferReplaced)
|
||||
EXPECT_EQ(output[2], output_value);
|
||||
}
|
||||
|
||||
} // namespace blender::fn::tests
|
||||
} // namespace blender::fn::multi_function::tests
|
||||
|
@@ -6,28 +6,28 @@
|
||||
#include "FN_multi_function_builder.hh"
|
||||
#include "FN_multi_function_test_common.hh"
|
||||
|
||||
namespace blender::fn::tests {
|
||||
namespace blender::fn::multi_function::tests {
|
||||
namespace {
|
||||
|
||||
class AddFunction : public MultiFunction {
|
||||
public:
|
||||
AddFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder("Add", signature);
|
||||
Signature signature;
|
||||
SignatureBuilder builder("Add", signature);
|
||||
builder.single_input<int>("A");
|
||||
builder.single_input<int>("B");
|
||||
builder.single_output<int>("Result");
|
||||
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> &b = params.readonly_single_input<int>(1, "B");
|
||||
@@ -47,12 +47,12 @@ TEST(multi_function, AddFunction)
|
||||
Array<int> input2 = {10, 20, 30};
|
||||
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(input2.as_span());
|
||||
params.add_uninitialized_single_output(output.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
|
||||
fn.call({0, 2}, params, context);
|
||||
|
||||
@@ -74,11 +74,11 @@ TEST(multi_function, AddPrefixFunction)
|
||||
|
||||
std::string prefix = "AB";
|
||||
|
||||
MFParamsBuilder params(fn, strings.size());
|
||||
ParamsBuilder params(fn, strings.size());
|
||||
params.add_readonly_single_input(&prefix);
|
||||
params.add_single_mutable(strings.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
|
||||
fn.call({0, 2, 3}, params, context);
|
||||
|
||||
@@ -96,11 +96,11 @@ TEST(multi_function, CreateRangeFunction)
|
||||
GVectorArray_TypedMutableRef<int> ranges_ref{ranges};
|
||||
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_vector_output(ranges);
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
|
||||
fn.call({0, 1, 2, 3}, params, context);
|
||||
|
||||
@@ -128,11 +128,11 @@ TEST(multi_function, GenericAppendFunction)
|
||||
vectors_ref.append(2, 6);
|
||||
Array<int> values = {5, 7, 3, 1};
|
||||
|
||||
MFParamsBuilder params(fn, vectors.size());
|
||||
ParamsBuilder params(fn, vectors.size());
|
||||
params.add_vector_mutable(vectors);
|
||||
params.add_readonly_single_input(values.as_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
|
||||
fn.call(IndexRange(vectors.size()), params, context);
|
||||
|
||||
@@ -156,10 +156,10 @@ TEST(multi_function, CustomMF_Constant)
|
||||
|
||||
Array<int> outputs(4, 0);
|
||||
|
||||
MFParamsBuilder params(fn, outputs.size());
|
||||
ParamsBuilder params(fn, outputs.size());
|
||||
params.add_uninitialized_single_output(outputs.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
|
||||
fn.call({0, 2, 3}, params, context);
|
||||
|
||||
@@ -176,10 +176,10 @@ TEST(multi_function, CustomMF_GenericConstant)
|
||||
|
||||
Array<int> outputs(4, 0);
|
||||
|
||||
MFParamsBuilder params(fn, outputs.size());
|
||||
ParamsBuilder params(fn, outputs.size());
|
||||
params.add_uninitialized_single_output(outputs.as_mutable_span());
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder 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_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);
|
||||
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
|
||||
fn.call({1, 2, 3}, params, context);
|
||||
|
||||
@@ -220,20 +220,20 @@ TEST(multi_function, IgnoredOutputs)
|
||||
{
|
||||
OptionalOutputsFunction fn;
|
||||
{
|
||||
MFParamsBuilder params(fn, 10);
|
||||
ParamsBuilder params(fn, 10);
|
||||
params.add_ignored_single_output("Out 1");
|
||||
params.add_ignored_single_output("Out 2");
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
fn.call(IndexRange(10), params, context);
|
||||
}
|
||||
{
|
||||
Array<int> results_1(10);
|
||||
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_2.as_mutable_span(), "Out 2");
|
||||
MFContextBuilder context;
|
||||
ContextBuilder context;
|
||||
fn.call(IndexRange(10), params, context);
|
||||
|
||||
EXPECT_EQ(results_1[0], 5);
|
||||
@@ -244,4 +244,4 @@ TEST(multi_function, IgnoredOutputs)
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace blender::fn::tests
|
||||
} // namespace blender::fn::multi_function::tests
|
||||
|
@@ -2,26 +2,26 @@
|
||||
|
||||
#include "FN_multi_function.hh"
|
||||
|
||||
namespace blender::fn::tests {
|
||||
namespace blender::fn::multi_function::tests {
|
||||
|
||||
class AddPrefixFunction : public MultiFunction {
|
||||
public:
|
||||
AddPrefixFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder{"Add Prefix", signature};
|
||||
Signature signature;
|
||||
SignatureBuilder builder{"Add Prefix", signature};
|
||||
builder.single_input<std::string>("Prefix");
|
||||
builder.single_mutable<std::string>("Strings");
|
||||
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");
|
||||
MutableSpan<std::string> strings = params.single_mutable<std::string>(1, "Strings");
|
||||
@@ -36,20 +36,20 @@ class CreateRangeFunction : public MultiFunction {
|
||||
public:
|
||||
CreateRangeFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder{"Create Range", signature};
|
||||
Signature signature;
|
||||
SignatureBuilder builder{"Create Range", signature};
|
||||
builder.single_input<int>("Size");
|
||||
builder.vector_output<int>("Range");
|
||||
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");
|
||||
GVectorArray &ranges = params.vector_output(1, "Range");
|
||||
@@ -65,18 +65,18 @@ class CreateRangeFunction : public MultiFunction {
|
||||
|
||||
class GenericAppendFunction : public MultiFunction {
|
||||
private:
|
||||
MFSignature signature_;
|
||||
Signature signature_;
|
||||
|
||||
public:
|
||||
GenericAppendFunction(const CPPType &type)
|
||||
{
|
||||
MFSignatureBuilder builder{"Append", signature_};
|
||||
SignatureBuilder builder{"Append", signature_};
|
||||
builder.vector_mutable("Vector", type);
|
||||
builder.single_input("Value", type);
|
||||
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");
|
||||
const GVArray &values = params.readonly_single_input(1, "Value");
|
||||
@@ -94,20 +94,20 @@ class ConcatVectorsFunction : public MultiFunction {
|
||||
public:
|
||||
ConcatVectorsFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder{"Concat Vectors", signature};
|
||||
Signature signature;
|
||||
SignatureBuilder builder{"Concat Vectors", signature};
|
||||
builder.vector_mutable<int>("A");
|
||||
builder.vector_input<int>("B");
|
||||
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);
|
||||
const GVVectorArray &b = params.readonly_vector_input(1);
|
||||
@@ -119,20 +119,20 @@ class AppendFunction : public MultiFunction {
|
||||
public:
|
||||
AppendFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder{"Append", signature};
|
||||
Signature signature;
|
||||
SignatureBuilder builder{"Append", signature};
|
||||
builder.vector_mutable<int>("Vector");
|
||||
builder.single_input<int>("Value");
|
||||
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);
|
||||
const VArray<int> &values = params.readonly_single_input<int>(1);
|
||||
@@ -147,20 +147,20 @@ class SumVectorFunction : public MultiFunction {
|
||||
public:
|
||||
SumVectorFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder{"Sum Vectors", signature};
|
||||
Signature signature;
|
||||
SignatureBuilder builder{"Sum Vectors", signature};
|
||||
builder.vector_input<int>("Vector");
|
||||
builder.single_output<int>("Sum");
|
||||
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);
|
||||
MutableSpan<int> sums = params.uninitialized_single_output<int>(1);
|
||||
@@ -179,20 +179,20 @@ class OptionalOutputsFunction : public MultiFunction {
|
||||
public:
|
||||
OptionalOutputsFunction()
|
||||
{
|
||||
static MFSignature signature = create_signature();
|
||||
static Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static MFSignature create_signature()
|
||||
static Signature create_signature()
|
||||
{
|
||||
MFSignature signature;
|
||||
MFSignatureBuilder builder{"Optional Outputs", signature};
|
||||
Signature signature;
|
||||
SignatureBuilder builder{"Optional Outputs", signature};
|
||||
builder.single_output<int>("Out 1");
|
||||
builder.single_output<std::string>("Out 2");
|
||||
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")) {
|
||||
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
|
||||
|
@@ -17,10 +17,10 @@ namespace blender::geometry {
|
||||
|
||||
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",
|
||||
[](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>(
|
||||
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 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",
|
||||
[](const float curve_length, const float sample_length) {
|
||||
/* Find the number of sampled segments by dividing the total length by
|
||||
@@ -37,7 +37,7 @@ static fn::Field<int> get_count_input_from_length(const fn::Field<float> &length
|
||||
const int count = int(curve_length / sample_length) + 1;
|
||||
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(
|
||||
get_count_fn,
|
||||
|
@@ -125,17 +125,16 @@ using blender::fn::ValueOrFieldCPPType;
|
||||
using blender::nodes::FieldInferencingInterface;
|
||||
using blender::nodes::GeoNodeExecParams;
|
||||
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::GeometryInfoLog;
|
||||
using blender::nodes::geo_eval_log::GeoModifierLog;
|
||||
using blender::nodes::geo_eval_log::GeoNodeLog;
|
||||
using blender::nodes::geo_eval_log::GeoTreeLog;
|
||||
using blender::nodes::geo_eval_log::NamedAttributeUsage;
|
||||
using blender::nodes::geo_eval_log::NodeWarning;
|
||||
using blender::nodes::geo_eval_log::NodeWarningType;
|
||||
using blender::nodes::geo_eval_log::ValueLog;
|
||||
using blender::threading::EnumerableThreadSpecific;
|
||||
|
||||
static void initData(ModifierData *md)
|
||||
{
|
||||
|
@@ -31,8 +31,8 @@ struct Depsgraph;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
namespace lf = fn::lazy_function;
|
||||
using lf::LazyFunction;
|
||||
using mf::MultiFunction;
|
||||
|
||||
/**
|
||||
* Data that is passed into geometry nodes evaluation from the modifier.
|
||||
|
@@ -51,8 +51,8 @@ inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&cal
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized();
|
||||
static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = mf::build::exec_presets::Materialized();
|
||||
|
||||
/* This is just an utility function to keep the individual cases smaller. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -118,8 +118,8 @@ inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized();
|
||||
static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = mf::build::exec_presets::Materialized();
|
||||
|
||||
/* This is just an utility function to keep the individual cases smaller. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -180,21 +180,21 @@ inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback
|
||||
|
||||
switch (operation) {
|
||||
case NODE_MATH_MULTIPLY_ADD:
|
||||
return dispatch(fn::build_mf::exec_presets::AllSpanOrSingle(),
|
||||
return dispatch(mf::build::exec_presets::AllSpanOrSingle(),
|
||||
[](float a, float b, float c) { return a * b + c; });
|
||||
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 {
|
||||
return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
|
||||
});
|
||||
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); });
|
||||
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); });
|
||||
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); });
|
||||
}
|
||||
return false;
|
||||
@@ -214,8 +214,8 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl3(const NodeVectorMathOperation
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized();
|
||||
static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = mf::build::exec_presets::Materialized();
|
||||
|
||||
/* This is just a utility function to keep the individual cases smaller. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -269,7 +269,7 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl(const NodeVectorMathOperation
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::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. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -302,8 +302,8 @@ inline bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOpera
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized();
|
||||
static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = mf::build::exec_presets::Materialized();
|
||||
|
||||
/* This is just a utility function to keep the individual cases smaller. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -341,7 +341,7 @@ inline bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperat
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_slow = fn::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. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -373,7 +373,7 @@ inline bool try_dispatch_float_math_fl3_to_fl(const NodeVectorMathOperation oper
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::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. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -402,7 +402,7 @@ inline bool try_dispatch_float_math_fl3_fl_to_fl3(const NodeVectorMathOperation
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::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. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
@@ -433,8 +433,8 @@ inline bool try_dispatch_float_math_fl3_to_fl3(const NodeVectorMathOperation ope
|
||||
return false;
|
||||
}
|
||||
|
||||
static auto exec_preset_fast = fn::build_mf::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = fn::build_mf::exec_presets::Materialized();
|
||||
static auto exec_preset_fast = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_slow = mf::build::exec_presets::Materialized();
|
||||
|
||||
/* This is just a utility function to keep the individual cases smaller. */
|
||||
auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
|
||||
|
@@ -8,8 +8,6 @@
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
using namespace fn::multi_function_types;
|
||||
|
||||
class NodeMultiFunctions;
|
||||
|
||||
/**
|
||||
@@ -19,8 +17,8 @@ class NodeMultiFunctionBuilder : NonCopyable, NonMovable {
|
||||
private:
|
||||
const bNode &node_;
|
||||
const bNodeTree &tree_;
|
||||
std::shared_ptr<MultiFunction> owned_built_fn_;
|
||||
const MultiFunction *built_fn_ = nullptr;
|
||||
std::shared_ptr<mf::MultiFunction> owned_built_fn_;
|
||||
const mf::MultiFunction *built_fn_ = nullptr;
|
||||
|
||||
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
|
||||
* have to match the available sockets in the node.
|
||||
*/
|
||||
void set_matching_fn(const MultiFunction *fn);
|
||||
void set_matching_fn(const MultiFunction &fn);
|
||||
void set_matching_fn(const mf::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
|
||||
@@ -50,8 +48,8 @@ class NodeMultiFunctionBuilder : NonCopyable, NonMovable {
|
||||
class NodeMultiFunctions {
|
||||
public:
|
||||
struct Item {
|
||||
const MultiFunction *fn = nullptr;
|
||||
std::shared_ptr<MultiFunction> owned_fn;
|
||||
const mf::MultiFunction *fn = nullptr;
|
||||
std::shared_ptr<mf::MultiFunction> owned_fn;
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -82,12 +80,12 @@ inline const bNodeTree &NodeMultiFunctionBuilder::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;
|
||||
}
|
||||
|
||||
inline void NodeMultiFunctionBuilder::set_matching_fn(const MultiFunction &fn)
|
||||
inline void NodeMultiFunctionBuilder::set_matching_fn(const mf::MultiFunction &fn)
|
||||
{
|
||||
built_fn_ = &fn;
|
||||
}
|
||||
|
@@ -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:
|
||||
int main_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)
|
||||
: 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);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Align Euler to Vector", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Align Euler to Vector", signature};
|
||||
builder.single_input<float3>("Rotation");
|
||||
builder.single_input<float>("Factor");
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -158,7 +158,7 @@ class MF_AlignEulerToVector : public fn::MultiFunction {
|
||||
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<float> &factors = params.readonly_single_input<float>(1, "Factor");
|
||||
|
@@ -65,26 +65,26 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
||||
}
|
||||
}
|
||||
|
||||
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 and_fn = fn::build_mf::SI2_SO<bool, bool, bool>(
|
||||
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto and_fn = mf::build::SI2_SO<bool, bool, bool>(
|
||||
"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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
@@ -49,20 +49,20 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
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);
|
||||
|
||||
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); });
|
||||
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) {
|
||||
ColorGeometry4f r_color;
|
||||
hsv_to_rgb(h, s, v, &r_color.r, &r_color.g, &r_color.b);
|
||||
r_color.a = a;
|
||||
return r_color;
|
||||
});
|
||||
static 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) {
|
||||
ColorGeometry4f color;
|
||||
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)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
@@ -164,45 +164,45 @@ static float component_average(float3 a)
|
||||
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;
|
||||
|
||||
static auto exec_preset_all = fn::build_mf::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_first_two = fn::build_mf::exec_presets::SomeSpanOrSingle<0, 1>();
|
||||
static auto exec_preset_all = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto exec_preset_first_two = mf::build::exec_presets::SomeSpanOrSingle<0, 1>();
|
||||
|
||||
switch (data->data_type) {
|
||||
case SOCK_FLOAT:
|
||||
switch (data->operation) {
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; },
|
||||
exec_preset_first_two);
|
||||
@@ -212,32 +212,32 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case SOCK_INT:
|
||||
switch (data->operation) {
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
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);
|
||||
return &fn;
|
||||
}
|
||||
@@ -248,35 +248,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case NODE_COMPARE_LESS_THAN:
|
||||
switch (data->mode) {
|
||||
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",
|
||||
[](float3 a, float3 b) { return component_average(a) < component_average(b); },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return math::length(a) < math::length(b); },
|
||||
exec_preset_all);
|
||||
@@ -287,35 +287,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case NODE_COMPARE_LESS_EQUAL:
|
||||
switch (data->mode) {
|
||||
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",
|
||||
[](float3 a, float3 b) { return component_average(a) <= component_average(b); },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return math::length(a) <= math::length(b); },
|
||||
exec_preset_all);
|
||||
@@ -326,35 +326,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case NODE_COMPARE_GREATER_THAN:
|
||||
switch (data->mode) {
|
||||
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",
|
||||
[](float3 a, float3 b) { return component_average(a) > component_average(b); },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return math::length(a) > math::length(b); },
|
||||
exec_preset_all);
|
||||
@@ -365,35 +365,35 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case NODE_COMPARE_GREATER_EQUAL:
|
||||
switch (data->mode) {
|
||||
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",
|
||||
[](float3 a, float3 b) { return component_average(a) >= component_average(b); },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; },
|
||||
exec_preset_first_two);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; },
|
||||
exec_preset_all);
|
||||
return &fn;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b) { return math::length(a) >= math::length(b); },
|
||||
exec_preset_all);
|
||||
@@ -404,7 +404,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case NODE_COMPARE_EQUAL:
|
||||
switch (data->mode) {
|
||||
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",
|
||||
[](float3 a, float3 b, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float comp, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float angle, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float 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:
|
||||
switch (data->mode) {
|
||||
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",
|
||||
[](float3 a, float3 b, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float comp, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float angle, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float 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;
|
||||
}
|
||||
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",
|
||||
[](float3 a, float3 b, float 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:
|
||||
switch (data->operation) {
|
||||
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",
|
||||
[](ColorGeometry4f a, ColorGeometry4f b, float 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;
|
||||
}
|
||||
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",
|
||||
[](ColorGeometry4f a, ColorGeometry4f b, float 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;
|
||||
}
|
||||
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",
|
||||
[](ColorGeometry4f a, ColorGeometry4f 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;
|
||||
}
|
||||
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",
|
||||
[](ColorGeometry4f a, ColorGeometry4f 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:
|
||||
switch (data->operation) {
|
||||
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; });
|
||||
return &fn;
|
||||
}
|
||||
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; });
|
||||
return &fn;
|
||||
}
|
||||
@@ -565,7 +565,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -36,16 +36,16 @@ static void node_label(const bNodeTree * /*tree*/, const bNode *node, char *labe
|
||||
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 round_fn = fn::build_mf::SI1_SO<float, int>(
|
||||
static auto exec_preset = mf::build::exec_presets::AllSpanOrSingle();
|
||||
static auto round_fn = mf::build::SI1_SO<float, int>(
|
||||
"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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const bNode &bnode = builder.node();
|
||||
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)
|
||||
|
@@ -25,7 +25,7 @@ static void node_build_multi_function(blender::nodes::NodeMultiFunctionBuilder &
|
||||
const bNode &bnode = builder.node();
|
||||
NodeInputColor *node_storage = static_cast<NodeInputColor *>(bnode.storage);
|
||||
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)
|
||||
|
@@ -24,7 +24,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
const bNode &bnode = builder.node();
|
||||
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)
|
||||
|
@@ -10,24 +10,24 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
b.add_output<decl::String>(N_("Tab"));
|
||||
}
|
||||
|
||||
class MF_SpecialCharacters : public fn::MultiFunction {
|
||||
class MF_SpecialCharacters : public mf::MultiFunction {
|
||||
public:
|
||||
MF_SpecialCharacters()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Special Characters", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Special Characters", signature};
|
||||
builder.single_output<std::string>("Line Break");
|
||||
builder.single_output<std::string>("Tab");
|
||||
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> tab = params.uninitialized_single_output<std::string>(1, "Tab");
|
||||
|
@@ -23,7 +23,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
const bNode &bnode = builder.node();
|
||||
NodeInputString *node_storage = static_cast<NodeInputString *>(bnode.storage);
|
||||
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)
|
||||
|
@@ -25,7 +25,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
const bNode &bnode = builder.node();
|
||||
NodeInputVector *node_storage = static_cast<NodeInputVector *>(bnode.storage);
|
||||
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)
|
||||
|
@@ -141,7 +141,7 @@ static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
|
||||
switch (data_type) {
|
||||
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",
|
||||
[](float3 min_value, float3 max_value, int id, int seed) -> float3 {
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](float min_value, float max_value, int id, int seed) -> float {
|
||||
const float value = noise::hash_to_float(seed, id);
|
||||
return value * (max_value - min_value) + min_value;
|
||||
},
|
||||
fn::build_mf::exec_presets::SomeSpanOrSingle<2>());
|
||||
mf::build::exec_presets::SomeSpanOrSingle<2>());
|
||||
builder.set_matching_fn(fn);
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](int min_value, int max_value, int id, int seed) -> int {
|
||||
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). */
|
||||
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);
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](float probability, int id, int seed) -> bool {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@@ -30,10 +30,8 @@ static std::string replace_all(const StringRefNull str,
|
||||
|
||||
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
|
||||
{
|
||||
static auto substring_fn =
|
||||
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) {
|
||||
static auto substring_fn = mf::build::SI3_SO<std::string, std::string, std::string, std::string>(
|
||||
"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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
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) {
|
||||
float input_mat[3][3];
|
||||
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);
|
||||
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",
|
||||
[](const float3 &input, const float3 &axis, float angle) {
|
||||
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);
|
||||
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) {
|
||||
float input_mat[3][3];
|
||||
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);
|
||||
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) {
|
||||
float input_mat[3][3];
|
||||
eul_to_mat3(input_mat, input);
|
||||
@@ -107,12 +107,12 @@ static const fn::MultiFunction *get_multi_function(const bNode &bnode)
|
||||
short space = bnode.custom2;
|
||||
if (type == FN_NODE_ROTATE_EULER_TYPE_AXIS_ANGLE) {
|
||||
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;
|
||||
}
|
||||
if (type == FN_NODE_ROTATE_EULER_TYPE_EULER) {
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
@@ -37,18 +37,18 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
node->storage = data;
|
||||
}
|
||||
|
||||
class SeparateRGBAFunction : public fn::MultiFunction {
|
||||
class SeparateRGBAFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateRGBAFunction()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Separate Color", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Color", signature};
|
||||
builder.single_input<ColorGeometry4f>("Color");
|
||||
builder.single_output<float>("Red");
|
||||
builder.single_output<float>("Green");
|
||||
@@ -57,7 +57,7 @@ class SeparateRGBAFunction : public fn::MultiFunction {
|
||||
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,
|
||||
"Color");
|
||||
@@ -99,18 +99,18 @@ class SeparateRGBAFunction : public fn::MultiFunction {
|
||||
}
|
||||
};
|
||||
|
||||
class SeparateHSVAFunction : public fn::MultiFunction {
|
||||
class SeparateHSVAFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateHSVAFunction()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Separate Color", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Color", signature};
|
||||
builder.single_input<ColorGeometry4f>("Color");
|
||||
builder.single_output<float>("Hue");
|
||||
builder.single_output<float>("Saturation");
|
||||
@@ -119,7 +119,7 @@ class SeparateHSVAFunction : public fn::MultiFunction {
|
||||
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,
|
||||
"Color");
|
||||
@@ -140,18 +140,18 @@ class SeparateHSVAFunction : public fn::MultiFunction {
|
||||
}
|
||||
};
|
||||
|
||||
class SeparateHSLAFunction : public fn::MultiFunction {
|
||||
class SeparateHSLAFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateHSLAFunction()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Separate Color", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate Color", signature};
|
||||
builder.single_input<ColorGeometry4f>("Color");
|
||||
builder.single_output<float>("Hue");
|
||||
builder.single_output<float>("Saturation");
|
||||
@@ -160,7 +160,7 @@ class SeparateHSLAFunction : public fn::MultiFunction {
|
||||
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,
|
||||
"Color");
|
||||
|
@@ -16,7 +16,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
|
||||
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) {
|
||||
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));
|
||||
|
@@ -16,7 +16,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
|
||||
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()); });
|
||||
builder.set_matching_fn(&str_len_fn);
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
|
||||
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) {
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(std::max(0, b)) << a;
|
||||
|
@@ -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
|
||||
* sample lengths lie on, and how far along the segment they are.
|
||||
*/
|
||||
class SampleFloatSegmentsFunction : public fn::MultiFunction {
|
||||
class SampleFloatSegmentsFunction : public mf::MultiFunction {
|
||||
private:
|
||||
Array<float> accumulated_lengths_;
|
||||
GeometryNodeCurveSampleMode length_mode_;
|
||||
@@ -211,14 +211,14 @@ class SampleFloatSegmentsFunction : public fn::MultiFunction {
|
||||
const GeometryNodeCurveSampleMode 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);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample Curve Index", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Curve Index", signature};
|
||||
builder.single_input<float>("Length");
|
||||
|
||||
builder.single_output<int>("Curve Index");
|
||||
@@ -226,7 +226,7 @@ class SampleFloatSegmentsFunction : public fn::MultiFunction {
|
||||
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");
|
||||
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:
|
||||
/**
|
||||
* 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_;
|
||||
GeometryNodeCurveSampleMode length_mode_;
|
||||
|
||||
fn::MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
std::optional<bke::CurvesFieldContext> source_context_;
|
||||
std::unique_ptr<FieldEvaluator> source_evaluator_;
|
||||
@@ -266,10 +266,10 @@ class SampleCurveFunction : public fn::MultiFunction {
|
||||
this->evaluate_source();
|
||||
}
|
||||
|
||||
fn::MFSignature create_signature()
|
||||
mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample Curve", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Curve", signature};
|
||||
builder.single_input<int>("Curve Index");
|
||||
builder.single_input<float>("Length");
|
||||
builder.single_output<float3>("Position");
|
||||
@@ -279,7 +279,7 @@ class SampleCurveFunction : public fn::MultiFunction {
|
||||
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>(
|
||||
2, "Position");
|
||||
|
@@ -1325,10 +1325,10 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
|
||||
/* Create a combined field from the offset and the scale so the field evaluator
|
||||
* can take care of the multiplication and to simplify each extrude function. */
|
||||
static auto multiply_fn = fn::build_mf::SI2_SO<float3, float, float3>(
|
||||
static auto multiply_fn = mf::build::SI2_SO<float3, float, float3>(
|
||||
"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>(
|
||||
FieldOperation(multiply_fn, {std::move(offset_field), std::move(scale_field)}));
|
||||
const Field<float3> final_offset{std::move(multiply_op)};
|
||||
|
@@ -45,7 +45,7 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
|
||||
node->storage = tex;
|
||||
}
|
||||
|
||||
class ImageFieldsFunction : public fn::MultiFunction {
|
||||
class ImageFieldsFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const int8_t interpolation_;
|
||||
const int8_t extension_;
|
||||
@@ -64,7 +64,7 @@ class ImageFieldsFunction : public fn::MultiFunction {
|
||||
image_(image),
|
||||
image_user_(image_user)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
|
||||
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_);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"ImageFunction", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"ImageFunction", signature};
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_output<ColorGeometry4f>("Color");
|
||||
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");
|
||||
MutableSpan<ColorGeometry4f> r_color = params.uninitialized_single_output<ColorGeometry4f>(
|
||||
|
@@ -121,10 +121,10 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
|
||||
/* Use another multi-function operation to make sure the input radius is greater than zero.
|
||||
* TODO: Use mutable multi-function once that is supported. */
|
||||
static auto max_zero_fn = fn::build_mf::SI1_SO<float, float>(
|
||||
static auto max_zero_fn = mf::build::SI1_SO<float, float>(
|
||||
__func__,
|
||||
[](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>(
|
||||
FieldOperation(max_zero_fn, {std::move(radius)}));
|
||||
Field<float> positive_radius(std::move(max_zero_op), 0);
|
||||
|
@@ -129,7 +129,7 @@ static bool calculate_pointcloud_proximity(const VArray<float3> &positions,
|
||||
return true;
|
||||
}
|
||||
|
||||
class ProximityFunction : public fn::MultiFunction {
|
||||
class ProximityFunction : public mf::MultiFunction {
|
||||
private:
|
||||
GeometrySet target_;
|
||||
GeometryNodeProximityTargetType type_;
|
||||
@@ -138,21 +138,21 @@ class ProximityFunction : public fn::MultiFunction {
|
||||
ProximityFunction(GeometrySet target, GeometryNodeProximityTargetType type)
|
||||
: target_(std::move(target)), type_(type)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Geometry Proximity", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Geometry Proximity", signature};
|
||||
builder.single_input<float3>("Source Position");
|
||||
builder.single_output<float3>("Position");
|
||||
builder.single_output<float>("Distance");
|
||||
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,
|
||||
"Source Position");
|
||||
|
@@ -202,7 +202,7 @@ static void raycast_to_mesh(IndexMask mask,
|
||||
}
|
||||
}
|
||||
|
||||
class RaycastFunction : public fn::MultiFunction {
|
||||
class RaycastFunction : public mf::MultiFunction {
|
||||
private:
|
||||
GeometrySet target_;
|
||||
GeometryNodeRaycastMapMode mapping_;
|
||||
@@ -217,7 +217,7 @@ class RaycastFunction : public fn::MultiFunction {
|
||||
* the field inputs for better performance. */
|
||||
const eAttrDomain domain_ = ATTR_DOMAIN_CORNER;
|
||||
|
||||
fn::MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
public:
|
||||
RaycastFunction(GeometrySet target, GField src_field, GeometryNodeRaycastMapMode mapping)
|
||||
@@ -229,10 +229,10 @@ class RaycastFunction : public fn::MultiFunction {
|
||||
this->set_signature(&signature_);
|
||||
}
|
||||
|
||||
fn::MFSignature create_signature()
|
||||
mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Geometry Proximity", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Geometry Proximity", signature};
|
||||
builder.single_input<float3>("Source Position");
|
||||
builder.single_input<float3>("Ray Direction");
|
||||
builder.single_input<float>("Ray Length");
|
||||
@@ -246,7 +246,7 @@ class RaycastFunction : public fn::MultiFunction {
|
||||
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
|
||||
* output is required, so always retrieve a span from the evaluator in that case (it's
|
||||
|
@@ -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
|
||||
* internally.
|
||||
*/
|
||||
class SampleIndexFunction : public fn::MultiFunction {
|
||||
class SampleIndexFunction : public mf::MultiFunction {
|
||||
GeometrySet src_geometry_;
|
||||
GField src_field_;
|
||||
eAttrDomain domain_;
|
||||
bool clamp_;
|
||||
|
||||
fn::MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
std::optional<bke::GeometryFieldContext> geometry_context_;
|
||||
std::unique_ptr<FieldEvaluator> evaluator_;
|
||||
@@ -206,10 +206,10 @@ class SampleIndexFunction : public fn::MultiFunction {
|
||||
this->evaluate_field();
|
||||
}
|
||||
|
||||
fn::MFSignature create_signature()
|
||||
mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample Index", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Index", signature};
|
||||
builder.single_input<int>("Index");
|
||||
builder.single_output("Value", src_field_.cpp_type());
|
||||
return signature;
|
||||
@@ -229,7 +229,7 @@ class SampleIndexFunction : public fn::MultiFunction {
|
||||
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");
|
||||
GMutableSpan dst = params.uninitialized_single_output(1, "Value");
|
||||
|
@@ -232,13 +232,13 @@ static const GeometryComponent *find_source_component(const GeometrySet &geometr
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class SampleNearestFunction : public fn::MultiFunction {
|
||||
class SampleNearestFunction : public mf::MultiFunction {
|
||||
GeometrySet source_;
|
||||
eAttrDomain domain_;
|
||||
|
||||
const GeometryComponent *src_component_;
|
||||
|
||||
fn::MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
public:
|
||||
SampleNearestFunction(GeometrySet geometry, eAttrDomain domain)
|
||||
@@ -251,16 +251,16 @@ class SampleNearestFunction : public fn::MultiFunction {
|
||||
this->src_component_ = find_source_component(source_, domain_);
|
||||
}
|
||||
|
||||
fn::MFSignature create_signature()
|
||||
mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample Nearest", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Nearest", signature};
|
||||
builder.single_input<float3>("Position");
|
||||
builder.single_output<int>("Index");
|
||||
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");
|
||||
MutableSpan<int> indices = params.uninitialized_single_output<int>(1, "Index");
|
||||
|
@@ -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
|
||||
* it for later.
|
||||
*/
|
||||
class SampleNearestSurfaceFunction : public fn::MultiFunction {
|
||||
class SampleNearestSurfaceFunction : public mf::MultiFunction {
|
||||
GeometrySet source_;
|
||||
GField src_field_;
|
||||
|
||||
@@ -128,7 +128,7 @@ class SampleNearestSurfaceFunction : public fn::MultiFunction {
|
||||
*/
|
||||
eAttrDomain domain_ = ATTR_DOMAIN_CORNER;
|
||||
|
||||
fn::MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
std::optional<bke::MeshFieldContext> source_context_;
|
||||
std::unique_ptr<FieldEvaluator> source_evaluator_;
|
||||
@@ -144,16 +144,16 @@ class SampleNearestSurfaceFunction : public fn::MultiFunction {
|
||||
this->evaluate_source_field();
|
||||
}
|
||||
|
||||
fn::MFSignature create_signature()
|
||||
mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample Nearest Surface", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Nearest Surface", signature};
|
||||
builder.single_input<float3>("Position");
|
||||
builder.single_output("Value", src_field_.cpp_type());
|
||||
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");
|
||||
GMutableSpan dst = params.uninitialized_single_output_if_required(1, "Value");
|
||||
|
@@ -105,7 +105,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams ¶ms)
|
||||
}
|
||||
}
|
||||
|
||||
class SampleMeshBarycentricFunction : public fn::MultiFunction {
|
||||
class SampleMeshBarycentricFunction : public mf::MultiFunction {
|
||||
GeometrySet source_;
|
||||
GField src_field_;
|
||||
|
||||
@@ -116,7 +116,7 @@ class SampleMeshBarycentricFunction : public fn::MultiFunction {
|
||||
*/
|
||||
eAttrDomain domain_ = ATTR_DOMAIN_CORNER;
|
||||
|
||||
fn::MFSignature signature_;
|
||||
mf::Signature signature_;
|
||||
|
||||
std::optional<bke::MeshFieldContext> source_context_;
|
||||
std::unique_ptr<FieldEvaluator> source_evaluator_;
|
||||
@@ -134,17 +134,17 @@ class SampleMeshBarycentricFunction : public fn::MultiFunction {
|
||||
this->evaluate_source();
|
||||
}
|
||||
|
||||
fn::MFSignature create_signature()
|
||||
mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample Barycentric Triangles", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample Barycentric Triangles", signature};
|
||||
builder.single_input<int>("Triangle Index");
|
||||
builder.single_input<float3>("Barycentric Weight");
|
||||
builder.single_output("Value", src_field_.cpp_type());
|
||||
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,
|
||||
"Triangle Index");
|
||||
@@ -185,7 +185,7 @@ class SampleMeshBarycentricFunction : public fn::MultiFunction {
|
||||
}
|
||||
};
|
||||
|
||||
class ReverseUVSampleFunction : public fn::MultiFunction {
|
||||
class ReverseUVSampleFunction : public mf::MultiFunction {
|
||||
GeometrySet source_;
|
||||
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_.ensure_owns_direct_data();
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
this->evaluate_source();
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Sample UV Surface", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Sample UV Surface", signature};
|
||||
builder.single_input<float2>("Sample UV");
|
||||
builder.single_output<bool>("Is Valid");
|
||||
builder.single_output<int>("Triangle Index");
|
||||
@@ -216,7 +216,7 @@ class ReverseUVSampleFunction : public fn::MultiFunction {
|
||||
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");
|
||||
MutableSpan<bool> is_valid = params.uninitialized_single_output_if_required<bool>(1,
|
||||
|
@@ -171,7 +171,7 @@ template<typename T> void switch_fields(GeoNodeExecParams ¶ms, const StringR
|
||||
Field<T> falses_field = params.extract_input<Field<T>>(name_false);
|
||||
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) {
|
||||
return condition ? true_value : false_value;
|
||||
});
|
||||
|
@@ -37,7 +37,6 @@ namespace blender::nodes {
|
||||
|
||||
using fn::ValueOrField;
|
||||
using fn::ValueOrFieldCPPType;
|
||||
using namespace fn::multi_function_types;
|
||||
|
||||
static const CPPType *get_socket_cpp_type(const bNodeSocketType &typeinfo)
|
||||
{
|
||||
@@ -353,8 +352,8 @@ static void execute_multi_function_on_value_or_field(
|
||||
}
|
||||
else {
|
||||
/* In this case, the multi-function is evaluated directly. */
|
||||
MFParamsBuilder params{fn, 1};
|
||||
MFContextBuilder context;
|
||||
mf::ParamsBuilder params{fn, 1};
|
||||
mf::ContextBuilder context;
|
||||
|
||||
for (const int i : input_types.index_range()) {
|
||||
const ValueOrFieldCPPType &type = *input_types[i];
|
||||
@@ -445,7 +444,7 @@ class LazyFunctionForMutedNode : public LazyFunction {
|
||||
if (from_type != nullptr && to_type != nullptr) {
|
||||
if (conversions.is_convertible(from_type->value, to_type->value)) {
|
||||
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(
|
||||
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 (conversions_->is_convertible(from_field_type->value, to_field_type->value)) {
|
||||
const MultiFunction &multi_fn = *conversions_->get_conversion_multi_function(
|
||||
MFDataType::ForSingle(from_field_type->value),
|
||||
MFDataType::ForSingle(to_field_type->value));
|
||||
mf::DataType::ForSingle(from_field_type->value),
|
||||
mf::DataType::ForSingle(to_field_type->value));
|
||||
auto fn = std::make_unique<LazyFunctionForMultiFunctionConversion>(
|
||||
multi_fn, *from_field_type, *to_field_type);
|
||||
lf::Node &conversion_node = lf_graph_->add_function(*fn);
|
||||
|
@@ -44,10 +44,10 @@ static int gpu_shader_clamp(GPUMaterial *mat,
|
||||
|
||||
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)",
|
||||
[](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) {
|
||||
if (a < b) {
|
||||
return clamp_f(value, a, b);
|
||||
|
@@ -87,28 +87,28 @@ static int gpu_shader_valtorgb(GPUMaterial *mat,
|
||||
return GPU_stack_link(mat, node, "valtorgb", in, out, tex, GPU_constant(&layer));
|
||||
}
|
||||
|
||||
class ColorBandFunction : public fn::MultiFunction {
|
||||
class ColorBandFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const ColorBand &color_band_;
|
||||
|
||||
public:
|
||||
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);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Color Band", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Color Band", signature};
|
||||
builder.single_input<float>("Value");
|
||||
builder.single_output<ColorGeometry4f>("Color");
|
||||
builder.single_output<float>("Alpha");
|
||||
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");
|
||||
MutableSpan<ColorGeometry4f> colors = params.uninitialized_single_output<ColorGeometry4f>(
|
||||
|
@@ -63,28 +63,28 @@ static int gpu_shader_curve_vec(GPUMaterial *mat,
|
||||
GPU_uniform(end_slopes));
|
||||
}
|
||||
|
||||
class CurveVecFunction : public fn::MultiFunction {
|
||||
class CurveVecFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const CurveMapping &cumap_;
|
||||
|
||||
public:
|
||||
CurveVecFunction(const CurveMapping &cumap) : cumap_(cumap)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Curve Vec", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Curve Vec", signature};
|
||||
builder.single_input<float>("Fac");
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_output<float3>("Vector");
|
||||
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<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));
|
||||
}
|
||||
|
||||
class CurveRGBFunction : public fn::MultiFunction {
|
||||
class CurveRGBFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const CurveMapping &cumap_;
|
||||
|
||||
public:
|
||||
CurveRGBFunction(const CurveMapping &cumap) : cumap_(cumap)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Curve RGB", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Curve RGB", signature};
|
||||
builder.single_input<float>("Fac");
|
||||
builder.single_input<ColorGeometry4f>("Color");
|
||||
builder.single_output<ColorGeometry4f>("Color");
|
||||
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<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));
|
||||
}
|
||||
|
||||
class CurveFloatFunction : public fn::MultiFunction {
|
||||
class CurveFloatFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const CurveMapping &cumap_;
|
||||
|
||||
public:
|
||||
CurveFloatFunction(const CurveMapping &cumap) : cumap_(cumap)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Curve Float", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Curve Float", signature};
|
||||
builder.single_input<float>("Factor");
|
||||
builder.single_input<float>("Value");
|
||||
builder.single_output<float>("Value");
|
||||
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> &val_in = params.readonly_single_input<float>(1, "Value");
|
||||
|
@@ -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()
|
||||
{
|
||||
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)",
|
||||
[](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);
|
||||
@@ -243,12 +243,12 @@ template<bool Clamp> static auto build_float_linear()
|
||||
}
|
||||
return result;
|
||||
},
|
||||
fn::build_mf::exec_presets::SomeSpanOrSingle<0>());
|
||||
mf::build::exec_presets::SomeSpanOrSingle<0>());
|
||||
}
|
||||
|
||||
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)",
|
||||
[](float value, float from_min, float from_max, float to_min, float to_max, float steps)
|
||||
-> float {
|
||||
@@ -260,12 +260,12 @@ template<bool Clamp> static auto build_float_stepped()
|
||||
}
|
||||
return result;
|
||||
},
|
||||
fn::build_mf::exec_presets::SomeSpanOrSingle<0>());
|
||||
mf::build::exec_presets::SomeSpanOrSingle<0>());
|
||||
}
|
||||
|
||||
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)",
|
||||
[](const float3 &value,
|
||||
const float3 &from_min,
|
||||
@@ -279,12 +279,12 @@ template<bool Clamp> static auto build_vector_linear()
|
||||
}
|
||||
return result;
|
||||
},
|
||||
fn::build_mf::exec_presets::SomeSpanOrSingle<0>());
|
||||
mf::build::exec_presets::SomeSpanOrSingle<0>());
|
||||
}
|
||||
|
||||
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)",
|
||||
[](const float3 &value,
|
||||
const float3 &from_min,
|
||||
@@ -300,7 +300,7 @@ template<bool Clamp> static auto build_vector_stepped()
|
||||
}
|
||||
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)
|
||||
@@ -335,7 +335,7 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](const float3 &value,
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](const float3 &value,
|
||||
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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@@ -397,7 +397,7 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](float value, float from_min, float from_max, float to_min, float to_max)
|
||||
-> float {
|
||||
@@ -406,12 +406,12 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
|
||||
factor = (3.0f - 2.0f * factor) * (factor * factor);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
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",
|
||||
[](float value, float from_min, float from_max, float to_min, float to_max)
|
||||
-> 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);
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@@ -102,14 +102,14 @@ static int gpu_shader_math(GPUMaterial *mat,
|
||||
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 fn::MultiFunction *base_fn = nullptr;
|
||||
const mf::MultiFunction *base_fn = nullptr;
|
||||
|
||||
try_dispatch_float_math_fl_to_fl(
|
||||
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);
|
||||
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(
|
||||
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);
|
||||
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(
|
||||
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);
|
||||
base_fn = &fn;
|
||||
});
|
||||
@@ -140,17 +140,17 @@ static const fn::MultiFunction *get_base_multi_function(const bNode &node)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
class ClampWrapperFunction : public fn::MultiFunction {
|
||||
class ClampWrapperFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const fn::MultiFunction &fn_;
|
||||
const mf::MultiFunction &fn_;
|
||||
|
||||
public:
|
||||
ClampWrapperFunction(const fn::MultiFunction &fn) : fn_(fn)
|
||||
ClampWrapperFunction(const mf::MultiFunction &fn) : fn_(fn)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -168,7 +168,7 @@ class ClampWrapperFunction : public fn::MultiFunction {
|
||||
|
||||
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;
|
||||
if (clamp_output) {
|
||||
|
@@ -351,7 +351,7 @@ static int gpu_shader_mix(GPUMaterial *mat,
|
||||
return ret;
|
||||
}
|
||||
|
||||
class MixColorFunction : public fn::MultiFunction {
|
||||
class MixColorFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const bool clamp_factor_;
|
||||
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)
|
||||
: 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);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"MixColor", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"MixColor", signature};
|
||||
builder.single_input<float>("Factor");
|
||||
builder.single_input<ColorGeometry4f>("A");
|
||||
builder.single_input<ColorGeometry4f>("B");
|
||||
@@ -376,7 +376,7 @@ class MixColorFunction : public fn::MultiFunction {
|
||||
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<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;
|
||||
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) {
|
||||
case SOCK_FLOAT: {
|
||||
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) {
|
||||
return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
|
||||
});
|
||||
return &fn;
|
||||
}
|
||||
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) {
|
||||
return math::interpolate(a, b, t);
|
||||
});
|
||||
@@ -430,14 +430,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
case SOCK_VECTOR: {
|
||||
if (clamp_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) {
|
||||
return math::interpolate(a, b, std::clamp(t, 0.0f, 1.0f));
|
||||
});
|
||||
return &fn;
|
||||
}
|
||||
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) {
|
||||
t = math::clamp(t, 0.0f, 1.0f);
|
||||
return a * (float3(1.0f) - t) + b * t;
|
||||
@@ -447,14 +447,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
}
|
||||
else {
|
||||
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) {
|
||||
return math::interpolate(a, b, t);
|
||||
});
|
||||
return &fn;
|
||||
}
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
}
|
||||
|
@@ -91,7 +91,7 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat,
|
||||
return ret;
|
||||
}
|
||||
|
||||
class MixRGBFunction : public fn::MultiFunction {
|
||||
class MixRGBFunction : public mf::MultiFunction {
|
||||
private:
|
||||
bool clamp_;
|
||||
int type_;
|
||||
@@ -99,14 +99,14 @@ class MixRGBFunction : public fn::MultiFunction {
|
||||
public:
|
||||
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);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"MixRGB", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"MixRGB", signature};
|
||||
builder.single_input<float>("Fac");
|
||||
builder.single_input<ColorGeometry4f>("Color1");
|
||||
builder.single_input<ColorGeometry4f>("Color2");
|
||||
@@ -114,7 +114,7 @@ class MixRGBFunction : public fn::MultiFunction {
|
||||
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<ColorGeometry4f> &col1 = params.readonly_single_input<ColorGeometry4f>(1,
|
||||
|
@@ -27,18 +27,18 @@ static int gpu_shader_seprgb(GPUMaterial *mat,
|
||||
return GPU_stack_link(mat, node, "separate_rgb", in, out);
|
||||
}
|
||||
|
||||
class SeparateRGBFunction : public fn::MultiFunction {
|
||||
class SeparateRGBFunction : public mf::MultiFunction {
|
||||
public:
|
||||
SeparateRGBFunction()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Separate RGB", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate RGB", signature};
|
||||
builder.single_input<ColorGeometry4f>("Color");
|
||||
builder.single_output<float>("R");
|
||||
builder.single_output<float>("G");
|
||||
@@ -46,7 +46,7 @@ class SeparateRGBFunction : public fn::MultiFunction {
|
||||
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,
|
||||
"Color");
|
||||
@@ -109,7 +109,7 @@ static int gpu_shader_combrgb(GPUMaterial *mat,
|
||||
|
||||
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); });
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
@@ -27,18 +27,18 @@ static int gpu_shader_sepxyz(GPUMaterial *mat,
|
||||
return GPU_stack_link(mat, node, "separate_xyz", in, out);
|
||||
}
|
||||
|
||||
class MF_SeparateXYZ : public fn::MultiFunction {
|
||||
class MF_SeparateXYZ : public mf::MultiFunction {
|
||||
public:
|
||||
MF_SeparateXYZ()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Separate XYZ", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Separate XYZ", signature};
|
||||
builder.single_input<float3>("XYZ");
|
||||
builder.single_output<float>("X");
|
||||
builder.single_output<float>("Y");
|
||||
@@ -46,7 +46,7 @@ class MF_SeparateXYZ : public fn::MultiFunction {
|
||||
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");
|
||||
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 auto fn = fn::build_mf::SI3_SO<float, float, float, float3>(
|
||||
static auto fn = mf::build::SI3_SO<float, float, float, float3>(
|
||||
"Combine Vector",
|
||||
[](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);
|
||||
}
|
||||
|
||||
|
@@ -108,7 +108,7 @@ static int node_shader_gpu_tex_brick(GPUMaterial *mat,
|
||||
GPU_constant(&squash_freq));
|
||||
}
|
||||
|
||||
class BrickFunction : public fn::MultiFunction {
|
||||
class BrickFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const float offset_;
|
||||
const int offset_freq_;
|
||||
@@ -122,14 +122,14 @@ class BrickFunction : public fn::MultiFunction {
|
||||
const int 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);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"BrickTexture", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"BrickTexture", signature};
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_input<ColorGeometry4f>("Color1");
|
||||
builder.single_input<ColorGeometry4f>("Color2");
|
||||
@@ -204,7 +204,7 @@ class BrickFunction : public fn::MultiFunction {
|
||||
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<ColorGeometry4f> &color1_values = params.readonly_single_input<ColorGeometry4f>(
|
||||
|
@@ -44,18 +44,18 @@ static int node_shader_gpu_tex_checker(GPUMaterial *mat,
|
||||
return GPU_stack_link(mat, node, "node_tex_checker", in, out);
|
||||
}
|
||||
|
||||
class NodeTexChecker : public fn::MultiFunction {
|
||||
class NodeTexChecker : public mf::MultiFunction {
|
||||
public:
|
||||
NodeTexChecker()
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Checker", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Checker", signature};
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_input<ColorGeometry4f>("Color1");
|
||||
builder.single_input<ColorGeometry4f>("Color2");
|
||||
@@ -65,7 +65,7 @@ class NodeTexChecker : public fn::MultiFunction {
|
||||
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<ColorGeometry4f> &color1 = params.readonly_single_input<ColorGeometry4f>(
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
class GradientFunction : public fn::MultiFunction {
|
||||
class GradientFunction : public mf::MultiFunction {
|
||||
private:
|
||||
int gradient_type_;
|
||||
|
||||
public:
|
||||
GradientFunction(int gradient_type) : gradient_type_(gradient_type)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"GradientFunction", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"GradientFunction", signature};
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_output<ColorGeometry4f>("Color");
|
||||
builder.single_output<float>("Fac");
|
||||
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");
|
||||
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
class MagicFunction : public fn::MultiFunction {
|
||||
class MagicFunction : public mf::MultiFunction {
|
||||
private:
|
||||
int depth_;
|
||||
|
||||
public:
|
||||
MagicFunction(int depth) : depth_(depth)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"MagicFunction", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"MagicFunction", signature};
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_input<float>("Scale");
|
||||
builder.single_input<float>("Distortion");
|
||||
@@ -71,7 +71,7 @@ class MagicFunction : public fn::MultiFunction {
|
||||
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<float> &scale = params.readonly_single_input<float>(1, "Scale");
|
||||
|
@@ -125,7 +125,7 @@ static void node_shader_update_tex_musgrave(bNodeTree *ntree, bNode *node)
|
||||
node_sock_label(outFacSock, "Height");
|
||||
}
|
||||
|
||||
class MusgraveFunction : public fn::MultiFunction {
|
||||
class MusgraveFunction : public mf::MultiFunction {
|
||||
private:
|
||||
const int dimensions_;
|
||||
const int musgrave_type_;
|
||||
@@ -136,7 +136,7 @@ class MusgraveFunction : public fn::MultiFunction {
|
||||
{
|
||||
BLI_assert(dimensions >= 1 && dimensions <= 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(2, 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]);
|
||||
}
|
||||
|
||||
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;
|
||||
fn::MFSignatureBuilder builder{"Musgrave", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Musgrave", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -195,7 +195,7 @@ class MusgraveFunction : public fn::MultiFunction {
|
||||
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> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
|
@@ -81,7 +81,7 @@ static void node_shader_update_tex_noise(bNodeTree *ntree, bNode *node)
|
||||
nodeSetSocketAvailability(ntree, sockW, storage.dimensions == 1 || storage.dimensions == 4);
|
||||
}
|
||||
|
||||
class NoiseFunction : public fn::MultiFunction {
|
||||
class NoiseFunction : public mf::MultiFunction {
|
||||
private:
|
||||
int dimensions_;
|
||||
|
||||
@@ -89,7 +89,7 @@ class NoiseFunction : public fn::MultiFunction {
|
||||
NoiseFunction(int dimensions) : dimensions_(dimensions)
|
||||
{
|
||||
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(2),
|
||||
create_signature(3),
|
||||
@@ -98,10 +98,10 @@ class NoiseFunction : public fn::MultiFunction {
|
||||
this->set_signature(&signatures[dimensions - 1]);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature(int dimensions)
|
||||
static mf::Signature create_signature(int dimensions)
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"Noise", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"Noise", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -121,7 +121,7 @@ class NoiseFunction : public fn::MultiFunction {
|
||||
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);
|
||||
const VArray<float> &scale = params.readonly_single_input<float>(param++, "Scale");
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
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:
|
||||
int dimensions_;
|
||||
int feature_;
|
||||
@@ -191,7 +191,7 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
|
||||
{
|
||||
BLI_assert(dimensions >= 2 && dimensions <= 4);
|
||||
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(3, 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]);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature(int dimensions, int feature)
|
||||
static mf::Signature create_signature(int dimensions, int feature)
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"voronoi_minowski", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"voronoi_minowski", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -237,7 +237,7 @@ class VoronoiMinowskiFunction : public fn::MultiFunction {
|
||||
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> {
|
||||
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:
|
||||
int dimensions_;
|
||||
int feature_;
|
||||
@@ -626,7 +626,7 @@ class VoronoiMetricFunction : public fn::MultiFunction {
|
||||
{
|
||||
BLI_assert(dimensions >= 1 && dimensions <= 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(2, 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]);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature(int dimensions, int feature)
|
||||
static mf::Signature create_signature(int dimensions, int feature)
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"voronoi_metric", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"voronoi_metric", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -674,7 +674,7 @@ class VoronoiMetricFunction : public fn::MultiFunction {
|
||||
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> {
|
||||
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:
|
||||
int dimensions_;
|
||||
int feature_;
|
||||
@@ -1144,7 +1144,7 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
|
||||
{
|
||||
BLI_assert(dimensions >= 1 && dimensions <= 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(2, 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]);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature(int dimensions, int feature)
|
||||
static mf::Signature create_signature(int dimensions, int feature)
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"voronoi_edge", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"voronoi_edge", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -1182,7 +1182,7 @@ class VoronoiEdgeFunction : public fn::MultiFunction {
|
||||
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> {
|
||||
return params.readonly_single_input<float3>(param_index, "Vector");
|
||||
|
@@ -80,7 +80,7 @@ static int node_shader_gpu_tex_wave(GPUMaterial *mat,
|
||||
GPU_constant(&wave_profile));
|
||||
}
|
||||
|
||||
class WaveFunction : public fn::MultiFunction {
|
||||
class WaveFunction : public mf::MultiFunction {
|
||||
private:
|
||||
int wave_type_;
|
||||
int bands_direction_;
|
||||
@@ -94,14 +94,14 @@ class WaveFunction : public fn::MultiFunction {
|
||||
rings_direction_(rings_direction),
|
||||
wave_profile_(wave_profile)
|
||||
{
|
||||
static fn::MFSignature signature = create_signature();
|
||||
static mf::Signature signature = create_signature();
|
||||
this->set_signature(&signature);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature()
|
||||
static mf::Signature create_signature()
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"MagicFunction", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"MagicFunction", signature};
|
||||
builder.single_input<float3>("Vector");
|
||||
builder.single_input<float>("Scale");
|
||||
builder.single_input<float>("Distortion");
|
||||
@@ -114,7 +114,7 @@ class WaveFunction : public fn::MultiFunction {
|
||||
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<float> &scale = params.readonly_single_input<float>(1, "Scale");
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
class WhiteNoiseFunction : public fn::MultiFunction {
|
||||
class WhiteNoiseFunction : public mf::MultiFunction {
|
||||
private:
|
||||
int dimensions_;
|
||||
|
||||
@@ -71,7 +71,7 @@ class WhiteNoiseFunction : public fn::MultiFunction {
|
||||
WhiteNoiseFunction(int dimensions) : dimensions_(dimensions)
|
||||
{
|
||||
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(2),
|
||||
create_signature(3),
|
||||
@@ -80,10 +80,10 @@ class WhiteNoiseFunction : public fn::MultiFunction {
|
||||
this->set_signature(&signatures[dimensions - 1]);
|
||||
}
|
||||
|
||||
static fn::MFSignature create_signature(int dimensions)
|
||||
static mf::Signature create_signature(int dimensions)
|
||||
{
|
||||
fn::MFSignature signature;
|
||||
fn::MFSignatureBuilder builder{"WhiteNoise", signature};
|
||||
mf::Signature signature;
|
||||
mf::SignatureBuilder builder{"WhiteNoise", signature};
|
||||
|
||||
if (ELEM(dimensions, 2, 3, 4)) {
|
||||
builder.single_input<float3>("Vector");
|
||||
@@ -98,7 +98,7 @@ class WhiteNoiseFunction : public fn::MultiFunction {
|
||||
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);
|
||||
|
||||
|
@@ -29,7 +29,7 @@ static void sh_node_value_build_multi_function(NodeMultiFunctionBuilder &builder
|
||||
{
|
||||
const bNodeSocket *bsocket = (bNodeSocket *)builder.node().outputs.first;
|
||||
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
|
||||
|
@@ -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);
|
||||
|
||||
const fn::MultiFunction *multi_fn = nullptr;
|
||||
const mf::MultiFunction *multi_fn = nullptr;
|
||||
|
||||
try_dispatch_float_math_fl3_fl3_to_fl3(
|
||||
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);
|
||||
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(
|
||||
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);
|
||||
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(
|
||||
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);
|
||||
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(
|
||||
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);
|
||||
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(
|
||||
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);
|
||||
multi_fn = &fn;
|
||||
});
|
||||
@@ -283,7 +283,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
|
||||
try_dispatch_float_math_fl3_to_fl3(
|
||||
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
|
||||
static 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);
|
||||
multi_fn = &fn;
|
||||
});
|
||||
@@ -293,7 +293,7 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
|
||||
try_dispatch_float_math_fl3_to_fl(
|
||||
operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
|
||||
static 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);
|
||||
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)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
@@ -96,7 +96,7 @@ static float3 sh_node_vector_rotate_euler(const float3 &vector,
|
||||
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;
|
||||
const int mode = node.custom1;
|
||||
@@ -104,14 +104,14 @@ static const fn::MultiFunction *get_multi_function(const bNode &node)
|
||||
switch (mode) {
|
||||
case NODE_VECTOR_ROTATE_TYPE_AXIS: {
|
||||
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",
|
||||
[](const float3 &in, const float3 ¢er, const float3 &axis, float angle) {
|
||||
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
|
||||
});
|
||||
return &fn;
|
||||
}
|
||||
static 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",
|
||||
[](const float3 &in, const float3 ¢er, const float3 &axis, float 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: {
|
||||
float3 axis = float3(1.0f, 0.0f, 0.0f);
|
||||
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 ¢er, float angle) {
|
||||
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
|
||||
});
|
||||
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 ¢er, float 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: {
|
||||
float3 axis = float3(0.0f, 1.0f, 0.0f);
|
||||
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 ¢er, float angle) {
|
||||
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
|
||||
});
|
||||
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 ¢er, float 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: {
|
||||
float3 axis = float3(0.0f, 0.0f, 1.0f);
|
||||
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 ¢er, float angle) {
|
||||
return sh_node_vector_rotate_around_axis(in, center, axis, -angle);
|
||||
});
|
||||
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 ¢er, float 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: {
|
||||
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 ¢er, const float3 &rotation) {
|
||||
return sh_node_vector_rotate_euler(in, center, rotation, true);
|
||||
});
|
||||
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 ¢er, const float3 &rotation) {
|
||||
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)
|
||||
{
|
||||
const fn::MultiFunction *fn = get_multi_function(builder.node());
|
||||
const mf::MultiFunction *fn = get_multi_function(builder.node());
|
||||
builder.set_matching_fn(fn);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user