Page MenuHome
Paste P2881

(An Untitled Masterwork)
ActivePublic

Authored by Jacques Lucke (JacquesLucke) on Apr 4 2022, 11:14 AM.
/**
* Generates a multi-function with the following parameters:
* 1. single input (SI) of type In1
* 2. single input (SI) of type In2
* 3. single output (SO) of type Out1
*/
template<typename In1, typename In2, typename Out1>
class CustomMF_SI_SI_SO : public MultiFunction {
private:
using FunctionT =
std::function<void(IndexMask, const VArray<In1> &, const VArray<In2> &, MutableSpan<Out1>)>;
FunctionT function_;
MFSignature signature_;
public:
CustomMF_SI_SI_SO(const char *name, FunctionT function) : function_(std::move(function))
{
MFSignatureBuilder signature{name};
signature.single_input<In1>("In1");
signature.single_input<In2>("In2");
signature.single_output<Out1>("Out1");
signature_ = signature.build();
this->set_signature(&signature_);
}
template<typename ElementFuncT>
CustomMF_SI_SI_SO(const char *name, ElementFuncT element_fn)
: CustomMF_SI_SI_SO(name, CustomMF_SI_SI_SO::create_function(element_fn))
{
}
template<typename ElementFuncT> static FunctionT create_function(ElementFuncT element_fn)
{
return [=](IndexMask mask,
const VArray<In1> &in1,
const VArray<In2> &in2,
MutableSpan<Out1> out1) {
/* Devirtualization results in a 2-3x speedup for some simple functions. */
devirtualize_varray2(in1, in2, [&](const auto &in1, const auto &in2) {
mask.to_best_mask_type(
[&](const auto &mask) { execute_SI_SI_SO(element_fn, mask, in1, in2, out1.data()); });
});
};
}
template<typename ElementFuncT, typename MaskT, typename In1Array, typename In2Array>
BLI_NOINLINE static void execute_SI_SI_SO(const ElementFuncT &element_fn,
MaskT mask,
const In1Array &in1,
const In2Array &in2,
Out1 *__restrict r_out)
{
for (const int64_t i : mask) {
new (r_out + i) Out1(element_fn(in1[i], in2[i]));
}
}
void call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const override
{
const VArray<In1> &in1 = params.readonly_single_input<In1>(0);
const VArray<In2> &in2 = params.readonly_single_input<In2>(1);
MutableSpan<Out1> out1 = params.uninitialized_single_output<Out1>(2);
function_(mask, in1, in2, out1);
}
};

Event Timeline