Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2022-04-26 18:12:34 +0300
committerJacques Lucke <jacques@blender.org>2022-04-26 18:12:34 +0300
commitae94e36cfb2f3bc9a99b638782092d9c71d4b3c7 (patch)
treedc54dc643a2c498af1d3de97b471115607a8d3b4 /source/blender/nodes
parent9a53599180041cf9501e2ac6150c9f900a3a3fc0 (diff)
Geometry Nodes: refactor array devirtualization
Goals: * Better high level control over where devirtualization occurs. There is always a trade-off between performance and compile-time/binary-size. * Simplify using array devirtualization. * Better performance for cases where devirtualization wasn't used before. Many geometry nodes accept fields as inputs. Internally, that means that the execution functions have to accept so called "virtual arrays" as inputs. Those can be e.g. actual arrays, just single values, or lazily computed arrays. Due to these different possible virtual arrays implementations, access to individual elements is slower than it would be if everything was just a normal array (access does through a virtual function call). For more complex execution functions, this overhead does not matter, but for small functions (like a simple addition) it very much does. The virtual function call also prevents the compiler from doing some optimizations (e.g. loop unrolling and inserting simd instructions). The solution is to "devirtualize" the virtual arrays for small functions where the overhead is measurable. Essentially, the function is generated many times with different array types as input. Then there is a run-time dispatch that calls the best implementation. We have been doing devirtualization in e.g. math nodes for a long time already. This patch just generalizes the concept and makes it easier to control. It also makes it easier to investigate the different trade-offs when it comes to devirtualization. Nodes that we've optimized using devirtualization before didn't get a speedup. However, a couple of nodes are using devirtualization now, that didn't before. Those got a 2-4x speedup in common cases. * Map Range * Random Value * Switch * Combine XYZ Differential Revision: https://developer.blender.org/D14628
Diffstat (limited to 'source/blender/nodes')
-rw-r--r--source/blender/nodes/NOD_math_functions.hh251
-rw-r--r--source/blender/nodes/function/nodes/node_fn_boolean_math.cc35
-rw-r--r--source/blender/nodes/function/nodes/node_fn_compare.cc186
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_to_int.cc15
-rw-r--r--source/blender/nodes/function/nodes/node_fn_random_value.cc206
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc18
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc12
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_switch.cc35
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_map_range.cc527
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc26
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc54
14 files changed, 588 insertions, 789 deletions
diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh
index e58c1068368..51057f600f4 100644
--- a/source/blender/nodes/NOD_math_functions.hh
+++ b/source/blender/nodes/NOD_math_functions.hh
@@ -9,6 +9,8 @@
#include "BLI_math_vector.hh"
#include "BLI_string_ref.hh"
+#include "FN_multi_function_builder.hh"
+
namespace blender::nodes {
struct FloatMathOperationInfo {
@@ -49,55 +51,58 @@ inline bool try_dispatch_float_math_fl_to_fl(const int operation, Callback &&cal
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+ static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
+
/* This is just an utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_MATH_EXPONENT:
- return dispatch([](float a) { return expf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return expf(a); });
case NODE_MATH_SQRT:
- return dispatch([](float a) { return safe_sqrtf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return safe_sqrtf(a); });
case NODE_MATH_INV_SQRT:
- return dispatch([](float a) { return safe_inverse_sqrtf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return safe_inverse_sqrtf(a); });
case NODE_MATH_ABSOLUTE:
- return dispatch([](float a) { return fabs(a); });
+ return dispatch(exec_preset_fast, [](float a) { return fabs(a); });
case NODE_MATH_RADIANS:
- return dispatch([](float a) { return (float)DEG2RAD(a); });
+ return dispatch(exec_preset_fast, [](float a) { return (float)DEG2RAD(a); });
case NODE_MATH_DEGREES:
- return dispatch([](float a) { return (float)RAD2DEG(a); });
+ return dispatch(exec_preset_fast, [](float a) { return (float)RAD2DEG(a); });
case NODE_MATH_SIGN:
- return dispatch([](float a) { return compatible_signf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return compatible_signf(a); });
case NODE_MATH_ROUND:
- return dispatch([](float a) { return floorf(a + 0.5f); });
+ return dispatch(exec_preset_fast, [](float a) { return floorf(a + 0.5f); });
case NODE_MATH_FLOOR:
- return dispatch([](float a) { return floorf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return floorf(a); });
case NODE_MATH_CEIL:
- return dispatch([](float a) { return ceilf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return ceilf(a); });
case NODE_MATH_FRACTION:
- return dispatch([](float a) { return a - floorf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return a - floorf(a); });
case NODE_MATH_TRUNC:
- return dispatch([](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); });
+ return dispatch(exec_preset_fast, [](float a) { return a >= 0.0f ? floorf(a) : ceilf(a); });
case NODE_MATH_SINE:
- return dispatch([](float a) { return sinf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return sinf(a); });
case NODE_MATH_COSINE:
- return dispatch([](float a) { return cosf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return cosf(a); });
case NODE_MATH_TANGENT:
- return dispatch([](float a) { return tanf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return tanf(a); });
case NODE_MATH_SINH:
- return dispatch([](float a) { return sinhf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return sinhf(a); });
case NODE_MATH_COSH:
- return dispatch([](float a) { return coshf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return coshf(a); });
case NODE_MATH_TANH:
- return dispatch([](float a) { return tanhf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return tanhf(a); });
case NODE_MATH_ARCSINE:
- return dispatch([](float a) { return safe_asinf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return safe_asinf(a); });
case NODE_MATH_ARCCOSINE:
- return dispatch([](float a) { return safe_acosf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return safe_acosf(a); });
case NODE_MATH_ARCTANGENT:
- return dispatch([](float a) { return atanf(a); });
+ return dispatch(exec_preset_slow, [](float a) { return atanf(a); });
}
return false;
}
@@ -113,41 +118,45 @@ inline bool try_dispatch_float_math_fl_fl_to_fl(const int operation, Callback &&
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+ static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
+
/* This is just an utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_MATH_ADD:
- return dispatch([](float a, float b) { return a + b; });
+ return dispatch(exec_preset_fast, [](float a, float b) { return a + b; });
case NODE_MATH_SUBTRACT:
- return dispatch([](float a, float b) { return a - b; });
+ return dispatch(exec_preset_fast, [](float a, float b) { return a - b; });
case NODE_MATH_MULTIPLY:
- return dispatch([](float a, float b) { return a * b; });
+ return dispatch(exec_preset_fast, [](float a, float b) { return a * b; });
case NODE_MATH_DIVIDE:
- return dispatch([](float a, float b) { return safe_divide(a, b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return safe_divide(a, b); });
case NODE_MATH_POWER:
- return dispatch([](float a, float b) { return safe_powf(a, b); });
+ return dispatch(exec_preset_slow, [](float a, float b) { return safe_powf(a, b); });
case NODE_MATH_LOGARITHM:
- return dispatch([](float a, float b) { return safe_logf(a, b); });
+ return dispatch(exec_preset_slow, [](float a, float b) { return safe_logf(a, b); });
case NODE_MATH_MINIMUM:
- return dispatch([](float a, float b) { return std::min(a, b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return std::min(a, b); });
case NODE_MATH_MAXIMUM:
- return dispatch([](float a, float b) { return std::max(a, b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return std::max(a, b); });
case NODE_MATH_LESS_THAN:
- return dispatch([](float a, float b) { return (float)(a < b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a < b); });
case NODE_MATH_GREATER_THAN:
- return dispatch([](float a, float b) { return (float)(a > b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return (float)(a > b); });
case NODE_MATH_MODULO:
- return dispatch([](float a, float b) { return safe_modf(a, b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return safe_modf(a, b); });
case NODE_MATH_SNAP:
- return dispatch([](float a, float b) { return floorf(safe_divide(a, b)) * b; });
+ return dispatch(exec_preset_fast,
+ [](float a, float b) { return floorf(safe_divide(a, b)) * b; });
case NODE_MATH_ARCTAN2:
- return dispatch([](float a, float b) { return atan2f(a, b); });
+ return dispatch(exec_preset_slow, [](float a, float b) { return atan2f(a, b); });
case NODE_MATH_PINGPONG:
- return dispatch([](float a, float b) { return pingpongf(a, b); });
+ return dispatch(exec_preset_fast, [](float a, float b) { return pingpongf(a, b); });
}
return false;
}
@@ -164,57 +173,29 @@ inline bool try_dispatch_float_math_fl_fl_fl_to_fl(const int operation, Callback
}
/* This is just an utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_MATH_MULTIPLY_ADD:
- return dispatch([](float a, float b, float c) { return a * b + c; });
+ return dispatch(fn::CustomMF_presets::AllSpanOrSingle(),
+ [](float a, float b, float c) { return a * b + c; });
case NODE_MATH_COMPARE:
- return dispatch([](float a, float b, float c) -> float {
- return ((a == b) || (fabsf(a - b) <= fmaxf(c, FLT_EPSILON))) ? 1.0f : 0.0f;
- });
+ return dispatch(fn::CustomMF_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([](float a, float b, float c) { return smoothminf(a, b, c); });
+ return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0, 1>(),
+ [](float a, float b, float c) { return smoothminf(a, b, c); });
case NODE_MATH_SMOOTH_MAX:
- return dispatch([](float a, float b, float c) { return -smoothminf(-a, -b, c); });
+ return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0, 1>(),
+ [](float a, float b, float c) { return -smoothminf(-a, -b, c); });
case NODE_MATH_WRAP:
- return dispatch([](float a, float b, float c) { return wrapf(a, b, c); });
- }
- return false;
-}
-
-/**
- * This is similar to try_dispatch_float_math_fl_to_fl, just with a different callback signature.
- */
-template<typename Callback>
-inline bool try_dispatch_float_math_fl_fl_to_bool(const NodeCompareOperation operation,
- Callback &&callback)
-{
- const FloatMathOperationInfo *info = get_float_compare_operation_info(operation);
- if (info == nullptr) {
- return false;
- }
-
- /* This is just an utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
- return true;
- };
-
- switch (operation) {
- case NODE_COMPARE_LESS_THAN:
- return dispatch([](float a, float b) { return a < b; });
- case NODE_COMPARE_LESS_EQUAL:
- return dispatch([](float a, float b) { return a <= b; });
- case NODE_COMPARE_GREATER_THAN:
- return dispatch([](float a, float b) { return a > b; });
- case NODE_COMPARE_GREATER_EQUAL:
- return dispatch([](float a, float b) { return a >= b; });
- default:
- return false;
+ return dispatch(fn::CustomMF_presets::SomeSpanOrSingle<0>(),
+ [](float a, float b, float c) { return wrapf(a, b, c); });
}
return false;
}
@@ -233,35 +214,41 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl3(const NodeVectorMathOperation
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+ static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_ADD:
- return dispatch([](float3 a, float3 b) { return a + b; });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a + b; });
case NODE_VECTOR_MATH_SUBTRACT:
- return dispatch([](float3 a, float3 b) { return a - b; });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a - b; });
case NODE_VECTOR_MATH_MULTIPLY:
- return dispatch([](float3 a, float3 b) { return a * b; });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return a * b; });
case NODE_VECTOR_MATH_DIVIDE:
- return dispatch([](float3 a, float3 b) { return safe_divide(a, b); });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return safe_divide(a, b); });
case NODE_VECTOR_MATH_CROSS_PRODUCT:
- return dispatch([](float3 a, float3 b) { return cross_high_precision(a, b); });
+ return dispatch(exec_preset_fast,
+ [](float3 a, float3 b) { return cross_high_precision(a, b); });
case NODE_VECTOR_MATH_PROJECT:
- return dispatch([](float3 a, float3 b) { return project(a, b); });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return project(a, b); });
case NODE_VECTOR_MATH_REFLECT:
- return dispatch([](float3 a, float3 b) { return reflect(a, normalize(b)); });
+ return dispatch(exec_preset_fast,
+ [](float3 a, float3 b) { return reflect(a, normalize(b)); });
case NODE_VECTOR_MATH_SNAP:
- return dispatch([](float3 a, float3 b) { return floor(safe_divide(a, b)) * b; });
+ return dispatch(exec_preset_fast,
+ [](float3 a, float3 b) { return floor(safe_divide(a, b)) * b; });
case NODE_VECTOR_MATH_MODULO:
- return dispatch([](float3 a, float3 b) { return mod(a, b); });
+ return dispatch(exec_preset_slow, [](float3 a, float3 b) { return mod(a, b); });
case NODE_VECTOR_MATH_MINIMUM:
- return dispatch([](float3 a, float3 b) { return min(a, b); });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return min(a, b); });
case NODE_VECTOR_MATH_MAXIMUM:
- return dispatch([](float3 a, float3 b) { return max(a, b); });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return max(a, b); });
default:
return false;
}
@@ -282,17 +269,19 @@ inline bool try_dispatch_float_math_fl3_fl3_to_fl(const NodeVectorMathOperation
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_DOT_PRODUCT:
- return dispatch([](float3 a, float3 b) { return dot(a, b); });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return dot(a, b); });
case NODE_VECTOR_MATH_DISTANCE:
- return dispatch([](float3 a, float3 b) { return distance(a, b); });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b) { return distance(a, b); });
default:
return false;
}
@@ -313,21 +302,25 @@ inline bool try_dispatch_float_math_fl3_fl3_fl3_to_fl3(const NodeVectorMathOpera
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+ static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_MULTIPLY_ADD:
- return dispatch([](float3 a, float3 b, float3 c) { return a * b + c; });
+ return dispatch(exec_preset_fast, [](float3 a, float3 b, float3 c) { return a * b + c; });
case NODE_VECTOR_MATH_WRAP:
- return dispatch([](float3 a, float3 b, float3 c) {
+ return dispatch(exec_preset_slow, [](float3 a, float3 b, float3 c) {
return float3(wrapf(a.x, b.x, c.x), wrapf(a.y, b.y, c.y), wrapf(a.z, b.z, c.z));
});
case NODE_VECTOR_MATH_FACEFORWARD:
- return dispatch([](float3 a, float3 b, float3 c) { return faceforward(a, b, c); });
+ return dispatch(exec_preset_fast,
+ [](float3 a, float3 b, float3 c) { return faceforward(a, b, c); });
default:
return false;
}
@@ -348,15 +341,18 @@ inline bool try_dispatch_float_math_fl3_fl3_fl_to_fl3(const NodeVectorMathOperat
return false;
}
+ static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_REFRACT:
- return dispatch([](float3 a, float3 b, float c) { return refract(a, normalize(b), c); });
+ return dispatch(exec_preset_slow,
+ [](float3 a, float3 b, float c) { return refract(a, normalize(b), c); });
default:
return false;
}
@@ -377,15 +373,17 @@ inline bool try_dispatch_float_math_fl3_to_fl(const NodeVectorMathOperation oper
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_LENGTH:
- return dispatch([](float3 in) { return length(in); });
+ return dispatch(exec_preset_fast, [](float3 in) { return length(in); });
default:
return false;
}
@@ -404,15 +402,17 @@ inline bool try_dispatch_float_math_fl3_fl_to_fl3(const NodeVectorMathOperation
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_SCALE:
- return dispatch([](float3 a, float b) { return a * b; });
+ return dispatch(exec_preset_fast, [](float3 a, float b) { return a * b; });
default:
return false;
}
@@ -433,29 +433,36 @@ inline bool try_dispatch_float_math_fl3_to_fl3(const NodeVectorMathOperation ope
return false;
}
+ static auto exec_preset_fast = fn::CustomMF_presets::AllSpanOrSingle();
+ static auto exec_preset_slow = fn::CustomMF_presets::Materialized();
+
/* This is just a utility function to keep the individual cases smaller. */
- auto dispatch = [&](auto math_function) -> bool {
- callback(math_function, *info);
+ auto dispatch = [&](auto exec_preset, auto math_function) -> bool {
+ callback(exec_preset, math_function, *info);
return true;
};
switch (operation) {
case NODE_VECTOR_MATH_NORMALIZE:
- return dispatch([](float3 in) { return normalize(in); }); /* Should be safe. */
+ return dispatch(exec_preset_fast,
+ [](float3 in) { return normalize(in); }); /* Should be safe. */
case NODE_VECTOR_MATH_FLOOR:
- return dispatch([](float3 in) { return floor(in); });
+ return dispatch(exec_preset_fast, [](float3 in) { return floor(in); });
case NODE_VECTOR_MATH_CEIL:
- return dispatch([](float3 in) { return ceil(in); });
+ return dispatch(exec_preset_fast, [](float3 in) { return ceil(in); });
case NODE_VECTOR_MATH_FRACTION:
- return dispatch([](float3 in) { return fract(in); });
+ return dispatch(exec_preset_fast, [](float3 in) { return fract(in); });
case NODE_VECTOR_MATH_ABSOLUTE:
- return dispatch([](float3 in) { return abs(in); });
+ return dispatch(exec_preset_fast, [](float3 in) { return abs(in); });
case NODE_VECTOR_MATH_SINE:
- return dispatch([](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); });
+ return dispatch(exec_preset_slow,
+ [](float3 in) { return float3(sinf(in.x), sinf(in.y), sinf(in.z)); });
case NODE_VECTOR_MATH_COSINE:
- return dispatch([](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); });
+ return dispatch(exec_preset_slow,
+ [](float3 in) { return float3(cosf(in.x), cosf(in.y), cosf(in.z)); });
case NODE_VECTOR_MATH_TANGENT:
- return dispatch([](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); });
+ return dispatch(exec_preset_slow,
+ [](float3 in) { return float3(tanf(in.x), tanf(in.y), tanf(in.z)); });
default:
return false;
}
diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
index e29dc0c0c28..b6d7e6c9a5f 100644
--- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
+++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
@@ -70,23 +70,24 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
static const fn::MultiFunction *get_multi_function(bNode &bnode)
{
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> and_fn{"And",
- [](bool a, bool b) { return a && b; }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> or_fn{"Or",
- [](bool a, bool b) { return a || b; }};
- static fn::CustomMF_SI_SO<bool, bool> not_fn{"Not", [](bool a) { return !a; }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> nand_fn{"Not And",
- [](bool a, bool b) { return !(a && b); }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> nor_fn{"Nor",
- [](bool a, bool b) { return !(a || b); }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> xnor_fn{"Equal",
- [](bool a, bool b) { return a == b; }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> xor_fn{"Not Equal",
- [](bool a, bool b) { return a != b; }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> imply_fn{"Imply",
- [](bool a, bool b) { return !a || b; }};
- static fn::CustomMF_SI_SI_SO<bool, bool, bool> nimply_fn{"Subtract",
- [](bool a, bool b) { return a && !b; }};
+ static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle();
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> and_fn{
+ "And", [](bool a, bool b) { return a && b; }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> or_fn{
+ "Or", [](bool a, bool b) { return a || b; }, exec_preset};
+ static fn::CustomMF_SI_SO<bool, bool> not_fn{"Not", [](bool a) { return !a; }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> nand_fn{
+ "Not And", [](bool a, bool b) { return !(a && b); }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> nor_fn{
+ "Nor", [](bool a, bool b) { return !(a || b); }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> xnor_fn{
+ "Equal", [](bool a, bool b) { return a == b; }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> xor_fn{
+ "Not Equal", [](bool a, bool b) { return a != b; }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> imply_fn{
+ "Imply", [](bool a, bool b) { return !a || b; }, exec_preset};
+ static fn::CustomMF_SI_SI_SO<bool, bool, bool> nimply_fn{
+ "Subtract", [](bool a, bool b) { return a && !b; }, exec_preset};
switch (bnode.custom1) {
case NODE_BOOLEAN_MATH_AND:
diff --git a/source/blender/nodes/function/nodes/node_fn_compare.cc b/source/blender/nodes/function/nodes/node_fn_compare.cc
index e6fdf1820fa..7bc9d2d79e8 100644
--- a/source/blender/nodes/function/nodes/node_fn_compare.cc
+++ b/source/blender/nodes/function/nodes/node_fn_compare.cc
@@ -171,71 +171,77 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
{
const NodeFunctionCompare *data = (NodeFunctionCompare *)node.storage;
+ static auto exec_preset_all = fn::CustomMF_presets::AllSpanOrSingle();
+ static auto exec_preset_first_two = fn::CustomMF_presets::SomeSpanOrSingle<0, 1>();
+
switch (data->data_type) {
case SOCK_FLOAT:
switch (data->operation) {
case NODE_COMPARE_LESS_THAN: {
static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
- "Less Than", [](float a, float b) { return a < b; }};
+ "Less Than", [](float a, float b) { return a < b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_LESS_EQUAL: {
static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
- "Less Equal", [](float a, float b) { return a <= b; }};
+ "Less Equal", [](float a, float b) { return a <= b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_GREATER_THAN: {
static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
- "Greater Than", [](float a, float b) { return a > b; }};
+ "Greater Than", [](float a, float b) { return a > b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_GREATER_EQUAL: {
static fn::CustomMF_SI_SI_SO<float, float, bool> fn{
- "Greater Equal", [](float a, float b) { return a >= b; }};
+ "Greater Equal", [](float a, float b) { return a >= b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_EQUAL: {
static fn::CustomMF_SI_SI_SI_SO<float, float, float, bool> fn{
- "Equal", [](float a, float b, float epsilon) { return std::abs(a - b) <= epsilon; }};
+ "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 fn::CustomMF_SI_SI_SI_SO<float, float, float, bool> fn{
"Not Equal",
- [](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; }};
+ [](float a, float b, float epsilon) { return std::abs(a - b) > epsilon; },
+ exec_preset_first_two};
return &fn;
}
break;
case SOCK_INT:
switch (data->operation) {
case NODE_COMPARE_LESS_THAN: {
- static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Less Than",
- [](int a, int b) { return a < b; }};
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{
+ "Less Than", [](int a, int b) { return a < b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_LESS_EQUAL: {
- static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Less Equal",
- [](int a, int b) { return a <= b; }};
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{
+ "Less Equal", [](int a, int b) { return a <= b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_GREATER_THAN: {
- static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Greater Than",
- [](int a, int b) { return a > b; }};
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{
+ "Greater Than", [](int a, int b) { return a > b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_GREATER_EQUAL: {
- static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Greater Equal",
- [](int a, int b) { return a >= b; }};
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{
+ "Greater Equal", [](int a, int b) { return a >= b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_EQUAL: {
- static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Equal",
- [](int a, int b) { return a == b; }};
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{
+ "Equal", [](int a, int b) { return a == b; }, exec_preset_all};
return &fn;
}
case NODE_COMPARE_NOT_EQUAL: {
- static fn::CustomMF_SI_SI_SO<int, int, bool> fn{"Not Equal",
- [](int a, int b) { return a != b; }};
+ static fn::CustomMF_SI_SI_SO<int, int, bool> fn{
+ "Not Equal", [](int a, int b) { return a != b; }, exec_preset_all};
return &fn;
}
}
@@ -247,31 +253,36 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
case NODE_COMPARE_MODE_AVERAGE: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Less Than - Average",
- [](float3 a, float3 b) { return component_average(a) < component_average(b); }};
+ [](float3 a, float3 b) { return component_average(a) < component_average(b); },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_DOT_PRODUCT: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Less Than - Dot Product",
- [](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; }};
+ [](float3 a, float3 b, float comp) { return math::dot(a, b) < comp; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DIRECTION: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Less Than - Direction",
- [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; }};
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) < angle; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_ELEMENT: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Less Than - Element-wise",
- [](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; }};
+ [](float3 a, float3 b) { return a.x < b.x && a.y < b.y && a.z < b.z; },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_LENGTH: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Less Than - Length",
- [](float3 a, float3 b) { return math::length(a) < math::length(b); }};
+ [](float3 a, float3 b) { return math::length(a) < math::length(b); },
+ exec_preset_all};
return &fn;
}
}
@@ -281,31 +292,36 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
case NODE_COMPARE_MODE_AVERAGE: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Less Equal - Average",
- [](float3 a, float3 b) { return component_average(a) <= component_average(b); }};
+ [](float3 a, float3 b) { return component_average(a) <= component_average(b); },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_DOT_PRODUCT: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Less Equal - Dot Product",
- [](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; }};
+ [](float3 a, float3 b, float comp) { return math::dot(a, b) <= comp; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DIRECTION: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Less Equal - Direction",
- [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; }};
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) <= angle; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_ELEMENT: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Less Equal - Element-wise",
- [](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; }};
+ [](float3 a, float3 b) { return a.x <= b.x && a.y <= b.y && a.z <= b.z; },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_LENGTH: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Less Equal - Length",
- [](float3 a, float3 b) { return math::length(a) <= math::length(b); }};
+ [](float3 a, float3 b) { return math::length(a) <= math::length(b); },
+ exec_preset_all};
return &fn;
}
}
@@ -315,31 +331,36 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
case NODE_COMPARE_MODE_AVERAGE: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Greater Than - Average",
- [](float3 a, float3 b) { return component_average(a) > component_average(b); }};
+ [](float3 a, float3 b) { return component_average(a) > component_average(b); },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_DOT_PRODUCT: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Greater Than - Dot Product",
- [](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; }};
+ [](float3 a, float3 b, float comp) { return math::dot(a, b) > comp; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DIRECTION: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Greater Than - Direction",
- [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; }};
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) > angle; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_ELEMENT: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Greater Than - Element-wise",
- [](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; }};
+ [](float3 a, float3 b) { return a.x > b.x && a.y > b.y && a.z > b.z; },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_LENGTH: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Greater Than - Length",
- [](float3 a, float3 b) { return math::length(a) > math::length(b); }};
+ [](float3 a, float3 b) { return math::length(a) > math::length(b); },
+ exec_preset_all};
return &fn;
}
}
@@ -349,31 +370,36 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
case NODE_COMPARE_MODE_AVERAGE: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Greater Equal - Average",
- [](float3 a, float3 b) { return component_average(a) >= component_average(b); }};
+ [](float3 a, float3 b) { return component_average(a) >= component_average(b); },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_DOT_PRODUCT: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Greater Equal - Dot Product",
- [](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; }};
+ [](float3 a, float3 b, float comp) { return math::dot(a, b) >= comp; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DIRECTION: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
"Greater Equal - Direction",
- [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; }};
+ [](float3 a, float3 b, float angle) { return angle_v3v3(a, b) >= angle; },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_ELEMENT: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Greater Equal - Element-wise",
- [](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; }};
+ [](float3 a, float3 b) { return a.x >= b.x && a.y >= b.y && a.z >= b.z; },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_MODE_LENGTH: {
static fn::CustomMF_SI_SI_SO<float3, float3, bool> fn{
"Greater Equal - Length",
- [](float3 a, float3 b) { return math::length(a) >= math::length(b); }};
+ [](float3 a, float3 b) { return math::length(a) >= math::length(b); },
+ exec_preset_all};
return &fn;
}
}
@@ -382,38 +408,48 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
- "Equal - Average", [](float3 a, float3 b, float epsilon) {
+ "Equal - Average",
+ [](float3 a, float3 b, float epsilon) {
return abs(component_average(a) - component_average(b)) <= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DOT_PRODUCT: {
static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
- "Equal - Dot Product", [](float3 a, float3 b, float comp, float epsilon) {
+ "Equal - Dot Product",
+ [](float3 a, float3 b, float comp, float epsilon) {
return abs(math::dot(a, b) - comp) <= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DIRECTION: {
static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
- "Equal - Direction", [](float3 a, float3 b, float angle, float epsilon) {
+ "Equal - Direction",
+ [](float3 a, float3 b, float angle, float epsilon) {
return abs(angle_v3v3(a, b) - angle) <= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_ELEMENT: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
- "Equal - Element-wise", [](float3 a, float3 b, float epsilon) {
+ "Equal - Element-wise",
+ [](float3 a, float3 b, float epsilon) {
return abs(a.x - b.x) <= epsilon && abs(a.y - b.y) <= epsilon &&
abs(a.z - b.z) <= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_LENGTH: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
- "Equal - Length", [](float3 a, float3 b, float epsilon) {
+ "Equal - Length",
+ [](float3 a, float3 b, float epsilon) {
return abs(math::length(a) - math::length(b)) <= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
}
@@ -422,38 +458,48 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
switch (data->mode) {
case NODE_COMPARE_MODE_AVERAGE: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
- "Not Equal - Average", [](float3 a, float3 b, float epsilon) {
+ "Not Equal - Average",
+ [](float3 a, float3 b, float epsilon) {
return abs(component_average(a) - component_average(b)) > epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DOT_PRODUCT: {
static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
- "Not Equal - Dot Product", [](float3 a, float3 b, float comp, float epsilon) {
+ "Not Equal - Dot Product",
+ [](float3 a, float3 b, float comp, float epsilon) {
return abs(math::dot(a, b) - comp) >= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_DIRECTION: {
static fn::CustomMF_SI_SI_SI_SI_SO<float3, float3, float, float, bool> fn{
- "Not Equal - Direction", [](float3 a, float3 b, float angle, float epsilon) {
+ "Not Equal - Direction",
+ [](float3 a, float3 b, float angle, float epsilon) {
return abs(angle_v3v3(a, b) - angle) > epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_ELEMENT: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
- "Not Equal - Element-wise", [](float3 a, float3 b, float epsilon) {
+ "Not Equal - Element-wise",
+ [](float3 a, float3 b, float epsilon) {
return abs(a.x - b.x) > epsilon && abs(a.y - b.y) > epsilon &&
abs(a.z - b.z) > epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_MODE_LENGTH: {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, bool> fn{
- "Not Equal - Length", [](float3 a, float3 b, float epsilon) {
+ "Not Equal - Length",
+ [](float3 a, float3 b, float epsilon) {
return abs(math::length(a) - math::length(b)) > epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
}
@@ -464,32 +510,40 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
switch (data->operation) {
case NODE_COMPARE_EQUAL: {
static fn::CustomMF_SI_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, float, bool> fn{
- "Equal", [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
+ "Equal",
+ [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
return abs(a.r - b.r) <= epsilon && abs(a.g - b.g) <= epsilon &&
abs(a.b - b.b) <= epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_NOT_EQUAL: {
static fn::CustomMF_SI_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, float, bool> fn{
- "Not Equal", [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
+ "Not Equal",
+ [](ColorGeometry4f a, ColorGeometry4f b, float epsilon) {
return abs(a.r - b.r) > epsilon && abs(a.g - b.g) > epsilon &&
abs(a.b - b.b) > epsilon;
- }};
+ },
+ exec_preset_first_two};
return &fn;
}
case NODE_COMPARE_COLOR_BRIGHTER: {
static fn::CustomMF_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, bool> fn{
- "Brighter", [](ColorGeometry4f a, ColorGeometry4f b) {
+ "Brighter",
+ [](ColorGeometry4f a, ColorGeometry4f b) {
return rgb_to_grayscale(a) > rgb_to_grayscale(b);
- }};
+ },
+ exec_preset_all};
return &fn;
}
case NODE_COMPARE_COLOR_DARKER: {
static fn::CustomMF_SI_SI_SO<ColorGeometry4f, ColorGeometry4f, bool> fn{
- "Darker", [](ColorGeometry4f a, ColorGeometry4f b) {
+ "Darker",
+ [](ColorGeometry4f a, ColorGeometry4f b) {
return rgb_to_grayscale(a) < rgb_to_grayscale(b);
- }};
+ },
+ exec_preset_all};
return &fn;
}
}
diff --git a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
index fddc0e99082..9c9d8620a7e 100644
--- a/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
+++ b/source/blender/nodes/function/nodes/node_fn_float_to_int.cc
@@ -2,6 +2,7 @@
#include <cmath>
+#include "BLI_noise.hh"
#include "BLI_string.h"
#include "RNA_enum_types.h"
@@ -40,11 +41,15 @@ static void node_float_to_int_label(const bNodeTree *UNUSED(ntree),
static const fn::MultiFunction *get_multi_function(bNode &bnode)
{
- static fn::CustomMF_SI_SO<float, int> round_fn{"Round", [](float a) { return (int)round(a); }};
- static fn::CustomMF_SI_SO<float, int> floor_fn{"Floor", [](float a) { return (int)floor(a); }};
- static fn::CustomMF_SI_SO<float, int> ceil_fn{"Ceiling", [](float a) { return (int)ceil(a); }};
- static fn::CustomMF_SI_SO<float, int> trunc_fn{"Truncate",
- [](float a) { return (int)trunc(a); }};
+ static auto exec_preset = fn::CustomMF_presets::AllSpanOrSingle();
+ static fn::CustomMF_SI_SO<float, int> round_fn{
+ "Round", [](float a) { return (int)round(a); }, exec_preset};
+ static fn::CustomMF_SI_SO<float, int> floor_fn{
+ "Floor", [](float a) { return (int)floor(a); }, exec_preset};
+ static fn::CustomMF_SI_SO<float, int> ceil_fn{
+ "Ceiling", [](float a) { return (int)ceil(a); }, exec_preset};
+ static fn::CustomMF_SI_SO<float, int> trunc_fn{
+ "Truncate", [](float a) { return (int)trunc(a); }, exec_preset};
switch (static_cast<FloatToIntRoundingMode>(bnode.custom1)) {
case FN_NODE_FLOAT_TO_INT_ROUND:
diff --git a/source/blender/nodes/function/nodes/node_fn_random_value.cc b/source/blender/nodes/function/nodes/node_fn_random_value.cc
index 3c4513d4e62..a0942ced1be 100644
--- a/source/blender/nodes/function/nodes/node_fn_random_value.cc
+++ b/source/blender/nodes/function/nodes/node_fn_random_value.cc
@@ -134,162 +134,6 @@ static void fn_node_random_value_gather_link_search(GatherLinkSearchOpParams &pa
}
}
-class RandomVectorFunction : public fn::MultiFunction {
- public:
- RandomVectorFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Random Value"};
- signature.single_input<float3>("Min");
- signature.single_input<float3>("Max");
- signature.single_input<int>("ID");
- signature.single_input<int>("Seed");
- signature.single_output<float3>("Value");
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float3> &min_values = params.readonly_single_input<float3>(0, "Min");
- const VArray<float3> &max_values = params.readonly_single_input<float3>(1, "Max");
- const VArray<int> &ids = params.readonly_single_input<int>(2, "ID");
- const VArray<int> &seeds = params.readonly_single_input<int>(3, "Seed");
- MutableSpan<float3> values = params.uninitialized_single_output<float3>(4, "Value");
-
- for (int64_t i : mask) {
- const float3 min_value = min_values[i];
- const float3 max_value = max_values[i];
- const int seed = seeds[i];
- const int id = ids[i];
-
- const float x = noise::hash_to_float(seed, id, 0);
- const float y = noise::hash_to_float(seed, id, 1);
- const float z = noise::hash_to_float(seed, id, 2);
-
- values[i] = float3(x, y, z) * (max_value - min_value) + min_value;
- }
- }
-};
-
-class RandomFloatFunction : public fn::MultiFunction {
- public:
- RandomFloatFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Random Value"};
- signature.single_input<float>("Min");
- signature.single_input<float>("Max");
- signature.single_input<int>("ID");
- signature.single_input<int>("Seed");
- signature.single_output<float>("Value");
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float> &min_values = params.readonly_single_input<float>(0, "Min");
- const VArray<float> &max_values = params.readonly_single_input<float>(1, "Max");
- const VArray<int> &ids = params.readonly_single_input<int>(2, "ID");
- const VArray<int> &seeds = params.readonly_single_input<int>(3, "Seed");
- MutableSpan<float> values = params.uninitialized_single_output<float>(4, "Value");
-
- for (int64_t i : mask) {
- const float min_value = min_values[i];
- const float max_value = max_values[i];
- const int seed = seeds[i];
- const int id = ids[i];
-
- const float value = noise::hash_to_float(seed, id);
- values[i] = value * (max_value - min_value) + min_value;
- }
- }
-};
-
-class RandomIntFunction : public fn::MultiFunction {
- public:
- RandomIntFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Random Value"};
- signature.single_input<int>("Min");
- signature.single_input<int>("Max");
- signature.single_input<int>("ID");
- signature.single_input<int>("Seed");
- signature.single_output<int>("Value");
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<int> &min_values = params.readonly_single_input<int>(0, "Min");
- const VArray<int> &max_values = params.readonly_single_input<int>(1, "Max");
- const VArray<int> &ids = params.readonly_single_input<int>(2, "ID");
- const VArray<int> &seeds = params.readonly_single_input<int>(3, "Seed");
- MutableSpan<int> values = params.uninitialized_single_output<int>(4, "Value");
-
- /* Add one to the maximum and use floor to produce an even
- * distribution for the first and last values (See T93591). */
- for (int64_t i : mask) {
- const float min_value = min_values[i];
- const float max_value = max_values[i] + 1.0f;
- const int seed = seeds[i];
- const int id = ids[i];
-
- const float value = noise::hash_to_float(id, seed);
- values[i] = floor(value * (max_value - min_value) + min_value);
- }
- }
-};
-
-class RandomBoolFunction : public fn::MultiFunction {
- public:
- RandomBoolFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Random Value"};
- signature.single_input<float>("Probability");
- signature.single_input<int>("ID");
- signature.single_input<int>("Seed");
- signature.single_output<bool>("Value");
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float> &probabilities = params.readonly_single_input<float>(0, "Probability");
- const VArray<int> &ids = params.readonly_single_input<int>(1, "ID");
- const VArray<int> &seeds = params.readonly_single_input<int>(2, "Seed");
- MutableSpan<bool> values = params.uninitialized_single_output<bool>(3, "Value");
-
- for (int64_t i : mask) {
- const int seed = seeds[i];
- const int id = ids[i];
- const float probability = probabilities[i];
- values[i] = noise::hash_to_float(id, seed) <= probability;
- }
- }
-};
-
static void fn_node_random_value_build_multi_function(NodeMultiFunctionBuilder &builder)
{
const NodeRandomValue &storage = node_storage(builder.node());
@@ -297,22 +141,64 @@ static void fn_node_random_value_build_multi_function(NodeMultiFunctionBuilder &
switch (data_type) {
case CD_PROP_FLOAT3: {
- static RandomVectorFunction fn;
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float3>>
+ fn{"Random Vector",
+ [](float3 min_value, float3 max_value, int id, int seed, float3 *r_value) {
+ const float x = noise::hash_to_float(seed, id, 0);
+ const float y = noise::hash_to_float(seed, id, 1);
+ const float z = noise::hash_to_float(seed, id, 2);
+ *r_value = float3(x, y, z) * (max_value - min_value) + min_value;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<2>()};
builder.set_matching_fn(fn);
break;
}
case CD_PROP_FLOAT: {
- static RandomFloatFunction fn;
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float>>
+ fn{"Random Float",
+ [](float min_value, float max_value, int id, int seed, float *r_value) {
+ const float value = noise::hash_to_float(seed, id);
+ *r_value = value * (max_value - min_value) + min_value;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<2>()};
builder.set_matching_fn(fn);
break;
}
case CD_PROP_INT32: {
- static RandomIntFunction fn;
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, int>>
+ fn{"Random Int",
+ [](int min_value, int max_value, int id, int seed, int *r_value) {
+ const float value = noise::hash_to_float(id, seed);
+ /* Add one to the maximum and use floor to produce an even
+ * distribution for the first and last values (See T93591). */
+ *r_value = floor(value * (max_value + 1 - min_value) + min_value);
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<2>()};
builder.set_matching_fn(fn);
break;
}
case CD_PROP_BOOL: {
- static RandomBoolFunction fn;
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, int>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, bool>>
+ fn{"Random Bool",
+ [](float probability, int id, int seed, bool *r_value) {
+ *r_value = noise::hash_to_float(id, seed) <= probability;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<1>()};
builder.set_matching_fn(fn);
break;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index 121ee015d2d..e0348f27e51 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -551,8 +551,10 @@ static Field<int> get_curve_count_field(GeoNodeExecParams params,
const GeometryNodeCurveResampleMode mode)
{
if (mode == GEO_NODE_CURVE_RESAMPLE_COUNT) {
- static fn::CustomMF_SI_SO<int, int> max_one_fn("Clamp Above One",
- [](int value) { return std::max(1, value); });
+ static fn::CustomMF_SI_SO<int, int> max_one_fn(
+ "Clamp Above One",
+ [](int value) { return std::max(1, value); },
+ fn::CustomMF_presets::AllSpanOrSingle());
auto clamp_op = std::make_shared<FieldOperation>(
FieldOperation(max_one_fn, {Field<int>(params.extract_input<Field<int>>("Count"))}));
@@ -561,12 +563,14 @@ static Field<int> get_curve_count_field(GeoNodeExecParams params,
if (mode == GEO_NODE_CURVE_RESAMPLE_LENGTH) {
static fn::CustomMF_SI_SI_SO<float, float, int> get_count_fn(
- "Length Input to Count", [](const float curve_length, const float sample_length) {
+ "Length Input to Count",
+ [](const float curve_length, const float sample_length) {
/* Find the number of sampled segments by dividing the total length by
* the sample length. Then there is one more sampled point than segment. */
const int count = int(curve_length / sample_length) + 1;
return std::max(1, count);
- });
+ },
+ fn::CustomMF_presets::AllSpanOrSingle());
auto get_count_op = std::make_shared<FieldOperation>(
FieldOperation(get_count_fn,
@@ -588,9 +592,11 @@ static Field<int> get_curve_count_field(GeoNodeExecParams params,
static Field<bool> get_selection_field(GeoNodeExecParams params)
{
static fn::CustomMF_SI_SI_SO<bool, int, bool> get_selection_fn(
- "Create Curve Selection", [](const bool orig_selection, const int evaluated_points_num) {
+ "Create Curve Selection",
+ [](const bool orig_selection, const int evaluated_points_num) {
return orig_selection && evaluated_points_num > 1;
- });
+ },
+ fn::CustomMF_presets::AllSpanOrSingle());
auto selection_op = std::make_shared<FieldOperation>(
FieldOperation(get_selection_fn,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
index 6661d03a851..9077b59254c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
@@ -203,9 +203,11 @@ static Field<float> get_length_input_field(const GeoNodeExecParams &params,
/* Just make sure the length is in bounds of the curve. */
Field<float> length_field = params.get_input<Field<float>>("Length");
auto clamp_fn = std::make_unique<fn::CustomMF_SI_SO<float, float>>(
- __func__, [curve_total_length](float length) {
+ __func__,
+ [curve_total_length](float length) {
return std::clamp(length, 0.0f, curve_total_length);
- });
+ },
+ fn::CustomMF_presets::AllSpanOrSingle());
auto clamp_op = std::make_shared<FieldOperation>(
FieldOperation(std::move(clamp_fn), {std::move(length_field)}));
@@ -215,10 +217,12 @@ static Field<float> get_length_input_field(const GeoNodeExecParams &params,
/* Convert the factor to a length and clamp it to the bounds of the curve. */
Field<float> factor_field = params.get_input<Field<float>>("Factor");
auto clamp_fn = std::make_unique<fn::CustomMF_SI_SO<float, float>>(
- __func__, [curve_total_length](float factor) {
+ __func__,
+ [curve_total_length](float factor) {
const float length = factor * curve_total_length;
return std::clamp(length, 0.0f, curve_total_length);
- });
+ },
+ fn::CustomMF_presets::AllSpanOrSingle());
auto process_op = std::make_shared<FieldOperation>(
FieldOperation(std::move(clamp_fn), {std::move(factor_field)}));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index 0072fbcde93..4591cfa1da2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -1274,7 +1274,9 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Create a combined field from the offset and the scale so the field evaluator
* can take care of the multiplication and to simplify each extrude function. */
static fn::CustomMF_SI_SI_SO<float3, float, float3> multiply_fn{
- "Scale", [](const float3 &offset, const float scale) { return offset * scale; }};
+ "Scale",
+ [](const float3 &offset, const float scale) { return offset * scale; },
+ fn::CustomMF_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)};
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
index 6a7aab1cea7..1a0cc53cb6c 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
@@ -124,7 +124,9 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Use another multi-function operation to make sure the input radius is greater than zero.
* TODO: Use mutable multi-function once that is supported. */
static fn::CustomMF_SI_SO<float, float> max_zero_fn(
- __func__, [](float value) { return std::max(0.0f, value); });
+ __func__,
+ [](float value) { return std::max(0.0f, value); },
+ fn::CustomMF_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);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_switch.cc b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
index 6e27b346407..ddc87e3dac4 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_switch.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_switch.cc
@@ -139,35 +139,6 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
}
}
-template<typename T> class SwitchFieldsFunction : public fn::MultiFunction {
- public:
- SwitchFieldsFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Switch"};
- signature.single_input<bool>("Switch");
- signature.single_input<T>("False");
- signature.single_input<T>("True");
- signature.single_output<T>("Output");
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<bool> &switches = params.readonly_single_input<bool>(0, "Switch");
- const VArray<T> &falses = params.readonly_single_input<T>(1, "False");
- const VArray<T> &trues = params.readonly_single_input<T>(2, "True");
- MutableSpan<T> values = params.uninitialized_single_output_if_required<T>(3, "Output");
- for (int64_t i : mask) {
- new (&values[i]) T(switches[i] ? trues[i] : falses[i]);
- }
- }
-};
-
template<typename T> void switch_fields(GeoNodeExecParams &params, const StringRef suffix)
{
if (params.lazy_require_input("Switch")) {
@@ -190,7 +161,11 @@ template<typename T> void switch_fields(GeoNodeExecParams &params, const StringR
Field<T> falses_field = params.extract_input<Field<T>>(name_false);
Field<T> trues_field = params.extract_input<Field<T>>(name_true);
- auto switch_fn = std::make_unique<SwitchFieldsFunction<T>>();
+ static fn::CustomMF_SI_SI_SI_SO<bool, T, T, T> switch_fn{
+ "Switch", [](bool condition, const T &false_value, const T &true_value) {
+ return condition ? true_value : false_value;
+ }};
+
auto switch_op = std::make_shared<FieldOperation>(FieldOperation(
std::move(switch_fn),
{std::move(switches_field), std::move(falses_field), std::move(trues_field)}));
diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
index 8e7934bf34e..9ba9a279c57 100644
--- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
@@ -223,327 +223,106 @@ static float3 clamp_range(const float3 value, const float3 min, const float3 max
clamp_range(value.z, min.z, max.z));
}
-static void map_range_vector_signature(fn::MFSignatureBuilder *signature, bool use_steps)
+template<bool Clamp> static auto build_float_linear()
{
- signature->single_input<float3>("Vector");
- signature->single_input<float3>("From Min");
- signature->single_input<float3>("From Max");
- signature->single_input<float3>("To Min");
- signature->single_input<float3>("To Max");
- if (use_steps) {
- signature->single_input<float3>("Steps");
- }
- signature->single_output<float3>("Vector");
+ return fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float>>{
+ Clamp ? "Map Range (clamped)" : "Map Range (unclamped)",
+ [](float value, float from_min, float from_max, float to_min, float to_max, float *r_value) {
+ const float factor = safe_divide(value - from_min, from_max - from_min);
+ float result = to_min + factor * (to_max - to_min);
+ if constexpr (Clamp) {
+ result = clamp_range(result, to_min, to_max);
+ }
+ *r_value = result;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
}
-class MapRangeVectorFunction : public fn::MultiFunction {
- private:
- bool clamp_;
-
- public:
- MapRangeVectorFunction(bool clamp) : clamp_(clamp)
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Vector Map Range"};
- map_range_vector_signature(&signature, false);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector");
- const VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min");
- const VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max");
- const VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min");
- const VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max");
- MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector");
-
- for (int64_t i : mask) {
- float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- results[i] = factor * (to_max[i] - to_min[i]) + to_min[i];
- }
-
- if (clamp_) {
- for (int64_t i : mask) {
- results[i] = clamp_range(results[i], to_min[i], to_max[i]);
- }
- }
- }
-};
-
-class MapRangeSteppedVectorFunction : public fn::MultiFunction {
- private:
- bool clamp_;
-
- public:
- MapRangeSteppedVectorFunction(bool clamp) : clamp_(clamp)
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Vector Map Range Stepped"};
- map_range_vector_signature(&signature, true);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector");
- const VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min");
- const VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max");
- const VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min");
- const VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max");
- const VArray<float3> &steps = params.readonly_single_input<float3>(5, "Steps");
- MutableSpan<float3> results = params.uninitialized_single_output<float3>(6, "Vector");
-
- for (int64_t i : mask) {
- float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- factor = math::safe_divide(math::floor(factor * (steps[i] + 1.0f)), steps[i]);
- results[i] = factor * (to_max[i] - to_min[i]) + to_min[i];
- }
-
- if (clamp_) {
- for (int64_t i : mask) {
- results[i] = clamp_range(results[i], to_min[i], to_max[i]);
- }
- }
- }
-};
-
-class MapRangeSmoothstepVectorFunction : public fn::MultiFunction {
- public:
- MapRangeSmoothstepVectorFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Vector Map Range Smoothstep"};
- map_range_vector_signature(&signature, false);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector");
- const VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min");
- const VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max");
- const VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min");
- const VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max");
- MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector");
-
- for (int64_t i : mask) {
- float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- clamp_v3(factor, 0.0f, 1.0f);
- factor = (float3(3.0f) - 2.0f * factor) * (factor * factor);
- results[i] = factor * (to_max[i] - to_min[i]) + to_min[i];
- }
- }
-};
-
-class MapRangeSmootherstepVectorFunction : public fn::MultiFunction {
- public:
- MapRangeSmootherstepVectorFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Vector Map Range Smoothstep"};
- map_range_vector_signature(&signature, false);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float3> &values = params.readonly_single_input<float3>(0, "Vector");
- const VArray<float3> &from_min = params.readonly_single_input<float3>(1, "From Min");
- const VArray<float3> &from_max = params.readonly_single_input<float3>(2, "From Max");
- const VArray<float3> &to_min = params.readonly_single_input<float3>(3, "To Min");
- const VArray<float3> &to_max = params.readonly_single_input<float3>(4, "To Max");
- MutableSpan<float3> results = params.uninitialized_single_output<float3>(5, "Vector");
-
- for (int64_t i : mask) {
- float3 factor = math::safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- clamp_v3(factor, 0.0f, 1.0f);
- factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f);
- results[i] = factor * (to_max[i] - to_min[i]) + to_min[i];
- }
- }
-};
-
-static void map_range_signature(fn::MFSignatureBuilder *signature, bool use_steps)
+template<bool Clamp> static auto build_float_stepped()
{
- signature->single_input<float>("Value");
- signature->single_input<float>("From Min");
- signature->single_input<float>("From Max");
- signature->single_input<float>("To Min");
- signature->single_input<float>("To Max");
- if (use_steps) {
- signature->single_input<float>("Steps");
- }
- signature->single_output<float>("Result");
+ return fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, 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 *r_value) {
+ float factor = safe_divide(value - from_min, from_max - from_min);
+ factor = safe_divide(floorf(factor * (steps + 1.0f)), steps);
+ float result = to_min + factor * (to_max - to_min);
+ if constexpr (Clamp) {
+ result = clamp_range(result, to_min, to_max);
+ }
+ *r_value = result;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
}
-class MapRangeFunction : public fn::MultiFunction {
- private:
- bool clamp_;
-
- public:
- MapRangeFunction(bool clamp) : clamp_(clamp)
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Map Range"};
- map_range_signature(&signature, false);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float> &values = params.readonly_single_input<float>(0, "Value");
- const VArray<float> &from_min = params.readonly_single_input<float>(1, "From Min");
- const VArray<float> &from_max = params.readonly_single_input<float>(2, "From Max");
- const VArray<float> &to_min = params.readonly_single_input<float>(3, "To Min");
- const VArray<float> &to_max = params.readonly_single_input<float>(4, "To Max");
- MutableSpan<float> results = params.uninitialized_single_output<float>(5, "Result");
-
- for (int64_t i : mask) {
- float factor = safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- results[i] = to_min[i] + factor * (to_max[i] - to_min[i]);
- }
-
- if (clamp_) {
- for (int64_t i : mask) {
- results[i] = clamp_range(results[i], to_min[i], to_max[i]);
- }
- }
- }
-};
-
-class MapRangeSteppedFunction : public fn::MultiFunction {
- private:
- bool clamp_;
-
- public:
- MapRangeSteppedFunction(bool clamp) : clamp_(clamp)
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Map Range Stepped"};
- map_range_signature(&signature, true);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float> &values = params.readonly_single_input<float>(0, "Value");
- const VArray<float> &from_min = params.readonly_single_input<float>(1, "From Min");
- const VArray<float> &from_max = params.readonly_single_input<float>(2, "From Max");
- const VArray<float> &to_min = params.readonly_single_input<float>(3, "To Min");
- const VArray<float> &to_max = params.readonly_single_input<float>(4, "To Max");
- const VArray<float> &steps = params.readonly_single_input<float>(5, "Steps");
- MutableSpan<float> results = params.uninitialized_single_output<float>(6, "Result");
-
- for (int64_t i : mask) {
- float factor = safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- factor = safe_divide(floorf(factor * (steps[i] + 1.0f)), steps[i]);
- results[i] = to_min[i] + factor * (to_max[i] - to_min[i]);
- }
-
- if (clamp_) {
- for (int64_t i : mask) {
- results[i] = clamp_range(results[i], to_min[i], to_max[i]);
- }
- }
- }
-};
-
-class MapRangeSmoothstepFunction : public fn::MultiFunction {
- public:
- MapRangeSmoothstepFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Map Range Smoothstep"};
- map_range_signature(&signature, false);
- return signature.build();
- }
-
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float> &values = params.readonly_single_input<float>(0, "Value");
- const VArray<float> &from_min = params.readonly_single_input<float>(1, "From Min");
- const VArray<float> &from_max = params.readonly_single_input<float>(2, "From Max");
- const VArray<float> &to_min = params.readonly_single_input<float>(3, "To Min");
- const VArray<float> &to_max = params.readonly_single_input<float>(4, "To Max");
- MutableSpan<float> results = params.uninitialized_single_output<float>(5, "Result");
-
- for (int64_t i : mask) {
- float factor = safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- factor = std::clamp(factor, 0.0f, 1.0f);
- factor = (3.0f - 2.0f * factor) * (factor * factor);
- results[i] = to_min[i] + factor * (to_max[i] - to_min[i]);
- }
- }
-};
-
-class MapRangeSmootherstepFunction : public fn::MultiFunction {
- public:
- MapRangeSmootherstepFunction()
- {
- static fn::MFSignature signature = create_signature();
- this->set_signature(&signature);
- }
-
- static fn::MFSignature create_signature()
- {
- fn::MFSignatureBuilder signature{"Map Range Smoothstep"};
- map_range_signature(&signature, false);
- return signature.build();
- }
+template<bool Clamp> static auto build_vector_linear()
+{
+ return fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float3>>{
+ Clamp ? "Vector Map Range (clamped)" : "Vector Map Range (unclamped)",
+ [](const float3 &value,
+ const float3 &from_min,
+ const float3 &from_max,
+ const float3 &to_min,
+ const float3 &to_max,
+ float3 *r_value) {
+ float3 factor = math::safe_divide(value - from_min, from_max - from_min);
+ float3 result = factor * (to_max - to_min) + to_min;
+ if constexpr (Clamp) {
+ result = clamp_range(result, to_min, to_max);
+ }
+ *r_value = result;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
+}
- void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override
- {
- const VArray<float> &values = params.readonly_single_input<float>(0, "Value");
- const VArray<float> &from_min = params.readonly_single_input<float>(1, "From Min");
- const VArray<float> &from_max = params.readonly_single_input<float>(2, "From Max");
- const VArray<float> &to_min = params.readonly_single_input<float>(3, "To Min");
- const VArray<float> &to_max = params.readonly_single_input<float>(4, "To Max");
- MutableSpan<float> results = params.uninitialized_single_output<float>(5, "Result");
-
- for (int64_t i : mask) {
- float factor = safe_divide(values[i] - from_min[i], from_max[i] - from_min[i]);
- factor = std::clamp(factor, 0.0f, 1.0f);
- factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f);
- results[i] = to_min[i] + factor * (to_max[i] - to_min[i]);
- }
- }
-};
+template<bool Clamp> static auto build_vector_stepped()
+{
+ return fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float3>>{
+ Clamp ? "Vector Map Range Stepped (clamped)" : "Vector Map Range Stepped (unclamped)",
+ [](const float3 &value,
+ const float3 &from_min,
+ const float3 &from_max,
+ const float3 &to_min,
+ const float3 &to_max,
+ const float3 &steps,
+ float3 *r_value) {
+ float3 factor = math::safe_divide(value - from_min, from_max - from_min);
+ factor = math::safe_divide(math::floor(factor * (steps + 1.0f)), steps);
+ float3 result = factor * (to_max - to_min) + to_min;
+ if constexpr (Clamp) {
+ result = clamp_range(result, to_min, to_max);
+ }
+ *r_value = result;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
+}
static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &builder)
{
@@ -556,34 +335,70 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
switch (interpolation_type) {
case NODE_MAP_RANGE_LINEAR: {
if (clamp) {
- static MapRangeVectorFunction fn_with_clamp{true};
- builder.set_matching_fn(fn_with_clamp);
+ static auto fn = build_vector_linear<true>();
+ builder.set_matching_fn(fn);
}
else {
- static MapRangeVectorFunction fn_without_clamp{false};
- builder.set_matching_fn(fn_without_clamp);
+ static auto fn = build_vector_linear<false>();
+ builder.set_matching_fn(fn);
}
break;
}
case NODE_MAP_RANGE_STEPPED: {
if (clamp) {
- static MapRangeSteppedVectorFunction fn_stepped_with_clamp{true};
- builder.set_matching_fn(fn_stepped_with_clamp);
+ static auto fn = build_vector_stepped<true>();
+ builder.set_matching_fn(fn);
}
else {
- static MapRangeSteppedVectorFunction fn_stepped_without_clamp{false};
- builder.set_matching_fn(fn_stepped_without_clamp);
+ static auto fn = build_vector_stepped<false>();
+ builder.set_matching_fn(fn);
}
break;
}
case NODE_MAP_RANGE_SMOOTHSTEP: {
- static MapRangeSmoothstepVectorFunction smoothstep;
- builder.set_matching_fn(smoothstep);
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float3>>
+ fn{"Vector Map Range Smoothstep",
+ [](const float3 &value,
+ const float3 &from_min,
+ const float3 &from_max,
+ const float3 &to_min,
+ const float3 &to_max,
+ float3 *r_value) {
+ float3 factor = math::safe_divide(value - from_min, from_max - from_min);
+ clamp_v3(factor, 0.0f, 1.0f);
+ factor = (float3(3.0f) - 2.0f * factor) * (factor * factor);
+ *r_value = factor * (to_max - to_min) + to_min;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
+ builder.set_matching_fn(fn);
break;
}
case NODE_MAP_RANGE_SMOOTHERSTEP: {
- static MapRangeSmootherstepVectorFunction smootherstep;
- builder.set_matching_fn(smootherstep);
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float3>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float3>>
+ fn{"Vector Map Range Smootherstep",
+ [](const float3 &value,
+ const float3 &from_min,
+ const float3 &from_max,
+ const float3 &to_min,
+ const float3 &to_max,
+ float3 *r_value) {
+ float3 factor = math::safe_divide(value - from_min, from_max - from_min);
+ clamp_v3(factor, 0.0f, 1.0f);
+ factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f);
+ *r_value = factor * (to_max - to_min) + to_min;
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
+ builder.set_matching_fn(fn);
break;
}
default:
@@ -594,34 +409,70 @@ static void sh_node_map_range_build_multi_function(NodeMultiFunctionBuilder &bui
switch (interpolation_type) {
case NODE_MAP_RANGE_LINEAR: {
if (clamp) {
- static MapRangeFunction fn_with_clamp{true};
- builder.set_matching_fn(fn_with_clamp);
+ static auto fn = build_float_linear<true>();
+ builder.set_matching_fn(fn);
}
else {
- static MapRangeFunction fn_without_clamp{false};
- builder.set_matching_fn(fn_without_clamp);
+ static auto fn = build_float_linear<false>();
+ builder.set_matching_fn(fn);
}
break;
}
case NODE_MAP_RANGE_STEPPED: {
if (clamp) {
- static MapRangeSteppedFunction fn_stepped_with_clamp{true};
- builder.set_matching_fn(fn_stepped_with_clamp);
+ static auto fn = build_float_stepped<true>();
+ builder.set_matching_fn(fn);
}
else {
- static MapRangeSteppedFunction fn_stepped_without_clamp{false};
- builder.set_matching_fn(fn_stepped_without_clamp);
+ static auto fn = build_float_stepped<false>();
+ builder.set_matching_fn(fn);
}
break;
}
case NODE_MAP_RANGE_SMOOTHSTEP: {
- static MapRangeSmoothstepFunction smoothstep;
- builder.set_matching_fn(smoothstep);
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float>>
+ fn{"Map Range Smoothstep",
+ [](float value,
+ float from_min,
+ float from_max,
+ float to_min,
+ float to_max,
+ float *r_value) {
+ float factor = safe_divide(value - from_min, from_max - from_min);
+ factor = std::clamp(factor, 0.0f, 1.0f);
+ factor = (3.0f - 2.0f * factor) * (factor * factor);
+ *r_value = to_min + factor * (to_max - to_min);
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
+ builder.set_matching_fn(fn);
break;
}
case NODE_MAP_RANGE_SMOOTHERSTEP: {
- static MapRangeSmootherstepFunction smootherstep;
- builder.set_matching_fn(smootherstep);
+ static fn::CustomMF<fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleInput, float>,
+ fn::MFParamTag<fn::MFParamCategory::SingleOutput, float>>
+ fn{"Map Range Smoothstep",
+ [](float value,
+ float from_min,
+ float from_max,
+ float to_min,
+ float to_max,
+ float *r_value) {
+ float factor = safe_divide(value - from_min, from_max - from_min);
+ factor = std::clamp(factor, 0.0f, 1.0f);
+ factor = factor * factor * factor * (factor * (factor * 6.0f - 15.0f) + 10.0f);
+ *r_value = to_min + factor * (to_max - to_min);
+ },
+ fn::CustomMF_presets::SomeSpanOrSingle<0>()};
+ builder.set_matching_fn(fn);
break;
}
default:
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc
index a828011a3ab..8a2b18d7d76 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_math.cc
@@ -106,28 +106,30 @@ static const fn::MultiFunction *get_base_multi_function(bNode &node)
const int mode = node.custom1;
const fn::MultiFunction *base_fn = nullptr;
- try_dispatch_float_math_fl_to_fl(mode, [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SO<float, float> fn{info.title_case_name.c_str(), function};
- base_fn = &fn;
- });
+ try_dispatch_float_math_fl_to_fl(
+ mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SO<float, float> fn{
+ info.title_case_name.c_str(), function, devi_fn};
+ base_fn = &fn;
+ });
if (base_fn != nullptr) {
return base_fn;
}
- try_dispatch_float_math_fl_fl_to_fl(mode,
- [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SI_SO<float, float, float> fn{
- info.title_case_name.c_str(), function};
- base_fn = &fn;
- });
+ try_dispatch_float_math_fl_fl_to_fl(
+ mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SI_SO<float, float, float> fn{
+ info.title_case_name.c_str(), function, devi_fn};
+ base_fn = &fn;
+ });
if (base_fn != nullptr) {
return base_fn;
}
try_dispatch_float_math_fl_fl_fl_to_fl(
- mode, [&](auto function, const FloatMathOperationInfo &info) {
+ mode, [&](auto devi_fn, auto function, const FloatMathOperationInfo &info) {
static fn::CustomMF_SI_SI_SI_SO<float, float, float, float> fn{
- info.title_case_name.c_str(), function};
+ info.title_case_name.c_str(), function, devi_fn};
base_fn = &fn;
});
if (base_fn != nullptr) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc
index 0d751157817..94a6febe92e 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcomb_xyz.cc
@@ -106,7 +106,9 @@ static int gpu_shader_combxyz(GPUMaterial *mat,
static void sh_node_combxyz_build_multi_function(NodeMultiFunctionBuilder &builder)
{
static fn::CustomMF_SI_SI_SI_SO<float, float, float, float3> fn{
- "Combine Vector", [](float x, float y, float z) { return float3(x, y, z); }};
+ "Combine Vector",
+ [](float x, float y, float z) { return float3(x, y, z); },
+ fn::CustomMF_presets::AllSpanOrSingle()};
builder.set_matching_fn(fn);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
index 02a3552704e..21f5c44c640 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
@@ -231,20 +231,20 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
const fn::MultiFunction *multi_fn = nullptr;
- try_dispatch_float_math_fl3_fl3_to_fl3(operation,
- [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
- info.title_case_name.c_str(), function};
- multi_fn = &fn;
- });
+ try_dispatch_float_math_fl3_fl3_to_fl3(
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SI_SO<float3, float3, float3> fn{
+ info.title_case_name.c_str(), function, exec_preset};
+ multi_fn = &fn;
+ });
if (multi_fn != nullptr) {
return multi_fn;
}
try_dispatch_float_math_fl3_fl3_fl3_to_fl3(
- operation, [&](auto function, const FloatMathOperationInfo &info) {
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float3, float3> fn{
- info.title_case_name.c_str(), function};
+ info.title_case_name.c_str(), function, exec_preset};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -252,38 +252,39 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
}
try_dispatch_float_math_fl3_fl3_fl_to_fl3(
- operation, [&](auto function, const FloatMathOperationInfo &info) {
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
static fn::CustomMF_SI_SI_SI_SO<float3, float3, float, float3> fn{
- info.title_case_name.c_str(), function};
+ info.title_case_name.c_str(), function, exec_preset};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
return multi_fn;
}
- try_dispatch_float_math_fl3_fl3_to_fl(operation,
- [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SI_SO<float3, float3, float> fn{
- info.title_case_name.c_str(), function};
- multi_fn = &fn;
- });
+ try_dispatch_float_math_fl3_fl3_to_fl(
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SI_SO<float3, float3, float> fn{
+ info.title_case_name.c_str(), function, exec_preset};
+ multi_fn = &fn;
+ });
if (multi_fn != nullptr) {
return multi_fn;
}
- try_dispatch_float_math_fl3_fl_to_fl3(operation,
- [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SI_SO<float3, float, float3> fn{
- info.title_case_name.c_str(), function};
- multi_fn = &fn;
- });
+ try_dispatch_float_math_fl3_fl_to_fl3(
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SI_SO<float3, float, float3> fn{
+ info.title_case_name.c_str(), function, exec_preset};
+ multi_fn = &fn;
+ });
if (multi_fn != nullptr) {
return multi_fn;
}
try_dispatch_float_math_fl3_to_fl3(
- operation, [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SO<float3, float3> fn{info.title_case_name.c_str(), function};
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SO<float3, float3> fn{
+ info.title_case_name.c_str(), function, exec_preset};
multi_fn = &fn;
});
if (multi_fn != nullptr) {
@@ -291,8 +292,9 @@ static const fn::MultiFunction *get_multi_function(bNode &node)
}
try_dispatch_float_math_fl3_to_fl(
- operation, [&](auto function, const FloatMathOperationInfo &info) {
- static fn::CustomMF_SI_SO<float3, float> fn{info.title_case_name.c_str(), function};
+ operation, [&](auto exec_preset, auto function, const FloatMathOperationInfo &info) {
+ static fn::CustomMF_SI_SO<float3, float> fn{
+ info.title_case_name.c_str(), function, exec_preset};
multi_fn = &fn;
});
if (multi_fn != nullptr) {