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/shader
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/shader')
-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
4 files changed, 234 insertions, 377 deletions
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) {