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:
Diffstat (limited to 'source/blender/functions/FN_multi_function_params.hh')
-rw-r--r--source/blender/functions/FN_multi_function_params.hh68
1 files changed, 63 insertions, 5 deletions
diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh
index 5af86c7c284..cae105e7c19 100644
--- a/source/blender/functions/FN_multi_function_params.hh
+++ b/source/blender/functions/FN_multi_function_params.hh
@@ -38,6 +38,7 @@ class MFParamsBuilder {
private:
ResourceScope scope_;
const MFSignature *signature_;
+ IndexMask mask_;
int64_t min_array_size_;
Vector<const GVArray *> virtual_arrays_;
Vector<GMutableSpan> mutable_spans_;
@@ -46,13 +47,18 @@ class MFParamsBuilder {
friend class MFParams;
- public:
- MFParamsBuilder(const MFSignature &signature, int64_t min_array_size)
- : signature_(&signature), min_array_size_(min_array_size)
+ MFParamsBuilder(const MFSignature &signature, const IndexMask mask)
+ : signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size())
{
}
- MFParamsBuilder(const class MultiFunction &fn, int64_t min_array_size);
+ public:
+ MFParamsBuilder(const class MultiFunction &fn, int64_t size);
+ /**
+ * The indices referenced by the #mask has to live longer than the params builder. This is
+ * because the it might have to destruct elements for all masked indices in the end.
+ */
+ MFParamsBuilder(const class MultiFunction &fn, const IndexMask *mask);
template<typename T> void add_readonly_single_input_value(T value, StringRef expected_name = "")
{
@@ -112,6 +118,17 @@ class MFParamsBuilder {
BLI_assert(ref.size() >= min_array_size_);
mutable_spans_.append(ref);
}
+ void add_ignored_single_output(StringRef expected_name = "")
+ {
+ this->assert_current_param_name(expected_name);
+ const int param_index = this->current_param_index();
+ const MFParamType &param_type = signature_->param_types[param_index];
+ BLI_assert(param_type.category() == MFParamType::SingleOutput);
+ const CPPType &type = param_type.data_type().single_type();
+ /* An empty span indicates that this is ignored. */
+ const GMutableSpan dummy_span{type};
+ mutable_spans_.append(dummy_span);
+ }
void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "")
{
@@ -176,6 +193,19 @@ class MFParamsBuilder {
#endif
}
+ void assert_current_param_name(StringRef expected_name)
+ {
+ UNUSED_VARS_NDEBUG(expected_name);
+#ifdef DEBUG
+ if (expected_name.is_empty()) {
+ return;
+ }
+ const int param_index = this->current_param_index();
+ StringRef actual_name = signature_->param_names[param_index];
+ BLI_assert(actual_name == expected_name);
+#endif
+ }
+
int current_param_index() const
{
return virtual_arrays_.size() + mutable_spans_.size() + virtual_vector_arrays_.size() +
@@ -204,6 +234,19 @@ class MFParams {
return *builder_->virtual_arrays_[data_index];
}
+ /**
+ * \return True when the caller provided a buffer for this output parameter. This allows the
+ * called multi-function to skip some computation. It is still valid to call
+ * #uninitialized_single_output when this returns false. In this case a new temporary buffer is
+ * allocated.
+ */
+ bool single_output_is_required(int param_index, StringRef name = "")
+ {
+ this->assert_correct_param(param_index, name, MFParamType::SingleOutput);
+ int data_index = builder_->signature_->data_index(param_index);
+ return !builder_->mutable_spans_[data_index].is_empty();
+ }
+
template<typename T>
MutableSpan<T> uninitialized_single_output(int param_index, StringRef name = "")
{
@@ -213,7 +256,22 @@ class MFParams {
{
this->assert_correct_param(param_index, name, MFParamType::SingleOutput);
int data_index = builder_->signature_->data_index(param_index);
- return builder_->mutable_spans_[data_index];
+ GMutableSpan span = builder_->mutable_spans_[data_index];
+ if (span.is_empty()) {
+ /* The output is ignored by the caller, but the multi-function does not handle this case. So
+ * create a temporary buffer that the multi-function can write to. */
+ const CPPType &type = span.type();
+ void *buffer = builder_->scope_.linear_allocator().allocate(
+ builder_->min_array_size_ * type.size(), type.alignment());
+ if (!type.is_trivially_destructible()) {
+ /* Make sure the temporary elements will be destructed in the end. */
+ builder_->scope_.add_destruct_call(
+ [&type, buffer, mask = builder_->mask_]() { type.destruct_indices(buffer, mask); },
+ __func__);
+ }
+ span = GMutableSpan{type, buffer, builder_->min_array_size_};
+ }
+ return span;
}
template<typename T>