Blender V4.3
FN_multi_function_params.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
16#include <mutex>
17#include <variant>
18
22#include "BLI_resource_scope.hh"
23
25
27
29 private:
30 std::unique_ptr<ResourceScope> scope_;
31 const Signature *signature_;
32 const IndexMask &mask_;
33 int64_t min_array_size_;
35 actual_params_;
36
37 friend class Params;
38
39 ParamsBuilder(const Signature &signature, const IndexMask &mask);
40
41 public:
46 ParamsBuilder(const class MultiFunction &fn, const IndexMask *mask);
47
48 template<typename T> void add_readonly_single_input_value(T value, StringRef expected_name = "");
49 template<typename T>
50 void add_readonly_single_input(const T *value, StringRef expected_name = "");
51 void add_readonly_single_input(const GSpan span, StringRef expected_name = "");
52 void add_readonly_single_input(GPointer value, StringRef expected_name = "");
53 void add_readonly_single_input(GVArray varray, StringRef expected_name = "");
54
55 void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "");
56 void add_readonly_vector_input(const GSpan single_vector, StringRef expected_name = "");
57 void add_readonly_vector_input(const GVVectorArray &ref, StringRef expected_name = "");
58
59 template<typename T>
60 void add_uninitialized_single_output(T *value, StringRef expected_name = "");
61 void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = "");
62
63 void add_ignored_single_output(StringRef expected_name = "");
64
65 void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "");
66
67 void add_single_mutable(GMutableSpan ref, StringRef expected_name = "");
68
69 void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = "");
70
71 int next_param_index() const;
72
73 GMutableSpan computed_array(int param_index);
74
75 GVectorArray &computed_vector_array(int param_index);
76
77 private:
78 void assert_current_param_type(ParamType param_type, StringRef expected_name = "");
79 void assert_current_param_name(StringRef expected_name);
80
81 int current_param_index() const;
82
83 ResourceScope &resource_scope();
84
85 void add_unused_output_for_unsupporting_function(const CPPType &type);
86};
87
88class Params {
89 private:
90 ParamsBuilder *builder_;
91
92 public:
93 Params(ParamsBuilder &builder) : builder_(&builder) {}
94
95 template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "");
96 const GVArray &readonly_single_input(int param_index, StringRef name = "");
97
104 bool single_output_is_required(int param_index, StringRef name = "");
105
106 template<typename T>
107 MutableSpan<T> uninitialized_single_output(int param_index, StringRef name = "");
108 GMutableSpan uninitialized_single_output(int param_index, StringRef name = "");
109
114 template<typename T>
117
118 template<typename T>
119 const VVectorArray<T> &readonly_vector_input(int param_index, StringRef name = "");
120 const GVVectorArray &readonly_vector_input(int param_index, StringRef name = "");
121
122 template<typename T>
123 GVectorArray_TypedMutableRef<T> vector_output(int param_index, StringRef name = "");
124 GVectorArray &vector_output(int param_index, StringRef name = "");
125
126 template<typename T> MutableSpan<T> single_mutable(int param_index, StringRef name = "");
127 GMutableSpan single_mutable(int param_index, StringRef name = "");
128
129 template<typename T>
130 GVectorArray_TypedMutableRef<T> vector_mutable(int param_index, StringRef name = "");
131 GVectorArray &vector_mutable(int param_index, StringRef name = "");
132
133 private:
134 void assert_correct_param(int param_index, StringRef name, ParamType param_type);
135 void assert_correct_param(int param_index, StringRef name, ParamCategory category);
136};
137
138/* -------------------------------------------------------------------- */
142inline ParamsBuilder::ParamsBuilder(const Signature &signature, const IndexMask &mask)
143 : signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size())
144{
145 actual_params_.reserve(signature.params.size());
146}
147
148template<typename T>
150{
151 this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get<T>()), expected_name);
152 actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
155 min_array_size_,
156 &value);
157}
158
159template<typename T>
160inline void ParamsBuilder::add_readonly_single_input(const T *value, StringRef expected_name)
161{
162 this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get<T>()), expected_name);
163 actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
166 min_array_size_,
167 value);
168}
169
170inline void ParamsBuilder::add_readonly_single_input(const GSpan span, StringRef expected_name)
171{
172 this->assert_current_param_type(ParamType::ForSingleInput(span.type()), expected_name);
173 BLI_assert(span.size() >= min_array_size_);
174 actual_params_.append_unchecked_as(std::in_place_type<GVArray>, varray_tag::span{}, span);
175}
176
178{
179 this->assert_current_param_type(ParamType::ForSingleInput(*value.type()), expected_name);
180 actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
182 *value.type(),
183 min_array_size_,
184 value.get());
185}
186
188{
189 this->assert_current_param_type(ParamType::ForSingleInput(varray.type()), expected_name);
190 BLI_assert(varray.size() >= min_array_size_);
191 actual_params_.append_unchecked_as(std::in_place_type<GVArray>, std::move(varray));
192}
193
195 StringRef expected_name)
196{
198 this->resource_scope().construct<GVVectorArray_For_GVectorArray>(vector_array),
199 expected_name);
200}
201
202inline void ParamsBuilder::add_readonly_vector_input(const GSpan single_vector,
203 StringRef expected_name)
204{
205 this->add_readonly_vector_input(this->resource_scope().construct<GVVectorArray_For_SingleGSpan>(
206 single_vector, min_array_size_),
207 expected_name);
208}
209
211 StringRef expected_name)
212{
213 this->assert_current_param_type(ParamType::ForVectorInput(ref.type()), expected_name);
214 BLI_assert(ref.size() >= min_array_size_);
215 actual_params_.append_unchecked_as(std::in_place_type<const GVVectorArray *>, &ref);
216}
217
218template<typename T>
220{
221 this->add_uninitialized_single_output(GMutableSpan(CPPType::get<T>(), value, 1), expected_name);
222}
223
225 StringRef expected_name)
226{
227 this->assert_current_param_type(ParamType::ForSingleOutput(ref.type()), expected_name);
228 BLI_assert(ref.size() >= min_array_size_);
229 actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
230}
231
233{
234 this->assert_current_param_name(expected_name);
235 const int param_index = this->current_param_index();
236 const ParamType &param_type = signature_->params[param_index].type;
238 const DataType data_type = param_type.data_type();
239 const CPPType &type = data_type.single_type();
240
241 if (bool(signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)) {
242 /* An empty span indicates that this is ignored. */
243 const GMutableSpan dummy_span{type};
244 actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, dummy_span);
245 }
246 else {
247 this->add_unused_output_for_unsupporting_function(type);
248 }
249}
250
251inline void ParamsBuilder::add_vector_output(GVectorArray &vector_array, StringRef expected_name)
252{
253 this->assert_current_param_type(ParamType::ForVectorOutput(vector_array.type()), expected_name);
254 BLI_assert(vector_array.size() >= min_array_size_);
255 actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
256}
257
259{
260 this->assert_current_param_type(ParamType::ForMutableSingle(ref.type()), expected_name);
261 BLI_assert(ref.size() >= min_array_size_);
262 actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
263}
264
265inline void ParamsBuilder::add_vector_mutable(GVectorArray &vector_array, StringRef expected_name)
266{
267 this->assert_current_param_type(ParamType::ForMutableVector(vector_array.type()), expected_name);
268 BLI_assert(vector_array.size() >= min_array_size_);
269 actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
270}
271
273{
274 return actual_params_.size();
275}
276
278{
279 BLI_assert(ELEM(signature_->params[param_index].type.category(),
282 return std::get<GMutableSpan>(actual_params_[param_index]);
283}
284
286{
287 BLI_assert(ELEM(signature_->params[param_index].type.category(),
290 return *std::get<GVectorArray *>(actual_params_[param_index]);
291}
292
293inline void ParamsBuilder::assert_current_param_type(ParamType param_type, StringRef expected_name)
294{
295 UNUSED_VARS_NDEBUG(param_type, expected_name);
296#ifndef NDEBUG
297 int param_index = this->current_param_index();
298
299 if (expected_name != "") {
300 StringRef actual_name = signature_->params[param_index].name;
301 BLI_assert(actual_name == expected_name);
302 }
303
304 ParamType expected_type = signature_->params[param_index].type;
305 BLI_assert(expected_type == param_type);
306#endif
307}
308
309inline void ParamsBuilder::assert_current_param_name(StringRef expected_name)
310{
311 UNUSED_VARS_NDEBUG(expected_name);
312#ifndef NDEBUG
313 if (expected_name.is_empty()) {
314 return;
315 }
316 const int param_index = this->current_param_index();
317 StringRef actual_name = signature_->params[param_index].name;
318 BLI_assert(actual_name == expected_name);
319#endif
320}
321
322inline int ParamsBuilder::current_param_index() const
323{
324 return actual_params_.size();
325}
326
327inline ResourceScope &ParamsBuilder::resource_scope()
328{
329 if (!scope_) {
330 scope_ = std::make_unique<ResourceScope>();
331 }
332 return *scope_;
333}
334
337/* -------------------------------------------------------------------- */
341template<typename T>
343{
344 const GVArray &varray = this->readonly_single_input(param_index, name);
345 return varray.typed<T>();
346}
347
348inline const GVArray &Params::readonly_single_input(int param_index, StringRef name)
349{
350 this->assert_correct_param(param_index, name, ParamCategory::SingleInput);
351 return std::get<GVArray>(builder_->actual_params_[param_index]);
352}
353
354inline bool Params::single_output_is_required(int param_index, StringRef name)
355{
356 this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
357 return !std::get<GMutableSpan>(builder_->actual_params_[param_index]).is_empty();
358}
359
360template<typename T>
362{
363 return this->uninitialized_single_output(param_index, name).typed<T>();
364}
365
367{
368 this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
370 !bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput));
371 GMutableSpan span = std::get<GMutableSpan>(builder_->actual_params_[param_index]);
372 BLI_assert(span.size() >= builder_->min_array_size_);
373 return span;
374}
375
376template<typename T>
378 StringRef name)
379{
380 return this->uninitialized_single_output_if_required(param_index, name).typed<T>();
381}
382
384 StringRef name)
385{
386 this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
388 bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput));
389 return std::get<GMutableSpan>(builder_->actual_params_[param_index]);
390}
391
392template<typename T>
393inline const VVectorArray<T> &Params::readonly_vector_input(int param_index, StringRef name)
394{
395 const GVVectorArray &vector_array = this->readonly_vector_input(param_index, name);
396 return builder_->resource_scope().construct<VVectorArray_For_GVVectorArray<T>>(vector_array);
397}
398
399inline const GVVectorArray &Params::readonly_vector_input(int param_index, StringRef name)
400{
401 this->assert_correct_param(param_index, name, ParamCategory::VectorInput);
402 return *std::get<const GVVectorArray *>(builder_->actual_params_[param_index]);
403}
404
405template<typename T>
407{
408 return {this->vector_output(param_index, name)};
409}
410
411inline GVectorArray &Params::vector_output(int param_index, StringRef name)
412{
413 this->assert_correct_param(param_index, name, ParamCategory::VectorOutput);
414 return *std::get<GVectorArray *>(builder_->actual_params_[param_index]);
415}
416
417template<typename T> inline MutableSpan<T> Params::single_mutable(int param_index, StringRef name)
418{
419 return this->single_mutable(param_index, name).typed<T>();
420}
421
422inline GMutableSpan Params::single_mutable(int param_index, StringRef name)
423{
424 this->assert_correct_param(param_index, name, ParamCategory::SingleMutable);
425 return std::get<GMutableSpan>(builder_->actual_params_[param_index]);
426}
427
428template<typename T>
430{
431 return {this->vector_mutable(param_index, name)};
432}
433
434inline GVectorArray &Params::vector_mutable(int param_index, StringRef name)
435{
436 this->assert_correct_param(param_index, name, ParamCategory::VectorMutable);
437 return *std::get<GVectorArray *>(builder_->actual_params_[param_index]);
438}
439
440inline void Params::assert_correct_param(int param_index, StringRef name, ParamType param_type)
441{
442 UNUSED_VARS_NDEBUG(param_index, name, param_type);
443#ifndef NDEBUG
444 BLI_assert(builder_->signature_->params[param_index].type == param_type);
445 if (name.size() > 0) {
446 BLI_assert(builder_->signature_->params[param_index].name == name);
447 }
448#endif
449}
450
451inline void Params::assert_correct_param(int param_index, StringRef name, ParamCategory category)
452{
453 UNUSED_VARS_NDEBUG(param_index, name, category);
454#ifndef NDEBUG
455 BLI_assert(builder_->signature_->params[param_index].type.category() == category);
456 if (name.size() > 0) {
457 BLI_assert(builder_->signature_->params[param_index].name == name);
458 }
459#endif
460}
461
464} // namespace blender::fn::multi_function
#define BLI_assert(a)
Definition BLI_assert.h:50
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
static const CPPType & get()
const CPPType & type() const
const CPPType & type() const
int64_t size() const
const CPPType & type() const
T & construct(Args &&...args)
constexpr bool is_empty() const
static ParamType ForVectorInput(const CPPType &base_type)
static ParamType ForSingleOutput(const CPPType &type)
static ParamType ForVectorOutput(const CPPType &base_type)
static ParamType ForMutableSingle(const CPPType &type)
static ParamType ForMutableVector(const CPPType &base_type)
static ParamType ForSingleInput(const CPPType &type)
void add_single_mutable(GMutableSpan ref, StringRef expected_name="")
GVectorArray & computed_vector_array(int param_index)
void add_ignored_single_output(StringRef expected_name="")
void add_uninitialized_single_output(T *value, StringRef expected_name="")
void add_vector_output(GVectorArray &vector_array, StringRef expected_name="")
void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name="")
ParamsBuilder(const class MultiFunction &fn, const IndexMask *mask)
void add_readonly_single_input(const T *value, StringRef expected_name="")
void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name="")
void add_readonly_single_input_value(T value, StringRef expected_name="")
MutableSpan< T > uninitialized_single_output_if_required(int param_index, StringRef name="")
const VVectorArray< T > & readonly_vector_input(int param_index, StringRef name="")
MutableSpan< T > uninitialized_single_output(int param_index, StringRef name="")
GVectorArray_TypedMutableRef< T > vector_mutable(int param_index, StringRef name="")
GVectorArray_TypedMutableRef< T > vector_output(int param_index, StringRef name="")
MutableSpan< T > single_mutable(int param_index, StringRef name="")
VArray< T > readonly_single_input(int param_index, StringRef name="")
bool single_output_is_required(int param_index, StringRef name="")
__int64 int64_t
Definition stdint.h:89