Blender V5.0
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
15
16#include <variant>
17
21#include "BLI_resource_scope.hh"
22
24
26
27class ParamsBuilder {
28 private:
29 std::unique_ptr<ResourceScope> scope_;
30 const Signature *signature_;
31 const IndexMask &mask_;
32 int64_t min_array_size_;
34 actual_params_;
35
36 friend class Params;
37
38 ParamsBuilder(const Signature &signature, const IndexMask &mask);
39
40 public:
46
47 template<typename T> void add_readonly_single_input_value(T value, StringRef expected_name = "");
48 template<typename T>
49 void add_readonly_single_input(const T *value, StringRef expected_name = "");
50 void add_readonly_single_input(const GSpan span, StringRef expected_name = "");
51 void add_readonly_single_input(GPointer value, StringRef expected_name = "");
52 void add_readonly_single_input(GVArray varray, StringRef expected_name = "");
53
54 void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "");
55 void add_readonly_vector_input(const GSpan single_vector, StringRef expected_name = "");
56 void add_readonly_vector_input(const GVVectorArray &ref, StringRef expected_name = "");
57
58 template<typename T>
59 void add_uninitialized_single_output(T *value, StringRef expected_name = "");
60 void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = "");
61
62 void add_ignored_single_output(StringRef expected_name = "");
63
64 void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "");
65
66 void add_single_mutable(GMutableSpan ref, StringRef expected_name = "");
67
68 void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = "");
69
70 int next_param_index() const;
71
72 GMutableSpan computed_array(int param_index);
73
74 GVectorArray &computed_vector_array(int param_index);
75
76 private:
77 void assert_current_param_type(ParamType param_type, StringRef expected_name = "");
78 void assert_current_param_name(StringRef expected_name);
79
80 int current_param_index() const;
81
82 ResourceScope &resource_scope();
83
84 void add_unused_output_for_unsupporting_function(const CPPType &type);
85};
86
87class Params {
88 private:
89 ParamsBuilder *builder_;
90
91 public:
92 Params(ParamsBuilder &builder) : builder_(&builder) {}
93
94 template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "");
95 const GVArray &readonly_single_input(int param_index, StringRef name = "");
96
103 bool single_output_is_required(int param_index, StringRef name = "");
104
105 template<typename T>
108
113 template<typename T>
116
117 template<typename T>
118 const VVectorArray<T> &readonly_vector_input(int param_index, StringRef name = "");
119 const GVVectorArray &readonly_vector_input(int param_index, StringRef name = "");
120
121 template<typename T>
123 GVectorArray &vector_output(int param_index, StringRef name = "");
124
125 template<typename T> MutableSpan<T> single_mutable(int param_index, StringRef name = "");
126 GMutableSpan single_mutable(int param_index, StringRef name = "");
127
128 template<typename T>
130 GVectorArray &vector_mutable(int param_index, StringRef name = "");
131
132 private:
133 void assert_correct_param(int param_index, StringRef name, ParamType param_type);
134 void assert_correct_param(int param_index, StringRef name, ParamCategory category);
135};
136
137/* -------------------------------------------------------------------- */
140
141inline ParamsBuilder::ParamsBuilder(const Signature &signature, const IndexMask &mask)
142 : signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size())
143{
144 actual_params_.reserve(signature.params.size());
145}
146
147template<typename T>
149{
150 this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get<T>()), expected_name);
151 actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
154 min_array_size_,
155 &value);
156}
157
158template<typename T>
159inline void ParamsBuilder::add_readonly_single_input(const T *value, StringRef expected_name)
160{
161 this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get<T>()), expected_name);
162 actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
165 min_array_size_,
166 value);
167}
168
169inline void ParamsBuilder::add_readonly_single_input(const GSpan span, StringRef expected_name)
170{
171 this->assert_current_param_type(ParamType::ForSingleInput(span.type()), expected_name);
172 BLI_assert(span.size() >= min_array_size_);
173 actual_params_.append_unchecked_as(std::in_place_type<GVArray>, varray_tag::span{}, span);
174}
175
177{
178 this->assert_current_param_type(ParamType::ForSingleInput(*value.type()), expected_name);
179 actual_params_.append_unchecked_as(std::in_place_type<GVArray>,
181 *value.type(),
182 min_array_size_,
183 value.get());
184}
185
187{
188 this->assert_current_param_type(ParamType::ForSingleInput(varray.type()), expected_name);
189 BLI_assert(varray.size() >= min_array_size_);
190 actual_params_.append_unchecked_as(std::in_place_type<GVArray>, std::move(varray));
191}
192
194 StringRef expected_name)
195{
197 this->resource_scope().construct<GVVectorArray_For_GVectorArray>(vector_array),
198 expected_name);
199}
200
201inline void ParamsBuilder::add_readonly_vector_input(const GSpan single_vector,
202 StringRef expected_name)
203{
204 this->add_readonly_vector_input(this->resource_scope().construct<GVVectorArray_For_SingleGSpan>(
205 single_vector, min_array_size_),
206 expected_name);
207}
208
210 StringRef expected_name)
211{
212 this->assert_current_param_type(ParamType::ForVectorInput(ref.type()), expected_name);
213 BLI_assert(ref.size() >= min_array_size_);
214 actual_params_.append_unchecked_as(std::in_place_type<const GVVectorArray *>, &ref);
215}
216
217template<typename T>
219{
220 this->add_uninitialized_single_output(GMutableSpan(CPPType::get<T>(), value, 1), expected_name);
221}
222
224 StringRef expected_name)
225{
226 this->assert_current_param_type(ParamType::ForSingleOutput(ref.type()), expected_name);
227 BLI_assert(ref.size() >= min_array_size_);
228 actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
229}
230
232{
233 this->assert_current_param_name(expected_name);
234 const int param_index = this->current_param_index();
235 const ParamType &param_type = signature_->params[param_index].type;
237 const DataType data_type = param_type.data_type();
238 const CPPType &type = data_type.single_type();
239
240 if (bool(signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)) {
241 /* An empty span indicates that this is ignored. */
242 const GMutableSpan dummy_span{type};
243 actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, dummy_span);
244 }
245 else {
246 this->add_unused_output_for_unsupporting_function(type);
247 }
248}
249
250inline void ParamsBuilder::add_vector_output(GVectorArray &vector_array, StringRef expected_name)
251{
252 this->assert_current_param_type(ParamType::ForVectorOutput(vector_array.type()), expected_name);
253 BLI_assert(vector_array.size() >= min_array_size_);
254 actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
255}
256
258{
259 this->assert_current_param_type(ParamType::ForMutableSingle(ref.type()), expected_name);
260 BLI_assert(ref.size() >= min_array_size_);
261 actual_params_.append_unchecked_as(std::in_place_type<GMutableSpan>, ref);
262}
263
264inline void ParamsBuilder::add_vector_mutable(GVectorArray &vector_array, StringRef expected_name)
265{
266 this->assert_current_param_type(ParamType::ForMutableVector(vector_array.type()), expected_name);
267 BLI_assert(vector_array.size() >= min_array_size_);
268 actual_params_.append_unchecked_as(std::in_place_type<GVectorArray *>, &vector_array);
269}
270
272{
273 return actual_params_.size();
274}
275
277{
278 BLI_assert(ELEM(signature_->params[param_index].type.category(),
281 return std::get<GMutableSpan>(actual_params_[param_index]);
282}
283
285{
286 BLI_assert(ELEM(signature_->params[param_index].type.category(),
289 return *std::get<GVectorArray *>(actual_params_[param_index]);
290}
291
292inline void ParamsBuilder::assert_current_param_type(ParamType param_type, StringRef expected_name)
293{
294 UNUSED_VARS_NDEBUG(param_type, expected_name);
295#ifndef NDEBUG
296 int param_index = this->current_param_index();
297
298 if (expected_name != "") {
299 StringRef actual_name = signature_->params[param_index].name;
300 BLI_assert(actual_name == expected_name);
301 }
302
303 ParamType expected_type = signature_->params[param_index].type;
304 BLI_assert(expected_type == param_type);
305#endif
306}
307
308inline void ParamsBuilder::assert_current_param_name(StringRef expected_name)
309{
310 UNUSED_VARS_NDEBUG(expected_name);
311#ifndef NDEBUG
312 if (expected_name.is_empty()) {
313 return;
314 }
315 const int param_index = this->current_param_index();
316 StringRef actual_name = signature_->params[param_index].name;
317 BLI_assert(actual_name == expected_name);
318#endif
319}
320
321inline int ParamsBuilder::current_param_index() const
322{
323 return actual_params_.size();
324}
325
326inline ResourceScope &ParamsBuilder::resource_scope()
327{
328 if (!scope_) {
329 scope_ = std::make_unique<ResourceScope>();
330 }
331 return *scope_;
332}
333
335
336/* -------------------------------------------------------------------- */
339
340template<typename T>
342{
343 const GVArray &varray = this->readonly_single_input(param_index, name);
344 return varray.typed<T>();
345}
346
348{
349 this->assert_correct_param(param_index, name, ParamCategory::SingleInput);
350 return std::get<GVArray>(builder_->actual_params_[param_index]);
351}
352
354{
355 this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
356 return !std::get<GMutableSpan>(builder_->actual_params_[param_index]).is_empty();
357}
358
359template<typename T>
361{
362 return this->uninitialized_single_output(param_index, name).typed<T>();
363}
364
366{
367 this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
369 !bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput));
370 GMutableSpan span = std::get<GMutableSpan>(builder_->actual_params_[param_index]);
371 BLI_assert(span.size() >= builder_->min_array_size_);
372 return span;
373}
374
375template<typename T>
378{
379 return this->uninitialized_single_output_if_required(param_index, name).typed<T>();
380}
381
384{
385 this->assert_correct_param(param_index, name, ParamCategory::SingleOutput);
387 bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput));
388 return std::get<GMutableSpan>(builder_->actual_params_[param_index]);
389}
390
391template<typename T>
393{
394 const GVVectorArray &vector_array = this->readonly_vector_input(param_index, name);
395 return builder_->resource_scope().construct<VVectorArray_For_GVVectorArray<T>>(vector_array);
396}
397
399{
400 this->assert_correct_param(param_index, name, ParamCategory::VectorInput);
401 return *std::get<const GVVectorArray *>(builder_->actual_params_[param_index]);
402}
403
404template<typename T>
406{
407 return {this->vector_output(param_index, name)};
408}
409
411{
412 this->assert_correct_param(param_index, name, ParamCategory::VectorOutput);
413 return *std::get<GVectorArray *>(builder_->actual_params_[param_index]);
414}
415
416template<typename T> inline MutableSpan<T> Params::single_mutable(int param_index, StringRef name)
417{
418 return this->single_mutable(param_index, name).typed<T>();
419}
420
422{
423 this->assert_correct_param(param_index, name, ParamCategory::SingleMutable);
424 return std::get<GMutableSpan>(builder_->actual_params_[param_index]);
425}
426
427template<typename T>
429{
430 return {this->vector_mutable(param_index, name)};
431}
432
434{
435 this->assert_correct_param(param_index, name, ParamCategory::VectorMutable);
436 return *std::get<GVectorArray *>(builder_->actual_params_[param_index]);
437}
438
439inline void Params::assert_correct_param(int param_index, StringRef name, ParamType param_type)
440{
441 UNUSED_VARS_NDEBUG(param_index, name, param_type);
442#ifndef NDEBUG
443 BLI_assert(builder_->signature_->params[param_index].type == param_type);
444 if (name.size() > 0) {
445 BLI_assert(builder_->signature_->params[param_index].name == name);
446 }
447#endif
448}
449
450inline void Params::assert_correct_param(int param_index, StringRef name, ParamCategory category)
451{
452 UNUSED_VARS_NDEBUG(param_index, name, category);
453#ifndef NDEBUG
454 BLI_assert(builder_->signature_->params[param_index].type.category() == category);
455 if (name.size() > 0) {
456 BLI_assert(builder_->signature_->params[param_index].name == name);
457 }
458#endif
459}
460
462
463} // namespace blender::fn::multi_function
#define BLI_assert(a)
Definition BLI_assert.h:46
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
long long int int64_t
static const CPPType & get()
const CPPType & type() const
const CPPType * type() const
const void * get() const
const CPPType & type() const
int64_t size() const
const CPPType & type() const
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="")
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define T
const char * name