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/function
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/function')
-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
4 files changed, 194 insertions, 248 deletions
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;
}