diff --git a/source/blender/functions/FN_multi_function_data_type.hh b/source/blender/functions/FN_multi_function_data_type.hh index 60b545d97cd..5cc67233623 100644 --- a/source/blender/functions/FN_multi_function_data_type.hh +++ b/source/blender/functions/FN_multi_function_data_type.hh @@ -28,76 +28,105 @@ class DataType { Category category_; const CPPType *type_; - DataType(Category category, const CPPType &type) : category_(category), type_(&type) {} + DataType(Category category, const CPPType &type); public: DataType() = default; - static DataType ForSingle(const CPPType &type) - { - return DataType(Single, type); - } + static DataType ForSingle(const CPPType &type); + static DataType ForVector(const CPPType &type); - static DataType ForVector(const CPPType &type) - { - return DataType(Vector, type); - } + template static DataType ForSingle(); + template static DataType ForVector(); - template static DataType ForSingle() - { - return DataType::ForSingle(CPPType::get()); - } + bool is_single() const; + bool is_vector() const; - template static DataType ForVector() - { - return DataType::ForVector(CPPType::get()); - } + Category category() const; - bool is_single() const - { - return category_ == Single; - } - - bool is_vector() const - { - return category_ == Vector; - } - - Category category() const - { - return category_; - } - - const CPPType &single_type() const - { - BLI_assert(this->is_single()); - return *type_; - } - - const CPPType &vector_base_type() const - { - BLI_assert(this->is_vector()); - return *type_; - } + const CPPType &single_type() const; + const CPPType &vector_base_type() const; BLI_STRUCT_EQUALITY_OPERATORS_2(DataType, category_, type_) - std::string to_string() const - { - switch (category_) { - case Single: - return type_->name(); - case Vector: - return type_->name() + " Vector"; - } - BLI_assert(false); - return ""; - } + std::string to_string() const; - uint64_t hash() const - { - return get_default_hash(*type_, category_); - } + uint64_t hash() const; }; +/* -------------------------------------------------------------------- */ +/** \name #DataType Inline Methods + * \{ */ + +inline DataType::DataType(Category category, const CPPType &type) + : category_(category), type_(&type) +{ +} + +inline DataType DataType::ForSingle(const CPPType &type) +{ + return DataType(Single, type); +} + +inline DataType DataType::ForVector(const CPPType &type) +{ + return DataType(Vector, type); +} + +template inline DataType DataType::ForSingle() +{ + return DataType::ForSingle(CPPType::get()); +} + +template inline DataType DataType::ForVector() +{ + return DataType::ForVector(CPPType::get()); +} + +inline bool DataType::is_single() const +{ + return category_ == Single; +} + +inline bool DataType::is_vector() const +{ + return category_ == Vector; +} + +inline DataType::Category DataType::category() const +{ + return category_; +} + +inline const CPPType &DataType::single_type() const +{ + BLI_assert(this->is_single()); + return *type_; +} + +inline const CPPType &DataType::vector_base_type() const +{ + BLI_assert(this->is_vector()); + return *type_; +} + +inline std::string DataType::to_string() const +{ + switch (category_) { + case Single: + return type_->name(); + case Vector: + return type_->name() + " Vector"; + } + BLI_assert(false); + return ""; +} + +inline uint64_t DataType::hash() const +{ + return get_default_hash(*type_, category_); +} + +/** \} */ + } // namespace blender::fn::multi_function diff --git a/source/blender/functions/FN_multi_function_param_type.hh b/source/blender/functions/FN_multi_function_param_type.hh index 9f63e6bdb9e..54020f254ea 100644 --- a/source/blender/functions/FN_multi_function_param_type.hh +++ b/source/blender/functions/FN_multi_function_param_type.hh @@ -51,97 +51,120 @@ class ParamType { DataType data_type_; public: - ParamType(InterfaceType interface_type, DataType data_type) - : interface_type_(interface_type), data_type_(data_type) - { - } + ParamType(InterfaceType interface_type, DataType data_type); - static ParamType ForSingleInput(const CPPType &type) - { - return ParamType(InterfaceType::Input, DataType::ForSingle(type)); - } + static ParamType ForSingleInput(const CPPType &type); + 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 ForVectorInput(const CPPType &base_type) - { - return ParamType(InterfaceType::Input, DataType::ForVector(base_type)); - } + const DataType &data_type() const; + InterfaceType interface_type() const; + ParamCategory category() const; - static ParamType ForSingleOutput(const CPPType &type) - { - return ParamType(InterfaceType::Output, DataType::ForSingle(type)); - } - - static ParamType ForVectorOutput(const CPPType &base_type) - { - return ParamType(InterfaceType::Output, DataType::ForVector(base_type)); - } - - static ParamType ForMutableSingle(const CPPType &type) - { - return ParamType(InterfaceType::Mutable, DataType::ForSingle(type)); - } - - static ParamType ForMutableVector(const CPPType &base_type) - { - return ParamType(InterfaceType::Mutable, DataType::ForVector(base_type)); - } - - const DataType &data_type() const - { - return data_type_; - } - - InterfaceType interface_type() const - { - return interface_type_; - } - - ParamCategory category() const - { - switch (data_type_.category()) { - case DataType::Single: { - switch (interface_type_) { - case Input: - return ParamCategory::SingleInput; - case Output: - return ParamCategory::SingleOutput; - case Mutable: - return ParamCategory::SingleMutable; - } - break; - } - case DataType::Vector: { - switch (interface_type_) { - case Input: - return ParamCategory::VectorInput; - case Output: - return ParamCategory::VectorOutput; - case Mutable: - return ParamCategory::VectorMutable; - } - break; - } - } - BLI_assert_unreachable(); - return ParamCategory::SingleInput; - } - - bool is_input_or_mutable() const - { - return ELEM(interface_type_, Input, Mutable); - } - - bool is_output_or_mutable() const - { - return ELEM(interface_type_, Output, Mutable); - } - - bool is_output() const - { - return interface_type_ == Output; - } + bool is_input_or_mutable() const; + bool is_output_or_mutable() const; + bool is_output() const; BLI_STRUCT_EQUALITY_OPERATORS_2(ParamType, interface_type_, data_type_) }; +/* -------------------------------------------------------------------- */ +/** \name #ParamType Inline Methods + * \{ */ + +inline ParamType::ParamType(InterfaceType interface_type, DataType data_type) + : interface_type_(interface_type), data_type_(data_type) +{ +} + +inline ParamType ParamType::ForSingleInput(const CPPType &type) +{ + return ParamType(InterfaceType::Input, DataType::ForSingle(type)); +} + +inline ParamType ParamType::ForVectorInput(const CPPType &base_type) +{ + return ParamType(InterfaceType::Input, DataType::ForVector(base_type)); +} + +inline ParamType ParamType::ForSingleOutput(const CPPType &type) +{ + return ParamType(InterfaceType::Output, DataType::ForSingle(type)); +} + +inline ParamType ParamType::ForVectorOutput(const CPPType &base_type) +{ + return ParamType(InterfaceType::Output, DataType::ForVector(base_type)); +} + +inline ParamType ParamType::ForMutableSingle(const CPPType &type) +{ + return ParamType(InterfaceType::Mutable, DataType::ForSingle(type)); +} + +inline ParamType ParamType::ForMutableVector(const CPPType &base_type) +{ + return ParamType(InterfaceType::Mutable, DataType::ForVector(base_type)); +} + +inline const DataType &ParamType::data_type() const +{ + return data_type_; +} + +inline ParamType::InterfaceType ParamType::interface_type() const +{ + return interface_type_; +} + +inline ParamCategory ParamType::category() const +{ + switch (data_type_.category()) { + case DataType::Single: { + switch (interface_type_) { + case Input: + return ParamCategory::SingleInput; + case Output: + return ParamCategory::SingleOutput; + case Mutable: + return ParamCategory::SingleMutable; + } + break; + } + case DataType::Vector: { + switch (interface_type_) { + case Input: + return ParamCategory::VectorInput; + case Output: + return ParamCategory::VectorOutput; + case Mutable: + return ParamCategory::VectorMutable; + } + break; + } + } + BLI_assert_unreachable(); + return ParamCategory::SingleInput; +} + +inline bool ParamType::is_input_or_mutable() const +{ + return ELEM(interface_type_, Input, Mutable); +} + +inline bool ParamType::is_output_or_mutable() const +{ + return ELEM(interface_type_, Output, Mutable); +} + +inline bool ParamType::is_output() const +{ + return interface_type_ == Output; +} + +/** \} */ + } // namespace blender::fn::multi_function diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh index 6e30120bb5d..54f33175194 100644 --- a/source/blender/functions/FN_multi_function_params.hh +++ b/source/blender/functions/FN_multi_function_params.hh @@ -36,11 +36,7 @@ class ParamsBuilder { friend class Params; - ParamsBuilder(const Signature &signature, const IndexMask &mask) - : signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size()) - { - actual_params_.reserve(signature.params.size()); - } + ParamsBuilder(const Signature &signature, const IndexMask &mask); public: /** @@ -49,182 +45,42 @@ class ParamsBuilder { */ ParamsBuilder(const class MultiFunction &fn, const IndexMask *mask); - template void add_readonly_single_input_value(T value, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get()), expected_name); - actual_params_.append_unchecked_as(std::in_place_type, - varray_tag::single{}, - CPPType::get(), - min_array_size_, - &value); - } - template void add_readonly_single_input(const T *value, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get()), expected_name); - actual_params_.append_unchecked_as(std::in_place_type, - varray_tag::single_ref{}, - CPPType::get(), - min_array_size_, - value); - } - void add_readonly_single_input(const GSpan span, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForSingleInput(span.type()), expected_name); - BLI_assert(span.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, varray_tag::span{}, span); - } - void add_readonly_single_input(GPointer value, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForSingleInput(*value.type()), expected_name); - actual_params_.append_unchecked_as(std::in_place_type, - varray_tag::single_ref{}, - *value.type(), - min_array_size_, - value.get()); - } - void add_readonly_single_input(GVArray varray, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForSingleInput(varray.type()), expected_name); - BLI_assert(varray.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, std::move(varray)); - } + template void add_readonly_single_input_value(T value, StringRef expected_name = ""); + template + void add_readonly_single_input(const T *value, StringRef expected_name = ""); + void add_readonly_single_input(const GSpan span, StringRef expected_name = ""); + void add_readonly_single_input(GPointer value, StringRef expected_name = ""); + void add_readonly_single_input(GVArray varray, StringRef expected_name = ""); - void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "") - { - this->add_readonly_vector_input( - this->resource_scope().construct(vector_array), - expected_name); - } - void add_readonly_vector_input(const GSpan single_vector, StringRef expected_name = "") - { - this->add_readonly_vector_input( - this->resource_scope().construct(single_vector, - min_array_size_), - expected_name); - } - void add_readonly_vector_input(const GVVectorArray &ref, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForVectorInput(ref.type()), expected_name); - BLI_assert(ref.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, &ref); - } + void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = ""); + void add_readonly_vector_input(const GSpan single_vector, StringRef expected_name = ""); + void add_readonly_vector_input(const GVVectorArray &ref, StringRef expected_name = ""); - template void add_uninitialized_single_output(T *value, StringRef expected_name = "") - { - this->add_uninitialized_single_output(GMutableSpan(CPPType::get(), value, 1), - expected_name); - } - void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForSingleOutput(ref.type()), expected_name); - BLI_assert(ref.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, 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 ParamType ¶m_type = signature_->params[param_index].type; - BLI_assert(param_type.category() == ParamCategory::SingleOutput); - const DataType data_type = param_type.data_type(); - const CPPType &type = data_type.single_type(); + template + void add_uninitialized_single_output(T *value, StringRef expected_name = ""); + void add_uninitialized_single_output(GMutableSpan ref, StringRef expected_name = ""); - if (bool(signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)) { - /* An empty span indicates that this is ignored. */ - const GMutableSpan dummy_span{type}; - actual_params_.append_unchecked_as(std::in_place_type, dummy_span); - } - else { - this->add_unused_output_for_unsupporting_function(type); - } - } + void add_ignored_single_output(StringRef expected_name = ""); - void add_vector_output(GVectorArray &vector_array, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForVectorOutput(vector_array.type()), - expected_name); - BLI_assert(vector_array.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, &vector_array); - } + void add_vector_output(GVectorArray &vector_array, StringRef expected_name = ""); - void add_single_mutable(GMutableSpan ref, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForMutableSingle(ref.type()), expected_name); - BLI_assert(ref.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, ref); - } + void add_single_mutable(GMutableSpan ref, StringRef expected_name = ""); - void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = "") - { - this->assert_current_param_type(ParamType::ForMutableVector(vector_array.type()), - expected_name); - BLI_assert(vector_array.size() >= min_array_size_); - actual_params_.append_unchecked_as(std::in_place_type, &vector_array); - } + void add_vector_mutable(GVectorArray &vector_array, StringRef expected_name = ""); - int next_param_index() const - { - return actual_params_.size(); - } + int next_param_index() const; - GMutableSpan computed_array(int param_index) - { - BLI_assert(ELEM(signature_->params[param_index].type.category(), - ParamCategory::SingleOutput, - ParamCategory::SingleMutable)); - return std::get(actual_params_[param_index]); - } + GMutableSpan computed_array(int param_index); - GVectorArray &computed_vector_array(int param_index) - { - BLI_assert(ELEM(signature_->params[param_index].type.category(), - ParamCategory::VectorOutput, - ParamCategory::VectorMutable)); - return *std::get(actual_params_[param_index]); - } + GVectorArray &computed_vector_array(int param_index); private: - void assert_current_param_type(ParamType param_type, StringRef expected_name = "") - { - UNUSED_VARS_NDEBUG(param_type, expected_name); -#ifndef NDEBUG - int param_index = this->current_param_index(); + void assert_current_param_type(ParamType param_type, StringRef expected_name = ""); + void assert_current_param_name(StringRef expected_name); - if (expected_name != "") { - StringRef actual_name = signature_->params[param_index].name; - BLI_assert(actual_name == expected_name); - } + int current_param_index() const; - ParamType expected_type = signature_->params[param_index].type; - BLI_assert(expected_type == param_type); -#endif - } - - void assert_current_param_name(StringRef expected_name) - { - UNUSED_VARS_NDEBUG(expected_name); -#ifndef NDEBUG - if (expected_name.is_empty()) { - return; - } - const int param_index = this->current_param_index(); - StringRef actual_name = signature_->params[param_index].name; - BLI_assert(actual_name == expected_name); -#endif - } - - int current_param_index() const - { - return actual_params_.size(); - } - - ResourceScope &resource_scope() - { - if (!scope_) { - scope_ = std::make_unique(); - } - return *scope_; - } + ResourceScope &resource_scope(); void add_unused_output_for_unsupporting_function(const CPPType &type); }; @@ -236,16 +92,8 @@ class Params { public: Params(ParamsBuilder &builder) : builder_(&builder) {} - template VArray readonly_single_input(int param_index, StringRef name = "") - { - const GVArray &varray = this->readonly_single_input(param_index, name); - return varray.typed(); - } - const GVArray &readonly_single_input(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::SingleInput); - return std::get(builder_->actual_params_[param_index]); - } + template VArray readonly_single_input(int param_index, StringRef name = ""); + const GVArray &readonly_single_input(int param_index, StringRef name = ""); /** * \return True when the caller provided a buffer for this output parameter. This allows the @@ -253,110 +101,364 @@ class Params { * #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, ParamCategory::SingleOutput); - return !std::get(builder_->actual_params_[param_index]).is_empty(); - } + bool single_output_is_required(int param_index, StringRef name = ""); template - MutableSpan uninitialized_single_output(int param_index, StringRef name = "") - { - return this->uninitialized_single_output(param_index, name).typed(); - } - GMutableSpan uninitialized_single_output(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::SingleOutput); - BLI_assert( - !bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)); - GMutableSpan span = std::get(builder_->actual_params_[param_index]); - BLI_assert(span.size() >= builder_->min_array_size_); - return span; - } + MutableSpan uninitialized_single_output(int param_index, StringRef name = ""); + GMutableSpan uninitialized_single_output(int param_index, StringRef name = ""); /** * Same as #uninitialized_single_output, but returns an empty span when the output is not * required. */ template - MutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = "") - { - return this->uninitialized_single_output_if_required(param_index, name).typed(); - } - GMutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::SingleOutput); - BLI_assert( - bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)); - return std::get(builder_->actual_params_[param_index]); - } + MutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = ""); + GMutableSpan uninitialized_single_output_if_required(int param_index, StringRef name = ""); template - const VVectorArray &readonly_vector_input(int param_index, StringRef name = "") - { - const GVVectorArray &vector_array = this->readonly_vector_input(param_index, name); - return builder_->resource_scope().construct>(vector_array); - } - const GVVectorArray &readonly_vector_input(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::VectorInput); - return *std::get(builder_->actual_params_[param_index]); - } + const VVectorArray &readonly_vector_input(int param_index, StringRef name = ""); + const GVVectorArray &readonly_vector_input(int param_index, StringRef name = ""); template - GVectorArray_TypedMutableRef vector_output(int param_index, StringRef name = "") - { - return {this->vector_output(param_index, name)}; - } - GVectorArray &vector_output(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::VectorOutput); - return *std::get(builder_->actual_params_[param_index]); - } + GVectorArray_TypedMutableRef vector_output(int param_index, StringRef name = ""); + GVectorArray &vector_output(int param_index, StringRef name = ""); - template MutableSpan single_mutable(int param_index, StringRef name = "") - { - return this->single_mutable(param_index, name).typed(); - } - GMutableSpan single_mutable(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::SingleMutable); - return std::get(builder_->actual_params_[param_index]); - } + template MutableSpan single_mutable(int param_index, StringRef name = ""); + GMutableSpan single_mutable(int param_index, StringRef name = ""); template - GVectorArray_TypedMutableRef vector_mutable(int param_index, StringRef name = "") - { - return {this->vector_mutable(param_index, name)}; - } - GVectorArray &vector_mutable(int param_index, StringRef name = "") - { - this->assert_correct_param(param_index, name, ParamCategory::VectorMutable); - return *std::get(builder_->actual_params_[param_index]); - } + GVectorArray_TypedMutableRef vector_mutable(int param_index, StringRef name = ""); + GVectorArray &vector_mutable(int param_index, StringRef name = ""); private: - void assert_correct_param(int param_index, StringRef name, ParamType param_type) - { - UNUSED_VARS_NDEBUG(param_index, name, param_type); -#ifndef NDEBUG - BLI_assert(builder_->signature_->params[param_index].type == param_type); - if (name.size() > 0) { - BLI_assert(builder_->signature_->params[param_index].name == name); - } -#endif - } - - void assert_correct_param(int param_index, StringRef name, ParamCategory category) - { - UNUSED_VARS_NDEBUG(param_index, name, category); -#ifndef NDEBUG - BLI_assert(builder_->signature_->params[param_index].type.category() == category); - if (name.size() > 0) { - BLI_assert(builder_->signature_->params[param_index].name == name); - } -#endif - } + void assert_correct_param(int param_index, StringRef name, ParamType param_type); + void assert_correct_param(int param_index, StringRef name, ParamCategory category); }; +/* -------------------------------------------------------------------- */ +/** \name #Paramsbuilder Inline Methods + * \{ */ + +inline ParamsBuilder::ParamsBuilder(const Signature &signature, const IndexMask &mask) + : signature_(&signature), mask_(mask), min_array_size_(mask.min_array_size()) +{ + actual_params_.reserve(signature.params.size()); +} + +template +inline void ParamsBuilder::add_readonly_single_input_value(T value, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get()), expected_name); + actual_params_.append_unchecked_as(std::in_place_type, + varray_tag::single{}, + CPPType::get(), + min_array_size_, + &value); +} + +template +inline void ParamsBuilder::add_readonly_single_input(const T *value, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForSingleInput(CPPType::get()), expected_name); + actual_params_.append_unchecked_as(std::in_place_type, + varray_tag::single_ref{}, + CPPType::get(), + min_array_size_, + value); +} + +inline void ParamsBuilder::add_readonly_single_input(const GSpan span, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForSingleInput(span.type()), expected_name); + BLI_assert(span.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, varray_tag::span{}, span); +} + +inline void ParamsBuilder::add_readonly_single_input(GPointer value, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForSingleInput(*value.type()), expected_name); + actual_params_.append_unchecked_as(std::in_place_type, + varray_tag::single_ref{}, + *value.type(), + min_array_size_, + value.get()); +} + +inline void ParamsBuilder::add_readonly_single_input(GVArray varray, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForSingleInput(varray.type()), expected_name); + BLI_assert(varray.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, std::move(varray)); +} + +inline void ParamsBuilder::add_readonly_vector_input(const GVectorArray &vector_array, + StringRef expected_name) +{ + this->add_readonly_vector_input( + this->resource_scope().construct(vector_array), + expected_name); +} + +inline void ParamsBuilder::add_readonly_vector_input(const GSpan single_vector, + StringRef expected_name) +{ + this->add_readonly_vector_input(this->resource_scope().construct( + single_vector, min_array_size_), + expected_name); +} + +inline void ParamsBuilder::add_readonly_vector_input(const GVVectorArray &ref, + StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForVectorInput(ref.type()), expected_name); + BLI_assert(ref.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, &ref); +} + +template +inline void ParamsBuilder::add_uninitialized_single_output(T *value, StringRef expected_name) +{ + this->add_uninitialized_single_output(GMutableSpan(CPPType::get(), value, 1), expected_name); +} + +inline void ParamsBuilder::add_uninitialized_single_output(GMutableSpan ref, + StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForSingleOutput(ref.type()), expected_name); + BLI_assert(ref.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, ref); +} + +inline void ParamsBuilder::add_ignored_single_output(StringRef expected_name) +{ + this->assert_current_param_name(expected_name); + const int param_index = this->current_param_index(); + const ParamType ¶m_type = signature_->params[param_index].type; + BLI_assert(param_type.category() == ParamCategory::SingleOutput); + const DataType data_type = param_type.data_type(); + const CPPType &type = data_type.single_type(); + + if (bool(signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)) { + /* An empty span indicates that this is ignored. */ + const GMutableSpan dummy_span{type}; + actual_params_.append_unchecked_as(std::in_place_type, dummy_span); + } + else { + this->add_unused_output_for_unsupporting_function(type); + } +} + +inline void ParamsBuilder::add_vector_output(GVectorArray &vector_array, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForVectorOutput(vector_array.type()), expected_name); + BLI_assert(vector_array.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, &vector_array); +} + +inline void ParamsBuilder::add_single_mutable(GMutableSpan ref, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForMutableSingle(ref.type()), expected_name); + BLI_assert(ref.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, ref); +} + +inline void ParamsBuilder::add_vector_mutable(GVectorArray &vector_array, StringRef expected_name) +{ + this->assert_current_param_type(ParamType::ForMutableVector(vector_array.type()), expected_name); + BLI_assert(vector_array.size() >= min_array_size_); + actual_params_.append_unchecked_as(std::in_place_type, &vector_array); +} + +inline int ParamsBuilder::next_param_index() const +{ + return actual_params_.size(); +} + +inline GMutableSpan ParamsBuilder::computed_array(int param_index) +{ + BLI_assert(ELEM(signature_->params[param_index].type.category(), + ParamCategory::SingleOutput, + ParamCategory::SingleMutable)); + return std::get(actual_params_[param_index]); +} + +inline GVectorArray &ParamsBuilder::computed_vector_array(int param_index) +{ + BLI_assert(ELEM(signature_->params[param_index].type.category(), + ParamCategory::VectorOutput, + ParamCategory::VectorMutable)); + return *std::get(actual_params_[param_index]); +} + +inline void ParamsBuilder::assert_current_param_type(ParamType param_type, StringRef expected_name) +{ + UNUSED_VARS_NDEBUG(param_type, expected_name); +#ifndef NDEBUG + int param_index = this->current_param_index(); + + if (expected_name != "") { + StringRef actual_name = signature_->params[param_index].name; + BLI_assert(actual_name == expected_name); + } + + ParamType expected_type = signature_->params[param_index].type; + BLI_assert(expected_type == param_type); +#endif +} + +inline void ParamsBuilder::assert_current_param_name(StringRef expected_name) +{ + UNUSED_VARS_NDEBUG(expected_name); +#ifndef NDEBUG + if (expected_name.is_empty()) { + return; + } + const int param_index = this->current_param_index(); + StringRef actual_name = signature_->params[param_index].name; + BLI_assert(actual_name == expected_name); +#endif +} + +inline int ParamsBuilder::current_param_index() const +{ + return actual_params_.size(); +} + +inline ResourceScope &ParamsBuilder::resource_scope() +{ + if (!scope_) { + scope_ = std::make_unique(); + } + return *scope_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #Params Inline Methods + * \{ */ + +template +inline VArray Params::readonly_single_input(int param_index, StringRef name) +{ + const GVArray &varray = this->readonly_single_input(param_index, name); + return varray.typed(); +} + +inline const GVArray &Params::readonly_single_input(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::SingleInput); + return std::get(builder_->actual_params_[param_index]); +} + +inline bool Params::single_output_is_required(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::SingleOutput); + return !std::get(builder_->actual_params_[param_index]).is_empty(); +} + +template +inline MutableSpan Params::uninitialized_single_output(int param_index, StringRef name) +{ + return this->uninitialized_single_output(param_index, name).typed(); +} + +inline GMutableSpan Params::uninitialized_single_output(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::SingleOutput); + BLI_assert( + !bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)); + GMutableSpan span = std::get(builder_->actual_params_[param_index]); + BLI_assert(span.size() >= builder_->min_array_size_); + return span; +} + +template +inline MutableSpan Params::uninitialized_single_output_if_required(int param_index, + StringRef name) +{ + return this->uninitialized_single_output_if_required(param_index, name).typed(); +} + +inline GMutableSpan Params::uninitialized_single_output_if_required(int param_index, + StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::SingleOutput); + BLI_assert( + bool(builder_->signature_->params[param_index].flag & ParamFlag::SupportsUnusedOutput)); + return std::get(builder_->actual_params_[param_index]); +} + +template +inline const VVectorArray &Params::readonly_vector_input(int param_index, StringRef name) +{ + const GVVectorArray &vector_array = this->readonly_vector_input(param_index, name); + return builder_->resource_scope().construct>(vector_array); +} + +inline const GVVectorArray &Params::readonly_vector_input(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::VectorInput); + return *std::get(builder_->actual_params_[param_index]); +} + +template +inline GVectorArray_TypedMutableRef Params::vector_output(int param_index, StringRef name) +{ + return {this->vector_output(param_index, name)}; +} + +inline GVectorArray &Params::vector_output(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::VectorOutput); + return *std::get(builder_->actual_params_[param_index]); +} + +template inline MutableSpan Params::single_mutable(int param_index, StringRef name) +{ + return this->single_mutable(param_index, name).typed(); +} + +inline GMutableSpan Params::single_mutable(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::SingleMutable); + return std::get(builder_->actual_params_[param_index]); +} + +template +inline GVectorArray_TypedMutableRef Params::vector_mutable(int param_index, StringRef name) +{ + return {this->vector_mutable(param_index, name)}; +} + +inline GVectorArray &Params::vector_mutable(int param_index, StringRef name) +{ + this->assert_correct_param(param_index, name, ParamCategory::VectorMutable); + return *std::get(builder_->actual_params_[param_index]); +} + +inline void Params::assert_correct_param(int param_index, StringRef name, ParamType param_type) +{ + UNUSED_VARS_NDEBUG(param_index, name, param_type); +#ifndef NDEBUG + BLI_assert(builder_->signature_->params[param_index].type == param_type); + if (name.size() > 0) { + BLI_assert(builder_->signature_->params[param_index].name == name); + } +#endif +} + +inline void Params::assert_correct_param(int param_index, StringRef name, ParamCategory category) +{ + UNUSED_VARS_NDEBUG(param_index, name, category); +#ifndef NDEBUG + BLI_assert(builder_->signature_->params[param_index].type.category() == category); + if (name.size() > 0) { + BLI_assert(builder_->signature_->params[param_index].name == name); + } +#endif +} + +/** \} */ + } // namespace blender::fn::multi_function diff --git a/source/blender/functions/FN_multi_function_signature.hh b/source/blender/functions/FN_multi_function_signature.hh index ef93371724d..1efbc8c8dc2 100644 --- a/source/blender/functions/FN_multi_function_signature.hh +++ b/source/blender/functions/FN_multi_function_signature.hh @@ -51,123 +51,175 @@ class SignatureBuilder { Signature &signature_; public: - SignatureBuilder(const char *function_name, Signature &signature_to_build) - : signature_(signature_to_build) - { - signature_.function_name = function_name; - } + SignatureBuilder(const char *function_name, Signature &signature_to_build); /* Input Parameter Types */ - template void single_input(const char *name) - { - this->single_input(name, CPPType::get()); - } - void single_input(const char *name, const CPPType &type) - { - this->input(name, DataType::ForSingle(type)); - } - template void vector_input(const char *name) - { - this->vector_input(name, CPPType::get()); - } - void vector_input(const char *name, const CPPType &base_type) - { - this->input(name, DataType::ForVector(base_type)); - } - void input(const char *name, DataType data_type) - { - signature_.params.append({ParamType(ParamType::Input, data_type), name}); - } + template void single_input(const char *name); + void single_input(const char *name, const CPPType &type); + template void vector_input(const char *name); + void vector_input(const char *name, const CPPType &base_type); + void input(const char *name, DataType data_type); /* Output Parameter Types */ - template void single_output(const char *name, const ParamFlag flag = ParamFlag::None) - { - this->single_output(name, CPPType::get(), flag); - } - void single_output(const char *name, const CPPType &type, const ParamFlag flag = ParamFlag::None) - { - this->output(name, DataType::ForSingle(type), flag); - } - template void vector_output(const char *name, const ParamFlag flag = ParamFlag::None) - { - this->vector_output(name, CPPType::get(), flag); - } + template + void single_output(const char *name, const ParamFlag flag = ParamFlag::None); + void single_output(const char *name, + const CPPType &type, + const ParamFlag flag = ParamFlag::None); + template + void vector_output(const char *name, const ParamFlag flag = ParamFlag::None); void vector_output(const char *name, const CPPType &base_type, - const ParamFlag flag = ParamFlag::None) - { - this->output(name, DataType::ForVector(base_type), flag); - } - void output(const char *name, DataType data_type, const ParamFlag flag = ParamFlag::None) - { - signature_.params.append({ParamType(ParamType::Output, data_type), name, flag}); - } + const ParamFlag flag = ParamFlag::None); + void output(const char *name, DataType data_type, const ParamFlag flag = ParamFlag::None); /* Mutable Parameter Types */ - template void single_mutable(const char *name) - { - this->single_mutable(name, CPPType::get()); - } - void single_mutable(const char *name, const CPPType &type) - { - this->mutable_(name, DataType::ForSingle(type)); - } - template void vector_mutable(const char *name) - { - this->vector_mutable(name, CPPType::get()); - } - void vector_mutable(const char *name, const CPPType &base_type) - { - this->mutable_(name, DataType::ForVector(base_type)); - } - void mutable_(const char *name, DataType data_type) - { - signature_.params.append({ParamType(ParamType::Mutable, data_type), name}); - } - - void add(const char *name, const ParamType ¶m_type) - { - switch (param_type.interface_type()) { - case ParamType::Input: - this->input(name, param_type.data_type()); - break; - case ParamType::Mutable: - this->mutable_(name, param_type.data_type()); - break; - case ParamType::Output: - this->output(name, param_type.data_type()); - break; - } - } + template void single_mutable(const char *name); + void single_mutable(const char *name, const CPPType &type); + template void vector_mutable(const char *name); + void vector_mutable(const char *name, const CPPType &base_type); + void mutable_(const char *name, DataType data_type); template - void add(ParamTag /*tag*/, const char *name) - { - switch (Category) { - case ParamCategory::SingleInput: - this->single_input(name); - return; - case ParamCategory::VectorInput: - this->vector_input(name); - return; - case ParamCategory::SingleOutput: - this->single_output(name); - return; - case ParamCategory::VectorOutput: - this->vector_output(name); - return; - case ParamCategory::SingleMutable: - this->single_mutable(name); - return; - case ParamCategory::VectorMutable: - this->vector_mutable(name); - return; - } - BLI_assert_unreachable(); - } + void add(ParamTag /*tag*/, const char *name); + void add(const char *name, const ParamType ¶m_type); }; +/* -------------------------------------------------------------------- */ +/** \name #SignatureBuilder Inline Methods + * \{ */ + +inline SignatureBuilder::SignatureBuilder(const char *function_name, Signature &signature_to_build) + : signature_(signature_to_build) +{ + signature_.function_name = function_name; +} + +template inline void SignatureBuilder::single_input(const char *name) +{ + this->single_input(name, CPPType::get()); +} + +inline void SignatureBuilder::single_input(const char *name, const CPPType &type) +{ + this->input(name, DataType::ForSingle(type)); +} + +template inline void SignatureBuilder::vector_input(const char *name) +{ + this->vector_input(name, CPPType::get()); +} + +inline void SignatureBuilder::vector_input(const char *name, const CPPType &base_type) +{ + this->input(name, DataType::ForVector(base_type)); +} + +inline void SignatureBuilder::input(const char *name, DataType data_type) +{ + signature_.params.append({ParamType(ParamType::Input, data_type), name}); +} + +template +inline void SignatureBuilder::single_output(const char *name, const ParamFlag flag) +{ + this->single_output(name, CPPType::get(), flag); +} + +inline void SignatureBuilder::single_output(const char *name, + const CPPType &type, + const ParamFlag flag) +{ + this->output(name, DataType::ForSingle(type), flag); +} + +template +inline void SignatureBuilder::vector_output(const char *name, const ParamFlag flag) +{ + this->vector_output(name, CPPType::get(), flag); +} + +inline void SignatureBuilder::vector_output(const char *name, + const CPPType &base_type, + const ParamFlag flag) +{ + this->output(name, DataType::ForVector(base_type), flag); +} + +inline void SignatureBuilder::output(const char *name, DataType data_type, const ParamFlag flag) +{ + signature_.params.append({ParamType(ParamType::Output, data_type), name, flag}); +} + +template inline void SignatureBuilder::single_mutable(const char *name) +{ + this->single_mutable(name, CPPType::get()); +} + +inline void SignatureBuilder::single_mutable(const char *name, const CPPType &type) +{ + this->mutable_(name, DataType::ForSingle(type)); +} + +template inline void SignatureBuilder::vector_mutable(const char *name) +{ + this->vector_mutable(name, CPPType::get()); +} + +inline void SignatureBuilder::vector_mutable(const char *name, const CPPType &base_type) +{ + this->mutable_(name, DataType::ForVector(base_type)); +} + +inline void SignatureBuilder::mutable_(const char *name, DataType data_type) +{ + signature_.params.append({ParamType(ParamType::Mutable, data_type), name}); +} + +inline void SignatureBuilder::add(const char *name, const ParamType ¶m_type) +{ + switch (param_type.interface_type()) { + case ParamType::Input: + this->input(name, param_type.data_type()); + break; + case ParamType::Mutable: + this->mutable_(name, param_type.data_type()); + break; + case ParamType::Output: + this->output(name, param_type.data_type()); + break; + } +} + +template +inline void SignatureBuilder::add(ParamTag /*tag*/, const char *name) +{ + switch (Category) { + case ParamCategory::SingleInput: + this->single_input(name); + return; + case ParamCategory::VectorInput: + this->vector_input(name); + return; + case ParamCategory::SingleOutput: + this->single_output(name); + return; + case ParamCategory::VectorOutput: + this->vector_output(name); + return; + case ParamCategory::SingleMutable: + this->single_mutable(name); + return; + case ParamCategory::VectorMutable: + this->vector_mutable(name); + return; + } + BLI_assert_unreachable(); +} + +/** \} */ + } // namespace blender::fn::multi_function