diff options
97 files changed, 3378 insertions, 2272 deletions
diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index 6a87375e5e2..47f62b52a0f 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -115,10 +115,10 @@ struct AttributeInitDefault : public AttributeInit { * Note that this can be used to fill the new attribute with the default */ struct AttributeInitVArray : public AttributeInit { - const blender::fn::GVArray *varray; + blender::fn::GVArray varray; - AttributeInitVArray(const blender::fn::GVArray *varray) - : AttributeInit(Type::VArray), varray(varray) + AttributeInitVArray(blender::fn::GVArray varray) + : AttributeInit(Type::VArray), varray(std::move(varray)) { } }; @@ -150,9 +150,7 @@ namespace blender::bke { using fn::CPPType; using fn::GVArray; -using fn::GVArrayPtr; using fn::GVMutableArray; -using fn::GVMutableArrayPtr; const CPPType *custom_data_type_to_cpp_type(const CustomDataType type); CustomDataType cpp_type_to_custom_data_type(const CPPType &type); @@ -164,14 +162,14 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains) */ struct ReadAttributeLookup { /* The virtual array that is used to read from this attribute. */ - GVArrayPtr varray; + GVArray varray; /* Domain the attribute lives on in the geometry. */ AttributeDomain domain; /* Convenience function to check if the attribute has been found. */ operator bool() const { - return this->varray.get() != nullptr; + return this->varray; } }; @@ -180,7 +178,7 @@ struct ReadAttributeLookup { */ struct WriteAttributeLookup { /* The virtual array that is used to read from and write to the attribute. */ - GVMutableArrayPtr varray; + GVMutableArray varray; /* Domain the attributes lives on in the geometry. */ AttributeDomain domain; /* Call this after changing the attribute to invalidate caches that depend on this attribute. */ @@ -189,7 +187,7 @@ struct WriteAttributeLookup { /* Convenience function to check if the attribute has been found. */ operator bool() const { - return this->varray.get() != nullptr; + return this->varray; } }; @@ -209,7 +207,7 @@ class OutputAttribute { using SaveFn = std::function<void(OutputAttribute &)>; private: - GVMutableArrayPtr varray_; + GVMutableArray varray_; AttributeDomain domain_ = ATTR_DOMAIN_AUTO; SaveFn save_; std::unique_ptr<fn::GVMutableArray_GSpan> optional_span_varray_; @@ -219,7 +217,7 @@ class OutputAttribute { public: OutputAttribute(); OutputAttribute(OutputAttribute &&other); - OutputAttribute(GVMutableArrayPtr varray, + OutputAttribute(GVMutableArray varray, AttributeDomain domain, SaveFn save, const bool ignore_old_values); @@ -229,7 +227,7 @@ class OutputAttribute { operator bool() const; GVMutableArray &operator*(); - GVMutableArray *operator->(); + fn::GVMutableArray *operator->(); GVMutableArray &varray(); AttributeDomain domain() const; const CPPType &cpp_type() const; @@ -247,16 +245,14 @@ class OutputAttribute { template<typename T> class OutputAttribute_Typed { private: OutputAttribute attribute_; - std::unique_ptr<fn::GVMutableArray_Typed<T>> optional_varray_; - VMutableArray<T> *varray_ = nullptr; + VMutableArray<T> varray_; public: OutputAttribute_Typed(); OutputAttribute_Typed(OutputAttribute attribute) : attribute_(std::move(attribute)) { if (attribute_) { - optional_varray_ = std::make_unique<fn::GVMutableArray_Typed<T>>(attribute_.varray()); - varray_ = &**optional_varray_; + varray_ = attribute_.varray().template typed<T>(); } } @@ -275,22 +271,22 @@ template<typename T> class OutputAttribute_Typed { operator bool() const { - return varray_ != nullptr; + return varray_; } VMutableArray<T> &operator*() { - return *varray_; + return varray_; } VMutableArray<T> *operator->() { - return varray_; + return &varray_; } VMutableArray<T> &varray() { - return *varray_; + return varray_; } AttributeDomain domain() const @@ -351,18 +347,17 @@ class CustomDataAttributes { std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const; - blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id, - const CustomDataType data_type, - const void *default_value) const; + blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id, + const CustomDataType data_type, + const void *default_value) const; template<typename T> - blender::fn::GVArray_Typed<T> get_for_read(const AttributeIDRef &attribute_id, - const T &default_value) const + blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const { const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>(); const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type); - GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value); - return blender::fn::GVArray_Typed<T>(std::move(varray)); + GVArray varray = this->get_for_read(attribute_id, type, &default_value); + return varray.typed<T>(); } std::optional<blender::fn::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id); @@ -465,7 +460,7 @@ inline bool AttributeIDRef::should_be_kept() const inline OutputAttribute::OutputAttribute() = default; inline OutputAttribute::OutputAttribute(OutputAttribute &&other) = default; -inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray, +inline OutputAttribute::OutputAttribute(GVMutableArray varray, AttributeDomain domain, SaveFn save, const bool ignore_old_values) @@ -478,22 +473,22 @@ inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray, inline OutputAttribute::operator bool() const { - return varray_.get() != nullptr; + return varray_; } inline GVMutableArray &OutputAttribute::operator*() { - return *varray_; + return varray_; } -inline GVMutableArray *OutputAttribute::operator->() +inline fn::GVMutableArray *OutputAttribute::operator->() { - return varray_.get(); + return &varray_; } inline GVMutableArray &OutputAttribute::varray() { - return *varray_; + return varray_; } inline AttributeDomain OutputAttribute::domain() const @@ -503,7 +498,7 @@ inline AttributeDomain OutputAttribute::domain() const inline const CPPType &OutputAttribute::cpp_type() const { - return varray_->type(); + return varray_.type(); } inline CustomDataType OutputAttribute::custom_data_type() const diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 58a89d0207a..63ada807c55 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -119,10 +119,21 @@ class GeometryComponent { /* Get a read-only attribute for the domain based on the given attribute. This can be used to * interpolate from one domain to another. * Returns null if the interpolation is not implemented. */ - virtual std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain( - std::unique_ptr<blender::fn::GVArray> varray, - const AttributeDomain from_domain, - const AttributeDomain to_domain) const; + blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const + { + return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain); + } + + template<typename T> + blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const + { + return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain) + .template typed<T>(); + } /* Returns true when the attribute has been deleted. */ bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id); @@ -146,16 +157,15 @@ class GeometryComponent { /* Get a virtual array to read the data of an attribute on the given domain and data type. * Returns null when the attribute does not exist or cannot be converted to the requested domain * and data type. */ - std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read( - const blender::bke::AttributeIDRef &attribute_id, - const AttributeDomain domain, - const CustomDataType data_type) const; + blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + const AttributeDomain domain, + const CustomDataType data_type) const; /* Get a virtual array to read the data of an attribute on the given domain. The data type is * left unchanged. Returns null when the attribute does not exist or cannot be adapted to the * requested domain. */ - std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read( - const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const; + blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + const AttributeDomain domain) const; /* Get a virtual array to read data of an attribute with the given data type. The domain is * left unchanged. Returns null when the attribute does not exist or cannot be converted to the @@ -165,25 +175,22 @@ class GeometryComponent { /* Get a virtual array to read the data of an attribute. If that is not possible, the returned * virtual array will contain a default value. This never returns null. */ - std::unique_ptr<blender::fn::GVArray> attribute_get_for_read( - const blender::bke::AttributeIDRef &attribute_id, - const AttributeDomain domain, - const CustomDataType data_type, - const void *default_value = nullptr) const; + blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + const AttributeDomain domain, + const CustomDataType data_type, + const void *default_value = nullptr) const; /* Should be used instead of the method above when the requested data type is known at compile * time for better type safety. */ template<typename T> - blender::fn::GVArray_Typed<T> attribute_get_for_read( - const blender::bke::AttributeIDRef &attribute_id, - const AttributeDomain domain, - const T &default_value) const + blender::VArray<T> attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + const AttributeDomain domain, + const T &default_value) const { const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>(); const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type); - std::unique_ptr varray = this->attribute_get_for_read( - attribute_id, domain, type, &default_value); - return blender::fn::GVArray_Typed<T>(std::move(varray)); + return this->attribute_get_for_read(attribute_id, domain, type, &default_value) + .template typed<T>(); } /** @@ -234,6 +241,11 @@ class GeometryComponent { private: virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const; + + virtual blender::fn::GVArray attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const; }; template<typename T> @@ -391,10 +403,6 @@ class MeshComponent : public GeometryComponent { Mesh *get_for_write(); int attribute_domain_size(const AttributeDomain domain) const final; - std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain( - std::unique_ptr<blender::fn::GVArray> varray, - const AttributeDomain from_domain, - const AttributeDomain to_domain) const final; bool is_empty() const final; @@ -405,6 +413,11 @@ class MeshComponent : public GeometryComponent { private: const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final; + + blender::fn::GVArray attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const final; }; /** A geometry component that stores a point cloud. */ @@ -469,10 +482,6 @@ class CurveComponent : public GeometryComponent { CurveEval *get_for_write(); int attribute_domain_size(const AttributeDomain domain) const final; - std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain( - std::unique_ptr<blender::fn::GVArray> varray, - const AttributeDomain from_domain, - const AttributeDomain to_domain) const final; bool is_empty() const final; @@ -485,6 +494,11 @@ class CurveComponent : public GeometryComponent { private: const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final; + + blender::fn::GVArray attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const final; }; class InstanceReference { @@ -759,9 +773,9 @@ class AttributeFieldInput : public fn::FieldInput { return name_; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const override; + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const override; std::string socket_inspection_name() const override; @@ -776,9 +790,9 @@ class IDAttributeFieldInput : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const override; + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const override; std::string socket_inspection_name() const override; @@ -815,9 +829,9 @@ class AnonymousAttributeFieldInput : public fn::FieldInput { return fn::Field<T>{field_input}; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const override; + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const override; std::string socket_inspection_name() const override; diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 1d34768b1a2..c332e9a8dac 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -187,14 +187,14 @@ class Spline { blender::MutableSpan<T> dst) const { this->sample_with_index_factors( - blender::fn::GVArray_For_VArray(src), index_factors, blender::fn::GMutableSpan(dst)); + blender::fn::GVArray(src), index_factors, blender::fn::GMutableSpan(dst)); } template<typename T> void sample_with_index_factors(blender::Span<T> src, blender::Span<float> index_factors, blender::MutableSpan<T> dst) const { - this->sample_with_index_factors(blender::VArray_For_Span(src), index_factors, dst); + this->sample_with_index_factors(blender::VArray<T>::ForSpan(src), index_factors, dst); } /** @@ -202,13 +202,11 @@ class Spline { * evaluated points. For poly splines, the lifetime of the returned virtual array must not * exceed the lifetime of the input data. */ - virtual blender::fn::GVArrayPtr interpolate_to_evaluated( - const blender::fn::GVArray &src) const = 0; - blender::fn::GVArrayPtr interpolate_to_evaluated(blender::fn::GSpan data) const; - template<typename T> - blender::fn::GVArray_Typed<T> interpolate_to_evaluated(blender::Span<T> data) const + virtual blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const = 0; + blender::fn::GVArray interpolate_to_evaluated(blender::fn::GSpan data) const; + template<typename T> blender::VArray<T> interpolate_to_evaluated(blender::Span<T> data) const { - return blender::fn::GVArray_Typed<T>(this->interpolate_to_evaluated(blender::fn::GSpan(data))); + return this->interpolate_to_evaluated(blender::fn::GSpan(data)).typed<T>(); } protected: @@ -350,7 +348,7 @@ class BezierSpline final : public Spline { }; InterpolationData interpolation_data_from_index_factor(const float index_factor) const; - virtual blender::fn::GVArrayPtr interpolate_to_evaluated( + virtual blender::fn::GVArray interpolate_to_evaluated( const blender::fn::GVArray &src) const override; void evaluate_segment(const int index, @@ -487,7 +485,7 @@ class NURBSpline final : public Spline { blender::Span<blender::float3> evaluated_positions() const final; - blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final; + blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final; protected: void correct_end_tangents() const final; @@ -538,7 +536,7 @@ class PolySpline final : public Spline { blender::Span<blender::float3> evaluated_positions() const final; - blender::fn::GVArrayPtr interpolate_to_evaluated(const blender::fn::GVArray &src) const final; + blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final; protected: void correct_end_tangents() const final; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index cd394a4ca42..f3ece270618 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -50,9 +50,7 @@ using blender::bke::AttributeIDRef; using blender::bke::OutputAttribute; using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_For_SingleValue; -using blender::fn::GVMutableArray_For_GMutableSpan; +using blender::fn::GVMutableArrayImpl_For_GMutableSpan; namespace blender::bke { @@ -207,7 +205,7 @@ fn::GMutableSpan OutputAttribute::as_span() { if (!optional_span_varray_) { const bool materialize_old_values = !ignore_old_values_; - optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(*varray_, + optional_span_varray_ = std::make_unique<fn::GVMutableArray_GSpan>(varray_, materialize_old_values); } fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_; @@ -257,8 +255,8 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data if (data == nullptr) { return false; } - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray.materialize_to_uninitialized(varray.index_range(), data); return true; } case AttributeInit::Type::MoveArray: { @@ -313,8 +311,8 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr if (data == nullptr) { return false; } - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), data); + const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray.materialize_to_uninitialized(varray.index_range(), data); return true; } case AttributeInit::Type::MoveArray: { @@ -345,8 +343,7 @@ static bool custom_data_layer_matches_attribute_id(const CustomDataLayer &layer, return layer.name == attribute_id.name(); } -GVArrayPtr BuiltinCustomDataLayerProvider::try_get_for_read( - const GeometryComponent &component) const +GVArray BuiltinCustomDataLayerProvider::try_get_for_read(const GeometryComponent &component) const { const CustomData *custom_data = custom_data_access_.get_const_custom_data(component); if (custom_data == nullptr) { @@ -511,7 +508,7 @@ ReadAttributeLookup CustomDataAttributeProvider::try_get_for_read( continue; } GSpan data{*type, layer.data, domain_size}; - return {std::make_unique<GVArray_For_GSpan>(data), domain_}; + return {GVArray::ForSpan(data), domain_}; } return {}; } @@ -541,7 +538,7 @@ WriteAttributeLookup CustomDataAttributeProvider::try_get_for_write( continue; } GMutableSpan data{*type, layer.data, domain_size}; - return {std::make_unique<GVMutableArray_For_GMutableSpan>(data), domain_}; + return {GVMutableArray::ForSpan(data), domain_}; } return {}; } @@ -751,25 +748,25 @@ std::optional<GSpan> CustomDataAttributes::get_for_read(const AttributeIDRef &at * value if the attribute doesn't exist. If no default value is provided, the default value for the * type will be used. */ -GVArrayPtr CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id, - const CustomDataType data_type, - const void *default_value) const +GVArray CustomDataAttributes::get_for_read(const AttributeIDRef &attribute_id, + const CustomDataType data_type, + const void *default_value) const { const CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type); std::optional<GSpan> attribute = this->get_for_read(attribute_id); if (!attribute) { const int domain_size = this->size_; - return std::make_unique<GVArray_For_SingleValue>( + return GVArray::ForSingle( *type, domain_size, (default_value == nullptr) ? type->default_value() : default_value); } if (attribute->type() == *type) { - return std::make_unique<GVArray_For_GSpan>(*attribute); + return GVArray::ForSpan(*attribute); } const blender::nodes::DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions(); - return conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), *type); + return conversions.try_convert(GVArray::ForSpan(*attribute), *type); } std::optional<GMutableSpan> CustomDataAttributes::get_for_write(const AttributeIDRef &attribute_id) @@ -922,8 +919,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( return {}; } -std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_adapt_domain( - std::unique_ptr<blender::fn::GVArray> varray, +blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, const AttributeDomain from_domain, const AttributeDomain to_domain) const { @@ -1110,15 +1107,15 @@ std::optional<AttributeMetaData> GeometryComponent::attribute_get_meta_data( return result; } -static std::unique_ptr<blender::fn::GVArray> try_adapt_data_type( - std::unique_ptr<blender::fn::GVArray> varray, const blender::fn::CPPType &to_type) +static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray, + const blender::fn::CPPType &to_type) { const blender::nodes::DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions(); return conversions.try_convert(std::move(varray), to_type); } -std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_read( +blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( const AttributeIDRef &attribute_id, const AttributeDomain domain, const CustomDataType data_type) const @@ -1128,7 +1125,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r return {}; } - std::unique_ptr<blender::fn::GVArray> varray = std::move(attribute.varray); + blender::fn::GVArray varray = std::move(attribute.varray); if (!ELEM(domain, ATTR_DOMAIN_AUTO, attribute.domain)) { varray = this->attribute_try_adapt_domain(std::move(varray), attribute.domain, domain); if (!varray) { @@ -1138,7 +1135,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type); BLI_assert(cpp_type != nullptr); - if (varray->type() != *cpp_type) { + if (varray.type() != *cpp_type) { varray = try_adapt_data_type(std::move(varray), *cpp_type); if (!varray) { return {}; @@ -1148,7 +1145,7 @@ std::unique_ptr<blender::fn::GVArray> GeometryComponent::attribute_try_get_for_r return varray; } -std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_try_get_for_read( +blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( const AttributeIDRef &attribute_id, const AttributeDomain domain) const { if (!this->attribute_domain_supported(domain)) { @@ -1176,7 +1173,7 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( } const blender::fn::CPPType *type = blender::bke::custom_data_type_to_cpp_type(data_type); BLI_assert(type != nullptr); - if (attribute.varray->type() == *type) { + if (attribute.varray.type() == *type) { return attribute; } const blender::nodes::DataTypeConversions &conversions = @@ -1184,14 +1181,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain}; } -std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read( - const AttributeIDRef &attribute_id, - const AttributeDomain domain, - const CustomDataType data_type, - const void *default_value) const +blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id, + const AttributeDomain domain, + const CustomDataType data_type, + const void *default_value) const { - std::unique_ptr<blender::bke::GVArray> varray = this->attribute_try_get_for_read( - attribute_id, domain, data_type); + blender::fn::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type); if (varray) { return varray; } @@ -1200,11 +1195,11 @@ std::unique_ptr<blender::bke::GVArray> GeometryComponent::attribute_get_for_read default_value = type->default_value(); } const int domain_size = this->attribute_domain_size(domain); - return std::make_unique<blender::fn::GVArray_For_SingleValue>(*type, domain_size, default_value); + return blender::fn::GVArray::ForSingle(*type, domain_size, default_value); } class GVMutableAttribute_For_OutputAttribute - : public blender::fn::GVMutableArray_For_GMutableSpan { + : public blender::fn::GVMutableArrayImpl_For_GMutableSpan { public: GeometryComponent *component; std::string attribute_name; @@ -1213,7 +1208,7 @@ class GVMutableAttribute_For_OutputAttribute GVMutableAttribute_For_OutputAttribute(GMutableSpan data, GeometryComponent &component, const AttributeIDRef &attribute_id) - : blender::fn::GVMutableArray_For_GMutableSpan(data), component(&component) + : blender::fn::GVMutableArrayImpl_For_GMutableSpan(data), component(&component) { if (attribute_id.is_named()) { this->attribute_name = attribute_id.name(); @@ -1239,7 +1234,8 @@ static void save_output_attribute(OutputAttribute &output_attribute) using namespace blender::bke; GVMutableAttribute_For_OutputAttribute &varray = - dynamic_cast<GVMutableAttribute_For_OutputAttribute &>(output_attribute.varray()); + dynamic_cast<GVMutableAttribute_For_OutputAttribute &>( + *output_attribute.varray().get_implementation()); GeometryComponent &component = *varray.component; AttributeIDRef attribute_id; @@ -1267,7 +1263,7 @@ static void save_output_attribute(OutputAttribute &output_attribute) BUFFER_FOR_CPP_TYPE_VALUE(varray.type(), buffer); for (const int i : IndexRange(varray.size())) { varray.get(i, buffer); - write_attribute.varray->set_by_relocate(i, buffer); + write_attribute.varray.set_by_relocate(i, buffer); } if (write_attribute.tag_modified_fn) { write_attribute.tag_modified_fn(); @@ -1310,9 +1306,9 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, if (!attribute) { if (default_value) { const int64_t domain_size = component.attribute_domain_size(domain); - const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; - component.attribute_try_create_builtin(attribute_name, - AttributeInitVArray(&default_varray)); + component.attribute_try_create_builtin( + attribute_name, + AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value))); } else { component.attribute_try_create_builtin(attribute_name, AttributeInitDefault()); @@ -1327,9 +1323,8 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, /* Builtin attribute is on different domain. */ return {}; } - - GVMutableArrayPtr varray = std::move(attribute.varray); - if (varray->type() == *cpp_type) { + GVMutableArray varray = std::move(attribute.varray); + if (varray.type() == *cpp_type) { /* Builtin attribute matches exactly. */ return OutputAttribute(std::move(varray), domain, @@ -1349,9 +1344,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, WriteAttributeLookup attribute = component.attribute_try_get_for_write(attribute_id); if (!attribute) { if (default_value) { - const GVArray_For_SingleValueRef default_varray{*cpp_type, domain_size, default_value}; component.attribute_try_create( - attribute_id, domain, data_type, AttributeInitVArray(&default_varray)); + attribute_id, + domain, + data_type, + AttributeInitVArray(GVArray::ForSingleRef(*cpp_type, domain_size, default_value))); } else { component.attribute_try_create(attribute_id, domain, data_type, AttributeInitDefault()); @@ -1363,7 +1360,7 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, return {}; } } - if (attribute.domain == domain && attribute.varray->type() == *cpp_type) { + if (attribute.domain == domain && attribute.varray.type() == *cpp_type) { /* Existing generic attribute matches exactly. */ return OutputAttribute(std::move(attribute.varray), @@ -1382,11 +1379,11 @@ static OutputAttribute create_output_attribute(GeometryComponent &component, } else { /* Fill the temporary array with values from the existing attribute. */ - GVArrayPtr old_varray = component.attribute_get_for_read( + GVArray old_varray = component.attribute_get_for_read( attribute_id, domain, data_type, default_value); - old_varray->materialize_to_uninitialized(IndexRange(domain_size), data); + old_varray.materialize_to_uninitialized(IndexRange(domain_size), data); } - GVMutableArrayPtr varray = std::make_unique<GVMutableAttribute_For_OutputAttribute>( + GVMutableArray varray = GVMutableArray::For<GVMutableAttribute_For_OutputAttribute>( GMutableSpan{*cpp_type, data, domain_size}, component, attribute_id); return OutputAttribute(std::move(varray), domain, save_output_attribute, true); @@ -1410,21 +1407,21 @@ OutputAttribute GeometryComponent::attribute_try_get_for_output_only( namespace blender::bke { -const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, - IndexMask UNUSED(mask), - ResourceScope &scope) const +GVArray AttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &UNUSED(scope)) const { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); const CustomDataType data_type = cpp_type_to_custom_data_type(*type_); - GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type); + GVArray attribute = component.attribute_try_get_for_read(name_, domain, data_type); if (attribute) { - return scope.add(std::move(attribute)); + return attribute; } } - return nullptr; + return {}; } std::string AttributeFieldInput::socket_inspection_name() const @@ -1457,25 +1454,25 @@ static StringRef get_random_id_attribute_name(const AttributeDomain domain) } } -const GVArray *IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const +GVArray IDAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); const StringRef name = get_random_id_attribute_name(domain); - GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32); + GVArray attribute = component.attribute_try_get_for_read(name, domain, CD_PROP_INT32); if (attribute) { - BLI_assert(attribute->size() == component.attribute_domain_size(domain)); - return scope.add(std::move(attribute)); + BLI_assert(attribute.size() == component.attribute_domain_size(domain)); + return attribute; } /* Use the index as the fallback if no random ID attribute exists. */ return fn::IndexFieldInput::get_index_varray(mask, scope); } - return nullptr; + return {}; } std::string IDAttributeFieldInput::socket_inspection_name() const @@ -1495,19 +1492,20 @@ bool IDAttributeFieldInput::is_equal_to(const fn::FieldNode &other) const return dynamic_cast<const IDAttributeFieldInput *>(&other) != nullptr; } -const GVArray *AnonymousAttributeFieldInput::get_varray_for_context( - const fn::FieldContext &context, IndexMask UNUSED(mask), ResourceScope &scope) const +GVArray AnonymousAttributeFieldInput::get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &UNUSED(scope)) const { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); const CustomDataType data_type = cpp_type_to_custom_data_type(*type_); - GVArrayPtr attribute = component.attribute_try_get_for_read( + GVArray attribute = component.attribute_try_get_for_read( anonymous_id_.get(), domain, data_type); - return scope.add(std::move(attribute)); + return attribute; } - return nullptr; + return {}; } std::string AnonymousAttributeFieldInput::socket_inspection_name() const diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh index 140498bdb01..b77d7010efa 100644 --- a/source/blender/blenkernel/intern/attribute_access_intern.hh +++ b/source/blender/blenkernel/intern/attribute_access_intern.hh @@ -24,9 +24,6 @@ namespace blender::bke { -using fn::GVArrayPtr; -using fn::GVMutableArrayPtr; - /** * Utility to group together multiple functions that are used to access custom data on geometry * components in a generic way. @@ -86,7 +83,7 @@ class BuiltinAttributeProvider { { } - virtual GVArrayPtr try_get_for_read(const GeometryComponent &component) const = 0; + virtual GVArray try_get_for_read(const GeometryComponent &component) const = 0; virtual WriteAttributeLookup try_get_for_write(GeometryComponent &component) const = 0; virtual bool try_delete(GeometryComponent &component) const = 0; virtual bool try_create(GeometryComponent &UNUSED(component), @@ -188,8 +185,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider { */ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider { private: - using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size); - using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size); + using AsReadAttribute = GVArray (*)(const void *data, const int domain_size); + using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size); const AttributeDomain domain_; const CustomDataType attribute_type_; const CustomDataType stored_type_; @@ -232,8 +229,8 @@ class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider { * if the stored type is the same as the attribute type. */ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { - using AsReadAttribute = GVArrayPtr (*)(const void *data, const int domain_size); - using AsWriteAttribute = GVMutableArrayPtr (*)(void *data, const int domain_size); + using AsReadAttribute = GVArray (*)(const void *data, const int domain_size); + using AsWriteAttribute = GVMutableArray (*)(void *data, const int domain_size); using UpdateOnRead = void (*)(const GeometryComponent &component); using UpdateOnWrite = void (*)(GeometryComponent &component); const CustomDataType stored_type_; @@ -266,7 +263,7 @@ class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final; + GVArray try_get_for_read(const GeometryComponent &component) const final; WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final; bool try_delete(GeometryComponent &component) const final; bool try_create(GeometryComponent &component, const AttributeInit &initializer) const final; diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 1ef205c6903..03525e32a52 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -32,8 +32,6 @@ using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVArray_Typed; -using blender::fn::GVArrayPtr; namespace blender::bke { @@ -76,7 +74,7 @@ static void vert_extrude_to_mesh_data(const Spline &spline, Span<float3> positions = spline.evaluated_positions(); Span<float3> tangents = spline.evaluated_tangents(); Span<float3> normals = spline.evaluated_normals(); - GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii()); + VArray<float> radii = spline.interpolate_to_evaluated(spline.radii()); for (const int i : IndexRange(eval_size)) { float4x4 point_matrix = float4x4::from_normalized_axis_data( positions[i], normals[i], tangents[i]); @@ -227,7 +225,7 @@ static void spline_extrude_to_mesh_data(const ResultInfo &info, Span<float3> normals = spline.evaluated_normals(); Span<float3> profile_positions = profile.evaluated_positions(); - GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii()); + VArray<float> radii = spline.interpolate_to_evaluated(spline.radii()); for (const int i_ring : IndexRange(info.spline_vert_len)) { float4x4 point_matrix = float4x4::from_normalized_axis_data( positions[i_ring], normals[i_ring], tangents[i_ring]); @@ -495,8 +493,8 @@ static void copy_curve_point_attribute_to_mesh(const GSpan src, const ResultInfo &info, ResultAttributeData &dst) { - GVArrayPtr interpolated_gvarray = info.spline.interpolate_to_evaluated(src); - GSpan interpolated = interpolated_gvarray->get_internal_span(); + GVArray interpolated_gvarray = info.spline.interpolate_to_evaluated(src); + GSpan interpolated = interpolated_gvarray.get_internal_span(); attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); @@ -561,8 +559,8 @@ static void copy_profile_point_attribute_to_mesh(const GSpan src, const ResultInfo &info, ResultAttributeData &dst) { - GVArrayPtr interpolated_gvarray = info.profile.interpolate_to_evaluated(src); - GSpan interpolated = interpolated_gvarray->get_internal_span(); + GVArray interpolated_gvarray = info.profile.interpolate_to_evaluated(src); + GSpan interpolated = interpolated_gvarray.get_internal_span(); attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index d3c3fcc1e67..0b80ff5acdf 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -28,10 +28,8 @@ using blender::fn::GMutableSpan; using blender::fn::GSpan; -using blender::fn::GVArray_For_GSpan; +using blender::fn::GVArray; using blender::fn::GVArray_GSpan; -using blender::fn::GVArrayPtr; -using blender::fn::GVMutableArray_For_GMutableSpan; /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation @@ -253,15 +251,15 @@ void adapt_curve_domain_point_to_spline_impl(const CurveEval &curve, } } -static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArrayPtr varray) +static GVArray adapt_curve_domain_point_to_spline(const CurveEval &curve, GVArray varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(curve.splines().size()); - adapt_curve_domain_point_to_spline_impl<T>(curve, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_curve_domain_point_to_spline_impl<T>(curve, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -272,29 +270,29 @@ static GVArrayPtr adapt_curve_domain_point_to_spline(const CurveEval &curve, GVA * attributes. The goal is to avoid copying the spline value for every one of its control points * unless it is necessary (in that case the materialize functions will be called). */ -template<typename T> class VArray_For_SplineToPoint final : public VArray<T> { - GVArrayPtr original_varray_; +template<typename T> class VArray_For_SplineToPoint final : public VArrayImpl<T> { + GVArray original_varray_; /* Store existing data materialized if it was not already a span. This is expected * to be worth it because a single spline's value will likely be accessed many times. */ - fn::GVArray_Span<T> original_data_; + VArray_Span<T> original_data_; Array<int> offsets_; public: - VArray_For_SplineToPoint(GVArrayPtr original_varray, Array<int> offsets) - : VArray<T>(offsets.last()), + VArray_For_SplineToPoint(GVArray original_varray, Array<int> offsets) + : VArrayImpl<T>(offsets.last()), original_varray_(std::move(original_varray)), - original_data_(*original_varray_), + original_data_(original_varray_.typed<T>()), offsets_(std::move(offsets)) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return original_data_[indices.spline_index]; } - void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize(const IndexMask mask, MutableSpan<T> r_span) const final { const int total_size = offsets_.last(); if (mask.is_range() && mask.as_range() == IndexRange(total_size)) { @@ -315,7 +313,7 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> { } } - void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final { T *dst = r_span.data(); const int total_size = offsets_.last(); @@ -338,29 +336,29 @@ template<typename T> class VArray_For_SplineToPoint final : public VArray<T> { } }; -static GVArrayPtr adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArrayPtr varray) +static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArray varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); Array<int> offsets = curve.control_point_offsets(); - new_varray = std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplineToPoint<T>>>( - offsets.last(), std::move(varray), std::move(offsets)); + new_varray = VArray<T>::template For<VArray_For_SplineToPoint<T>>(std::move(varray), + std::move(offsets)); }); return new_varray; } } // namespace blender::bke -GVArrayPtr CurveComponent::attribute_try_adapt_domain(GVArrayPtr varray, - const AttributeDomain from_domain, - const AttributeDomain to_domain) const +GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const { if (!varray) { return {}; } - if (varray->size() == 0) { + if (varray.is_empty()) { return {}; } if (from_domain == to_domain) { @@ -402,8 +400,8 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen namespace blender::bke { class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider { - using AsReadAttribute = GVArrayPtr (*)(const CurveEval &data); - using AsWriteAttribute = GVMutableArrayPtr (*)(CurveEval &data); + using AsReadAttribute = GVArray (*)(const CurveEval &data); + using AsWriteAttribute = GVMutableArray (*)(CurveEval &data); const AsReadAttribute as_read_attribute_; const AsWriteAttribute as_write_attribute_; @@ -424,7 +422,7 @@ class BuiltinSplineAttributeProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr) { @@ -483,19 +481,15 @@ static void set_spline_resolution(SplinePtr &spline, const int resolution) } } -static GVArrayPtr make_resolution_read_attribute(const CurveEval &curve) +static GVArray make_resolution_read_attribute(const CurveEval &curve) { - return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, int, get_spline_resolution>>( - curve.splines()); + return VArray<int>::ForDerivedSpan<SplinePtr, get_spline_resolution>(curve.splines()); } -static GVMutableArrayPtr make_resolution_write_attribute(CurveEval &curve) +static GVMutableArray make_resolution_write_attribute(CurveEval &curve) { - return std::make_unique<fn::GVMutableArray_For_DerivedSpan<SplinePtr, - int, - get_spline_resolution, - set_spline_resolution>>( - curve.splines()); + return VMutableArray<int>:: + ForDerivedSpan<SplinePtr, get_spline_resolution, set_spline_resolution>(curve.splines()); } static bool get_cyclic_value(const SplinePtr &spline) @@ -511,16 +505,14 @@ static void set_cyclic_value(SplinePtr &spline, const bool value) } } -static GVArrayPtr make_cyclic_read_attribute(const CurveEval &curve) +static GVArray make_cyclic_read_attribute(const CurveEval &curve) { - return std::make_unique<fn::GVArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value>>( - curve.splines()); + return VArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value>(curve.splines()); } -static GVMutableArrayPtr make_cyclic_write_attribute(CurveEval &curve) +static GVMutableArray make_cyclic_write_attribute(CurveEval &curve) { - return std::make_unique< - fn::GVMutableArray_For_DerivedSpan<SplinePtr, bool, get_cyclic_value, set_cyclic_value>>( + return VMutableArray<bool>::ForDerivedSpan<SplinePtr, get_cyclic_value, set_cyclic_value>( curve.splines()); } @@ -623,9 +615,9 @@ static void point_attribute_materialize_to_uninitialized(Span<Span<T>> data, } } -static GVArrayPtr varray_from_initializer(const AttributeInit &initializer, - const CustomDataType data_type, - const Span<SplinePtr> splines) +static GVArray varray_from_initializer(const AttributeInit &initializer, + const CustomDataType data_type, + const Span<SplinePtr> splines) { switch (initializer.type) { case AttributeInit::Type::Default: @@ -634,16 +626,15 @@ static GVArrayPtr varray_from_initializer(const AttributeInit &initializer, BLI_assert_unreachable(); return {}; case AttributeInit::Type::VArray: - return static_cast<const AttributeInitVArray &>(initializer).varray->shallow_copy(); + return static_cast<const AttributeInitVArray &>(initializer).varray; case AttributeInit::Type::MoveArray: int total_size = 0; for (const SplinePtr &spline : splines) { total_size += spline->size(); } - return std::make_unique<fn::GVArray_For_GSpan>( - GSpan(*bke::custom_data_type_to_cpp_type(data_type), - static_cast<const AttributeInitMove &>(initializer).data, - total_size)); + return GVArray::ForSpan(GSpan(*bke::custom_data_type_to_cpp_type(data_type), + static_cast<const AttributeInitMove &>(initializer).data, + total_size)); } BLI_assert_unreachable(); return {}; @@ -691,11 +682,11 @@ static bool create_point_attribute(GeometryComponent &component, /* We just created the attribute, it should exist. */ BLI_assert(write_attribute); - GVArrayPtr source_varray = varray_from_initializer(initializer, data_type, splines); + GVArray source_varray = varray_from_initializer(initializer, data_type, splines); /* TODO: When we can call a variant of #set_all with a virtual array argument, * this theoretically unnecessary materialize step could be removed. */ - GVArray_GSpan source_varray_span{*source_varray}; - write_attribute.varray->set_all(source_varray_span.data()); + GVArray_GSpan source_varray_span{source_varray}; + write_attribute.varray.set_all(source_varray_span.data()); if (initializer.type == AttributeInit::Type::MoveArray) { MEM_freeN(static_cast<const AttributeInitMove &>(initializer).data); @@ -723,29 +714,29 @@ static bool remove_point_attribute(GeometryComponent &component, /** * Virtual array for any control point data accessed with spans and an offset array. */ -template<typename T> class VArray_For_SplinePoints : public VArray<T> { +template<typename T> class VArray_For_SplinePoints : public VArrayImpl<T> { private: const Array<Span<T>> data_; Array<int> offsets_; public: VArray_For_SplinePoints(Array<Span<T>> data, Array<int> offsets) - : VArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) + : VArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return data_[indices.spline_index][indices.point_index]; } - void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize(data_.as_span(), offsets_, mask, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span); } @@ -754,30 +745,30 @@ template<typename T> class VArray_For_SplinePoints : public VArray<T> { /** * Mutable virtual array for any control point data accessed with spans and an offset array. */ -template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArray<T> { +template<typename T> class VMutableArray_For_SplinePoints final : public VMutableArrayImpl<T> { private: Array<MutableSpan<T>> data_; Array<int> offsets_; public: VMutableArray_For_SplinePoints(Array<MutableSpan<T>> data, Array<int> offsets) - : VMutableArray<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) + : VMutableArrayImpl<T>(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return data_[indices.spline_index][indices.point_index]; } - void set_impl(const int64_t index, T value) final + void set(const int64_t index, T value) final { const PointIndices indices = lookup_point_indices(offsets_, index); data_[indices.spline_index][indices.point_index] = value; } - void set_all_impl(Span<T> src) final + void set_all(Span<T> src) final { for (const int spline_index : data_.index_range()) { const int offset = offsets_[spline_index]; @@ -786,30 +777,28 @@ template<typename T> class VMutableArray_For_SplinePoints final : public VMutabl } } - void materialize_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize({(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, MutableSpan<T> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<T> r_span) const final { point_attribute_materialize_to_uninitialized( {(Span<T> *)data_.data(), data_.size()}, offsets_, mask, r_span); } }; -template<typename T> GVArrayPtr point_data_gvarray(Array<Span<T>> spans, Array<int> offsets) +template<typename T> VArray<T> point_data_varray(Array<Span<T>> spans, Array<int> offsets) { - return std::make_unique<fn::GVArray_For_EmbeddedVArray<T, VArray_For_SplinePoints<T>>>( - offsets.last(), std::move(spans), std::move(offsets)); + return VArray<T>::template For<VArray_For_SplinePoints<T>>(std::move(spans), std::move(offsets)); } template<typename T> -GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> offsets) +VMutableArray<T> point_data_varray(Array<MutableSpan<T>> spans, Array<int> offsets) { - return std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_SplinePoints<T>>>( - offsets.last(), std::move(spans), std::move(offsets)); + return VMutableArray<T>::template For<VMutableArray_For_SplinePoints<T>>(std::move(spans), + std::move(offsets)); } /** @@ -820,24 +809,24 @@ GVMutableArrayPtr point_data_gvarray(Array<MutableSpan<T>> spans, Array<int> off * \note There is no need to check the handle type to avoid changing auto handles, since * retrieving write access to the position data will mark them for recomputation anyway. */ -class VMutableArray_For_SplinePosition final : public VMutableArray<float3> { +class VMutableArray_For_SplinePosition final : public VMutableArrayImpl<float3> { private: MutableSpan<SplinePtr> splines_; Array<int> offsets_; public: VMutableArray_For_SplinePosition(MutableSpan<SplinePtr> splines, Array<int> offsets) - : VMutableArray<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)) + : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)) { } - float3 get_impl(const int64_t index) const final + float3 get(const int64_t index) const final { const PointIndices indices = lookup_point_indices(offsets_, index); return splines_[indices.spline_index]->positions()[indices.point_index]; } - void set_impl(const int64_t index, float3 value) final + void set(const int64_t index, float3 value) final { const PointIndices indices = lookup_point_indices(offsets_, index); Spline &spline = *splines_[indices.spline_index]; @@ -852,7 +841,7 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> { } } - void set_all_impl(Span<float3> src) final + void set_all(Span<float3> src) final { for (const int spline_index : splines_.index_range()) { Spline &spline = *splines_[spline_index]; @@ -885,21 +874,20 @@ class VMutableArray_For_SplinePosition final : public VMutableArray<float3> { return spans; } - void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final + void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { Array<Span<float3>> spans = this->get_position_spans(); point_attribute_materialize(spans.as_span(), offsets_, mask, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, - MutableSpan<float3> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final { Array<Span<float3>> spans = this->get_position_spans(); point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span); } }; -class VArray_For_BezierHandle final : public VArray<float3> { +class VArray_For_BezierHandle final : public VArrayImpl<float3> { private: Span<SplinePtr> splines_; Array<int> offsets_; @@ -907,7 +895,7 @@ class VArray_For_BezierHandle final : public VArray<float3> { public: VArray_For_BezierHandle(Span<SplinePtr> splines, Array<int> offsets, const bool is_right) - : VArray<float3>(offsets.last()), + : VArrayImpl<float3>(offsets.last()), splines_(std::move(splines)), offsets_(std::move(offsets)), is_right_(is_right) @@ -929,7 +917,7 @@ class VArray_For_BezierHandle final : public VArray<float3> { return float3(0); } - float3 get_impl(const int64_t index) const final + float3 get(const int64_t index) const final { return get_internal(index, splines_, offsets_, is_right_); } @@ -976,19 +964,18 @@ class VArray_For_BezierHandle final : public VArray<float3> { point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span); } - void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final + void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { materialize_internal(mask, splines_, offsets_, is_right_, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, - MutableSpan<float3> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final { materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span); } }; -class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { +class VMutableArray_For_BezierHandles final : public VMutableArrayImpl<float3> { private: MutableSpan<SplinePtr> splines_; Array<int> offsets_; @@ -998,19 +985,19 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { VMutableArray_For_BezierHandles(MutableSpan<SplinePtr> splines, Array<int> offsets, const bool is_right) - : VMutableArray<float3>(offsets.last()), + : VMutableArrayImpl<float3>(offsets.last()), splines_(splines), offsets_(std::move(offsets)), is_right_(is_right) { } - float3 get_impl(const int64_t index) const final + float3 get(const int64_t index) const final { return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_); } - void set_impl(const int64_t index, float3 value) final + void set(const int64_t index, float3 value) final { const PointIndices indices = lookup_point_indices(offsets_, index); Spline &spline = *splines_[indices.spline_index]; @@ -1026,7 +1013,7 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { } } - void set_all_impl(Span<float3> src) final + void set_all(Span<float3> src) final { for (const int spline_index : splines_.index_range()) { Spline &spline = *splines_[spline_index]; @@ -1049,13 +1036,12 @@ class VMutableArray_For_BezierHandles final : public VMutableArray<float3> { } } - void materialize_impl(const IndexMask mask, MutableSpan<float3> r_span) const final + void materialize(const IndexMask mask, MutableSpan<float3> r_span) const final { VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span); } - void materialize_to_uninitialized_impl(const IndexMask mask, - MutableSpan<float3> r_span) const final + void materialize_to_uninitialized(const IndexMask mask, MutableSpan<float3> r_span) const final { VArray_For_BezierHandle::materialize_to_uninitialized_internal( mask, splines_, offsets_, is_right_, r_span); @@ -1097,7 +1083,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const override + GVArray try_get_for_read(const GeometryComponent &component) const override { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr) { @@ -1110,7 +1096,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu Span<SplinePtr> splines = curve->splines(); if (splines.size() == 1) { - return std::make_unique<fn::GVArray_For_GSpan>(get_span_(*splines.first())); + return GVArray::ForSpan(get_span_(*splines.first())); } Array<int> offsets = curve->control_point_offsets(); @@ -1119,7 +1105,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu spans[i] = get_span_(*splines[i]); } - return point_data_gvarray(spans, offsets); + return point_data_varray(spans, offsets); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override @@ -1144,8 +1130,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu MutableSpan<SplinePtr> splines = curve->splines(); if (splines.size() == 1) { - return {std::make_unique<fn::GVMutableArray_For_GMutableSpan>( - get_mutable_span_(*splines.first())), + return {GVMutableArray::ForSpan(get_mutable_span_(*splines.first())), domain_, std::move(tag_modified_fn)}; } @@ -1156,7 +1141,7 @@ template<typename T> class BuiltinPointAttributeProvider : public BuiltinAttribu spans[i] = get_mutable_span_(*splines[i]); } - return {point_data_gvarray(spans, offsets), domain_, tag_modified_fn}; + return {point_data_varray(spans, offsets), domain_, tag_modified_fn}; } bool try_delete(GeometryComponent &component) const final @@ -1248,10 +1233,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider<flo }; Array<int> offsets = curve->control_point_offsets(); - return {std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<float3, - VMutableArray_For_SplinePosition>>( - offsets.last(), curve->splines(), std::move(offsets)), + return {VMutableArray<float3>::For<VMutableArray_For_SplinePosition>(curve->splines(), + std::move(offsets)), domain_, tag_modified_fn}; } @@ -1273,7 +1256,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const override + GVArray try_get_for_read(const GeometryComponent &component) const override { const CurveEval *curve = get_curve_from_component_for_read(component); if (curve == nullptr) { @@ -1285,8 +1268,8 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { } Array<int> offsets = curve->control_point_offsets(); - return std::make_unique<fn::GVArray_For_EmbeddedVArray<float3, VArray_For_BezierHandle>>( - offsets.last(), curve->splines(), std::move(offsets), is_right_); + return VArray<float3>::For<VArray_For_BezierHandle>( + curve->splines(), std::move(offsets), is_right_); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override @@ -1303,12 +1286,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); }; Array<int> offsets = curve->control_point_offsets(); - return { - std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<float3, VMutableArray_For_BezierHandles>>( - offsets.last(), curve->splines(), std::move(offsets), is_right_), - domain_, - tag_modified_fn}; + return {VMutableArray<float3>::For<VMutableArray_For_BezierHandles>( + curve->splines(), std::move(offsets), is_right_), + domain_, + tag_modified_fn}; } bool try_delete(GeometryComponent &UNUSED(component)) const final @@ -1387,7 +1368,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* First check for the simpler situation when we can return a simpler span virtual array. */ if (spans.size() == 1) { - return {std::make_unique<GVArray_For_GSpan>(spans.first()), ATTR_DOMAIN_POINT}; + return {GVArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT}; } ReadAttributeLookup attribute = {}; @@ -1399,7 +1380,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { data[i] = spans[i].typed<T>(); BLI_assert(data[i].data() != nullptr); } - attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT}; + attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; }); return attribute; } @@ -1440,7 +1421,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { /* First check for the simpler situation when we can return a simpler span virtual array. */ if (spans.size() == 1) { - return {std::make_unique<GVMutableArray_For_GMutableSpan>(spans.first()), ATTR_DOMAIN_POINT}; + return {GVMutableArray::ForSpan(spans.first()), ATTR_DOMAIN_POINT}; } WriteAttributeLookup attribute = {}; @@ -1452,7 +1433,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { data[i] = spans[i].typed<T>(); BLI_assert(data[i].data() != nullptr); } - attribute = {point_data_gvarray(data, offsets), ATTR_DOMAIN_POINT}; + attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; }); return attribute; } diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc index 5fe77000519..047bceda4fe 100644 --- a/source/blender/blenkernel/intern/geometry_component_instances.cc +++ b/source/blender/blenkernel/intern/geometry_component_instances.cc @@ -389,25 +389,22 @@ class InstancePositionAttributeProvider final : public BuiltinAttributeProvider { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const InstancesComponent &instances_component = static_cast<const InstancesComponent &>( component); Span<float4x4> transforms = instances_component.instance_transforms(); - return std::make_unique<fn::GVArray_For_DerivedSpan<float4x4, float3, get_transform_position>>( - transforms); + return VArray<float3>::ForDerivedSpan<float4x4, get_transform_position>(transforms); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final { InstancesComponent &instances_component = static_cast<InstancesComponent &>(component); MutableSpan<float4x4> transforms = instances_component.instance_transforms(); - return { - std::make_unique<fn::GVMutableArray_For_DerivedSpan<float4x4, - float3, - get_transform_position, - set_transform_position>>(transforms), - domain_}; + return {VMutableArray<float3>::ForDerivedSpan<float4x4, + get_transform_position, + set_transform_position>(transforms), + domain_}; } bool try_delete(GeometryComponent &UNUSED(component)) const final @@ -435,13 +432,13 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const InstancesComponent &instances = static_cast<const InstancesComponent &>(component); if (instances.instance_ids().is_empty()) { return {}; } - return std::make_unique<fn::GVArray_For_Span<int>>(instances.instance_ids()); + return VArray<int>::ForSpan(instances.instance_ids()); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const final @@ -450,8 +447,7 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider { if (instances.instance_ids().is_empty()) { return {}; } - return {std::make_unique<fn::GVMutableArray_For_MutableSpan<int>>(instances.instance_ids()), - domain_}; + return {VMutableArray<int>::ForSpan(instances.instance_ids()), domain_}; } bool try_delete(GeometryComponent &component) const final @@ -477,8 +473,8 @@ class InstanceIDAttributeProvider final : public BuiltinAttributeProvider { break; } case AttributeInit::Type::VArray: { - const GVArray *varray = static_cast<const AttributeInitVArray &>(initializer).varray; - varray->materialize_to_uninitialized(IndexRange(varray->size()), ids.data()); + const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray; + varray.materialize_to_uninitialized(varray.index_range(), ids.data()); break; } case AttributeInit::Type::MoveArray: { diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index c3e39c0b2cb..86a52b420b6 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -32,8 +32,6 @@ /* Can't include BKE_object_deform.h right now, due to an enum forward declaration. */ extern "C" MDeformVert *BKE_object_defgroup_data_create(ID *id); -using blender::fn::GVArray; - /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation * \{ */ @@ -203,17 +201,17 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { /* We compute all interpolated values at once, because for this interpolation, one has to * iterate over all loops anyway. */ Array<T> values(mesh.totvert); - adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_corner_to_point_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -239,14 +237,14 @@ static void adapt_mesh_domain_point_to_corner_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_point_to_corner(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_point_to_corner(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); Array<T> values(mesh.totloop); - adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_point_to_corner_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); }); return new_varray; } @@ -295,15 +293,15 @@ void adapt_mesh_domain_corner_to_face_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_corner_to_face(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_corner_to_face(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totpoly); - adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_corner_to_face_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -368,15 +366,15 @@ void adapt_mesh_domain_corner_to_edge_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_corner_to_edge(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_corner_to_edge(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totedge); - adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_corner_to_edge_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -424,15 +422,15 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_face_to_point(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totvert); - adapt_mesh_domain_face_to_point_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_face_to_point_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -453,15 +451,15 @@ void adapt_mesh_domain_face_to_corner_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_face_to_corner(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_face_to_corner(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totloop); - adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_face_to_corner_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -507,15 +505,15 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_face_to_edge(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totedge); - adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_face_to_edge_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -567,15 +565,15 @@ void adapt_mesh_domain_point_to_face_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_point_to_face(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_point_to_face(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totpoly); - adapt_mesh_domain_point_to_face_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_point_to_face_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -617,15 +615,15 @@ void adapt_mesh_domain_point_to_edge_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_point_to_edge(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_point_to_edge(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totedge); - adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_point_to_edge_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -678,15 +676,15 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_edge_to_corner(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totloop); - adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_edge_to_corner_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -728,15 +726,15 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_edge_to_point(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totvert); - adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_edge_to_point_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -788,15 +786,15 @@ void adapt_mesh_domain_edge_to_face_impl(const Mesh &mesh, } } -static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr varray) +static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &varray) { - GVArrayPtr new_varray; - attribute_math::convert_to_static_type(varray->type(), [&](auto dummy) { + GVArray new_varray; + attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { Array<T> values(mesh.totpoly); - adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray->typed<T>(), values); - new_varray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + adapt_mesh_domain_edge_to_face_impl<T>(mesh, varray.typed<T>(), values); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); return new_varray; @@ -804,15 +802,15 @@ static GVArrayPtr adapt_mesh_domain_edge_to_face(const Mesh &mesh, GVArrayPtr va } // namespace blender::bke -blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( - blender::fn::GVArrayPtr varray, +blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl( + const blender::fn::GVArray &varray, const AttributeDomain from_domain, const AttributeDomain to_domain) const { if (!varray) { return {}; } - if (varray->size() == 0) { + if (varray.size() == 0) { return {}; } if (from_domain == to_domain) { @@ -823,11 +821,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_CORNER: { switch (to_domain) { case ATTR_DOMAIN_POINT: - return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, varray); case ATTR_DOMAIN_FACE: - return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_corner_to_face(*mesh_, varray); case ATTR_DOMAIN_EDGE: - return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_corner_to_edge(*mesh_, varray); default: break; } @@ -836,11 +834,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_POINT: { switch (to_domain) { case ATTR_DOMAIN_CORNER: - return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_point_to_corner(*mesh_, varray); case ATTR_DOMAIN_FACE: - return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_point_to_face(*mesh_, varray); case ATTR_DOMAIN_EDGE: - return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_point_to_edge(*mesh_, varray); default: break; } @@ -849,11 +847,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_FACE: { switch (to_domain) { case ATTR_DOMAIN_POINT: - return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_face_to_point(*mesh_, varray); case ATTR_DOMAIN_CORNER: - return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_face_to_corner(*mesh_, varray); case ATTR_DOMAIN_EDGE: - return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_face_to_edge(*mesh_, varray); default: break; } @@ -862,11 +860,11 @@ blender::fn::GVArrayPtr MeshComponent::attribute_try_adapt_domain( case ATTR_DOMAIN_EDGE: { switch (to_domain) { case ATTR_DOMAIN_CORNER: - return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_edge_to_corner(*mesh_, varray); case ATTR_DOMAIN_POINT: - return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_edge_to_point(*mesh_, varray); case ATTR_DOMAIN_FACE: - return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, std::move(varray)); + return blender::bke::adapt_mesh_domain_edge_to_face(*mesh_, varray); default: break; } @@ -896,9 +894,9 @@ static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &com namespace blender::bke { template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> -static GVArrayPtr make_derived_read_attribute(const void *data, const int domain_size) +static GVArray make_derived_read_attribute(const void *data, const int domain_size) { - return std::make_unique<fn::GVArray_For_DerivedSpan<StructT, ElemT, GetFunc>>( + return VArray<ElemT>::template ForDerivedSpan<StructT, GetFunc>( Span<StructT>((const StructT *)data, domain_size)); } @@ -906,23 +904,22 @@ template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, ElemT)> -static GVMutableArrayPtr make_derived_write_attribute(void *data, const int domain_size) +static GVMutableArray make_derived_write_attribute(void *data, const int domain_size) { - return std::make_unique<fn::GVMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>( + return VMutableArray<ElemT>::template ForDerivedSpan<StructT, GetFunc, SetFunc>( MutableSpan<StructT>((StructT *)data, domain_size)); } template<typename T> -static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size) +static GVArray make_array_read_attribute(const void *data, const int domain_size) { - return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size)); + return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size)); } template<typename T> -static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size) +static GVMutableArray make_array_write_attribute(void *data, const int domain_size) { - return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>( - MutableSpan<T>((T *)data, domain_size)); + return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size)); } static float3 get_vertex_position(const MVert &vert) @@ -999,23 +996,23 @@ static void set_crease(MEdge &edge, float value) edge.crease = round_fl_to_uchar_clamp(value * 255.0f); } -class VMutableArray_For_VertexWeights final : public VMutableArray<float> { +class VMutableArray_For_VertexWeights final : public VMutableArrayImpl<float> { private: MDeformVert *dverts_; const int dvert_index_; public: VMutableArray_For_VertexWeights(MDeformVert *dverts, const int totvert, const int dvert_index) - : VMutableArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) + : VMutableArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) { } - float get_impl(const int64_t index) const override + float get(const int64_t index) const override { return get_internal(dverts_, dvert_index_, index); } - void set_impl(const int64_t index, const float value) override + void set(const int64_t index, const float value) override { MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_); weight->weight = value; @@ -1036,18 +1033,18 @@ class VMutableArray_For_VertexWeights final : public VMutableArray<float> { } }; -class VArray_For_VertexWeights final : public VArray<float> { +class VArray_For_VertexWeights final : public VArrayImpl<float> { private: const MDeformVert *dverts_; const int dvert_index_; public: VArray_For_VertexWeights(const MDeformVert *dverts, const int totvert, const int dvert_index) - : VArray<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) + : VArrayImpl<float>(totvert), dverts_(dverts), dvert_index_(dvert_index) { } - float get_impl(const int64_t index) const override + float get(const int64_t index) const override { return VMutableArray_For_VertexWeights::get_internal(dverts_, dvert_index_, index); } @@ -1078,12 +1075,10 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { } if (mesh->dvert == nullptr) { static const float default_value = 0.0f; - return {std::make_unique<fn::GVArray_For_SingleValueRef>( - CPPType::get<float>(), mesh->totvert, &default_value), - ATTR_DOMAIN_POINT}; + return {VArray<float>::ForSingle(default_value, mesh->totvert), ATTR_DOMAIN_POINT}; } - return {std::make_unique<fn::GVArray_For_EmbeddedVArray<float, VArray_For_VertexWeights>>( - mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index), + return {VArray<float>::For<VArray_For_VertexWeights>( + mesh->dvert, mesh->totvert, vertex_group_index), ATTR_DOMAIN_POINT}; } @@ -1114,11 +1109,9 @@ class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer( &mesh->vdata, CD_MDEFORMVERT, mesh->totvert); } - return { - std::make_unique< - fn::GVMutableArray_For_EmbeddedVMutableArray<float, VMutableArray_For_VertexWeights>>( - mesh->totvert, mesh->dvert, mesh->totvert, vertex_group_index), - ATTR_DOMAIN_POINT}; + return {VMutableArray<float>::For<VMutableArray_For_VertexWeights>( + mesh->dvert, mesh->totvert, vertex_group_index), + ATTR_DOMAIN_POINT}; } bool try_delete(GeometryComponent &component, const AttributeIDRef &attribute_id) const final @@ -1184,7 +1177,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { { } - GVArrayPtr try_get_for_read(const GeometryComponent &component) const final + GVArray try_get_for_read(const GeometryComponent &component) const final { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); const Mesh *mesh = mesh_component.get_for_read(); @@ -1197,8 +1190,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { CustomData_has_layer(&mesh->pdata, CD_NORMAL)) { const void *data = CustomData_get_layer(&mesh->pdata, CD_NORMAL); - return std::make_unique<fn::GVArray_For_Span<float3>>( - Span<float3>((const float3 *)data, mesh->totpoly)); + return VArray<float3>::ForSpan(Span<float3>((const float3 *)data, mesh->totpoly)); } Array<float3> normals(mesh->totpoly); @@ -1207,7 +1199,7 @@ class NormalAttributeProvider final : public BuiltinAttributeProvider { BKE_mesh_calc_poly_normal(poly, &mesh->mloop[poly->loopstart], mesh->mvert, normals[i]); } - return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals)); + return VArray<float3>::ForContainer(std::move(normals)); } WriteAttributeLookup try_get_for_write(GeometryComponent &UNUSED(component)) const final diff --git a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc index dfb65a9078d..c6a1c61a96d 100644 --- a/source/blender/blenkernel/intern/geometry_component_pointcloud.cc +++ b/source/blender/blenkernel/intern/geometry_component_pointcloud.cc @@ -141,16 +141,15 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con namespace blender::bke { template<typename T> -static GVArrayPtr make_array_read_attribute(const void *data, const int domain_size) +static GVArray make_array_read_attribute(const void *data, const int domain_size) { - return std::make_unique<fn::GVArray_For_Span<T>>(Span<T>((const T *)data, domain_size)); + return VArray<T>::ForSpan(Span<T>((const T *)data, domain_size)); } template<typename T> -static GVMutableArrayPtr make_array_write_attribute(void *data, const int domain_size) +static GVMutableArray make_array_write_attribute(void *data, const int domain_size) { - return std::make_unique<fn::GVMutableArray_For_MutableSpan<T>>( - MutableSpan<T>((T *)data, domain_size)); + return VMutableArray<T>::ForSpan(MutableSpan<T>((T *)data, domain_size)); } /** diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 4133841ba49..c73da7d9659 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -360,12 +360,12 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, result.attribute_try_create( entry.key, domain_output, data_type_output, AttributeInitDefault()); WriteAttributeLookup write_attribute = result.attribute_try_get_for_write(attribute_id); - if (!write_attribute || &write_attribute.varray->type() != cpp_type || + if (!write_attribute || &write_attribute.varray.type() != cpp_type || write_attribute.domain != domain_output) { continue; } - fn::GVMutableArray_GSpan dst_span{*write_attribute.varray}; + fn::GVMutableArray_GSpan dst_span{write_attribute.varray}; int offset = 0; for (const GeometryInstanceGroup &set_group : set_groups) { @@ -377,11 +377,11 @@ static void join_attributes(Span<GeometryInstanceGroup> set_groups, if (domain_size == 0) { continue; /* Domain size is 0, so no need to increment the offset. */ } - GVArrayPtr source_attribute = component.attribute_try_get_for_read( + GVArray source_attribute = component.attribute_try_get_for_read( attribute_id, domain_output, data_type_output); if (source_attribute) { - fn::GVArray_GSpan src_span{*source_attribute}; + fn::GVArray_GSpan src_span{source_attribute}; const void *src_buffer = src_span.data(); for (const int UNUSED(i) : set_group.transforms.index_range()) { void *dst_buffer = dst_span[offset]; diff --git a/source/blender/blenkernel/intern/mesh_sample.cc b/source/blender/blenkernel/intern/mesh_sample.cc index 2274d34f0f1..a046cc68bf2 100644 --- a/source/blender/blenkernel/intern/mesh_sample.cc +++ b/source/blender/blenkernel/intern/mesh_sample.cc @@ -269,7 +269,7 @@ void MeshAttributeInterpolator::sample_attribute(const ReadAttributeLookup &src_ eAttributeMapMode mode) { if (src_attribute && dst_attribute) { - this->sample_data(*src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span()); + this->sample_data(src_attribute.varray, src_attribute.domain, mode, dst_attribute.as_span()); } } diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index c2c9d178171..52bbd2bec57 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -30,14 +30,12 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; using blender::attribute_math::convert_to_static_type; using blender::bke::AttributeIDRef; using blender::fn::GMutableSpan; using blender::fn::GSpan; using blender::fn::GVArray; -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_Typed; -using blender::fn::GVArrayPtr; Spline::Type Spline::type() const { @@ -416,7 +414,7 @@ Span<float3> Spline::evaluated_normals() const } /* Rotate the generated normals with the interpolated tilt data. */ - GVArray_Typed<float> tilts = this->interpolate_to_evaluated(this->tilts()); + VArray<float> tilts = this->interpolate_to_evaluated(this->tilts()); for (const int i : normals.index_range()) { normals[i] = rotate_direction_around_axis(normals[i], tangents[i], tilts[i]); } @@ -529,9 +527,9 @@ void Spline::bounds_min_max(float3 &min, float3 &max, const bool use_evaluated) } } -GVArrayPtr Spline::interpolate_to_evaluated(GSpan data) const +GVArray Spline::interpolate_to_evaluated(GSpan data) const { - return this->interpolate_to_evaluated(GVArray_For_GSpan(data)); + return this->interpolate_to_evaluated(GVArray::ForSpan(data)); } /** @@ -547,7 +545,7 @@ void Spline::sample_with_index_factors(const GVArray &src, blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); - const GVArray_Typed<T> src_typed = src.typed<T>(); + const VArray<T> src_typed = src.typed<T>(); MutableSpan<T> dst_typed = dst.typed<T>(); if (src.size() == 1) { dst_typed.fill(src_typed[0]); diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index 166fe0f5464..28db3da65d0 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -25,9 +25,8 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; using blender::fn::GVArray; -using blender::fn::GVArray_For_ArrayContainer; -using blender::fn::GVArrayPtr; void BezierSpline::copy_settings(Spline &dst) const { @@ -702,26 +701,26 @@ static void interpolate_to_evaluated_impl(const BezierSpline &spline, } } -GVArrayPtr BezierSpline::interpolate_to_evaluated(const GVArray &src) const +GVArray BezierSpline::interpolate_to_evaluated(const GVArray &src) const { BLI_assert(src.size() == this->size()); if (src.is_single()) { - return src.shallow_copy(); + return src; } const int eval_size = this->evaluated_points_size(); if (eval_size == 1) { - return src.shallow_copy(); + return src; } - GVArrayPtr new_varray; + GVArray new_varray; blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) { Array<T> values(eval_size); interpolate_to_evaluated_impl<T>(*this, src.typed<T>(), values); - new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index 6d30d8ba916..7fa332a0330 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -26,10 +26,8 @@ using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::VArray; using blender::fn::GVArray; -using blender::fn::GVArray_For_ArrayContainer; -using blender::fn::GVArray_Typed; -using blender::fn::GVArrayPtr; void NURBSpline::copy_settings(Spline &dst) const { @@ -410,23 +408,23 @@ void interpolate_to_evaluated_impl(Span<NURBSpline::BasisCache> weights, mixer.finalize(); } -GVArrayPtr NURBSpline::interpolate_to_evaluated(const GVArray &src) const +GVArray NURBSpline::interpolate_to_evaluated(const GVArray &src) const { BLI_assert(src.size() == this->size()); if (src.is_single()) { - return src.shallow_copy(); + return src; } Span<BasisCache> basis_cache = this->calculate_basis_cache(); - GVArrayPtr new_varray; + GVArray new_varray; blender::attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); if constexpr (!std::is_void_v<blender::attribute_math::DefaultMixer<T>>) { Array<T> values(this->evaluated_points_size()); interpolate_to_evaluated_impl<T>(basis_cache, src.typed<T>(), values); - new_varray = std::make_unique<GVArray_For_ArrayContainer<Array<T>>>(std::move(values)); + new_varray = VArray<T>::ForContainer(std::move(values)); } }); @@ -448,8 +446,8 @@ Span<float3> NURBSpline::evaluated_positions() const evaluated_position_cache_.resize(eval_size); /* TODO: Avoid copying the evaluated data from the temporary array. */ - GVArray_Typed<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span()); - evaluated->materialize(evaluated_position_cache_); + VArray<float3> evaluated = Spline::interpolate_to_evaluated(positions_.as_span()); + evaluated.materialize(evaluated_position_cache_); position_cache_dirty_ = false; return evaluated_position_cache_; diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc index 338b5d0ac9e..d495c977285 100644 --- a/source/blender/blenkernel/intern/spline_poly.cc +++ b/source/blender/blenkernel/intern/spline_poly.cc @@ -23,7 +23,6 @@ using blender::float3; using blender::MutableSpan; using blender::Span; using blender::fn::GVArray; -using blender::fn::GVArrayPtr; void PolySpline::copy_settings(Spline &UNUSED(dst)) const { @@ -122,9 +121,8 @@ Span<float3> PolySpline::evaluated_positions() const * the original data. Therefore the lifetime of the returned virtual array must not be longer than * the source data. */ -GVArrayPtr PolySpline::interpolate_to_evaluated(const GVArray &src) const +GVArray PolySpline::interpolate_to_evaluated(const GVArray &src) const { BLI_assert(src.size() == this->size()); - - return src.shallow_copy(); + return src; } diff --git a/source/blender/blenlib/BLI_any.hh b/source/blender/blenlib/BLI_any.hh new file mode 100644 index 00000000000..0fc5de5540f --- /dev/null +++ b/source/blender/blenlib/BLI_any.hh @@ -0,0 +1,319 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#pragma once + +/** \file + * \ingroup bli + * + * A #blender::Any is a type-safe container for single values of any copy constructible type. + * It is similar to #std::any but provides the following two additional features: + * - Adjustable inline buffer capacity and alignment. #std::any has a small inline buffer in most + * implementations as well, but its size is not guaranteed. + * - Can store additional user-defined type information without increasing the stack size of #Any. + */ + +#include <algorithm> +#include <utility> + +#include "BLI_memory_utils.hh" + +namespace blender { + +namespace detail { + +/** + * Contains function pointers that manage the memory in an #Any. + * Additional type specific #ExtraInfo can be embedded here as well. + */ +template<typename ExtraInfo> struct AnyTypeInfo { + void (*copy_construct)(void *dst, const void *src); + void (*move_construct)(void *dst, void *src); + void (*destruct)(void *src); + const void *(*get)(const void *src); + ExtraInfo extra_info; + + /** + * Used when #T is stored directly in the inline buffer of the #Any. + */ + template<typename T> static const AnyTypeInfo &get_for_inline() + { + static AnyTypeInfo funcs = {[](void *dst, const void *src) { new (dst) T(*(const T *)src); }, + [](void *dst, void *src) { new (dst) T(std::move(*(T *)src)); }, + [](void *src) { ((T *)src)->~T(); }, + [](const void *src) { return src; }, + ExtraInfo::template get<T>()}; + return funcs; + } + + /** + * Used when #T can't be stored directly in the inline buffer and is stored in a #std::unique_ptr + * instead. In this scenario, the #std::unique_ptr is stored in the inline buffer. + */ + template<typename T> static const AnyTypeInfo &get_for_unique_ptr() + { + using Ptr = std::unique_ptr<T>; + static AnyTypeInfo funcs = { + [](void *dst, const void *src) { new (dst) Ptr(new T(**(const Ptr *)src)); }, + [](void *dst, void *src) { new (dst) Ptr(new T(std::move(**(Ptr *)src))); }, + [](void *src) { ((Ptr *)src)->~Ptr(); }, + [](const void *src) -> const void * { return &**(const Ptr *)src; }, + ExtraInfo::template get<T>()}; + return funcs; + } + + /** + * Used when the #Any does not contain any type currently. + */ + static const AnyTypeInfo &get_for_empty() + { + static AnyTypeInfo funcs = {[](void *UNUSED(dst), const void *UNUSED(src)) {}, + [](void *UNUSED(dst), void *UNUSED(src)) {}, + [](void *UNUSED(src)) {}, + [](const void *UNUSED(src)) -> const void * { return nullptr; }, + ExtraInfo{}}; + return funcs; + } +}; + +/** + * Dummy extra info that is used when no additional type information should be stored in the #Any. + */ +struct NoExtraInfo { + template<typename T> static NoExtraInfo get() + { + return {}; + } +}; + +} // namespace detail + +template< + /** + * Either void or a struct that contains data members for additional type information. + * The struct has to have a static `ExtraInfo get<T>()` method that initializes the struct + * based on a type. + */ + typename ExtraInfo = void, + /** + * Size of the inline buffer. This allows types that are small enough to be stored directly + * inside the #Any without an additional allocation. + */ + size_t InlineBufferCapacity = 8, + /** + * Required minimum alignment of the inline buffer. If this is smaller than the alignment + * requirement of a used type, a separate allocation is necessary. + */ + size_t Alignment = 8> +class Any { + private: + /* Makes it possible to use void in the template parameters. */ + using RealExtraInfo = + std::conditional_t<std::is_void_v<ExtraInfo>, detail::NoExtraInfo, ExtraInfo>; + using Info = detail::AnyTypeInfo<RealExtraInfo>; + + /** + * Inline buffer that either contains nothing, the stored value directly, or a #std::unique_ptr + * to the value. + */ + AlignedBuffer<std::max(InlineBufferCapacity, sizeof(std::unique_ptr<int>)), Alignment> buffer_{}; + + /** + * Information about the type that is currently stored. + */ + const Info *info_ = &Info::get_for_empty(); + + public: + /** Only copy constructible types can be stored in #Any. */ + template<typename T> static constexpr inline bool is_allowed_v = std::is_copy_constructible_v<T>; + + /** + * Checks if the type will be stored in the inline buffer or if it requires a separate + * allocation. + */ + template<typename T> + static constexpr inline bool is_inline_v = std::is_nothrow_move_constructible_v<T> && + sizeof(T) <= InlineBufferCapacity && + alignof(T) <= Alignment; + + /** + * Checks if #T is the same type as this #Any, because in this case the behavior of e.g. the + * assignment operator is different. + */ + template<typename T> + static constexpr inline bool is_same_any_v = std::is_same_v<std::decay_t<T>, Any>; + + private: + template<typename T> const Info &get_info() const + { + using DecayT = std::decay_t<T>; + static_assert(is_allowed_v<DecayT>); + if constexpr (is_inline_v<DecayT>) { + return Info::template get_for_inline<DecayT>(); + } + else { + return Info::template get_for_unique_ptr<DecayT>(); + } + } + + public: + Any() = default; + + Any(const Any &other) : info_(other.info_) + { + info_->copy_construct(&buffer_, &other.buffer_); + } + + /** + * \note The #other #Any will not be empty afterwards if it was not before. Just its value is in + * a moved-from state. + */ + Any(Any &&other) noexcept : info_(other.info_) + { + info_->move_construct(&buffer_, &other.buffer_); + } + + /** + * Constructs a new #Any that contains the given type #T from #args. The #std::in_place_type_t is + * used to disambiguate this and the copy/move constructors. + */ + template<typename T, typename... Args> explicit Any(std::in_place_type_t<T>, Args &&...args) + { + using DecayT = std::decay_t<T>; + static_assert(is_allowed_v<DecayT>); + info_ = &this->template get_info<DecayT>(); + if constexpr (is_inline_v<DecayT>) { + /* Construct the value directly in the inline buffer. */ + new (&buffer_) DecayT(std::forward<Args>(args)...); + } + else { + /* Construct the value in a new allocation and store a #std::unique_ptr to it in the inline + * buffer. */ + new (&buffer_) std::unique_ptr<DecayT>(new DecayT(std::forward<Args>(args)...)); + } + } + + /** + * Constructs a new #Any that contains the given value. + */ + template<typename T, typename X = std::enable_if_t<!is_same_any_v<T>, void>> + Any(T &&value) : Any(std::in_place_type<T>, std::forward<T>(value)) + { + } + + ~Any() + { + info_->destruct(&buffer_); + } + + /** + * \note: Only needed because the template below does not count as copy assignment operator. + */ + Any &operator=(const Any &other) + { + if (this == &other) { + return *this; + } + this->~Any(); + new (this) Any(other); + return *this; + } + + /** Assign any value to the #Any. */ + template<typename T> Any &operator=(T &&other) + { + if constexpr (is_same_any_v<T>) { + if (this == &other) { + return *this; + } + } + this->~Any(); + new (this) Any(std::forward<T>(other)); + return *this; + } + + /** Destruct any existing value to make it empty. */ + void reset() + { + info_->destruct(&buffer_); + info_ = &Info::get_for_empty(); + } + + operator bool() const + { + return this->has_value(); + } + + bool has_value() const + { + return info_ != &Info::get_for_empty(); + } + + template<typename T, typename... Args> std::decay_t<T> &emplace(Args &&...args) + { + this->~Any(); + new (this) Any(std::in_place_type<T>, std::forward<Args>(args)...); + return this->get<T>(); + } + + /** Return true when the value that is currently stored is a #T. */ + template<typename T> bool is() const + { + return info_ == &this->template get_info<T>(); + } + + /** Get a pointer to the stored value. */ + void *get() + { + return const_cast<void *>(info_->get(&buffer_)); + } + + /** Get a pointer to the stored value. */ + const void *get() const + { + return info_->get(&buffer_); + } + + /** + * Get a reference to the stored value. This invokes undefined behavior when #T does not have the + * correct type. + */ + template<typename T> std::decay_t<T> &get() + { + BLI_assert(this->is<T>()); + return *static_cast<std::decay_t<T> *>(this->get()); + } + + /** + * Get a reference to the stored value. This invokes undefined behavior when #T does not have the + * correct type. + */ + template<typename T> const std::decay_t<T> &get() const + { + BLI_assert(this->is<T>()); + return *static_cast<const std::decay_t<T> *>(this->get()); + } + + /** + * Get extra information that has been stored for the contained type. + */ + const RealExtraInfo &extra_info() const + { + return info_->extra_info; + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 1c02bce8411..d9f83d3e1cb 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -37,148 +37,98 @@ * see of the increased compile time and binary size is worth it. */ +#include "BLI_any.hh" #include "BLI_array.hh" #include "BLI_index_mask.hh" #include "BLI_span.hh" namespace blender { -/* An immutable virtual array. */ -template<typename T> class VArray { +/* Forward declarations for generic virtual arrays. */ +namespace fn { +class GVArray; +class GVMutableArray; +}; // namespace fn + +/** + * Implements the specifics of how the elements of a virtual array are accessed. It contains a + * bunch of virtual methods that are wrapped by #VArray. + */ +template<typename T> class VArrayImpl { protected: + /** + * Number of elements in the virtual array. All virtual arrays have a size, but in some cases it + * may make sense to set it to the max value. + */ int64_t size_; public: - VArray(const int64_t size) : size_(size) + VArrayImpl(const int64_t size) : size_(size) { BLI_assert(size_ >= 0); } - virtual ~VArray() = default; - - T get(const int64_t index) const - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - return this->get_impl(index); - } + virtual ~VArrayImpl() = default; int64_t size() const { return size_; } - bool is_empty() const - { - return size_ == 0; - } - - IndexRange index_range() const - { - return IndexRange(size_); - } - - /* Returns true when the virtual array is stored as a span internally. */ - bool is_span() const - { - if (size_ == 0) { - return true; - } - return this->is_span_impl(); - } - - /* Returns the internally used span of the virtual array. This invokes undefined behavior is the - * virtual array is not stored as a span internally. */ - Span<T> get_internal_span() const - { - BLI_assert(this->is_span()); - if (size_ == 0) { - return {}; - } - return this->get_internal_span_impl(); - } + /** + * Get the element at #index. This does not return a reference, because the value may be computed + * on the fly. + */ + virtual T get(const int64_t index) const = 0; - /* Returns true when the virtual array returns the same value for every index. */ - bool is_single() const - { - if (size_ == 1) { - return true; - } - return this->is_single_impl(); - } - - /* Returns the value that is returned for every index. This invokes undefined behavior if the - * virtual array would not return the same value for every index. */ - T get_internal_single() const - { - BLI_assert(this->is_single()); - if (size_ == 1) { - return this->get(0); - } - return this->get_internal_single_impl(); - } - - /* Get the element at a specific index. Note that this operator cannot be used to assign values - * to an index, because the return value is not a reference. */ - T operator[](const int64_t index) const - { - return this->get(index); - } - - /* Copy the entire virtual array into a span. */ - void materialize(MutableSpan<T> r_span) const - { - this->materialize(IndexMask(size_), r_span); - } - - /* Copy some indices of the virtual array into a span. */ - void materialize(IndexMask mask, MutableSpan<T> r_span) const - { - BLI_assert(mask.min_array_size() <= size_); - this->materialize_impl(mask, r_span); - } - - void materialize_to_uninitialized(MutableSpan<T> r_span) const - { - this->materialize_to_uninitialized(IndexMask(size_), r_span); - } - - void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const - { - BLI_assert(mask.min_array_size() <= size_); - this->materialize_to_uninitialized_impl(mask, r_span); - } - - protected: - virtual T get_impl(const int64_t index) const = 0; - - virtual bool is_span_impl() const + /** + * Return true when the virtual array is a plain array internally. + */ + virtual bool is_span() const { return false; } - virtual Span<T> get_internal_span_impl() const + /** + * Return the span of the virtual array. + * This invokes undefined behavior when #is_span returned false. + */ + virtual Span<T> get_internal_span() const { + /* Provide a default implementation, so that subclasses don't have to provide it. This method + * should never be called because #is_span returns false by default. */ BLI_assert_unreachable(); return {}; } - virtual bool is_single_impl() const + /** + * Return true when the virtual array has the same value at every index. + */ + virtual bool is_single() const { return false; } - virtual T get_internal_single_impl() const + /** + * Return the value that is used at every index. + * This invokes undefined behavior when #is_single returned false. + */ + virtual T get_internal_single() const { /* Provide a default implementation, so that subclasses don't have to provide it. This method - * should never be called because `is_single_impl` returns false by default. */ + * should never be called because #is_single returns false by default. */ BLI_assert_unreachable(); return T(); } - virtual void materialize_impl(IndexMask mask, MutableSpan<T> r_span) const + /** + * Copy values from the virtual array into the provided span. The index of the value in the + * virtual is the same as the index in the span. + */ + virtual void materialize(IndexMask mask, MutableSpan<T> r_span) const { T *dst = r_span.data(); + /* Optimize for a few different common cases. */ if (this->is_span()) { const T *src = this->get_internal_span().data(); mask.foreach_index([&](const int64_t i) { dst[i] = src[i]; }); @@ -192,9 +142,13 @@ template<typename T> class VArray { } } - virtual void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<T> r_span) const + /** + * Same as #materialize but #r_span is expected to be uninitialized. + */ + virtual void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const { T *dst = r_span.data(); + /* Optimize for a few different common cases. */ if (this->is_span()) { const T *src = this->get_internal_span().data(); mask.foreach_index([&](const int64_t i) { new (dst + i) T(src[i]); }); @@ -207,43 +161,48 @@ template<typename T> class VArray { mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); }); } } -}; -/* Similar to VArray, but the elements are mutable. */ -template<typename T> class VMutableArray : public VArray<T> { - public: - VMutableArray(const int64_t size) : VArray<T>(size) + /** + * If this virtual wraps another #GVArray, this method should assign the wrapped array to the + * provided reference. This allows losslessly converting between generic and typed virtual + * arrays in all cases. + * Return true when the virtual array was assigned and false when nothing was done. + */ + virtual bool try_assign_GVArray(fn::GVArray &UNUSED(varray)) const { + return false; } - void set(const int64_t index, T value) + /** + * Return true when this virtual array may own any of the memory it references. This can be used + * for optimization purposes when converting or copying the virtual array. + */ + virtual bool may_have_ownership() const { - BLI_assert(index >= 0); - BLI_assert(index < this->size_); - this->set_impl(index, std::move(value)); + /* Use true by default to be on the safe side. Subclasses that know for sure that they don't + * own anything can overwrite this with false. */ + return true; } +}; - /* Copy the values from the source span to all elements in the virtual array. */ - void set_all(Span<T> src) - { - BLI_assert(src.size() == this->size_); - this->set_all_impl(src); - } +/* Similar to #VArrayImpl, but adds methods that allow modifying the referenced elements. */ +template<typename T> class VMutableArrayImpl : public VArrayImpl<T> { + public: + using VArrayImpl<T>::VArrayImpl; - MutableSpan<T> get_internal_span() - { - BLI_assert(this->is_span()); - Span<T> span = static_cast<const VArray<T> *>(this)->get_internal_span(); - return MutableSpan<T>(const_cast<T *>(span.data()), span.size()); - } + /** + * Assign the provided #value to the #index. + */ + virtual void set(const int64_t index, T value) = 0; - protected: - virtual void set_impl(const int64_t index, T value) = 0; - - virtual void set_all_impl(Span<T> src) + /** + * Copy all elements from the provided span into the virtual array. + */ + virtual void set_all(Span<T> src) { if (this->is_span()) { - const MutableSpan<T> span = this->get_internal_span(); + const Span<T> const_span = this->get_internal_span(); + const MutableSpan<T> span{(T *)const_span.data(), const_span.size()}; initialized_copy_n(src.data(), this->size_, span.data()); } else { @@ -253,95 +212,133 @@ template<typename T> class VMutableArray : public VArray<T> { } } } -}; -template<typename T> using VArrayPtr = std::unique_ptr<VArray<T>>; -template<typename T> using VMutableArrayPtr = std::unique_ptr<VMutableArray<T>>; + /** + * Similar to #VArrayImpl::try_assign_GVArray but for mutable virtual arrays. + */ + virtual bool try_assign_GVMutableArray(fn::GVMutableArray &UNUSED(varray)) const + { + return false; + } +}; /** * A virtual array implementation for a span. Methods in this class are final so that it can be * devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is used). */ -template<typename T> class VArray_For_Span : public VArray<T> { +template<typename T> class VArrayImpl_For_Span : public VArrayImpl<T> { protected: const T *data_ = nullptr; public: - VArray_For_Span(const Span<T> data) : VArray<T>(data.size()), data_(data.data()) + VArrayImpl_For_Span(const Span<T> data) : VArrayImpl<T>(data.size()), data_(data.data()) { } protected: - VArray_For_Span(const int64_t size) : VArray<T>(size) + VArrayImpl_For_Span(const int64_t size) : VArrayImpl<T>(size) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { return data_[index]; } - bool is_span_impl() const final + bool is_span() const final { return true; } - Span<T> get_internal_span_impl() const final + Span<T> get_internal_span() const final { return Span<T>(data_, this->size_); } }; -template<typename T> class VMutableArray_For_MutableSpan : public VMutableArray<T> { +/** + * A version of #VArrayImpl_For_Span that can not be subclassed. This allows safely overwriting the + * #may_have_ownership method. + */ +template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> { + public: + using VArrayImpl_For_Span<T>::VArrayImpl_For_Span; + + private: + bool may_have_ownership() const override + { + return false; + } +}; + +/** + * Like #VArrayImpl_For_Span but for mutable data. + */ +template<typename T> class VMutableArrayImpl_For_MutableSpan : public VMutableArrayImpl<T> { protected: T *data_ = nullptr; public: - VMutableArray_For_MutableSpan(const MutableSpan<T> data) - : VMutableArray<T>(data.size()), data_(data.data()) + VMutableArrayImpl_For_MutableSpan(const MutableSpan<T> data) + : VMutableArrayImpl<T>(data.size()), data_(data.data()) { } protected: - VMutableArray_For_MutableSpan(const int64_t size) : VMutableArray<T>(size) + VMutableArrayImpl_For_MutableSpan(const int64_t size) : VMutableArrayImpl<T>(size) { } - T get_impl(const int64_t index) const final + T get(const int64_t index) const final { return data_[index]; } - void set_impl(const int64_t index, T value) final + void set(const int64_t index, T value) final { data_[index] = value; } - bool is_span_impl() const override + bool is_span() const override { return true; } - Span<T> get_internal_span_impl() const override + Span<T> get_internal_span() const override { return Span<T>(data_, this->size_); } }; /** - * A variant of `VArray_For_Span` that owns the underlying data. + * Like #VArrayImpl_For_Span_final but for mutable data. + */ +template<typename T> +class VMutableArrayImpl_For_MutableSpan_final final : public VMutableArrayImpl_For_MutableSpan<T> { + public: + using VMutableArrayImpl_For_MutableSpan<T>::VMutableArrayImpl_For_MutableSpan; + + private: + bool may_have_ownership() const override + { + return false; + } +}; + +/** + * A variant of `VArrayImpl_For_Span` that owns the underlying data. * The `Container` type has to implement a `size()` and `data()` method. * The `data()` method has to return a pointer to the first element in the continuous array of * elements. */ template<typename Container, typename T = typename Container::value_type> -class VArray_For_ArrayContainer : public VArray_For_Span<T> { +class VArrayImpl_For_ArrayContainer : public VArrayImpl_For_Span<T> { private: Container container_; public: - VArray_For_ArrayContainer(Container container) - : VArray_For_Span<T>((int64_t)container.size()), container_(std::move(container)) + VArrayImpl_For_ArrayContainer(Container container) + : VArrayImpl_For_Span<T>((int64_t)container.size()), container_(std::move(container)) { this->data_ = container_.data(); } @@ -352,43 +349,671 @@ class VArray_For_ArrayContainer : public VArray_For_Span<T> { * so that it can be devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is * used). */ -template<typename T> class VArray_For_Single final : public VArray<T> { +template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> { private: T value_; public: - VArray_For_Single(T value, const int64_t size) : VArray<T>(size), value_(std::move(value)) + VArrayImpl_For_Single(T value, const int64_t size) + : VArrayImpl<T>(size), value_(std::move(value)) { } protected: - T get_impl(const int64_t UNUSED(index)) const override + T get(const int64_t UNUSED(index)) const override { return value_; } - bool is_span_impl() const override + bool is_span() const override { return this->size_ == 1; } - Span<T> get_internal_span_impl() const override + Span<T> get_internal_span() const override { return Span<T>(&value_, 1); } - bool is_single_impl() const override + bool is_single() const override { return true; } - T get_internal_single_impl() const override + T get_internal_single() const override { return value_; } }; /** + * This class makes it easy to create a virtual array for an existing function or lambda. The + * `GetFunc` should take a single `index` argument and return the value at that index. + */ +template<typename T, typename GetFunc> class VArrayImpl_For_Func final : public VArrayImpl<T> { + private: + GetFunc get_func_; + + public: + VArrayImpl_For_Func(const int64_t size, GetFunc get_func) + : VArrayImpl<T>(size), get_func_(std::move(get_func)) + { + } + + private: + T get(const int64_t index) const override + { + return get_func_(index); + } + + void materialize(IndexMask mask, MutableSpan<T> r_span) const override + { + T *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { dst[i] = get_func_(i); }); + } + + void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const override + { + T *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { new (dst + i) T(get_func_(i)); }); + } +}; + +/** + * \note: This is `final` so that #may_have_ownership can be implemented reliably. + */ +template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> +class VArrayImpl_For_DerivedSpan final : public VArrayImpl<ElemT> { + private: + const StructT *data_; + + public: + VArrayImpl_For_DerivedSpan(const Span<StructT> data) + : VArrayImpl<ElemT>(data.size()), data_(data.data()) + { + } + + private: + ElemT get(const int64_t index) const override + { + return GetFunc(data_[index]); + } + + void materialize(IndexMask mask, MutableSpan<ElemT> r_span) const override + { + ElemT *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); }); + } + + void materialize_to_uninitialized(IndexMask mask, MutableSpan<ElemT> r_span) const override + { + ElemT *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); }); + } + + bool may_have_ownership() const override + { + return false; + } +}; + +/** + * \note: This is `final` so that #may_have_ownership can be implemented reliably. + */ +template<typename StructT, + typename ElemT, + ElemT (*GetFunc)(const StructT &), + void (*SetFunc)(StructT &, ElemT)> +class VMutableArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> { + private: + StructT *data_; + + public: + VMutableArrayImpl_For_DerivedSpan(const MutableSpan<StructT> data) + : VMutableArrayImpl<ElemT>(data.size()), data_(data.data()) + { + } + + private: + ElemT get(const int64_t index) const override + { + return GetFunc(data_[index]); + } + + void set(const int64_t index, ElemT value) override + { + SetFunc(data_[index], std::move(value)); + } + + void materialize(IndexMask mask, MutableSpan<ElemT> r_span) const override + { + ElemT *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); }); + } + + void materialize_to_uninitialized(IndexMask mask, MutableSpan<ElemT> r_span) const override + { + ElemT *dst = r_span.data(); + mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); }); + } + + bool may_have_ownership() const override + { + return false; + } +}; + +namespace detail { + +/** + * Struct that can be passed as `ExtraInfo` into an #Any. + * This struct is only intended to be used by #VArrayCommon. + */ +template<typename T> struct VArrayAnyExtraInfo { + /** + * Gets the virtual array that is stored at the given pointer. + */ + const VArrayImpl<T> *(*get_varray)(const void *buffer) = + [](const void *UNUSED(buffer)) -> const VArrayImpl<T> * { return nullptr; }; + + template<typename StorageT> static VArrayAnyExtraInfo get() + { + /* These are the only allowed types in the #Any. */ + static_assert(std::is_base_of_v<VArrayImpl<T>, StorageT> || + std::is_same_v<StorageT, const VArrayImpl<T> *> || + std::is_same_v<StorageT, std::shared_ptr<const VArrayImpl<T>>>); + + /* Depending on how the virtual array implementation is stored in the #Any, a different + * #get_varray function is required. */ + if constexpr (std::is_base_of_v<VArrayImpl<T>, StorageT>) { + return {[](const void *buffer) { + return static_cast<const VArrayImpl<T> *>((const StorageT *)buffer); + }}; + } + else if constexpr (std::is_same_v<StorageT, const VArrayImpl<T> *>) { + return {[](const void *buffer) { return *(const StorageT *)buffer; }}; + } + else if constexpr (std::is_same_v<StorageT, std::shared_ptr<const VArrayImpl<T>>>) { + return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }}; + } + else { + BLI_assert_unreachable(); + return {}; + } + } +}; + +} // namespace detail + +/** + * Utility class to reduce code duplication for methods available on #VArray and #VMutableArray. + * Deriving #VMutableArray from #VArray would have some issues: + * - Static methods on #VArray would also be available on #VMutableArray. + * - It would allow assigning a #VArray to a #VMutableArray under some circumstances which is not + * allowed and could result in hard to find bugs. + */ +template<typename T> class VArrayCommon { + protected: + /** + * Store the virtual array implementation in an #Any. This makes it easy to avoid a memory + * allocation if the implementation is small enough and is copyable. This is the case for the + * most common virtual arrays. + * Other virtual array implementations are typically stored as #std::shared_ptr. That works even + * when the implementation itself is not copyable and makes copying #VArrayCommon cheaper. + */ + using Storage = Any<detail::VArrayAnyExtraInfo<T>, 24, 8>; + + /** + * Pointer to the currently contained virtual array implementation. This is allowed to be null. + */ + const VArrayImpl<T> *impl_ = nullptr; + /** + * Does the memory management for the virtual array implementation. It contains one of the + * following: + * - Inlined subclass of #VArrayImpl. + * - Non-owning pointer to a #VArrayImpl. + * - Shared pointer to a #VArrayImpl. + */ + Storage storage_; + + protected: + VArrayCommon() = default; + + /** Copy constructor. */ + VArrayCommon(const VArrayCommon &other) : storage_(other.storage_) + { + impl_ = this->impl_from_storage(); + } + + /** Move constructor. */ + VArrayCommon(VArrayCommon &&other) noexcept : storage_(std::move(other.storage_)) + { + impl_ = this->impl_from_storage(); + other.storage_.reset(); + other.impl_ = nullptr; + } + + /** + * Wrap an existing #VArrayImpl and don't take ownership of it. This should rarely be used in + * practice. + */ + VArrayCommon(const VArrayImpl<T> *impl) : impl_(impl) + { + storage_ = impl_; + } + + /** + * Wrap an existing #VArrayImpl that is contained in a #std::shared_ptr. This takes ownership. + */ + VArrayCommon(std::shared_ptr<const VArrayImpl<T>> impl) : impl_(impl.get()) + { + if (impl) { + storage_ = std::move(impl); + } + } + + /** + * Replace the contained #VArrayImpl. + */ + template<typename ImplT, typename... Args> void emplace(Args &&...args) + { + /* Make sure we are actually constructing a #VArrayImpl. */ + static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>); + if constexpr (std::is_copy_constructible_v<ImplT> && Storage::template is_inline_v<ImplT>) { + /* Only inline the implementatiton when it is copyable and when it fits into the inline + * buffer of the storage. */ + impl_ = &storage_.template emplace<ImplT>(std::forward<Args>(args)...); + } + else { + /* If it can't be inlined, create a new #std::shared_ptr instead and store that in the + * storage. */ + std::shared_ptr<const VArrayImpl<T>> ptr = std::make_shared<ImplT>( + std::forward<Args>(args)...); + impl_ = &*ptr; + storage_ = std::move(ptr); + } + } + + /** Utility to implement a copy assignment operator in a subclass. */ + void copy_from(const VArrayCommon &other) + { + if (this == &other) { + return; + } + storage_ = other.storage_; + impl_ = this->impl_from_storage(); + } + + /** Utility to implement a move assignment operator in a subclass. */ + void move_from(VArrayCommon &&other) noexcept + { + if (this == &other) { + return; + } + storage_ = std::move(other.storage_); + impl_ = this->impl_from_storage(); + other.storage_.reset(); + other.impl_ = nullptr; + } + + /** Get a pointer to the virtual array implementation that is currently stored in #storage_, or + * null. */ + const VArrayImpl<T> *impl_from_storage() const + { + return storage_.extra_info().get_varray(storage_.get()); + } + + public: + /** Return false when there is no virtual array implementation currently. */ + operator bool() const + { + return impl_ != nullptr; + } + + /** + * Get the element at a specific index. + * \note: This can't return a reference because the value may be computed on the fly. This also + * implies that one can not use this method for assignments. + */ + T operator[](const int64_t index) const + { + BLI_assert(*this); + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + return impl_->get(index); + } + + /** + * Same as the #operator[] but is sometimes easier to use when one has a pointer to a virtual + * array. + */ + T get(const int64_t index) const + { + return (*this)[index]; + } + + /** + * Return the size of the virtual array. It's allowed to call this method even when there is no + * virtual array. In this case 0 is returned. + */ + int64_t size() const + { + if (impl_ == nullptr) { + return 0; + } + return impl_->size(); + } + + /** True when the size is zero or when there is no virtual array. */ + bool is_empty() const + { + return this->size() == 0; + } + + IndexRange index_range() const + { + return IndexRange(this->size()); + } + + /** Return true when the virtual array is stored as a span internally. */ + bool is_span() const + { + BLI_assert(*this); + if (this->is_empty()) { + return true; + } + return impl_->is_span(); + } + + /** + * Returns the internally used span of the virtual array. This invokes undefined behavior is the + * virtual array is not stored as a span internally. + */ + Span<T> get_internal_span() const + { + BLI_assert(this->is_span()); + if (this->is_empty()) { + return {}; + } + return impl_->get_internal_span(); + } + + /** Return true when the virtual array returns the same value for every index. */ + bool is_single() const + { + BLI_assert(*this); + if (impl_->size() == 1) { + return true; + } + return impl_->is_single(); + } + + /** + * Return the value that is returned for every index. This invokes undefined behavior if the + * virtual array would not return the same value for every index. + */ + T get_internal_single() const + { + BLI_assert(this->is_single()); + if (impl_->size() == 1) { + return impl_->get(0); + } + return impl_->get_internal_single(); + } + + /** Copy the entire virtual array into a span. */ + void materialize(MutableSpan<T> r_span) const + { + this->materialize(IndexMask(this->size()), r_span); + } + + /** Copy some indices of the virtual array into a span. */ + void materialize(IndexMask mask, MutableSpan<T> r_span) const + { + BLI_assert(mask.min_array_size() <= this->size()); + impl_->materialize(mask, r_span); + } + + void materialize_to_uninitialized(MutableSpan<T> r_span) const + { + this->materialize_to_uninitialized(IndexMask(this->size()), r_span); + } + + void materialize_to_uninitialized(IndexMask mask, MutableSpan<T> r_span) const + { + BLI_assert(mask.min_array_size() <= this->size()); + impl_->materialize_to_uninitialized(mask, r_span); + } + + /** See #GVArrayImpl::try_assign_GVArray. */ + bool try_assign_GVArray(fn::GVArray &varray) const + { + return impl_->try_assign_GVArray(varray); + } + + /** See #GVArrayImpl::may_have_ownership. */ + bool may_have_ownership() const + { + return impl_->may_have_ownership(); + } +}; + +template<typename T> class VMutableArray; + +/** + * A #VArray wraps a virtual array implementation and provides easy access to its elements. It can + * be copied and moved. While it is relatively small, it should still be passed by reference if + * possible (other than e.g. #Span). + */ +template<typename T> class VArray : public VArrayCommon<T> { + friend VMutableArray<T>; + + public: + VArray() = default; + VArray(const VArray &other) = default; + VArray(VArray &&other) noexcept = default; + + VArray(const VArrayImpl<T> *impl) : VArrayCommon<T>(impl) + { + } + + VArray(std::shared_ptr<const VArrayImpl<T>> impl) : VArrayCommon<T>(std::move(impl)) + { + } + + /** + * Construct a new virtual array for a custom #VArrayImpl. + */ + template<typename ImplT, typename... Args> static VArray For(Args &&...args) + { + static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>); + VArray varray; + varray.template emplace<ImplT>(std::forward<Args>(args)...); + return varray; + } + + /** + * Construct a new virtual array that has the same value at every index. + */ + static VArray ForSingle(T value, const int64_t size) + { + return VArray::For<VArrayImpl_For_Single<T>>(std::move(value), size); + } + + /** + * Construct a new virtual array for an existing span. This does not take ownership of the + * underlying memory. + */ + static VArray ForSpan(Span<T> values) + { + return VArray::For<VArrayImpl_For_Span_final<T>>(values); + } + + /** + * Construct a new virtual that will invoke the provided function whenever an element is + * accessed. + */ + template<typename GetFunc> static VArray ForFunc(const int64_t size, GetFunc get_func) + { + return VArray::For<VArrayImpl_For_Func<T, decltype(get_func)>>(size, std::move(get_func)); + } + + /** + * Construct a new virtual array for an existing span with a mapping function. This does not take + * ownership of the span. + */ + template<typename StructT, T (*GetFunc)(const StructT &)> + static VArray ForDerivedSpan(Span<StructT> values) + { + return VArray::For<VArrayImpl_For_DerivedSpan<StructT, T, GetFunc>>(values); + } + + /** + * Construct a new virtual array for an existing container. Every container that lays out the + * elements in a plain array works. This takes ownership of the passed in container. If that is + * not desired, use #ForSpan instead. + */ + template<typename ContainerT> static VArray ForContainer(ContainerT container) + { + return VArray::For<VArrayImpl_For_ArrayContainer<ContainerT>>(std::move(container)); + } + + VArray &operator=(const VArray &other) + { + this->copy_from(other); + return *this; + } + + VArray &operator=(VArray &&other) noexcept + { + this->move_from(std::move(other)); + return *this; + } +}; + +/** + * Similar to #VArray but references a virtual array that can be modified. + */ +template<typename T> class VMutableArray : public VArrayCommon<T> { + public: + VMutableArray() = default; + VMutableArray(const VMutableArray &other) = default; + VMutableArray(VMutableArray &&other) noexcept = default; + + VMutableArray(const VMutableArrayImpl<T> *impl) : VArrayCommon<T>(impl) + { + } + + VMutableArray(std::shared_ptr<const VMutableArrayImpl<T>> impl) + : VArrayCommon<T>(std::move(impl)) + { + } + + /** + * Construct a new virtual array for a custom #VMutableArrayImpl. + */ + template<typename ImplT, typename... Args> static VMutableArray For(Args &&...args) + { + static_assert(std::is_base_of_v<VMutableArrayImpl<T>, ImplT>); + VMutableArray varray; + varray.template emplace<ImplT>(std::forward<Args>(args)...); + return varray; + } + + /** + * Construct a new virtual array for an existing span. This does not take ownership of the span. + */ + static VMutableArray ForSpan(MutableSpan<T> values) + { + return VMutableArray::For<VMutableArrayImpl_For_MutableSpan_final<T>>(values); + } + + /** + * Construct a new virtual array for an existing span with a mapping function. This does not take + * ownership of the span. + */ + template<typename StructT, T (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, T)> + static VMutableArray ForDerivedSpan(MutableSpan<StructT> values) + { + return VMutableArray::For<VMutableArrayImpl_For_DerivedSpan<StructT, T, GetFunc, SetFunc>>( + values); + } + + /** Convert to a #VArray by copying. */ + operator VArray<T>() const & + { + VArray<T> varray; + varray.copy_from(*this); + return varray; + } + + /** Convert to a #VArray by moving. */ + operator VArray<T>() &&noexcept + { + VArray<T> varray; + varray.move_from(std::move(*this)); + return varray; + } + + VMutableArray &operator=(const VMutableArray &other) + { + this->copy_from(other); + return *this; + } + + VMutableArray &operator=(VMutableArray &&other) noexcept + { + this->move_from(std::move(other)); + return *this; + } + + /** + * Get access to the internal span. This invokes undefined behavior if the #is_span returned + * false. + */ + MutableSpan<T> get_internal_span() const + { + BLI_assert(this->is_span()); + const Span<T> span = this->impl_->get_internal_span(); + return MutableSpan<T>(const_cast<T *>(span.data()), span.size()); + } + + /** + * Set the value at the given index. + */ + void set(const int64_t index, T value) + { + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + this->get_impl()->set(index, std::move(value)); + } + + /** + * Copy the values from the source span to all elements in the virtual array. + */ + void set_all(Span<T> src) + { + BLI_assert(src.size() == this->size()); + this->get_impl()->set_all(src); + } + + /** See #GVMutableArrayImpl::try_assign_GVMutableArray. */ + bool try_assign_GVMutableArray(fn::GVMutableArray &varray) const + { + return this->get_impl()->try_assign_GVMutableArray(varray); + } + + private: + /** Utility to get the pointer to the wrapped #VMutableArrayImpl. */ + VMutableArrayImpl<T> *get_impl() const + { + /* This cast is valid by the invariant that a #VMutableArray->impl_ is always a + * #VMutableArrayImpl. */ + return (VMutableArrayImpl<T> *)this->impl_; + } +}; + +/** * In many cases a virtual array is a span internally. In those cases, access to individual could * be much more efficient than calling a virtual method. When the underlying virtual array is not a * span, this class allocates a new array and copies the values over. @@ -401,11 +1026,11 @@ template<typename T> class VArray_For_Single final : public VArray<T> { */ template<typename T> class VArray_Span final : public Span<T> { private: - const VArray<T> &varray_; + VArray<T> varray_; Array<T> owned_data_; public: - VArray_Span(const VArray<T> &varray) : Span<T>(), varray_(varray) + VArray_Span(VArray<T> varray) : Span<T>(), varray_(std::move(varray)) { this->size_ = varray_.size(); if (varray_.is_span()) { @@ -421,7 +1046,7 @@ template<typename T> class VArray_Span final : public Span<T> { }; /** - * Same as VArray_Span, but for a mutable span. + * Same as #VArray_Span, but for a mutable span. * The important thing to note is that when changing this span, the results might not be * immediately reflected in the underlying virtual array (only when the virtual array is a span * internally). The #save method can be used to write all changes to the underlying virtual array, @@ -429,7 +1054,7 @@ template<typename T> class VArray_Span final : public Span<T> { */ template<typename T> class VMutableArray_Span final : public MutableSpan<T> { private: - VMutableArray<T> &varray_; + VMutableArray<T> varray_; Array<T> owned_data_; bool save_has_been_called_ = false; bool show_not_saved_warning_ = true; @@ -437,8 +1062,8 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> { public: /* Create a span for any virtual array. This is cheap when the virtual array is a span itself. If * not, a new array has to be allocated as a wrapper for the underlying virtual array. */ - VMutableArray_Span(VMutableArray<T> &varray, const bool copy_values_to_span = true) - : MutableSpan<T>(), varray_(varray) + VMutableArray_Span(VMutableArray<T> varray, const bool copy_values_to_span = true) + : MutableSpan<T>(), varray_(std::move(varray)) { this->size_ = varray_.size(); if (varray_.is_span()) { @@ -483,106 +1108,6 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> { }; /** - * This class makes it easy to create a virtual array for an existing function or lambda. The - * `GetFunc` should take a single `index` argument and return the value at that index. - */ -template<typename T, typename GetFunc> class VArray_For_Func final : public VArray<T> { - private: - GetFunc get_func_; - - public: - VArray_For_Func(const int64_t size, GetFunc get_func) - : VArray<T>(size), get_func_(std::move(get_func)) - { - } - - private: - T get_impl(const int64_t index) const override - { - return get_func_(index); - } - - void materialize_impl(IndexMask mask, MutableSpan<T> r_span) const override - { - T *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { dst[i] = get_func_(i); }); - } - - void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<T> r_span) const override - { - T *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { new (dst + i) T(get_func_(i)); }); - } -}; - -template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> -class VArray_For_DerivedSpan : public VArray<ElemT> { - private: - const StructT *data_; - - public: - VArray_For_DerivedSpan(const Span<StructT> data) : VArray<ElemT>(data.size()), data_(data.data()) - { - } - - private: - ElemT get_impl(const int64_t index) const override - { - return GetFunc(data_[index]); - } - - void materialize_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override - { - ElemT *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); }); - } - - void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override - { - ElemT *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); }); - } -}; - -template<typename StructT, - typename ElemT, - ElemT (*GetFunc)(const StructT &), - void (*SetFunc)(StructT &, ElemT)> -class VMutableArray_For_DerivedSpan : public VMutableArray<ElemT> { - private: - StructT *data_; - - public: - VMutableArray_For_DerivedSpan(const MutableSpan<StructT> data) - : VMutableArray<ElemT>(data.size()), data_(data.data()) - { - } - - private: - ElemT get_impl(const int64_t index) const override - { - return GetFunc(data_[index]); - } - - void set_impl(const int64_t index, ElemT value) override - { - SetFunc(data_[index], std::move(value)); - } - - void materialize_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override - { - ElemT *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { dst[i] = GetFunc(data_[i]); }); - } - - void materialize_to_uninitialized_impl(IndexMask mask, MutableSpan<ElemT> r_span) const override - { - ElemT *dst = r_span.data(); - mask.foreach_index([&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); }); - } -}; - -/** * Generate multiple versions of the given function optimized for different virtual arrays. * One has to be careful with nesting multiple devirtualizations, because that results in an * exponential number of function instantiations (increasing compile time and binary size). @@ -596,15 +1121,14 @@ inline void devirtualize_varray(const VArray<T> &varray, const Func &func, bool /* Support disabling the devirtualization to simplify benchmarking. */ if (enable) { if (varray.is_single()) { - /* `VArray_For_Single` can be used for devirtualization, because it is declared `final`. */ - const VArray_For_Single<T> varray_single{varray.get_internal_single(), varray.size()}; - func(varray_single); + /* `VArrayImpl_For_Single` can be used for devirtualization, because it is declared `final`. + */ + func(VArray<T>::ForSingle(varray.get_internal_single(), varray.size())); return; } if (varray.is_span()) { - /* `VArray_For_Span` can be used for devirtualization, because it is declared `final`. */ - const VArray_For_Span<T> varray_span{varray.get_internal_span()}; - func(varray_span); + /* `VArrayImpl_For_Span` can be used for devirtualization, because it is declared `final`. */ + func(VArray<T>::ForSpan(varray.get_internal_span())); return; } } @@ -629,27 +1153,23 @@ inline void devirtualize_varray2(const VArray<T1> &varray1, const bool is_single1 = varray1.is_single(); const bool is_single2 = varray2.is_single(); if (is_span1 && is_span2) { - const VArray_For_Span<T1> varray1_span{varray1.get_internal_span()}; - const VArray_For_Span<T2> varray2_span{varray2.get_internal_span()}; - func(varray1_span, varray2_span); + func(VArray<T1>::ForSpan(varray1.get_internal_span()), + VArray<T2>::ForSpan(varray2.get_internal_span())); return; } if (is_span1 && is_single2) { - const VArray_For_Span<T1> varray1_span{varray1.get_internal_span()}; - const VArray_For_Single<T2> varray2_single{varray2.get_internal_single(), varray2.size()}; - func(varray1_span, varray2_single); + func(VArray<T1>::ForSpan(varray1.get_internal_span()), + VArray<T2>::ForSingle(varray2.get_internal_single(), varray2.size())); return; } if (is_single1 && is_span2) { - const VArray_For_Single<T1> varray1_single{varray1.get_internal_single(), varray1.size()}; - const VArray_For_Span<T2> varray2_span{varray2.get_internal_span()}; - func(varray1_single, varray2_span); + func(VArray<T1>::ForSingle(varray1.get_internal_single(), varray1.size()), + VArray<T2>::ForSpan(varray2.get_internal_span())); return; } if (is_single1 && is_single2) { - const VArray_For_Single<T1> varray1_single{varray1.get_internal_single(), varray1.size()}; - const VArray_For_Single<T2> varray2_single{varray2.get_internal_single(), varray2.size()}; - func(varray1_single, varray2_single); + func(VArray<T1>::ForSingle(varray1.get_internal_single(), varray1.size()), + VArray<T2>::ForSingle(varray2.get_internal_single(), varray2.size())); return; } } diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 7db984aef5c..29493c799b3 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -165,6 +165,7 @@ set(SRC BLI_alloca.h BLI_allocator.hh + BLI_any.hh BLI_args.h BLI_array.h BLI_array.hh @@ -411,6 +412,7 @@ blender_add_lib(bf_blenlib "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") if(WITH_GTESTS) set(TEST_SRC + tests/BLI_any_test.cc tests/BLI_array_store_test.cc tests/BLI_array_test.cc tests/BLI_array_utils_test.cc diff --git a/source/blender/blenlib/tests/BLI_any_test.cc b/source/blender/blenlib/tests/BLI_any_test.cc new file mode 100644 index 00000000000..226088cf3c7 --- /dev/null +++ b/source/blender/blenlib/tests/BLI_any_test.cc @@ -0,0 +1,108 @@ +/* Apache License, Version 2.0 */ + +#include "BLI_any.hh" +#include "BLI_map.hh" + +#include "testing/testing.h" + +namespace blender::tests { + +TEST(any, DefaultConstructor) +{ + Any a; + EXPECT_FALSE(a.has_value()); +} + +TEST(any, AssignInt) +{ + Any<> a = 5; + EXPECT_TRUE(a.has_value()); + EXPECT_TRUE(a.is<int>()); + EXPECT_FALSE(a.is<float>()); + const int &value = a.get<int>(); + EXPECT_EQ(value, 5); + a = 10; + EXPECT_EQ(value, 10); + + Any b = a; + EXPECT_TRUE(b.has_value()); + EXPECT_EQ(b.get<int>(), 10); + + Any c = std::move(a); + EXPECT_TRUE(c); + EXPECT_EQ(c.get<int>(), 10); + + EXPECT_EQ(a.get<int>(), 10); /* NOLINT: bugprone-use-after-move */ + + a.reset(); + EXPECT_FALSE(a); +} + +TEST(any, AssignMap) +{ + Any<> a = Map<int, int>(); + EXPECT_TRUE(a.has_value()); + EXPECT_TRUE((a.is<Map<int, int>>())); + EXPECT_FALSE((a.is<Map<int, float>>())); + Map<int, int> &map = a.get<Map<int, int>>(); + map.add(4, 2); + EXPECT_EQ((a.get<Map<int, int>>().lookup(4)), 2); + + Any b = a; + EXPECT_TRUE(b); + EXPECT_EQ((b.get<Map<int, int>>().lookup(4)), 2); + + Any c = std::move(a); + c = c; + EXPECT_TRUE(b); + EXPECT_EQ((c.get<Map<int, int>>().lookup(4)), 2); + + EXPECT_TRUE((a.get<Map<int, int>>().is_empty())); /* NOLINT: bugprone-use-after-move */ +} + +TEST(any, AssignAny) +{ + Any<> a = 5; + Any<> b = std::string("hello"); + Any c; + + Any z; + EXPECT_FALSE(z.has_value()); + + z = a; + EXPECT_TRUE(z.has_value()); + EXPECT_EQ(z.get<int>(), 5); + + z = b; + EXPECT_EQ(z.get<std::string>(), "hello"); + + z = c; + EXPECT_FALSE(z.has_value()); + + z = Any(std::in_place_type<Any<>>, a); + EXPECT_FALSE(z.is<int>()); + EXPECT_TRUE(z.is<Any<>>()); + EXPECT_EQ(z.get<Any<>>().get<int>(), 5); +} + +struct ExtraSizeInfo { + size_t size; + + template<typename T> static ExtraSizeInfo get() + { + return {sizeof(T)}; + } +}; + +TEST(any, ExtraInfo) +{ + using MyAny = Any<ExtraSizeInfo>; + + MyAny a = 5; + EXPECT_EQ(a.extra_info().size, sizeof(int)); + + a = std::string("hello"); + EXPECT_EQ(a.extra_info().size, sizeof(std::string)); +} + +} // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc index a6d2ca10315..7a548e7c434 100644 --- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc +++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc @@ -12,7 +12,7 @@ namespace blender::tests { TEST(virtual_array, Span) { std::array<int, 5> data = {3, 4, 5, 6, 7}; - VArray_For_Span<int> varray{data}; + VArray<int> varray = VArray<int>::ForSpan(data); EXPECT_EQ(varray.size(), 5); EXPECT_EQ(varray.get(0), 3); EXPECT_EQ(varray.get(4), 7); @@ -23,7 +23,7 @@ TEST(virtual_array, Span) TEST(virtual_array, Single) { - VArray_For_Single<int> varray{10, 4}; + VArray<int> varray = VArray<int>::ForSingle(10, 4); EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray.get(0), 10); EXPECT_EQ(varray.get(3), 10); @@ -35,7 +35,7 @@ TEST(virtual_array, Array) { Array<int> array = {1, 2, 3, 5, 8}; { - VArray_For_ArrayContainer varray{array}; + VArray<int> varray = VArray<int>::ForContainer(array); EXPECT_EQ(varray.size(), 5); EXPECT_EQ(varray[0], 1); EXPECT_EQ(varray[2], 3); @@ -43,7 +43,7 @@ TEST(virtual_array, Array) EXPECT_TRUE(varray.is_span()); } { - VArray_For_ArrayContainer varray{std::move(array)}; + VArray<int> varray = VArray<int>::ForContainer(std::move(array)); EXPECT_EQ(varray.size(), 5); EXPECT_EQ(varray[0], 1); EXPECT_EQ(varray[2], 3); @@ -51,7 +51,7 @@ TEST(virtual_array, Array) EXPECT_TRUE(varray.is_span()); } { - VArray_For_ArrayContainer varray{array}; /* NOLINT: bugprone-use-after-move */ + VArray<int> varray = VArray<int>::ForContainer(array); /* NOLINT: bugprone-use-after-move */ EXPECT_TRUE(varray.is_empty()); } } @@ -59,7 +59,7 @@ TEST(virtual_array, Array) TEST(virtual_array, Vector) { Vector<int> vector = {9, 8, 7, 6}; - VArray_For_ArrayContainer varray{std::move(vector)}; + VArray<int> varray = VArray<int>::ForContainer(std::move(vector)); EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray[0], 9); EXPECT_EQ(varray[3], 6); @@ -68,7 +68,7 @@ TEST(virtual_array, Vector) TEST(virtual_array, StdVector) { std::vector<int> vector = {5, 6, 7, 8}; - VArray_For_ArrayContainer varray{std::move(vector)}; + VArray<int> varray = VArray<int>::ForContainer(std::move(vector)); EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray[0], 5); EXPECT_EQ(varray[1], 6); @@ -77,7 +77,7 @@ TEST(virtual_array, StdVector) TEST(virtual_array, StdArray) { std::array<int, 4> array = {2, 3, 4, 5}; - VArray_For_ArrayContainer varray{array}; + VArray<int> varray = VArray<int>::ForContainer(std::move(array)); EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray[0], 2); EXPECT_EQ(varray[1], 3); @@ -86,7 +86,7 @@ TEST(virtual_array, StdArray) TEST(virtual_array, VectorSet) { VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1}; - VArray_For_ArrayContainer varray{std::move(vector_set)}; + VArray<int> varray = VArray<int>::ForContainer(std::move(vector_set)); EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */ EXPECT_EQ(varray.size(), 4); EXPECT_EQ(varray[0], 5); @@ -98,7 +98,7 @@ TEST(virtual_array, VectorSet) TEST(virtual_array, Func) { auto func = [](int64_t index) { return (int)(index * index); }; - VArray_For_Func<int, decltype(func)> varray{10, func}; + VArray<int> varray = VArray<int>::ForFunc(10, func); EXPECT_EQ(varray.size(), 10); EXPECT_EQ(varray[0], 0); EXPECT_EQ(varray[3], 9); @@ -108,7 +108,7 @@ TEST(virtual_array, Func) TEST(virtual_array, AsSpan) { auto func = [](int64_t index) { return (int)(10 * index); }; - VArray_For_Func<int, decltype(func)> func_varray{10, func}; + VArray<int> func_varray = VArray<int>::ForFunc(10, func); VArray_Span span_varray{func_varray}; EXPECT_EQ(span_varray.size(), 10); Span<int> span = span_varray; @@ -134,13 +134,14 @@ TEST(virtual_array, DerivedSpan) vector.append({3, 4, 5}); vector.append({1, 1, 1}); { - VArray_For_DerivedSpan<std::array<int, 3>, int, get_x> varray{vector}; + VArray<int> varray = VArray<int>::ForDerivedSpan<std::array<int, 3>, get_x>(vector); EXPECT_EQ(varray.size(), 2); EXPECT_EQ(varray[0], 3); EXPECT_EQ(varray[1], 1); } { - VMutableArray_For_DerivedSpan<std::array<int, 3>, int, get_x, set_x> varray{vector}; + VMutableArray<int> varray = + VMutableArray<int>::ForDerivedSpan<std::array<int, 3>, get_x, set_x>(vector); EXPECT_EQ(varray.size(), 2); EXPECT_EQ(varray[0], 3); EXPECT_EQ(varray[1], 1); @@ -151,4 +152,32 @@ TEST(virtual_array, DerivedSpan) } } +TEST(virtual_array, MutableToImmutable) +{ + std::array<int, 4> array = {4, 2, 6, 4}; + { + VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array); + VArray<int> varray = mutable_varray; + EXPECT_TRUE(varray.is_span()); + EXPECT_EQ(varray.size(), 4); + EXPECT_EQ(varray[1], 2); + EXPECT_EQ(mutable_varray.size(), 4); + } + { + VMutableArray<int> mutable_varray = VMutableArray<int>::ForSpan(array); + EXPECT_EQ(mutable_varray.size(), 4); + VArray<int> varray = std::move(mutable_varray); + EXPECT_TRUE(varray.is_span()); + EXPECT_EQ(varray.size(), 4); + EXPECT_EQ(varray[1], 2); + EXPECT_EQ(mutable_varray.size(), 0); + } + { + VArray<int> varray = VMutableArray<int>::ForSpan(array); + EXPECT_TRUE(varray.is_span()); + EXPECT_EQ(varray.size(), 4); + EXPECT_EQ(varray[1], 2); + } +} + } // namespace blender::tests diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index cf048d1bbd8..fef84719bc4 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -78,7 +78,7 @@ static std::optional<eSpreadsheetColumnValueType> cpp_type_to_column_value_type( void ExtraColumns::foreach_default_column_ids( FunctionRef<void(const SpreadsheetColumnID &, bool is_extra)> fn) const { - for (const auto &item : columns_.items()) { + for (const auto item : columns_.items()) { SpreadsheetColumnID column_id; column_id.name = (char *)item.key.c_str(); fn(column_id, true); @@ -168,12 +168,12 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( if (!attribute) { return {}; } - const fn::GVArray *varray = scope_.add(std::move(attribute.varray)); + fn::GVArray varray = std::move(attribute.varray); if (attribute.domain != domain_) { return {}; } - int domain_size = varray->size(); - const CustomDataType type = bke::cpp_type_to_custom_data_type(varray->type()); + int domain_size = varray.size(); + const CustomDataType type = bke::cpp_type_to_custom_data_type(varray.type()); switch (type) { case CD_PROP_FLOAT: return column_values_from_function(SPREADSHEET_VALUE_TYPE_FLOAT, @@ -181,7 +181,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( domain_size, [varray](int index, CellValue &r_cell_value) { float value; - varray->get(index, &value); + varray.get(index, &value); r_cell_value.value_float = value; }); case CD_PROP_INT32: @@ -191,7 +191,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( domain_size, [varray](int index, CellValue &r_cell_value) { int value; - varray->get(index, &value); + varray.get(index, &value); r_cell_value.value_int = value; }, STREQ(column_id.name, "id") ? 5.5f : 0.0f); @@ -201,7 +201,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( domain_size, [varray](int index, CellValue &r_cell_value) { bool value; - varray->get(index, &value); + varray.get(index, &value); r_cell_value.value_bool = value; }); case CD_PROP_FLOAT2: { @@ -210,7 +210,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( domain_size, [varray](int index, CellValue &r_cell_value) { float2 value; - varray->get(index, &value); + varray.get(index, &value); r_cell_value.value_float2 = value; }); } @@ -220,7 +220,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( domain_size, [varray](int index, CellValue &r_cell_value) { float3 value; - varray->get(index, &value); + varray.get(index, &value); r_cell_value.value_float3 = value; }); } @@ -230,7 +230,7 @@ std::unique_ptr<ColumnValues> GeometryDataSource::get_column_values( domain_size, [varray](int index, CellValue &r_cell_value) { ColorGeometry4f value; - varray->get(index, &value); + varray.get(index, &value); r_cell_value.value_color = value; }); } @@ -738,7 +738,7 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet, const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain; const int domain_size = component.attribute_domain_size(domain); - for (const auto &item : fields_to_show.items()) { + for (const auto item : fields_to_show.items()) { StringRef name = item.key; const GField &field = item.value; diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh index 5e0302130af..fb488fdbfa9 100644 --- a/source/blender/functions/FN_field.hh +++ b/source/blender/functions/FN_field.hh @@ -248,9 +248,9 @@ class FieldInput : public FieldNode { * Get the value of this specific input based on the given context. The returned virtual array, * should live at least as long as the passed in #scope. May return null. */ - virtual const GVArray *get_varray_for_context(const FieldContext &context, - IndexMask mask, - ResourceScope &scope) const = 0; + virtual GVArray get_varray_for_context(const FieldContext &context, + IndexMask mask, + ResourceScope &scope) const = 0; virtual std::string socket_inspection_name() const; blender::StringRef debug_name() const; @@ -268,9 +268,9 @@ class FieldContext { public: ~FieldContext() = default; - virtual const GVArray *get_varray_for_input(const FieldInput &field_input, - IndexMask mask, - ResourceScope &scope) const; + virtual GVArray get_varray_for_input(const FieldInput &field_input, + IndexMask mask, + ResourceScope &scope) const; }; /** @@ -289,8 +289,8 @@ class FieldEvaluator : NonMovable, NonCopyable { const FieldContext &context_; const IndexMask mask_; Vector<GField> fields_to_evaluate_; - Vector<GVMutableArray *> dst_varrays_; - Vector<const GVArray *> evaluated_varrays_; + Vector<GVMutableArray> dst_varrays_; + Vector<GVArray> evaluated_varrays_; Vector<OutputPointerInfo> output_pointer_infos_; bool is_evaluated_ = false; @@ -317,13 +317,12 @@ class FieldEvaluator : NonMovable, NonCopyable { * \param field: Field to add to the evaluator. * \param dst: Mutable virtual array that the evaluated result for this field is be written into. */ - int add_with_destination(GField field, GVMutableArray &dst); + int add_with_destination(GField field, GVMutableArray dst); /** Same as #add_with_destination but typed. */ - template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> &dst) + template<typename T> int add_with_destination(Field<T> field, VMutableArray<T> dst) { - GVMutableArray &varray = scope_.construct<GVMutableArray_For_VMutableArray<T>>(dst); - return this->add_with_destination(GField(std::move(field)), varray); + return this->add_with_destination(GField(std::move(field)), GVMutableArray(std::move(dst))); } /** @@ -342,11 +341,10 @@ class FieldEvaluator : NonMovable, NonCopyable { */ template<typename T> int add_with_destination(Field<T> field, MutableSpan<T> dst) { - GVMutableArray &varray = scope_.construct<GVMutableArray_For_MutableSpan<T>>(dst); - return this->add_with_destination(std::move(field), varray); + return this->add_with_destination(std::move(field), VMutableArray<T>::ForSpan(dst)); } - int add(GField field, const GVArray **varray_ptr); + int add(GField field, GVArray *varray_ptr); /** * \param field: Field to add to the evaluator. @@ -354,14 +352,14 @@ class FieldEvaluator : NonMovable, NonCopyable { * assigned to the given position. * \return Index of the field in the evaluator which can be used in the #get_evaluated methods. */ - template<typename T> int add(Field<T> field, const VArray<T> **varray_ptr) + template<typename T> int add(Field<T> field, VArray<T> *varray_ptr) { const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field)); - dst_varrays_.append(nullptr); - output_pointer_infos_.append( - OutputPointerInfo{varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &scope) { - *(const VArray<T> **)dst = &*scope.construct<GVArray_Typed<T>>(varray); - }}); + dst_varrays_.append({}); + output_pointer_infos_.append(OutputPointerInfo{ + varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) { + *(VArray<T> *)dst = varray.typed<T>(); + }}); return field_index; } @@ -378,14 +376,12 @@ class FieldEvaluator : NonMovable, NonCopyable { const GVArray &get_evaluated(const int field_index) const { BLI_assert(is_evaluated_); - return *evaluated_varrays_[field_index]; + return evaluated_varrays_[field_index]; } - template<typename T> const VArray<T> &get_evaluated(const int field_index) + template<typename T> VArray<T> get_evaluated(const int field_index) { - const GVArray &varray = this->get_evaluated(field_index); - GVArray_Typed<T> &typed_varray = scope_.construct<GVArray_Typed<T>>(varray); - return *typed_varray; + return this->get_evaluated(field_index).typed<T>(); } /** @@ -396,11 +392,11 @@ class FieldEvaluator : NonMovable, NonCopyable { IndexMask get_evaluated_as_mask(const int field_index); }; -Vector<const GVArray *> evaluate_fields(ResourceScope &scope, - Span<GFieldRef> fields_to_evaluate, - IndexMask mask, - const FieldContext &context, - Span<GVMutableArray *> dst_varrays = {}); +Vector<GVArray> evaluate_fields(ResourceScope &scope, + Span<GFieldRef> fields_to_evaluate, + IndexMask mask, + const FieldContext &context, + Span<GVMutableArray> dst_varrays = {}); /* -------------------------------------------------------------------- */ /** \name Utility functions for simple field creation and evaluation @@ -429,11 +425,11 @@ class IndexFieldInput final : public FieldInput { public: IndexFieldInput(); - static GVArray *get_index_varray(IndexMask mask, ResourceScope &scope); + static GVArray get_index_varray(IndexMask mask, ResourceScope &scope); - const GVArray *get_varray_for_context(const FieldContext &context, - IndexMask mask, - ResourceScope &scope) const final; + GVArray get_varray_for_context(const FieldContext &context, + IndexMask mask, + ResourceScope &scope) const final; uint64_t hash() const override; bool is_equal_to(const fn::FieldNode &other) const override; diff --git a/source/blender/functions/FN_generic_vector_array.hh b/source/blender/functions/FN_generic_vector_array.hh index 179e85671f8..57efa1b5ba9 100644 --- a/source/blender/functions/FN_generic_vector_array.hh +++ b/source/blender/functions/FN_generic_vector_array.hh @@ -125,8 +125,7 @@ template<typename T> class GVectorArray_TypedMutableRef { void extend(const int64_t index, const VArray<T> &values) { - GVArray_For_VArray<T> array{values}; - this->extend(index, array); + vector_array_->extend(index, values); } MutableSpan<T> operator[](const int64_t index) diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh index 8aad017e68b..5d33a05a693 100644 --- a/source/blender/functions/FN_generic_virtual_array.hh +++ b/source/blender/functions/FN_generic_virtual_array.hh @@ -23,8 +23,7 @@ * the data type is only known at runtime. */ -#include <optional> - +#include "BLI_timeit.hh" #include "BLI_virtual_array.hh" #include "FN_generic_array.hh" @@ -32,940 +31,845 @@ namespace blender::fn { -template<typename T> class GVArray_Typed; -template<typename T> class GVMutableArray_Typed; +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl and #GVMutableArrayImpl. + * \{ */ class GVArray; +class GVArrayImpl; class GVMutableArray; +class GVMutableArrayImpl; -using GVArrayPtr = std::unique_ptr<GVArray>; -using GVMutableArrayPtr = std::unique_ptr<GVMutableArray>; - -/* A generically typed version of `VArray<T>`. */ -class GVArray { +/* A generically typed version of #VArrayImpl. */ +class GVArrayImpl { protected: const CPPType *type_; int64_t size_; public: - GVArray(const CPPType &type, const int64_t size) : type_(&type), size_(size) - { - BLI_assert(size_ >= 0); - } + GVArrayImpl(const CPPType &type, const int64_t size); + virtual ~GVArrayImpl() = default; - virtual ~GVArray() = default; + const CPPType &type() const; - const CPPType &type() const - { - return *type_; - } + int64_t size() const; - int64_t size() const - { - return size_; - } + virtual void get(const int64_t index, void *r_value) const; + virtual void get_to_uninitialized(const int64_t index, void *r_value) const = 0; - bool is_empty() const - { - return size_ == 0; - } + virtual bool is_span() const; + virtual GSpan get_internal_span() const; - /* Copies the value at the given index into the provided storage. The `r_value` pointer is - * expected to point to initialized memory. */ - void get(const int64_t index, void *r_value) const - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - this->get_impl(index, r_value); - } + virtual bool is_single() const; + virtual void get_internal_single(void *UNUSED(r_value)) const; - /* Same as `get`, but `r_value` is expected to point to uninitialized memory. */ - void get_to_uninitialized(const int64_t index, void *r_value) const - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - this->get_to_uninitialized_impl(index, r_value); - } + virtual void materialize(const IndexMask mask, void *dst) const; + virtual void materialize_to_uninitialized(const IndexMask mask, void *dst) const; - /* Returns true when the virtual array is stored as a span internally. */ - bool is_span() const - { - if (size_ == 0) { - return true; - } - return this->is_span_impl(); - } + virtual bool try_assign_VArray(void *varray) const; + virtual bool may_have_ownership() const; +}; - /* Returns the internally used span of the virtual array. This invokes undefined behavior is the - * virtual array is not stored as a span internally. */ - GSpan get_internal_span() const - { - BLI_assert(this->is_span()); - if (size_ == 0) { - return GSpan(*type_); - } - return this->get_internal_span_impl(); - } +/* A generic version of #VMutableArrayImpl. */ +class GVMutableArrayImpl : public GVArrayImpl { + public: + GVMutableArrayImpl(const CPPType &type, const int64_t size); - /* Returns true when the virtual array returns the same value for every index. */ - bool is_single() const - { - if (size_ == 1) { - return true; - } - return this->is_single_impl(); - } + virtual void set_by_copy(const int64_t index, const void *value); + virtual void set_by_relocate(const int64_t index, void *value); + virtual void set_by_move(const int64_t index, void *value) = 0; - /* Copies the value that is used for every element into `r_value`, which is expected to point to - * initialized memory. This invokes undefined behavior if the virtual array would not return the - * same value for every index. */ - void get_internal_single(void *r_value) const - { - BLI_assert(this->is_single()); - if (size_ == 1) { - this->get(0, r_value); - return; - } - this->get_internal_single_impl(r_value); - } + virtual void set_all(const void *src); - /* Same as `get_internal_single`, but `r_value` points to initialized memory. */ - void get_internal_single_to_uninitialized(void *r_value) const - { - type_->default_construct(r_value); - this->get_internal_single(r_value); - } + virtual bool try_assign_VMutableArray(void *varray) const; +}; - void materialize(void *dst) const; - void materialize(const IndexMask mask, void *dst) const; +/** \} */ - void materialize_to_uninitialized(void *dst) const; - void materialize_to_uninitialized(const IndexMask mask, void *dst) const; +/* -------------------------------------------------------------------- */ +/** \name #GVArray and #GVMutableArray + * \{ */ - template<typename T> const VArray<T> *try_get_internal_varray() const - { - BLI_assert(type_->is<T>()); - return (const VArray<T> *)this->try_get_internal_varray_impl(); - } +namespace detail { +struct GVArrayAnyExtraInfo { + const GVArrayImpl *(*get_varray)(const void *buffer) = + [](const void *UNUSED(buffer)) -> const GVArrayImpl * { return nullptr; }; - /* Create a typed virtual array for this generic virtual array. */ - template<typename T> GVArray_Typed<T> typed() const - { - return GVArray_Typed<T>(*this); - } + template<typename StorageT> static GVArrayAnyExtraInfo get(); +}; +} // namespace detail - GVArrayPtr shallow_copy() const; +class GVMutableArray; +/** + * Utility class to reduce code duplication between #GVArray and #GVMutableArray. + * It pretty much follows #VArrayCommon. Don't use this class outside of this header. + */ +class GVArrayCommon { protected: - virtual void get_impl(const int64_t index, void *r_value) const; - virtual void get_to_uninitialized_impl(const int64_t index, void *r_value) const = 0; + /** + * See #VArrayCommon for more information. The inline buffer is a bit larger here, because + * generic virtual array implementations often require a bit more space than typed ones. + */ + using Storage = Any<detail::GVArrayAnyExtraInfo, 40, 8>; - virtual bool is_span_impl() const; - virtual GSpan get_internal_span_impl() const; + const GVArrayImpl *impl_ = nullptr; + Storage storage_; - virtual bool is_single_impl() const; - virtual void get_internal_single_impl(void *UNUSED(r_value)) const; + protected: + GVArrayCommon(); + GVArrayCommon(const GVArrayCommon &other); + GVArrayCommon(GVArrayCommon &&other) noexcept; + GVArrayCommon(const GVArrayImpl *impl); + GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl); + ~GVArrayCommon(); - virtual void materialize_impl(const IndexMask mask, void *dst) const; - virtual void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const; + template<typename ImplT, typename... Args> void emplace(Args &&...args); - virtual const void *try_get_internal_varray_impl() const; -}; + void copy_from(const GVArrayCommon &other); + void move_from(GVArrayCommon &&other) noexcept; + + const GVArrayImpl *impl_from_storage() const; -/* Similar to GVArray, but supports changing the elements in the virtual array. */ -class GVMutableArray : public GVArray { public: - GVMutableArray(const CPPType &type, const int64_t size) : GVArray(type, size) - { - } + const CPPType &type() const; + operator bool() const; - void set_by_copy(const int64_t index, const void *value) - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - this->set_by_copy_impl(index, value); - } + int64_t size() const; + bool is_empty() const; + IndexRange index_range() const; - void set_by_move(const int64_t index, void *value) - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - this->set_by_move_impl(index, value); - } + template<typename T> bool try_assign_VArray(VArray<T> &varray) const; + bool may_have_ownership() const; - void set_by_relocate(const int64_t index, void *value) - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - this->set_by_relocate_impl(index, value); - } + void materialize(void *dst) const; + void materialize(const IndexMask mask, void *dst) const; - GMutableSpan get_internal_span() - { - BLI_assert(this->is_span()); - GSpan span = static_cast<const GVArray *>(this)->get_internal_span(); - return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size()); - } + void materialize_to_uninitialized(void *dst) const; + void materialize_to_uninitialized(const IndexMask mask, void *dst) const; - template<typename T> VMutableArray<T> *try_get_internal_mutable_varray() - { - BLI_assert(type_->is<T>()); - return (VMutableArray<T> *)this->try_get_internal_mutable_varray_impl(); - } + bool is_span() const; + GSpan get_internal_span() const; - /* Create a typed virtual array for this generic virtual array. */ - template<typename T> GVMutableArray_Typed<T> typed() - { - return GVMutableArray_Typed<T>(*this); - } + bool is_single() const; + void get_internal_single(void *r_value) const; + void get_internal_single_to_uninitialized(void *r_value) const; - void fill(const void *value); + void get(const int64_t index, void *r_value) const; + void get_to_uninitialized(const int64_t index, void *r_value) const; +}; - /* Copy the values from the source buffer to all elements in the virtual array. */ - void set_all(const void *src) - { - this->set_all_impl(src); - } +/** Generic version of #VArray. */ +class GVArray : public GVArrayCommon { + private: + friend GVMutableArray; - protected: - virtual void set_by_copy_impl(const int64_t index, const void *value); - virtual void set_by_relocate_impl(const int64_t index, void *value); - virtual void set_by_move_impl(const int64_t index, void *value) = 0; + public: + GVArray() = default; - virtual void set_all_impl(const void *src); + GVArray(const GVArray &other); + GVArray(GVArray &&other) noexcept; + GVArray(const GVArrayImpl *impl); + GVArray(std::shared_ptr<const GVArrayImpl> impl); - virtual void *try_get_internal_mutable_varray_impl(); -}; + template<typename T> GVArray(const VArray<T> &varray); + template<typename T> VArray<T> typed() const; -class GVArray_For_GSpan : public GVArray { - protected: - const void *data_ = nullptr; - const int64_t element_size_; + template<typename ImplT, typename... Args> static GVArray For(Args &&...args); - public: - GVArray_For_GSpan(const GSpan span) - : GVArray(span.type(), span.size()), data_(span.data()), element_size_(span.type().size()) - { - } + static GVArray ForSingle(const CPPType &type, const int64_t size, const void *value); + static GVArray ForSingleRef(const CPPType &type, const int64_t size, const void *value); + static GVArray ForSingleDefault(const CPPType &type, const int64_t size); + static GVArray ForSpan(GSpan span); + static GVArray ForGArray(GArray<> array); + static GVArray ForEmpty(const CPPType &type); - protected: - GVArray_For_GSpan(const CPPType &type, const int64_t size) - : GVArray(type, size), element_size_(type.size()) - { - } + GVArray slice(IndexRange slice) const; - void get_impl(const int64_t index, void *r_value) const override; - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override; + GVArray &operator=(const GVArray &other); + GVArray &operator=(GVArray &&other) noexcept; - bool is_span_impl() const override; - GSpan get_internal_span_impl() const override; + const GVArrayImpl *get_implementation() const + { + return impl_; + } }; -class GVArray_For_Empty : public GVArray { +/** Generic version of #VMutableArray. */ +class GVMutableArray : public GVArrayCommon { public: - GVArray_For_Empty(const CPPType &type) : GVArray(type, 0) - { - } + GVMutableArray() = default; + GVMutableArray(const GVMutableArray &other); + GVMutableArray(GVMutableArray &&other) noexcept; + GVMutableArray(GVMutableArrayImpl *impl); + GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl); - protected: - void get_to_uninitialized_impl(const int64_t UNUSED(index), void *UNUSED(r_value)) const override - { - BLI_assert(false); - } -}; + template<typename T> GVMutableArray(const VMutableArray<T> &varray); + template<typename T> VMutableArray<T> typed() const; -class GVMutableArray_For_GMutableSpan : public GVMutableArray { - protected: - void *data_ = nullptr; - const int64_t element_size_; + template<typename ImplT, typename... Args> static GVMutableArray For(Args &&...args); - public: - GVMutableArray_For_GMutableSpan(const GMutableSpan span) - : GVMutableArray(span.type(), span.size()), - data_(span.data()), - element_size_(span.type().size()) - { - } + static GVMutableArray ForSpan(GMutableSpan span); - protected: - GVMutableArray_For_GMutableSpan(const CPPType &type, const int64_t size) - : GVMutableArray(type, size), element_size_(type.size()) - { - } + operator GVArray() const &; + operator GVArray() &&noexcept; - void get_impl(const int64_t index, void *r_value) const override; - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override; + GVMutableArray &operator=(const GVMutableArray &other); + GVMutableArray &operator=(GVMutableArray &&other) noexcept; - void set_by_copy_impl(const int64_t index, const void *value) override; - void set_by_move_impl(const int64_t index, void *value) override; - void set_by_relocate_impl(const int64_t index, void *value) override; + GMutableSpan get_internal_span() const; - bool is_span_impl() const override; - GSpan get_internal_span_impl() const override; -}; + template<typename T> bool try_assign_VMutableArray(VMutableArray<T> &varray) const; -/* Generic virtual array where each element has the same value. The value is not owned. */ -class GVArray_For_SingleValueRef : public GVArray { - protected: - const void *value_ = nullptr; + void set_by_copy(const int64_t index, const void *value); + void set_by_move(const int64_t index, void *value); + void set_by_relocate(const int64_t index, void *value); - public: - GVArray_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value) - : GVArray(type, size), value_(value) - { - } + void fill(const void *value); + void set_all(const void *src); - protected: - GVArray_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArray(type, size) - { - } + GVMutableArrayImpl *get_implementation() const; - void get_impl(const int64_t index, void *r_value) const override; - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override; + private: + GVMutableArrayImpl *get_impl() const; +}; - bool is_span_impl() const override; - GSpan get_internal_span_impl() const override; +/** \} */ - bool is_single_impl() const override; - void get_internal_single_impl(void *r_value) const override; +/* -------------------------------------------------------------------- */ +/** \name #GVArray_GSpan and #GVMutableArray_GSpan. + * \{ */ + +/* A generic version of VArray_Span. */ +class GVArray_GSpan : public GSpan { + private: + GVArray varray_; + void *owned_data_ = nullptr; + + public: + GVArray_GSpan(GVArray varray); + ~GVArray_GSpan(); }; -/* Same as GVArray_For_SingleValueRef, but the value is owned. */ -class GVArray_For_SingleValue : public GVArray_For_SingleValueRef { +/* A generic version of VMutableArray_Span. */ +class GVMutableArray_GSpan : public GMutableSpan { + private: + GVMutableArray varray_; + void *owned_data_ = nullptr; + bool save_has_been_called_ = false; + bool show_not_saved_warning_ = true; + public: - GVArray_For_SingleValue(const CPPType &type, const int64_t size, const void *value); - ~GVArray_For_SingleValue(); + GVMutableArray_GSpan(GVMutableArray varray, bool copy_values_to_span = true); + ~GVMutableArray_GSpan(); + + void save(); + void disable_not_applied_warning(); }; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Conversions between generic and typed virtual arrays. + * \{ */ + /* Used to convert a typed virtual array into a generic one. */ -template<typename T> class GVArray_For_VArray : public GVArray { +template<typename T> class GVArrayImpl_For_VArray : public GVArrayImpl { protected: - const VArray<T> *varray_ = nullptr; + VArray<T> varray_; public: - GVArray_For_VArray(const VArray<T> &varray) - : GVArray(CPPType::get<T>(), varray.size()), varray_(&varray) + GVArrayImpl_For_VArray(VArray<T> varray) + : GVArrayImpl(CPPType::get<T>(), varray.size()), varray_(std::move(varray)) { } protected: - GVArray_For_VArray(const int64_t size) : GVArray(CPPType::get<T>(), size) + void get(const int64_t index, void *r_value) const override { + *(T *)r_value = varray_[index]; } - void get_impl(const int64_t index, void *r_value) const override + void get_to_uninitialized(const int64_t index, void *r_value) const override { - *(T *)r_value = varray_->get(index); + new (r_value) T(varray_[index]); } - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override + bool is_span() const override { - new (r_value) T(varray_->get(index)); + return varray_.is_span(); } - bool is_span_impl() const override + GSpan get_internal_span() const override { - return varray_->is_span(); + return GSpan(varray_.get_internal_span()); } - GSpan get_internal_span_impl() const override + bool is_single() const override { - return GSpan(varray_->get_internal_span()); + return varray_.is_single(); } - bool is_single_impl() const override + void get_internal_single(void *r_value) const override { - return varray_->is_single(); + *(T *)r_value = varray_.get_internal_single(); } - void get_internal_single_impl(void *r_value) const override + void materialize(const IndexMask mask, void *dst) const override { - *(T *)r_value = varray_->get_internal_single(); + varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); } - void materialize_impl(const IndexMask mask, void *dst) const override + void materialize_to_uninitialized(const IndexMask mask, void *dst) const override { - varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); } - void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override + bool try_assign_VArray(void *varray) const override { - varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); + *(VArray<T> *)varray = varray_; + return true; } - const void *try_get_internal_varray_impl() const override - { - return varray_; - } -}; - -class GVArray_For_GArray : public GVArray_For_GSpan { - protected: - GArray<> array_; - - public: - GVArray_For_GArray(GArray<> array) : GVArray_For_GSpan(array.as_span()), array_(std::move(array)) + bool may_have_ownership() const override { + return varray_.may_have_ownership(); } }; /* Used to convert any generic virtual array into a typed one. */ -template<typename T> class VArray_For_GVArray : public VArray<T> { +template<typename T> class VArrayImpl_For_GVArray : public VArrayImpl<T> { protected: - const GVArray *varray_ = nullptr; + GVArray varray_; public: - VArray_For_GVArray(const GVArray &varray) : VArray<T>(varray.size()), varray_(&varray) + VArrayImpl_For_GVArray(GVArray varray) : VArrayImpl<T>(varray.size()), varray_(std::move(varray)) { - BLI_assert(varray_->type().template is<T>()); + BLI_assert(varray_); + BLI_assert(varray_.type().is<T>()); } protected: - VArray_For_GVArray(const int64_t size) : VArray<T>(size) - { - } - - T get_impl(const int64_t index) const override + T get(const int64_t index) const override { T value; - varray_->get(index, &value); + varray_.get(index, &value); return value; } - bool is_span_impl() const override + bool is_span() const override { - return varray_->is_span(); + return varray_.is_span(); } - Span<T> get_internal_span_impl() const override + Span<T> get_internal_span() const override { - return varray_->get_internal_span().template typed<T>(); + return varray_.get_internal_span().template typed<T>(); } - bool is_single_impl() const override + bool is_single() const override { - return varray_->is_single(); + return varray_.is_single(); } - T get_internal_single_impl() const override + T get_internal_single() const override { T value; - varray_->get_internal_single(&value); + varray_.get_internal_single(&value); return value; } -}; - -/* Used to convert an generic mutable virtual array into a typed one. */ -template<typename T> class VMutableArray_For_GVMutableArray : public VMutableArray<T> { - protected: - GVMutableArray *varray_ = nullptr; - - public: - VMutableArray_For_GVMutableArray(GVMutableArray &varray) - : VMutableArray<T>(varray.size()), varray_(&varray) - { - BLI_assert(varray.type().template is<T>()); - } - - VMutableArray_For_GVMutableArray(const int64_t size) : VMutableArray<T>(size) - { - } - - private: - T get_impl(const int64_t index) const override - { - T value; - varray_->get(index, &value); - return value; - } - - void set_impl(const int64_t index, T value) override - { - varray_->set_by_relocate(index, &value); - } - - bool is_span_impl() const override - { - return varray_->is_span(); - } - Span<T> get_internal_span_impl() const override + bool try_assign_GVArray(GVArray &varray) const override { - return varray_->get_internal_span().template typed<T>(); + varray = varray_; + return true; } - bool is_single_impl() const override + bool may_have_ownership() const override { - return varray_->is_single(); - } - - T get_internal_single_impl() const override - { - T value; - varray_->get_internal_single(&value); - return value; + return varray_.may_have_ownership(); } }; /* Used to convert any typed virtual mutable array into a generic one. */ -template<typename T> class GVMutableArray_For_VMutableArray : public GVMutableArray { +template<typename T> class GVMutableArrayImpl_For_VMutableArray : public GVMutableArrayImpl { protected: - VMutableArray<T> *varray_ = nullptr; + VMutableArray<T> varray_; public: - GVMutableArray_For_VMutableArray(VMutableArray<T> &varray) - : GVMutableArray(CPPType::get<T>(), varray.size()), varray_(&varray) + GVMutableArrayImpl_For_VMutableArray(VMutableArray<T> varray) + : GVMutableArrayImpl(CPPType::get<T>(), varray.size()), varray_(std::move(varray)) { } protected: - GVMutableArray_For_VMutableArray(const int64_t size) : GVMutableArray(CPPType::get<T>(), size) + void get(const int64_t index, void *r_value) const override { + *(T *)r_value = varray_[index]; } - void get_impl(const int64_t index, void *r_value) const override + void get_to_uninitialized(const int64_t index, void *r_value) const override { - *(T *)r_value = varray_->get(index); + new (r_value) T(varray_[index]); } - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override + bool is_span() const override { - new (r_value) T(varray_->get(index)); + return varray_.is_span(); } - bool is_span_impl() const override + GSpan get_internal_span() const override { - return varray_->is_span(); - } - - GSpan get_internal_span_impl() const override - { - Span<T> span = varray_->get_internal_span(); + Span<T> span = varray_.get_internal_span(); return span; } - bool is_single_impl() const override + bool is_single() const override { - return varray_->is_single(); + return varray_.is_single(); } - void get_internal_single_impl(void *r_value) const override + void get_internal_single(void *r_value) const override { - *(T *)r_value = varray_->get_internal_single(); + *(T *)r_value = varray_.get_internal_single(); } - void set_by_copy_impl(const int64_t index, const void *value) override + void set_by_copy(const int64_t index, const void *value) override { const T &value_ = *(const T *)value; - varray_->set(index, value_); + varray_.set(index, value_); } - void set_by_relocate_impl(const int64_t index, void *value) override + void set_by_relocate(const int64_t index, void *value) override { T &value_ = *(T *)value; - varray_->set(index, std::move(value_)); + varray_.set(index, std::move(value_)); value_.~T(); } - void set_by_move_impl(const int64_t index, void *value) override + void set_by_move(const int64_t index, void *value) override { T &value_ = *(T *)value; - varray_->set(index, std::move(value_)); + varray_.set(index, std::move(value_)); } - void set_all_impl(const void *src) override + void set_all(const void *src) override { - varray_->set_all(Span((T *)src, size_)); + varray_.set_all(Span((T *)src, size_)); } - void materialize_impl(const IndexMask mask, void *dst) const override + void materialize(const IndexMask mask, void *dst) const override { - varray_->materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); } - void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override + void materialize_to_uninitialized(const IndexMask mask, void *dst) const override { - varray_->materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); + varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); } - const void *try_get_internal_varray_impl() const override + bool try_assign_VArray(void *varray) const override { - return (const VArray<T> *)varray_; + *(VArray<T> *)varray = varray_; + return true; } - void *try_get_internal_mutable_varray_impl() override + bool try_assign_VMutableArray(void *varray) const override { - return varray_; + *(VMutableArray<T> *)varray = varray_; + return true; } -}; - -/* A generic version of VArray_Span. */ -class GVArray_GSpan : public GSpan { - private: - const GVArray &varray_; - void *owned_data_ = nullptr; - - public: - GVArray_GSpan(const GVArray &varray); - ~GVArray_GSpan(); -}; - -/* A generic version of VMutableArray_Span. */ -class GVMutableArray_GSpan : public GMutableSpan { - private: - GVMutableArray &varray_; - void *owned_data_ = nullptr; - bool save_has_been_called_ = false; - bool show_not_saved_warning_ = true; - - public: - GVMutableArray_GSpan(GVMutableArray &varray, bool copy_values_to_span = true); - ~GVMutableArray_GSpan(); - - void save(); - void disable_not_applied_warning(); -}; - -/* Similar to GVArray_GSpan, but the resulting span is typed. */ -template<typename T> class GVArray_Span : public Span<T> { - private: - GVArray_GSpan varray_gspan_; - public: - GVArray_Span(const GVArray &varray) : varray_gspan_(varray) + bool may_have_ownership() const override { - BLI_assert(varray.type().is<T>()); - this->data_ = (const T *)varray_gspan_.data(); - this->size_ = varray_gspan_.size(); + return varray_.may_have_ownership(); } }; -template<typename T> class GVArray_For_OwnedVArray : public GVArray_For_VArray<T> { - private: - VArrayPtr<T> owned_varray_; +/* Used to convert an generic mutable virtual array into a typed one. */ +template<typename T> class VMutableArrayImpl_For_GVMutableArray : public VMutableArrayImpl<T> { + protected: + GVMutableArray varray_; public: - /* Takes ownership of varray and passes a reference to the base class. */ - GVArray_For_OwnedVArray(VArrayPtr<T> varray) - : GVArray_For_VArray<T>(*varray), owned_varray_(std::move(varray)) + VMutableArrayImpl_For_GVMutableArray(GVMutableArray varray) + : VMutableArrayImpl<T>(varray.size()), varray_(varray) { + BLI_assert(varray_); + BLI_assert(varray_.type().is<T>()); } -}; -template<typename T> class VArray_For_OwnedGVArray : public VArray_For_GVArray<T> { private: - GVArrayPtr owned_varray_; - - public: - /* Takes ownership of varray and passes a reference to the base class. */ - VArray_For_OwnedGVArray(GVArrayPtr varray) - : VArray_For_GVArray<T>(*varray), owned_varray_(std::move(varray)) + T get(const int64_t index) const override { + T value; + varray_.get(index, &value); + return value; } -}; -template<typename T> -class GVMutableArray_For_OwnedVMutableArray : public GVMutableArray_For_VMutableArray<T> { - private: - VMutableArrayPtr<T> owned_varray_; - - public: - /* Takes ownership of varray and passes a reference to the base class. */ - GVMutableArray_For_OwnedVMutableArray(VMutableArrayPtr<T> varray) - : GVMutableArray_For_VMutableArray<T>(*varray), owned_varray_(std::move(varray)) + void set(const int64_t index, T value) override { + varray_.set_by_relocate(index, &value); } -}; -template<typename T> -class VMutableArray_For_OwnedGVMutableArray : public VMutableArray_For_GVMutableArray<T> { - private: - GVMutableArrayPtr owned_varray_; - - public: - /* Takes ownership of varray and passes a reference to the base class. */ - VMutableArray_For_OwnedGVMutableArray(GVMutableArrayPtr varray) - : VMutableArray_For_GVMutableArray<T>(*varray), owned_varray_(std::move(varray)) + bool is_span() const override { + return varray_.is_span(); } -}; - -/* Utility to embed a typed virtual array into a generic one. This avoids one allocation and give - * the compiler more opportunity to optimize the generic virtual array. */ -template<typename T, typename VArrayT> -class GVArray_For_EmbeddedVArray : public GVArray_For_VArray<T> { - private: - VArrayT embedded_varray_; - public: - template<typename... Args> - GVArray_For_EmbeddedVArray(const int64_t size, Args &&...args) - : GVArray_For_VArray<T>(size), embedded_varray_(std::forward<Args>(args)...) + Span<T> get_internal_span() const override { - this->varray_ = &embedded_varray_; + return varray_.get_internal_span().template typed<T>(); } -}; -/* Same as GVArray_For_EmbeddedVArray, but for mutable virtual arrays. */ -template<typename T, typename VMutableArrayT> -class GVMutableArray_For_EmbeddedVMutableArray : public GVMutableArray_For_VMutableArray<T> { - private: - VMutableArrayT embedded_varray_; - - public: - template<typename... Args> - GVMutableArray_For_EmbeddedVMutableArray(const int64_t size, Args &&...args) - : GVMutableArray_For_VMutableArray<T>(size), embedded_varray_(std::forward<Args>(args)...) + bool is_single() const override { - this->varray_ = &embedded_varray_; + return varray_.is_single(); } -}; -/* Same as VArray_For_ArrayContainer, but for a generic virtual array. */ -template<typename Container, typename T = typename Container::value_type> -class GVArray_For_ArrayContainer - : public GVArray_For_EmbeddedVArray<T, VArray_For_ArrayContainer<Container, T>> { - public: - GVArray_For_ArrayContainer(Container container) - : GVArray_For_EmbeddedVArray<T, VArray_For_ArrayContainer<Container, T>>( - container.size(), std::move(container)) + T get_internal_single() const override { + T value; + varray_.get_internal_single(&value); + return value; } -}; -/* Same as VArray_For_DerivedSpan, but for a generic virtual array. */ -template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> -class GVArray_For_DerivedSpan - : public GVArray_For_EmbeddedVArray<ElemT, VArray_For_DerivedSpan<StructT, ElemT, GetFunc>> { - public: - GVArray_For_DerivedSpan(const Span<StructT> data) - : GVArray_For_EmbeddedVArray<ElemT, VArray_For_DerivedSpan<StructT, ElemT, GetFunc>>( - data.size(), data) + bool try_assign_GVArray(GVArray &varray) const override { + varray = varray_; + return true; } -}; -/* Same as VMutableArray_For_DerivedSpan, but for a generic virtual array. */ -template<typename StructT, - typename ElemT, - ElemT (*GetFunc)(const StructT &), - void (*SetFunc)(StructT &, ElemT)> -class GVMutableArray_For_DerivedSpan - : public GVMutableArray_For_EmbeddedVMutableArray< - ElemT, - VMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>> { - public: - GVMutableArray_For_DerivedSpan(const MutableSpan<StructT> data) - : GVMutableArray_For_EmbeddedVMutableArray< - ElemT, - VMutableArray_For_DerivedSpan<StructT, ElemT, GetFunc, SetFunc>>(data.size(), data) + bool try_assign_GVMutableArray(GVMutableArray &varray) const override { + varray = varray_; + return true; } -}; -/* Same as VArray_For_Span, but for a generic virtual array. */ -template<typename T> -class GVArray_For_Span : public GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>> { - public: - GVArray_For_Span(const Span<T> data) - : GVArray_For_EmbeddedVArray<T, VArray_For_Span<T>>(data.size(), data) + bool may_have_ownership() const override { + return varray_.may_have_ownership(); } }; -/* Same as VMutableArray_For_MutableSpan, but for a generic virtual array. */ -template<typename T> -class GVMutableArray_For_MutableSpan - : public GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_MutableSpan<T>> { +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl_For_GSpan and #GVMutableArrayImpl_For_GMutableSpan. + * \{ */ + +class GVArrayImpl_For_GSpan : public GVArrayImpl { + protected: + const void *data_ = nullptr; + const int64_t element_size_; + public: - GVMutableArray_For_MutableSpan(const MutableSpan<T> data) - : GVMutableArray_For_EmbeddedVMutableArray<T, VMutableArray_For_MutableSpan<T>>(data.size(), - data) - { - } + GVArrayImpl_For_GSpan(const GSpan span); + + protected: + GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size); + + void get(const int64_t index, void *r_value) const override; + void get_to_uninitialized(const int64_t index, void *r_value) const override; + + bool is_span() const override; + GSpan get_internal_span() const override; }; -/** - * Utility class to create the "best" typed virtual array for a given generic virtual array. - * In most cases we don't just want to use VArray_For_GVArray, because it adds an additional - * indirection on element-access that can be avoided in many cases (e.g. when the virtual array is - * just a span or single value). - * - * This is not a virtual array itself, but is used to get a virtual array. - */ -template<typename T> class GVArray_Typed { - private: - const VArray<T> *varray_; - /* Of these optional virtual arrays, at most one is constructed at any time. */ - std::optional<VArray_For_Span<T>> varray_span_; - std::optional<VArray_For_Single<T>> varray_single_; - std::optional<VArray_For_GVArray<T>> varray_any_; - GVArrayPtr owned_gvarray_; +class GVMutableArrayImpl_For_GMutableSpan : public GVMutableArrayImpl { + protected: + void *data_ = nullptr; + const int64_t element_size_; public: - explicit GVArray_Typed(const GVArray &gvarray) - { - BLI_assert(gvarray.type().is<T>()); - if (gvarray.is_span()) { - const GSpan span = gvarray.get_internal_span(); - varray_span_.emplace(span.typed<T>()); - varray_ = &*varray_span_; - } - else if (gvarray.is_single()) { - T single_value; - gvarray.get_internal_single(&single_value); - varray_single_.emplace(single_value, gvarray.size()); - varray_ = &*varray_single_; - } - else if (const VArray<T> *internal_varray = gvarray.try_get_internal_varray<T>()) { - varray_ = internal_varray; - } - else { - varray_any_.emplace(gvarray); - varray_ = &*varray_any_; - } - } + GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span); - /* Same as the constructor above, but also takes ownership of the passed in virtual array. */ - explicit GVArray_Typed(GVArrayPtr gvarray) : GVArray_Typed(*gvarray) - { - owned_gvarray_ = std::move(gvarray); - } + protected: + GVMutableArrayImpl_For_GMutableSpan(const CPPType &type, const int64_t size); - const VArray<T> &operator*() const - { - return *varray_; - } + public: + void get(const int64_t index, void *r_value) const override; + void get_to_uninitialized(const int64_t index, void *r_value) const override; - const VArray<T> *operator->() const - { - return varray_; - } + void set_by_copy(const int64_t index, const void *value) override; + void set_by_move(const int64_t index, void *value) override; + void set_by_relocate(const int64_t index, void *value) override; - /* Support implicit cast to the typed virtual array for convenience when `varray->typed<T>()` is - * used within an expression. */ - operator const VArray<T> &() const - { - return *varray_; - } + bool is_span() const override; + GSpan get_internal_span() const override; +}; - T operator[](const int64_t index) const - { - return varray_->get(index); - } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVArrayImpl. + * \{ */ + +inline GVArrayImpl::GVArrayImpl(const CPPType &type, const int64_t size) + : type_(&type), size_(size) +{ + BLI_assert(size_ >= 0); +} + +inline const CPPType &GVArrayImpl::type() const +{ + return *type_; +} + +inline int64_t GVArrayImpl::size() const +{ + return size_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVMutableArrayImpl. + * \{ */ + +inline void GVMutableArray::set_by_copy(const int64_t index, const void *value) +{ + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + this->get_impl()->set_by_copy(index, value); +} + +inline void GVMutableArray::set_by_move(const int64_t index, void *value) +{ + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + this->get_impl()->set_by_move(index, value); +} + +inline void GVMutableArray::set_by_relocate(const int64_t index, void *value) +{ + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + this->get_impl()->set_by_relocate(index, value); +} - int64_t size() const - { - return varray_->size(); +template<typename T> +inline bool GVMutableArray::try_assign_VMutableArray(VMutableArray<T> &varray) const +{ + BLI_assert(impl_->type().is<T>()); + return this->get_impl()->try_assign_VMutableArray(&varray); +} + +inline GVMutableArrayImpl *GVMutableArray::get_impl() const +{ + return (GVMutableArrayImpl *)impl_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVArrayCommon. + * \{ */ + +template<typename ImplT, typename... Args> inline void GVArrayCommon::emplace(Args &&...args) +{ + static_assert(std::is_base_of_v<GVArrayImpl, ImplT>); + if constexpr (std::is_copy_constructible_v<ImplT> && Storage::template is_inline_v<ImplT>) { + impl_ = &storage_.template emplace<ImplT>(std::forward<Args>(args)...); + } + else { + std::shared_ptr<const GVArrayImpl> ptr = std::make_shared<ImplT>(std::forward<Args>(args)...); + impl_ = &*ptr; + storage_ = std::move(ptr); + } +} + +/* Copies the value at the given index into the provided storage. The `r_value` pointer is + * expected to point to initialized memory. */ +inline void GVArrayCommon::get(const int64_t index, void *r_value) const +{ + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + impl_->get(index, r_value); +} + +/* Same as `get`, but `r_value` is expected to point to uninitialized memory. */ +inline void GVArrayCommon::get_to_uninitialized(const int64_t index, void *r_value) const +{ + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + impl_->get_to_uninitialized(index, r_value); +} + +template<typename T> inline bool GVArrayCommon::try_assign_VArray(VArray<T> &varray) const +{ + BLI_assert(impl_->type().is<T>()); + return impl_->try_assign_VArray(&varray); +} + +inline const CPPType &GVArrayCommon::type() const +{ + return impl_->type(); +} + +inline GVArrayCommon::operator bool() const +{ + return impl_ != nullptr; +} + +inline int64_t GVArrayCommon::size() const +{ + if (impl_ == nullptr) { + return 0; + } + return impl_->size(); +} + +inline bool GVArrayCommon::is_empty() const +{ + return this->size() == 0; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVArray. + * \{ */ + +namespace detail { +template<typename StorageT> inline GVArrayAnyExtraInfo GVArrayAnyExtraInfo::get() +{ + static_assert(std::is_base_of_v<GVArrayImpl, StorageT> || + std::is_same_v<StorageT, const GVArrayImpl *> || + std::is_same_v<StorageT, std::shared_ptr<const GVArrayImpl>>); + + if constexpr (std::is_base_of_v<GVArrayImpl, StorageT>) { + return {[](const void *buffer) { + return static_cast<const GVArrayImpl *>((const StorageT *)buffer); + }}; + } + else if constexpr (std::is_same_v<StorageT, const GVArrayImpl *>) { + return {[](const void *buffer) { return *(const StorageT *)buffer; }}; + } + else if constexpr (std::is_same_v<StorageT, std::shared_ptr<const GVArrayImpl>>) { + return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }}; + } + else { + BLI_assert_unreachable(); + return {}; + } +} +} // namespace detail + +template<typename ImplT, typename... Args> inline GVArray GVArray::For(Args &&...args) +{ + static_assert(std::is_base_of_v<GVArrayImpl, ImplT>); + GVArray varray; + varray.template emplace<ImplT>(std::forward<Args>(args)...); + return varray; +} + +template<typename T> inline GVArray::GVArray(const VArray<T> &varray) +{ + if (!varray) { + return; + } + if (varray.try_assign_GVArray(*this)) { + return; + } + /* Need to check this before the span/single special cases, because otherwise we might loose + * ownership to the referenced data when #varray goes out of scope. */ + if (varray.may_have_ownership()) { + *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); + } + else if (varray.is_span()) { + Span<T> data = varray.get_internal_span(); + *this = GVArray::ForSpan(data); + } + else if (varray.is_single()) { + T value = varray.get_internal_single(); + *this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), &value); + } + else { + *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); + } +} + +template<typename T> inline VArray<T> GVArray::typed() const +{ + if (!*this) { + return {}; + } + BLI_assert(impl_->type().is<T>()); + VArray<T> varray; + if (this->try_assign_VArray(varray)) { + return varray; + } + if (this->may_have_ownership()) { + return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this); + } + if (this->is_span()) { + const Span<T> span = this->get_internal_span().typed<T>(); + return VArray<T>::ForSpan(span); } - - IndexRange index_range() const - { - return IndexRange(this->size()); + if (this->is_single()) { + T value; + this->get_internal_single(&value); + return VArray<T>::ForSingle(value, this->size()); } -}; + return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this); +} -/* Same as GVArray_Typed, but for mutable virtual arrays. */ -template<typename T> class GVMutableArray_Typed { - private: - VMutableArray<T> *varray_; - std::optional<VMutableArray_For_MutableSpan<T>> varray_span_; - std::optional<VMutableArray_For_GVMutableArray<T>> varray_any_; - GVMutableArrayPtr owned_gvarray_; +/** \} */ - public: - explicit GVMutableArray_Typed(GVMutableArray &gvarray) - { - BLI_assert(gvarray.type().is<T>()); - if (gvarray.is_span()) { - const GMutableSpan span = gvarray.get_internal_span(); - varray_span_.emplace(span.typed<T>()); - varray_ = &*varray_span_; - } - else if (VMutableArray<T> *internal_varray = gvarray.try_get_internal_mutable_varray<T>()) { - varray_ = internal_varray; - } - else { - varray_any_.emplace(gvarray); - varray_ = &*varray_any_; - } - } +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVMutableArray. + * \{ */ - explicit GVMutableArray_Typed(GVMutableArrayPtr gvarray) : GVMutableArray_Typed(*gvarray) - { - owned_gvarray_ = std::move(gvarray); - } +template<typename ImplT, typename... Args> +inline GVMutableArray GVMutableArray::For(Args &&...args) +{ + static_assert(std::is_base_of_v<GVMutableArrayImpl, ImplT>); + GVMutableArray varray; + varray.emplace<ImplT>(std::forward<Args>(args)...); + return varray; +} - VMutableArray<T> &operator*() - { - return *varray_; +template<typename T> inline GVMutableArray::GVMutableArray(const VMutableArray<T> &varray) +{ + if (!varray) { + return; } - - VMutableArray<T> *operator->() - { - return varray_; + if (varray.try_assign_GVMutableArray(*this)) { + return; } - - operator VMutableArray<T> &() - { - return *varray_; + if (varray.may_have_ownership()) { + *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray); } - - T operator[](const int64_t index) const - { - return varray_->get(index); + else if (varray.is_span()) { + MutableSpan<T> data = varray.get_internal_span(); + *this = GVMutableArray::ForSpan(data); } - - int64_t size() const - { - return varray_->size(); + else { + *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray); } -}; - -class GVArray_For_SlicedGVArray : public GVArray { - protected: - const GVArray &varray_; - int64_t offset_; +} - public: - GVArray_For_SlicedGVArray(const GVArray &varray, const IndexRange slice) - : GVArray(varray.type(), slice.size()), varray_(varray), offset_(slice.start()) - { - BLI_assert(slice.one_after_last() <= varray.size()); +template<typename T> inline VMutableArray<T> GVMutableArray::typed() const +{ + if (!*this) { + return {}; } - - /* TODO: Add #materialize method. */ - void get_impl(const int64_t index, void *r_value) const override; - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override; -}; - -/** - * Utility class to create the "best" sliced virtual array. - */ -class GVArray_Slice { - private: - const GVArray *varray_; - /* Of these optional virtual arrays, at most one is constructed at any time. */ - std::optional<GVArray_For_GSpan> varray_span_; - std::optional<GVArray_For_SlicedGVArray> varray_any_; - - public: - GVArray_Slice(const GVArray &varray, const IndexRange slice); - - const GVArray &operator*() - { - return *varray_; + BLI_assert(this->type().is<T>()); + VMutableArray<T> varray; + if (this->try_assign_VMutableArray(varray)) { + return varray; } - - const GVArray *operator->() - { - return varray_; + if (this->may_have_ownership()) { + return VMutableArray<T>::template For<VMutableArrayImpl_For_GVMutableArray<T>>(*this); } - - operator const GVArray &() - { - return *varray_; + if (this->is_span()) { + const MutableSpan<T> span = this->get_internal_span().typed<T>(); + return VMutableArray<T>::ForSpan(span); } -}; + return VMutableArray<T>::template For<VMutableArrayImpl_For_GVMutableArray<T>>(*this); +} + +/** \} */ } // namespace blender::fn diff --git a/source/blender/functions/FN_generic_virtual_vector_array.hh b/source/blender/functions/FN_generic_virtual_vector_array.hh index 4155a55a801..b80e21eaef1 100644 --- a/source/blender/functions/FN_generic_virtual_vector_array.hh +++ b/source/blender/functions/FN_generic_virtual_vector_array.hh @@ -100,31 +100,31 @@ class GVVectorArray { } }; -class GVArray_For_GVVectorArrayIndex : public GVArray { +class GVArray_For_GVVectorArrayIndex : public GVArrayImpl { private: const GVVectorArray &vector_array_; const int64_t index_; public: GVArray_For_GVVectorArrayIndex(const GVVectorArray &vector_array, const int64_t index) - : GVArray(vector_array.type(), vector_array.get_vector_size(index)), + : GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)), vector_array_(vector_array), index_(index) { } protected: - void get_impl(const int64_t index_in_vector, void *r_value) const override; - void get_to_uninitialized_impl(const int64_t index_in_vector, void *r_value) const override; + void get(const int64_t index_in_vector, void *r_value) const override; + void get_to_uninitialized(const int64_t index_in_vector, void *r_value) const override; }; class GVVectorArray_For_SingleGVArray : public GVVectorArray { private: - const GVArray &array_; + GVArray varray_; public: - GVVectorArray_For_SingleGVArray(const GVArray &array, const int64_t size) - : GVVectorArray(array.type(), size), array_(array) + GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size) + : GVVectorArray(varray.type(), size), varray_(std::move(varray)) { } diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh index d187985de9d..5c7e75230f3 100644 --- a/source/blender/functions/FN_multi_function_params.hh +++ b/source/blender/functions/FN_multi_function_params.hh @@ -40,7 +40,7 @@ class MFParamsBuilder { const MFSignature *signature_; IndexMask mask_; int64_t min_array_size_; - Vector<const GVArray *> virtual_arrays_; + Vector<GVArray> virtual_arrays_; Vector<GMutableSpan> mutable_spans_; Vector<const GVVectorArray *> virtual_vector_arrays_; Vector<GVectorArray *> vector_arrays_; @@ -68,24 +68,22 @@ class MFParamsBuilder { template<typename T> void add_readonly_single_input(const T *value, StringRef expected_name = "") { this->add_readonly_single_input( - scope_.construct<GVArray_For_SingleValueRef>(CPPType::get<T>(), min_array_size_, value), - expected_name); + GVArray::ForSingleRef(CPPType::get<T>(), min_array_size_, value), expected_name); } void add_readonly_single_input(const GSpan span, StringRef expected_name = "") { - this->add_readonly_single_input(scope_.construct<GVArray_For_GSpan>(span), expected_name); + this->add_readonly_single_input(GVArray::ForSpan(span), expected_name); } void add_readonly_single_input(GPointer value, StringRef expected_name = "") { this->add_readonly_single_input( - scope_.construct<GVArray_For_SingleValueRef>(*value.type(), min_array_size_, value.get()), - expected_name); + GVArray::ForSingleRef(*value.type(), min_array_size_, value.get()), expected_name); } - void add_readonly_single_input(const GVArray &ref, StringRef expected_name = "") + void add_readonly_single_input(GVArray varray, StringRef expected_name = "") { - this->assert_current_param_type(MFParamType::ForSingleInput(ref.type()), expected_name); - BLI_assert(ref.size() >= min_array_size_); - virtual_arrays_.append(&ref); + this->assert_current_param_type(MFParamType::ForSingleInput(varray.type()), expected_name); + BLI_assert(varray.size() >= min_array_size_); + virtual_arrays_.append(varray); } void add_readonly_vector_input(const GVectorArray &vector_array, StringRef expected_name = "") @@ -221,16 +219,16 @@ class MFParams { { } - template<typename T> const VArray<T> &readonly_single_input(int param_index, StringRef name = "") + template<typename T> VArray<T> readonly_single_input(int param_index, StringRef name = "") { - const GVArray &array = this->readonly_single_input(param_index, name); - return builder_->scope_.construct<GVArray_Typed<T>>(array); + const GVArray &varray = this->readonly_single_input(param_index, name); + return varray.typed<T>(); } const GVArray &readonly_single_input(int param_index, StringRef name = "") { this->assert_correct_param(param_index, name, MFParamType::SingleInput); int data_index = builder_->signature_->data_index(param_index); - return *builder_->virtual_arrays_[data_index]; + return builder_->virtual_arrays_[data_index]; } /** diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc index 4de5e71c910..68a8446e6ae 100644 --- a/source/blender/functions/intern/field.cc +++ b/source/blender/functions/intern/field.cc @@ -81,19 +81,18 @@ static FieldTreeInfo preprocess_field_tree(Span<GFieldRef> entry_fields) /** * Retrieves the data from the context that is passed as input into the field. */ -static Vector<const GVArray *> get_field_context_inputs( +static Vector<GVArray> get_field_context_inputs( ResourceScope &scope, const IndexMask mask, const FieldContext &context, const Span<std::reference_wrapper<const FieldInput>> field_inputs) { - Vector<const GVArray *> field_context_inputs; + Vector<GVArray> field_context_inputs; for (const FieldInput &field_input : field_inputs) { - const GVArray *varray = context.get_varray_for_input(field_input, mask, scope); - if (varray == nullptr) { + GVArray varray = context.get_varray_for_input(field_input, mask, scope); + if (!varray) { const CPPType &type = field_input.cpp_type(); - varray = &scope.construct<GVArray_For_SingleValueRef>( - type, mask.min_array_size(), type.default_value()); + varray = GVArray::ForSingleDefault(type, mask.min_array_size()); } field_context_inputs.append(varray); } @@ -105,7 +104,7 @@ static Vector<const GVArray *> get_field_context_inputs( * for different indices. */ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info, - Span<const GVArray *> field_context_inputs) + Span<GVArray> field_context_inputs) { Set<GFieldRef> found_fields; Stack<GFieldRef> fields_to_check; @@ -114,8 +113,8 @@ static Set<GFieldRef> find_varying_fields(const FieldTreeInfo &field_tree_info, * start the tree search at the non-constant input fields and traverse through all fields that * depend on them. */ for (const int i : field_context_inputs.index_range()) { - const GVArray *varray = field_context_inputs[i]; - if (varray->is_single()) { + const GVArray &varray = field_context_inputs[i]; + if (varray.is_single()) { continue; } const FieldInput &field_input = field_tree_info.deduplicated_field_inputs[i]; @@ -278,29 +277,42 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure, * \return The computed virtual arrays for each provided field. If #dst_varrays is passed, the * provided virtual arrays are returned. */ -Vector<const GVArray *> evaluate_fields(ResourceScope &scope, - Span<GFieldRef> fields_to_evaluate, - IndexMask mask, - const FieldContext &context, - Span<GVMutableArray *> dst_varrays) +Vector<GVArray> evaluate_fields(ResourceScope &scope, + Span<GFieldRef> fields_to_evaluate, + IndexMask mask, + const FieldContext &context, + Span<GVMutableArray> dst_varrays) { - Vector<const GVArray *> r_varrays(fields_to_evaluate.size(), nullptr); + Vector<GVArray> r_varrays(fields_to_evaluate.size()); + Array<bool> is_output_written_to_dst(fields_to_evaluate.size(), false); const int array_size = mask.min_array_size(); + if (mask.is_empty()) { + for (const int i : fields_to_evaluate.index_range()) { + const CPPType &type = fields_to_evaluate[i].cpp_type(); + r_varrays[i] = GVArray::ForEmpty(type); + } + return r_varrays; + } + /* Destination arrays are optional. Create a small utility method to access them. */ - auto get_dst_varray_if_available = [&](int index) -> GVMutableArray * { + auto get_dst_varray = [&](int index) -> GVMutableArray { if (dst_varrays.is_empty()) { - return nullptr; + return {}; + } + const GVMutableArray &varray = dst_varrays[index]; + if (!varray) { + return {}; } - BLI_assert(dst_varrays[index] == nullptr || dst_varrays[index]->size() >= array_size); - return dst_varrays[index]; + BLI_assert(varray.size() >= array_size); + return varray; }; /* Traverse the field tree and prepare some data that is used in later steps. */ FieldTreeInfo field_tree_info = preprocess_field_tree(fields_to_evaluate); /* Get inputs that will be passed into the field when evaluated. */ - Vector<const GVArray *> field_context_inputs = get_field_context_inputs( + Vector<GVArray> field_context_inputs = get_field_context_inputs( scope, mask, context, field_tree_info.deduplicated_field_inputs); /* Finish fields that output an input varray directly. For those we don't have to do any further @@ -312,7 +324,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, } const FieldInput &field_input = static_cast<const FieldInput &>(field.node()); const int field_input_index = field_tree_info.deduplicated_field_inputs.index_of(field_input); - const GVArray *varray = field_context_inputs[field_input_index]; + const GVArray &varray = field_context_inputs[field_input_index]; r_varrays[out_index] = varray; } @@ -325,7 +337,7 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, Vector<GFieldRef> constant_fields_to_evaluate; Vector<int> constant_field_indices; for (const int i : fields_to_evaluate.index_range()) { - if (r_varrays[i] != nullptr) { + if (r_varrays[i]) { /* Already done. */ continue; } @@ -357,8 +369,8 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, MFContextBuilder mf_context; /* Provide inputs to the procedure executor. */ - for (const GVArray *varray : field_context_inputs) { - mf_params.add_readonly_single_input(*varray); + for (const GVArray &varray : field_context_inputs) { + mf_params.add_readonly_single_input(varray); } for (const int i : varying_fields_to_evaluate.index_range()) { @@ -367,9 +379,9 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, const int out_index = varying_field_indices[i]; /* Try to get an existing virtual array that the result should be written into. */ - GVMutableArray *output_varray = get_dst_varray_if_available(out_index); + GVMutableArray dst_varray = get_dst_varray(out_index); void *buffer; - if (output_varray == nullptr || !output_varray->is_span()) { + if (!dst_varray || !dst_varray.is_span()) { /* Allocate a new buffer for the computed result. */ buffer = scope.linear_allocator().allocate(type.size() * array_size, type.alignment()); @@ -379,14 +391,14 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, [buffer, mask, &type]() { type.destruct_indices(buffer, mask); }); } - r_varrays[out_index] = &scope.construct<GVArray_For_GSpan>( - GSpan{type, buffer, array_size}); + r_varrays[out_index] = GVArray::ForSpan({type, buffer, array_size}); } else { /* Write the result into the existing span. */ - buffer = output_varray->get_internal_span().data(); + buffer = dst_varray.get_internal_span().data(); - r_varrays[out_index] = output_varray; + r_varrays[out_index] = dst_varray; + is_output_written_to_dst[out_index] = true; } /* Pass output buffer to the procedure executor. */ @@ -404,15 +416,12 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, build_multi_function_procedure_for_fields( procedure, scope, field_tree_info, constant_fields_to_evaluate); MFProcedureExecutor procedure_executor{"Procedure", procedure}; - /* Run the code below even when the mask is empty, so that outputs are properly prepared. - * Higher level code can detect this as well and just skip evaluating the field. */ - const int mask_size = mask.is_empty() ? 0 : 1; - MFParamsBuilder mf_params{procedure_executor, mask_size}; + MFParamsBuilder mf_params{procedure_executor, 1}; MFContextBuilder mf_context; /* Provide inputs to the procedure executor. */ - for (const GVArray *varray : field_context_inputs) { - mf_params.add_readonly_single_input(*varray); + for (const GVArray &varray : field_context_inputs) { + mf_params.add_readonly_single_input(varray); } for (const int i : constant_fields_to_evaluate.index_range()) { @@ -421,55 +430,52 @@ Vector<const GVArray *> evaluate_fields(ResourceScope &scope, /* Allocate memory where the computed value will be stored in. */ void *buffer = scope.linear_allocator().allocate(type.size(), type.alignment()); - if (!type.is_trivially_destructible() && mask_size > 0) { - BLI_assert(mask_size == 1); + if (!type.is_trivially_destructible()) { /* Destruct value in the end. */ scope.add_destruct_call([buffer, &type]() { type.destruct(buffer); }); } /* Pass output buffer to the procedure executor. */ - mf_params.add_uninitialized_single_output({type, buffer, mask_size}); + mf_params.add_uninitialized_single_output({type, buffer, 1}); /* Create virtual array that can be used after the procedure has been executed below. */ const int out_index = constant_field_indices[i]; - r_varrays[out_index] = &scope.construct<GVArray_For_SingleValueRef>( - type, array_size, buffer); + r_varrays[out_index] = GVArray::ForSingleRef(type, array_size, buffer); } - procedure_executor.call(IndexRange(mask_size), mf_params, mf_context); + procedure_executor.call(IndexRange(1), mf_params, mf_context); } - /* Copy data to supplied destination arrays if necessary. In some cases the evaluation above has - * written the computed data in the right place already. */ + /* Copy data to supplied destination arrays if necessary. In some cases the evaluation above + * has written the computed data in the right place already. */ if (!dst_varrays.is_empty()) { for (const int out_index : fields_to_evaluate.index_range()) { - GVMutableArray *output_varray = get_dst_varray_if_available(out_index); - if (output_varray == nullptr) { + GVMutableArray dst_varray = get_dst_varray(out_index); + if (!dst_varray) { /* Caller did not provide a destination for this output. */ continue; } - const GVArray *computed_varray = r_varrays[out_index]; - BLI_assert(computed_varray->type() == output_varray->type()); - if (output_varray == computed_varray) { + const GVArray &computed_varray = r_varrays[out_index]; + BLI_assert(computed_varray.type() == dst_varray.type()); + if (is_output_written_to_dst[out_index]) { /* The result has been written into the destination provided by the caller already. */ continue; } /* Still have to copy over the data in the destination provided by the caller. */ - if (output_varray->is_span()) { + if (dst_varray.is_span()) { /* Materialize into a span. */ - computed_varray->materialize_to_uninitialized(mask, - output_varray->get_internal_span().data()); + computed_varray.materialize_to_uninitialized(mask, dst_varray.get_internal_span().data()); } else { /* Slower materialize into a different structure. */ - const CPPType &type = computed_varray->type(); + const CPPType &type = computed_varray.type(); BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); for (const int i : mask) { - computed_varray->get_to_uninitialized(i, buffer); - output_varray->set_by_relocate(i, buffer); + computed_varray.get_to_uninitialized(i, buffer); + dst_varray.set_by_relocate(i, buffer); } } - r_varrays[out_index] = output_varray; + r_varrays[out_index] = dst_varray; } } return r_varrays; @@ -485,8 +491,8 @@ void evaluate_constant_field(const GField &field, void *r_value) ResourceScope scope; FieldContext context; - Vector<const GVArray *> varrays = evaluate_fields(scope, {field}, IndexRange(1), context); - varrays[0]->get_to_uninitialized(0, r_value); + Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context); + varrays[0].get_to_uninitialized(0, r_value); } /** @@ -512,9 +518,9 @@ GField make_field_constant_if_possible(GField field) return GField{operation, 0}; } -const GVArray *FieldContext::get_varray_for_input(const FieldInput &field_input, - IndexMask mask, - ResourceScope &scope) const +GVArray FieldContext::get_varray_for_input(const FieldInput &field_input, + IndexMask mask, + ResourceScope &scope) const { /* By default ask the field input to create the varray. Another field context might overwrite * the context here. */ @@ -526,17 +532,15 @@ IndexFieldInput::IndexFieldInput() : FieldInput(CPPType::get<int>(), "Index") category_ = Category::Generated; } -GVArray *IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &scope) +GVArray IndexFieldInput::get_index_varray(IndexMask mask, ResourceScope &UNUSED(scope)) { auto index_func = [](int i) { return i; }; - return &scope.construct< - fn::GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>( - mask.min_array_size(), mask.min_array_size(), index_func); + return VArray<int>::ForFunc(mask.min_array_size(), index_func); } -const GVArray *IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context), - IndexMask mask, - ResourceScope &scope) const +GVArray IndexFieldInput::get_varray_for_context(const fn::FieldContext &UNUSED(context), + IndexMask mask, + ResourceScope &scope) const { /* TODO: Investigate a similar method to IndexRange::as_span() */ return get_index_varray(mask, scope); @@ -631,27 +635,26 @@ static Vector<int64_t> indices_from_selection(const VArray<bool> &selection) return indices; } -int FieldEvaluator::add_with_destination(GField field, GVMutableArray &dst) +int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst) { const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field)); - dst_varrays_.append(&dst); + dst_varrays_.append(dst); output_pointer_infos_.append({}); return field_index; } int FieldEvaluator::add_with_destination(GField field, GMutableSpan dst) { - GVMutableArray &varray = scope_.construct<GVMutableArray_For_GMutableSpan>(dst); - return this->add_with_destination(std::move(field), varray); + return this->add_with_destination(std::move(field), GVMutableArray::ForSpan(dst)); } -int FieldEvaluator::add(GField field, const GVArray **varray_ptr) +int FieldEvaluator::add(GField field, GVArray *varray_ptr) { const int field_index = fields_to_evaluate_.append_and_get_index(std::move(field)); dst_varrays_.append(nullptr); output_pointer_infos_.append(OutputPointerInfo{ varray_ptr, [](void *dst, const GVArray &varray, ResourceScope &UNUSED(scope)) { - *(const GVArray **)dst = &varray; + *(GVArray *)dst = varray; }}); return field_index; } @@ -676,7 +679,7 @@ void FieldEvaluator::evaluate() for (const int i : fields_to_evaluate_.index_range()) { OutputPointerInfo &info = output_pointer_infos_[i]; if (info.dst != nullptr) { - info.set(info.dst, *evaluated_varrays_[i], scope_); + info.set(info.dst, evaluated_varrays_[i], scope_); } } is_evaluated_ = true; @@ -684,17 +687,16 @@ void FieldEvaluator::evaluate() IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index) { - const GVArray &varray = this->get_evaluated(field_index); - GVArray_Typed<bool> typed_varray{varray}; + VArray<bool> varray = this->get_evaluated(field_index).typed<bool>(); - if (typed_varray->is_single()) { - if (typed_varray->get_internal_single()) { - return IndexRange(typed_varray.size()); + if (varray.is_single()) { + if (varray.get_internal_single()) { + return IndexRange(varray.size()); } return IndexRange(0); } - return scope_.add_value(indices_from_selection(*typed_varray)).as_span(); + return scope_.add_value(indices_from_selection(varray)).as_span(); } } // namespace blender::fn diff --git a/source/blender/functions/intern/generic_vector_array.cc b/source/blender/functions/intern/generic_vector_array.cc index ec95a283919..0d478007a5a 100644 --- a/source/blender/functions/intern/generic_vector_array.cc +++ b/source/blender/functions/intern/generic_vector_array.cc @@ -60,15 +60,14 @@ void GVectorArray::extend(const int64_t index, const GVArray &values) void GVectorArray::extend(const int64_t index, const GSpan values) { - GVArray_For_GSpan varray{values}; - this->extend(index, varray); + this->extend(index, GVArray::ForSpan(values)); } void GVectorArray::extend(IndexMask mask, const GVVectorArray &values) { for (const int i : mask) { GVArray_For_GVVectorArrayIndex array{values, i}; - this->extend(i, array); + this->extend(i, GVArray(&array)); } } diff --git a/source/blender/functions/intern/generic_virtual_array.cc b/source/blender/functions/intern/generic_virtual_array.cc index ea54f1e7c00..1fe1c2fc229 100644 --- a/source/blender/functions/intern/generic_virtual_array.cc +++ b/source/blender/functions/intern/generic_virtual_array.cc @@ -19,52 +19,10 @@ namespace blender::fn { /* -------------------------------------------------------------------- */ -/** \name #GVArray_For_ShallowCopy +/** \name #GVArrayImpl * \{ */ -class GVArray_For_ShallowCopy : public GVArray { - private: - const GVArray &varray_; - - public: - GVArray_For_ShallowCopy(const GVArray &varray) - : GVArray(varray.type(), varray.size()), varray_(varray) - { - } - - private: - void get_impl(const int64_t index, void *r_value) const override - { - varray_.get(index, r_value); - } - - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override - { - varray_.get_to_uninitialized(index, r_value); - } - - void materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const override - { - varray_.materialize_to_uninitialized(mask, dst); - } -}; -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVArray - * \{ */ - -void GVArray::materialize(void *dst) const -{ - this->materialize(IndexMask(size_), dst); -} - -void GVArray::materialize(const IndexMask mask, void *dst) const -{ - this->materialize_impl(mask, dst); -} - -void GVArray::materialize_impl(const IndexMask mask, void *dst) const +void GVArrayImpl::materialize(const IndexMask mask, void *dst) const { for (const int64_t i : mask) { void *elem_dst = POINTER_OFFSET(dst, type_->size() * i); @@ -72,18 +30,7 @@ void GVArray::materialize_impl(const IndexMask mask, void *dst) const } } -void GVArray::materialize_to_uninitialized(void *dst) const -{ - this->materialize_to_uninitialized(IndexMask(size_), dst); -} - -void GVArray::materialize_to_uninitialized(const IndexMask mask, void *dst) const -{ - BLI_assert(mask.min_array_size() <= size_); - this->materialize_to_uninitialized_impl(mask, dst); -} - -void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst) const +void GVArrayImpl::materialize_to_uninitialized(const IndexMask mask, void *dst) const { for (const int64_t i : mask) { void *elem_dst = POINTER_OFFSET(dst, type_->size() * i); @@ -91,83 +38,75 @@ void GVArray::materialize_to_uninitialized_impl(const IndexMask mask, void *dst) } } -void GVArray::get_impl(const int64_t index, void *r_value) const +void GVArrayImpl::get(const int64_t index, void *r_value) const { type_->destruct(r_value); - this->get_to_uninitialized_impl(index, r_value); + this->get_to_uninitialized(index, r_value); } -bool GVArray::is_span_impl() const +bool GVArrayImpl::is_span() const { return false; } -GSpan GVArray::get_internal_span_impl() const +GSpan GVArrayImpl::get_internal_span() const { BLI_assert(false); return GSpan(*type_); } -bool GVArray::is_single_impl() const +bool GVArrayImpl::is_single() const { return false; } -void GVArray::get_internal_single_impl(void *UNUSED(r_value)) const +void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const { BLI_assert(false); } -const void *GVArray::try_get_internal_varray_impl() const +bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const { - return nullptr; + return false; } -/** - * Creates a new `std::unique_ptr<GVArray>` based on this `GVArray`. - * The lifetime of the returned virtual array must not be longer than the lifetime of this virtual - * array. - */ -GVArrayPtr GVArray::shallow_copy() const +bool GVArrayImpl::may_have_ownership() const { - if (this->is_span()) { - return std::make_unique<GVArray_For_GSpan>(this->get_internal_span()); - } - if (this->is_single()) { - BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer); - this->get_internal_single(buffer); - std::unique_ptr new_varray = std::make_unique<GVArray_For_SingleValue>(*type_, size_, buffer); - type_->destruct(buffer); - return new_varray; - } - return std::make_unique<GVArray_For_ShallowCopy>(*this); + /* Use true as default to avoid accidentally creating subclasses that have this set to false but + * actually own data. Subclasses should set the to false instead. */ + return true; } /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVMutableArray +/** \name #GVMutableArrayImpl * \{ */ -void GVMutableArray::set_by_copy_impl(const int64_t index, const void *value) +GVMutableArrayImpl::GVMutableArrayImpl(const CPPType &type, const int64_t size) + : GVArrayImpl(type, size) +{ +} + +void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value) { BUFFER_FOR_CPP_TYPE_VALUE(*type_, buffer); type_->copy_construct(value, buffer); - this->set_by_move_impl(index, buffer); + this->set_by_move(index, buffer); type_->destruct(buffer); } -void GVMutableArray::set_by_relocate_impl(const int64_t index, void *value) +void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value) { - this->set_by_move_impl(index, value); + this->set_by_move(index, value); type_->destruct(value); } -void GVMutableArray::set_all_impl(const void *src) +void GVMutableArrayImpl::set_all(const void *src) { if (this->is_span()) { - const GMutableSpan span = this->get_internal_span(); - type_->copy_assign_n(src, span.data(), size_); + const GSpan span = this->get_internal_span(); + type_->copy_assign_n(src, const_cast<void *>(span.data()), size_); } else { for (int64_t i : IndexRange(size_)) { @@ -176,149 +115,224 @@ void GVMutableArray::set_all_impl(const void *src) } } -void *GVMutableArray::try_get_internal_mutable_varray_impl() -{ - return nullptr; -} - void GVMutableArray::fill(const void *value) { if (this->is_span()) { - const GMutableSpan span = this->get_internal_span(); - type_->fill_assign_n(value, span.data(), size_); + const GSpan span = this->get_internal_span(); + this->type().fill_assign_n(value, const_cast<void *>(span.data()), this->size()); } else { - for (int64_t i : IndexRange(size_)) { + for (int64_t i : IndexRange(this->size())) { this->set_by_copy(i, value); } } } +bool GVMutableArrayImpl::try_assign_VMutableArray(void *UNUSED(varray)) const +{ + return false; +} + /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_For_GSpan +/** \name #GVArrayImpl_For_GSpan * \{ */ -void GVArray_For_GSpan::get_impl(const int64_t index, void *r_value) const +GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GSpan span) + : GVArrayImpl(span.type(), span.size()), data_(span.data()), element_size_(span.type().size()) +{ +} + +GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const CPPType &type, const int64_t size) + : GVArrayImpl(type, size), element_size_(type.size()) +{ +} + +void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const { type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value); } -void GVArray_For_GSpan::get_to_uninitialized_impl(const int64_t index, void *r_value) const +void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const { type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value); } -bool GVArray_For_GSpan::is_span_impl() const +bool GVArrayImpl_For_GSpan::is_span() const { return true; } -GSpan GVArray_For_GSpan::get_internal_span_impl() const +GSpan GVArrayImpl_For_GSpan::get_internal_span() const { return GSpan(*type_, data_, size_); } +/** See #VArrayImpl_For_Span_final. */ +class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan { + public: + using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan; + + private: + bool may_have_ownership() const override + { + return false; + } +}; + /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVMutableArray_For_GMutableSpan +/** \name #GVMutableArrayImpl_For_GMutableSpan * \{ */ -void GVMutableArray_For_GMutableSpan::get_impl(const int64_t index, void *r_value) const +GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const GMutableSpan span) + : GVMutableArrayImpl(span.type(), span.size()), + data_(span.data()), + element_size_(span.type().size()) +{ +} + +GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan(const CPPType &type, + const int64_t size) + : GVMutableArrayImpl(type, size), element_size_(type.size()) +{ +} + +void GVMutableArrayImpl_For_GMutableSpan::get(const int64_t index, void *r_value) const { type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value); } -void GVMutableArray_For_GMutableSpan::get_to_uninitialized_impl(const int64_t index, - void *r_value) const +void GVMutableArrayImpl_For_GMutableSpan::get_to_uninitialized(const int64_t index, + void *r_value) const { type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value); } -void GVMutableArray_For_GMutableSpan::set_by_copy_impl(const int64_t index, const void *value) +void GVMutableArrayImpl_For_GMutableSpan::set_by_copy(const int64_t index, const void *value) { type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index)); } -void GVMutableArray_For_GMutableSpan::set_by_move_impl(const int64_t index, void *value) +void GVMutableArrayImpl_For_GMutableSpan::set_by_move(const int64_t index, void *value) { type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index)); } -void GVMutableArray_For_GMutableSpan::set_by_relocate_impl(const int64_t index, void *value) +void GVMutableArrayImpl_For_GMutableSpan::set_by_relocate(const int64_t index, void *value) { type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index)); } -bool GVMutableArray_For_GMutableSpan::is_span_impl() const +bool GVMutableArrayImpl_For_GMutableSpan::is_span() const { return true; } -GSpan GVMutableArray_For_GMutableSpan::get_internal_span_impl() const +GSpan GVMutableArrayImpl_For_GMutableSpan::get_internal_span() const { return GSpan(*type_, data_, size_); } +class GVMutableArrayImpl_For_GMutableSpan_final final + : public GVMutableArrayImpl_For_GMutableSpan { + public: + using GVMutableArrayImpl_For_GMutableSpan::GVMutableArrayImpl_For_GMutableSpan; + + private: + bool may_have_ownership() const override + { + return false; + } +}; + /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_For_SingleValueRef +/** \name #GVArrayImpl_For_SingleValueRef * \{ */ -void GVArray_For_SingleValueRef::get_impl(const int64_t UNUSED(index), void *r_value) const -{ - type_->copy_assign(value_, r_value); -} +/* Generic virtual array where each element has the same value. The value is not owned. */ +class GVArrayImpl_For_SingleValueRef : public GVArrayImpl { + protected: + const void *value_ = nullptr; -void GVArray_For_SingleValueRef::get_to_uninitialized_impl(const int64_t UNUSED(index), - void *r_value) const -{ - type_->copy_construct(value_, r_value); -} + public: + GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value) + : GVArrayImpl(type, size), value_(value) + { + } -bool GVArray_For_SingleValueRef::is_span_impl() const -{ - return size_ == 1; -} + protected: + GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size) + { + } -GSpan GVArray_For_SingleValueRef::get_internal_span_impl() const -{ - return GSpan{*type_, value_, 1}; -} + void get(const int64_t UNUSED(index), void *r_value) const override + { + type_->copy_assign(value_, r_value); + } + void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override + { + type_->copy_construct(value_, r_value); + } -bool GVArray_For_SingleValueRef::is_single_impl() const -{ - return true; -} + bool is_span() const override + { + return size_ == 1; + } + GSpan get_internal_span() const override + { + return GSpan{*type_, value_, 1}; + } -void GVArray_For_SingleValueRef::get_internal_single_impl(void *r_value) const -{ - type_->copy_assign(value_, r_value); -} + bool is_single() const override + { + return true; + } + void get_internal_single(void *r_value) const override + { + type_->copy_assign(value_, r_value); + } +}; + +class GVArrayImpl_For_SingleValueRef_final final : public GVArrayImpl_For_SingleValueRef { + public: + using GVArrayImpl_For_SingleValueRef::GVArrayImpl_For_SingleValueRef; + + private: + bool may_have_ownership() const override + { + return false; + } +}; /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_For_SingleValue +/** \name #GVArrayImpl_For_SingleValue * \{ */ -GVArray_For_SingleValue::GVArray_For_SingleValue(const CPPType &type, - const int64_t size, - const void *value) - : GVArray_For_SingleValueRef(type, size) -{ - value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__); - type.copy_construct(value, (void *)value_); -} +/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */ +class GVArrayImpl_For_SingleValue : public GVArrayImpl_For_SingleValueRef, + NonCopyable, + NonMovable { + public: + GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value) + : GVArrayImpl_For_SingleValueRef(type, size) + { + value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__); + type.copy_construct(value, (void *)value_); + } -GVArray_For_SingleValue::~GVArray_For_SingleValue() -{ - type_->destruct((void *)value_); - MEM_freeN((void *)value_); -} + ~GVArrayImpl_For_SingleValue() override + { + type_->destruct((void *)value_); + MEM_freeN((void *)value_); + } +}; /** \} */ @@ -326,7 +340,7 @@ GVArray_For_SingleValue::~GVArray_For_SingleValue() /** \name #GVArray_GSpan * \{ */ -GVArray_GSpan::GVArray_GSpan(const GVArray &varray) : GSpan(varray.type()), varray_(varray) +GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) { size_ = varray_.size(); if (varray_.is_span()) { @@ -353,8 +367,8 @@ GVArray_GSpan::~GVArray_GSpan() /** \name #GVMutableArray_GSpan * \{ */ -GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray &varray, const bool copy_values_to_span) - : GMutableSpan(varray.type()), varray_(varray) +GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span) + : GMutableSpan(varray.type()), varray_(std::move(varray)) { size_ = varray_.size(); if (varray_.is_span()) { @@ -405,48 +419,314 @@ void GVMutableArray_GSpan::disable_not_applied_warning() /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_For_SlicedGVArray +/** \name #GVArrayImpl_For_SlicedGVArray * \{ */ -void GVArray_For_SlicedGVArray::get_impl(const int64_t index, void *r_value) const +class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl { + protected: + GVArray varray_; + int64_t offset_; + + public: + GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice) + : GVArrayImpl(varray.type(), slice.size()), + varray_(std::move(varray)), + offset_(slice.start()) + { + BLI_assert(slice.one_after_last() <= varray_.size()); + } + + void get(const int64_t index, void *r_value) const override + { + varray_.get(index + offset_, r_value); + } + + void get_to_uninitialized(const int64_t index, void *r_value) const override + { + varray_.get_to_uninitialized(index + offset_, r_value); + } +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayCommon + * \{ */ + +GVArrayCommon::GVArrayCommon() = default; + +GVArrayCommon::GVArrayCommon(const GVArrayCommon &other) : storage_(other.storage_) +{ + impl_ = this->impl_from_storage(); +} + +GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_)) +{ + impl_ = this->impl_from_storage(); + other.storage_.reset(); + other.impl_ = nullptr; +} + +GVArrayCommon::GVArrayCommon(const GVArrayImpl *impl) : impl_(impl) +{ + storage_ = impl_; +} + +GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get()) +{ + if (impl) { + storage_ = std::move(impl); + } +} + +GVArrayCommon::~GVArrayCommon() = default; + +void GVArrayCommon::materialize(void *dst) const +{ + this->materialize(IndexMask(impl_->size()), dst); +} + +void GVArrayCommon::materialize(const IndexMask mask, void *dst) const +{ + impl_->materialize(mask, dst); +} + +void GVArrayCommon::materialize_to_uninitialized(void *dst) const +{ + this->materialize_to_uninitialized(IndexMask(impl_->size()), dst); +} + +void GVArrayCommon::materialize_to_uninitialized(const IndexMask mask, void *dst) const +{ + BLI_assert(mask.min_array_size() <= impl_->size()); + impl_->materialize_to_uninitialized(mask, dst); +} + +bool GVArrayCommon::may_have_ownership() const +{ + return impl_->may_have_ownership(); +} + +void GVArrayCommon::copy_from(const GVArrayCommon &other) +{ + if (this == &other) { + return; + } + storage_ = other.storage_; + impl_ = this->impl_from_storage(); +} + +void GVArrayCommon::move_from(GVArrayCommon &&other) noexcept +{ + if (this == &other) { + return; + } + storage_ = std::move(other.storage_); + impl_ = this->impl_from_storage(); + other.storage_.reset(); + other.impl_ = nullptr; +} + +/* Returns true when the virtual array is stored as a span internally. */ +bool GVArrayCommon::is_span() const +{ + if (this->is_empty()) { + return true; + } + return impl_->is_span(); +} + +/* Returns the internally used span of the virtual array. This invokes undefined behavior is the + * virtual array is not stored as a span internally. */ +GSpan GVArrayCommon::get_internal_span() const { - varray_.get(index + offset_, r_value); + BLI_assert(this->is_span()); + if (this->is_empty()) { + return GSpan(impl_->type()); + } + return impl_->get_internal_span(); } -void GVArray_For_SlicedGVArray::get_to_uninitialized_impl(const int64_t index, void *r_value) const +/* Returns true when the virtual array returns the same value for every index. */ +bool GVArrayCommon::is_single() const { - varray_.get_to_uninitialized(index + offset_, r_value); + if (impl_->size() == 1) { + return true; + } + return impl_->is_single(); +} + +/* Copies the value that is used for every element into `r_value`, which is expected to point to + * initialized memory. This invokes undefined behavior if the virtual array would not return the + * same value for every index. */ +void GVArrayCommon::get_internal_single(void *r_value) const +{ + BLI_assert(this->is_single()); + if (impl_->size() == 1) { + impl_->get(0, r_value); + return; + } + impl_->get_internal_single(r_value); +} + +/* Same as `get_internal_single`, but `r_value` points to initialized memory. */ +void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const +{ + impl_->type().default_construct(r_value); + this->get_internal_single(r_value); +} + +const GVArrayImpl *GVArrayCommon::impl_from_storage() const +{ + return storage_.extra_info().get_varray(storage_.get()); +} + +IndexRange GVArrayCommon::index_range() const +{ + return IndexRange(this->size()); } /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_Slice +/** \name #GVArray * \{ */ -GVArray_Slice::GVArray_Slice(const GVArray &varray, const IndexRange slice) +GVArray::GVArray(const GVArray &other) = default; + +GVArray::GVArray(GVArray &&other) noexcept = default; + +GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl) { - if (varray.is_span()) { - /* Create a new virtual for the sliced span. */ - const GSpan span = varray.get_internal_span(); - const GSpan sliced_span = span.slice(slice.start(), slice.size()); - varray_span_.emplace(sliced_span); - varray_ = &*varray_span_; - } - else if (varray.is_single()) { - /* Can just use the existing virtual array, because it's the same value for the indices in the - * slice anyway. */ - varray_ = &varray; - } - else { - /* Generic version when none of the above method works. - * We don't necessarily want to materialize the input varray because there might be - * large distances between the required indices. Then we would materialize many elements that - * are not accessed later on. - */ - varray_any_.emplace(varray, slice); - varray_ = &*varray_any_; +} + +GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl)) +{ +} + +GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value) +{ + return GVArray::For<GVArrayImpl_For_SingleValue>(type, size, value); +} + +GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value) +{ + return GVArray::For<GVArrayImpl_For_SingleValueRef_final>(type, size, value); +} + +GVArray GVArray::ForSingleDefault(const CPPType &type, const int64_t size) +{ + return GVArray::ForSingleRef(type, size, type.default_value()); +} + +GVArray GVArray::ForSpan(GSpan span) +{ + return GVArray::For<GVArrayImpl_For_GSpan_final>(span); +} + +class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan { + protected: + GArray<> array_; + + public: + GVArrayImpl_For_GArray(GArray<> array) + : GVArrayImpl_For_GSpan(array.as_span()), array_(std::move(array)) + { } +}; + +GVArray GVArray::ForGArray(GArray<> array) +{ + return GVArray::For<GVArrayImpl_For_GArray>(array); +} + +GVArray GVArray::ForEmpty(const CPPType &type) +{ + return GVArray::ForSpan(GSpan(type)); +} + +GVArray GVArray::slice(IndexRange slice) const +{ + return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice); +} + +GVArray &GVArray::operator=(const GVArray &other) +{ + this->copy_from(other); + return *this; +} + +GVArray &GVArray::operator=(GVArray &&other) noexcept +{ + this->move_from(std::move(other)); + return *this; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVMutableArray + * \{ */ + +GVMutableArray::GVMutableArray(const GVMutableArray &other) = default; +GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default; + +GVMutableArray::GVMutableArray(GVMutableArrayImpl *impl) : GVArrayCommon(impl) +{ +} + +GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl) + : GVArrayCommon(std::move(impl)) +{ +} + +GVMutableArray GVMutableArray::ForSpan(GMutableSpan span) +{ + return GVMutableArray::For<GVMutableArrayImpl_For_GMutableSpan_final>(span); +} + +GVMutableArray::operator GVArray() const & +{ + GVArray varray; + varray.copy_from(*this); + return varray; +} + +GVMutableArray::operator GVArray() &&noexcept +{ + GVArray varray; + varray.move_from(std::move(*this)); + return varray; +} + +GVMutableArray &GVMutableArray::operator=(const GVMutableArray &other) +{ + this->copy_from(other); + return *this; +} + +GVMutableArray &GVMutableArray::operator=(GVMutableArray &&other) noexcept +{ + this->move_from(std::move(other)); + return *this; +} + +GVMutableArrayImpl *GVMutableArray::get_implementation() const +{ + return this->get_impl(); +} + +/* Copy the values from the source buffer to all elements in the virtual array. */ +void GVMutableArray::set_all(const void *src) +{ + this->get_impl()->set_all(src); +} + +GMutableSpan GVMutableArray::get_internal_span() const +{ + BLI_assert(this->is_span()); + const GSpan span = impl_->get_internal_span(); + return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size()); } /** \} */ diff --git a/source/blender/functions/intern/generic_virtual_vector_array.cc b/source/blender/functions/intern/generic_virtual_vector_array.cc index 6b90ce993ae..e3c0d3109fa 100644 --- a/source/blender/functions/intern/generic_virtual_vector_array.cc +++ b/source/blender/functions/intern/generic_virtual_vector_array.cc @@ -18,13 +18,13 @@ namespace blender::fn { -void GVArray_For_GVVectorArrayIndex::get_impl(const int64_t index_in_vector, void *r_value) const +void GVArray_For_GVVectorArrayIndex::get(const int64_t index_in_vector, void *r_value) const { vector_array_.get_vector_element(index_, index_in_vector, r_value); } -void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t index_in_vector, - void *r_value) const +void GVArray_For_GVVectorArrayIndex::get_to_uninitialized(const int64_t index_in_vector, + void *r_value) const { type_->default_construct(r_value); vector_array_.get_vector_element(index_, index_in_vector, r_value); @@ -32,14 +32,14 @@ void GVArray_For_GVVectorArrayIndex::get_to_uninitialized_impl(const int64_t ind int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const { - return array_.size(); + return varray_.size(); } void GVVectorArray_For_SingleGVArray::get_vector_element_impl(const int64_t UNUSED(index), const int64_t index_in_vector, void *r_value) const { - array_.get(index_in_vector, r_value); + varray_.get(index_in_vector, r_value); } bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const diff --git a/source/blender/functions/intern/multi_function_parallel.cc b/source/blender/functions/intern/multi_function_parallel.cc index 5a8c621f0b3..eefe647644d 100644 --- a/source/blender/functions/intern/multi_function_parallel.cc +++ b/source/blender/functions/intern/multi_function_parallel.cc @@ -54,7 +54,6 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext const IndexRange input_slice_range{input_slice_start, input_slice_size}; MFParamsBuilder sub_params{fn_, sub_mask.min_array_size()}; - ResourceScope &scope = sub_params.resource_scope(); /* All parameters are sliced so that the wrapped multi-function does not have to take care of * the index offset. */ @@ -63,8 +62,7 @@ void ParallelMultiFunction::call(IndexMask full_mask, MFParams params, MFContext switch (param_type.category()) { case MFParamType::SingleInput: { const GVArray &varray = params.readonly_single_input(param_index); - const GVArray &sliced_varray = scope.construct<GVArray_Slice>(varray, input_slice_range); - sub_params.add_readonly_single_input(sliced_varray); + sub_params.add_readonly_single_input(varray.slice(input_slice_range)); break; } case MFParamType::SingleMutable: { diff --git a/source/blender/functions/intern/multi_function_procedure_executor.cc b/source/blender/functions/intern/multi_function_procedure_executor.cc index 6d2d121bafd..85d0cf4909f 100644 --- a/source/blender/functions/intern/multi_function_procedure_executor.cc +++ b/source/blender/functions/intern/multi_function_procedure_executor.cc @@ -66,6 +66,7 @@ struct VariableValue_GVArray : public VariableValue { VariableValue_GVArray(const GVArray &data) : VariableValue(static_type), data(data) { + BLI_assert(data); } }; @@ -756,7 +757,7 @@ class VariableState : NonCopyable, NonMovable { switch (value_->type) { case ValueType::GVArray: { - const GVArray_Typed<bool> varray{this->value_as<VariableValue_GVArray>()->data}; + const VArray<bool> varray = this->value_as<VariableValue_GVArray>()->data.typed<bool>(); for (const int i : mask) { r_indices[varray[i]].append(i); } diff --git a/source/blender/functions/tests/FN_field_test.cc b/source/blender/functions/tests/FN_field_test.cc index 041cdbd0f00..16a6c73183d 100644 --- a/source/blender/functions/tests/FN_field_test.cc +++ b/source/blender/functions/tests/FN_field_test.cc @@ -34,14 +34,12 @@ class IndexFieldInput final : public FieldInput { { } - const GVArray *get_varray_for_context(const FieldContext &UNUSED(context), - IndexMask mask, - ResourceScope &scope) const final + GVArray get_varray_for_context(const FieldContext &UNUSED(context), + IndexMask mask, + ResourceScope &UNUSED(scope)) const final { auto index_func = [](int i) { return i; }; - return &scope.construct< - GVArray_For_EmbeddedVArray<int, VArray_For_Func<int, decltype(index_func)>>>( - mask.min_array_size(), mask.min_array_size(), index_func); + return VArray<int>::ForFunc(mask.min_array_size(), index_func); } }; @@ -240,20 +238,20 @@ TEST(field, TwoFunctionsTwoOutputs) FieldContext field_context; FieldEvaluator field_evaluator{field_context, &mask}; - const VArray<int> *result_1 = nullptr; - const VArray<int> *result_2 = nullptr; + VArray<int> result_1; + VArray<int> result_2; field_evaluator.add(result_field_1, &result_1); field_evaluator.add(result_field_2, &result_2); field_evaluator.evaluate(); - EXPECT_EQ(result_1->get(2), 4); - EXPECT_EQ(result_1->get(4), 8); - EXPECT_EQ(result_1->get(6), 12); - EXPECT_EQ(result_1->get(8), 16); - EXPECT_EQ(result_2->get(2), 24); - EXPECT_EQ(result_2->get(4), 28); - EXPECT_EQ(result_2->get(6), 32); - EXPECT_EQ(result_2->get(8), 36); + EXPECT_EQ(result_1.get(2), 4); + EXPECT_EQ(result_1.get(4), 8); + EXPECT_EQ(result_1.get(6), 12); + EXPECT_EQ(result_1.get(8), 16); + EXPECT_EQ(result_2.get(2), 24); + EXPECT_EQ(result_2.get(4), 28); + EXPECT_EQ(result_2.get(6), 32); + EXPECT_EQ(result_2.get(8), 36); } TEST(field, SameFieldTwice) @@ -264,16 +262,16 @@ TEST(field, SameFieldTwice) FieldContext field_context; IndexMask mask{IndexRange(2)}; ResourceScope scope; - Vector<const GVArray *> results = evaluate_fields( + Vector<GVArray> results = evaluate_fields( scope, {constant_field, constant_field}, mask, field_context); - GVArray_Typed<int> varray1{*results[0]}; - GVArray_Typed<int> varray2{*results[1]}; + VArray<int> varray1 = results[0].typed<int>(); + VArray<int> varray2 = results[1].typed<int>(); - EXPECT_EQ(varray1->get(0), 10); - EXPECT_EQ(varray1->get(1), 10); - EXPECT_EQ(varray2->get(0), 10); - EXPECT_EQ(varray2->get(1), 10); + EXPECT_EQ(varray1.get(0), 10); + EXPECT_EQ(varray1.get(1), 10); + EXPECT_EQ(varray2.get(0), 10); + EXPECT_EQ(varray2.get(1), 10); } TEST(field, IgnoredOutput) @@ -283,12 +281,12 @@ TEST(field, IgnoredOutput) FieldContext field_context; FieldEvaluator field_evaluator{field_context, 10}; - const VArray<int> *results = nullptr; + VArray<int> results; field_evaluator.add(field, &results); field_evaluator.evaluate(); - EXPECT_EQ(results->get(0), 5); - EXPECT_EQ(results->get(3), 5); + EXPECT_EQ(results.get(0), 5); + EXPECT_EQ(results.get(3), 5); } } // namespace blender::fn::tests diff --git a/source/blender/functions/tests/FN_multi_function_procedure_test.cc b/source/blender/functions/tests/FN_multi_function_procedure_test.cc index 0b4b88fba3d..a0919d7926e 100644 --- a/source/blender/functions/tests/FN_multi_function_procedure_test.cc +++ b/source/blender/functions/tests/FN_multi_function_procedure_test.cc @@ -9,6 +9,43 @@ namespace blender::fn::tests { +TEST(multi_function_procedure, ConstantOutput) +{ + /** + * procedure(int *var2) { + * var1 = 5; + * var2 = var1 + var1; + * } + */ + + CustomMF_Constant<int> constant_fn{5}; + CustomMF_SI_SI_SO<int, int, int> add_fn{"Add", [](int a, int b) { return a + b; }}; + + MFProcedure procedure; + MFProcedureBuilder builder{procedure}; + + auto [var1] = builder.add_call<1>(constant_fn); + auto [var2] = builder.add_call<1>(add_fn, {var1, var1}); + builder.add_destruct(*var1); + builder.add_return(); + builder.add_output_parameter(*var2); + + EXPECT_TRUE(procedure.validate()); + + MFProcedureExecutor executor{"My Procedure", procedure}; + + MFParamsBuilder params{executor, 2}; + MFContextBuilder context; + + Array<int> output_array(2); + params.add_uninitialized_single_output(output_array.as_mutable_span()); + + executor.call(IndexRange(2), params, context); + + EXPECT_EQ(output_array[0], 10); + EXPECT_EQ(output_array[1], 10); +} + TEST(multi_function_procedure, SimpleTest) { /** diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index 24f0b6308ba..7aaaec9f0c5 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -50,23 +50,23 @@ static void copy_attributes_to_points(CurveEval &curve, /* Copy builtin control point attributes. */ if (source_attribute_ids.contains("tilt")) { - const fn::GVArray_Typed<float> tilt_attribute = mesh_component.attribute_get_for_read<float>( + const VArray<float> tilt_attribute = mesh_component.attribute_get_for_read<float>( "tilt", ATTR_DOMAIN_POINT, 0.0f); threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { for (const int i : range) { copy_attribute_to_points<float>( - *tilt_attribute, point_to_vert_maps[i], splines[i]->tilts()); + tilt_attribute, point_to_vert_maps[i], splines[i]->tilts()); } }); source_attribute_ids.remove_contained("tilt"); } if (source_attribute_ids.contains("radius")) { - const fn::GVArray_Typed<float> radius_attribute = mesh_component.attribute_get_for_read<float>( + const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>( "radius", ATTR_DOMAIN_POINT, 1.0f); threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { for (const int i : range) { copy_attribute_to_points<float>( - *radius_attribute, point_to_vert_maps[i], splines[i]->radii()); + radius_attribute, point_to_vert_maps[i], splines[i]->radii()); } }); source_attribute_ids.remove_contained("radius"); @@ -82,7 +82,7 @@ static void copy_attributes_to_points(CurveEval &curve, continue; } - const fn::GVArrayPtr mesh_attribute = mesh_component.attribute_try_get_for_read( + const fn::GVArray mesh_attribute = mesh_component.attribute_try_get_for_read( attribute_id, ATTR_DOMAIN_POINT); /* Some attributes might not exist if they were builtin attribute on domains that don't * have any elements, i.e. a face attribute on the output of the line primitive node. */ @@ -90,7 +90,7 @@ static void copy_attributes_to_points(CurveEval &curve, continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute->type()); + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(mesh_attribute.type()); threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { for (const int i : range) { @@ -101,10 +101,10 @@ static void copy_attributes_to_points(CurveEval &curve, BLI_assert(spline_attribute); /* Copy attribute based on the map for this spline. */ - attribute_math::convert_to_static_type(mesh_attribute->type(), [&](auto dummy) { + attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) { using T = decltype(dummy); copy_attribute_to_points<T>( - mesh_attribute->typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>()); + mesh_attribute.typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>()); }); } }); diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 6e1f21dbae0..700f32ee414 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -57,13 +57,8 @@ using fn::GPointer; using fn::GSpan; using fn::GVArray; using fn::GVArray_GSpan; -using fn::GVArray_Span; -using fn::GVArray_Typed; -using fn::GVArrayPtr; using fn::GVMutableArray; using fn::GVMutableArray_GSpan; -using fn::GVMutableArray_Typed; -using fn::GVMutableArrayPtr; using geometry_nodes_eval_log::NodeWarningType; /** @@ -316,21 +311,21 @@ class GeoNodeExecParams { * \note This will add an error message if the string socket is active and * the input attribute does not exist. */ - GVArrayPtr get_input_attribute(const StringRef name, - const GeometryComponent &component, - const AttributeDomain domain, - const CustomDataType type, - const void *default_value) const; + GVArray get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const; template<typename T> - GVArray_Typed<T> get_input_attribute(const StringRef name, - const GeometryComponent &component, - const AttributeDomain domain, - const T &default_value) const + VArray<T> get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const T &default_value) const { const CustomDataType type = bke::cpp_type_to_custom_data_type(CPPType::get<T>()); - GVArrayPtr varray = this->get_input_attribute(name, component, domain, type, &default_value); - return GVArray_Typed<T>(std::move(varray)); + GVArray varray = this->get_input_attribute(name, component, domain, type, &default_value); + return varray.typed<T>(); } /** diff --git a/source/blender/nodes/NOD_type_conversions.hh b/source/blender/nodes/NOD_type_conversions.hh index ec4859f0657..c8b24fd1260 100644 --- a/source/blender/nodes/NOD_type_conversions.hh +++ b/source/blender/nodes/NOD_type_conversions.hh @@ -21,7 +21,6 @@ namespace blender::nodes { using fn::CPPType; -using fn::GVArray; struct ConversionFunctions { const fn::MultiFunction *multi_function; @@ -73,9 +72,9 @@ class DataTypeConversions { const void *from_value, void *to_value) const; - fn::GVArrayPtr try_convert(fn::GVArrayPtr varray, const CPPType &to_type) const; + fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const; - fn::GVMutableArrayPtr try_convert(fn::GVMutableArrayPtr varray, const CPPType &to_type) const; + fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const; }; const DataTypeConversions &get_implicit_type_conversions(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc index b92d4704d63..b95548c2dee 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc @@ -179,9 +179,9 @@ static void align_rotations_on_component(GeometryComponent &component, return; } - GVArray_Typed<float> factors = params.get_input_attribute<float>( + VArray<float> factors = params.get_input_attribute<float>( "Factor", component, ATTR_DOMAIN_POINT, 1.0f); - GVArray_Typed<float3> vectors = params.get_input_attribute<float3>( + VArray<float3> vectors = params.get_input_attribute<float3>( "Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1}); float3 local_main_axis{0, 0, 0}; diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc index 91ff114a480..57821a5a3a4 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc @@ -156,7 +156,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam const AttributeDomain domain = get_result_domain(component, attribute_name, result_name); const int operation = static_cast<int>(storage.operation); - GVArrayPtr attribute_input = component.attribute_try_get_for_read( + GVArray attribute_input = component.attribute_try_get_for_read( attribute_name, domain, data_type); OutputAttribute attribute_result = component.attribute_try_get_for_output_only( @@ -185,7 +185,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam } } MutableSpan<float3> results = attribute_result.as_span<float3>(); - clamp_attribute<float3>(attribute_input->typed<float3>(), results, min, max); + clamp_attribute<float3>(attribute_input.typed<float3>(), results, min, max); break; } case CD_PROP_FLOAT: { @@ -193,10 +193,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam const float max = params.get_input<float>("Max_001"); MutableSpan<float> results = attribute_result.as_span<float>(); if (operation == NODE_CLAMP_RANGE && min > max) { - clamp_attribute<float>(attribute_input->typed<float>(), results, max, min); + clamp_attribute<float>(attribute_input.typed<float>(), results, max, min); } else { - clamp_attribute<float>(attribute_input->typed<float>(), results, min, max); + clamp_attribute<float>(attribute_input.typed<float>(), results, min, max); } break; } @@ -205,10 +205,10 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam const int max = params.get_input<int>("Max_002"); MutableSpan<int> results = attribute_result.as_span<int>(); if (operation == NODE_CLAMP_RANGE && min > max) { - clamp_attribute<int>(attribute_input->typed<int>(), results, max, min); + clamp_attribute<int>(attribute_input.typed<int>(), results, max, min); } else { - clamp_attribute<int>(attribute_input->typed<int>(), results, min, max); + clamp_attribute<int>(attribute_input.typed<int>(), results, min, max); } break; } @@ -231,7 +231,7 @@ static void clamp_attribute(GeometryComponent &component, const GeoNodeExecParam } MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>(); clamp_attribute<ColorGeometry4f>( - attribute_input->typed<ColorGeometry4f>(), results, min, max); + attribute_input.typed<ColorGeometry4f>(), results, min, max); break; } default: { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc index ab4b6aad545..061f5f3d7ee 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc @@ -85,7 +85,7 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon return; } - GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>( + VArray<float> attribute_in = component.attribute_get_for_read<float>( input_name, result_domain, 0.0f); MutableSpan<ColorGeometry4f> results = attribute_result.as_span(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc index d4c23380b4e..631e5cddd67 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc @@ -95,11 +95,11 @@ static void combine_attributes(GeometryComponent &component, const GeoNodeExecPa if (!attribute_result) { return; } - GVArray_Typed<float> attribute_x = params.get_input_attribute<float>( + VArray<float> attribute_x = params.get_input_attribute<float>( "X", component, result_domain, 0.0f); - GVArray_Typed<float> attribute_y = params.get_input_attribute<float>( + VArray<float> attribute_y = params.get_input_attribute<float>( "Y", component, result_domain, 0.0f); - GVArray_Typed<float> attribute_z = params.get_input_attribute<float>( + VArray<float> attribute_z = params.get_input_attribute<float>( "Z", component, result_domain, 0.0f); for (const int i : IndexRange(attribute_result->size())) { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc index e4e43a7b724..d9756577d2c 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc @@ -257,9 +257,9 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx const CustomDataType input_data_type = get_data_type(component, params, *node_storage); - GVArrayPtr attribute_a = params.get_input_attribute( + GVArray attribute_a = params.get_input_attribute( "A", component, result_domain, input_data_type, nullptr); - GVArrayPtr attribute_b = params.get_input_attribute( + GVArray attribute_b = params.get_input_attribute( "B", component, result_domain, input_data_type, nullptr); if (!attribute_a || !attribute_b) { @@ -276,47 +276,47 @@ static void attribute_compare_calc(GeometryComponent &component, const GeoNodeEx if (operation == NODE_FLOAT_COMPARE_EQUAL) { if (input_data_type == CD_PROP_FLOAT) { do_equal_operation_float( - attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span); + attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span); } else if (input_data_type == CD_PROP_FLOAT3) { do_equal_operation_float3( - attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span); + attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span); } else if (input_data_type == CD_PROP_COLOR) { - do_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(), - attribute_b->typed<ColorGeometry4f>(), + do_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(), + attribute_b.typed<ColorGeometry4f>(), threshold, result_span); } else if (input_data_type == CD_PROP_BOOL) { do_equal_operation_bool( - attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span); + attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span); } } else if (operation == NODE_FLOAT_COMPARE_NOT_EQUAL) { if (input_data_type == CD_PROP_FLOAT) { do_not_equal_operation_float( - attribute_a->typed<float>(), attribute_b->typed<float>(), threshold, result_span); + attribute_a.typed<float>(), attribute_b.typed<float>(), threshold, result_span); } else if (input_data_type == CD_PROP_FLOAT3) { do_not_equal_operation_float3( - attribute_a->typed<float3>(), attribute_b->typed<float3>(), threshold, result_span); + attribute_a.typed<float3>(), attribute_b.typed<float3>(), threshold, result_span); } else if (input_data_type == CD_PROP_COLOR) { - do_not_equal_operation_color4f(attribute_a->typed<ColorGeometry4f>(), - attribute_b->typed<ColorGeometry4f>(), + do_not_equal_operation_color4f(attribute_a.typed<ColorGeometry4f>(), + attribute_b.typed<ColorGeometry4f>(), threshold, result_span); } else if (input_data_type == CD_PROP_BOOL) { do_not_equal_operation_bool( - attribute_a->typed<bool>(), attribute_b->typed<bool>(), threshold, result_span); + attribute_a.typed<bool>(), attribute_b.typed<bool>(), threshold, result_span); } } } else { do_math_operation( - attribute_a->typed<float>(), attribute_b->typed<float>(), operation, result_span); + attribute_a.typed<float>(), attribute_b.typed<float>(), operation, result_span); } attribute_result.save(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc index dc05fa2c125..13ba8d13618 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc @@ -104,7 +104,7 @@ static void attribute_convert_calc(GeometryComponent &component, return; } - GVArrayPtr source_attribute = component.attribute_try_get_for_read( + GVArray source_attribute = component.attribute_try_get_for_read( source_name, result_domain, result_type); if (!source_attribute) { params.error_message_add(NodeWarningType::Error, @@ -118,7 +118,7 @@ static void attribute_convert_calc(GeometryComponent &component, return; } - GVArray_GSpan source_span{*source_attribute}; + GVArray_GSpan source_span{source_attribute}; GMutableSpan result_span = result_attribute.as_span(); BLI_assert(source_span.size() == result_span.size()); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc index 669ac21436f..af56df0dc3f 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc @@ -136,10 +136,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon switch (result_type) { case CD_PROP_FLOAT: { const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec; - GVArray_Typed<float> attribute_in = component.attribute_get_for_read<float>( + VArray<float> attribute_in = component.attribute_get_for_read<float>( input_name, result_domain, float(0.0f)); MutableSpan<float> results = attribute_result.as_span<float>(); - threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) { + threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) { for (const int i : range) { results[i] = BKE_curvemapping_evaluateF(cumap, 3, attribute_in[i]); } @@ -148,10 +148,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon } case CD_PROP_FLOAT3: { const CurveMapping *cumap = (CurveMapping *)node_storage.curve_vec; - GVArray_Typed<float3> attribute_in = component.attribute_get_for_read<float3>( + VArray<float3> attribute_in = component.attribute_get_for_read<float3>( input_name, result_domain, float3(0.0f)); MutableSpan<float3> results = attribute_result.as_span<float3>(); - threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) { + threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) { for (const int i : range) { BKE_curvemapping_evaluate3F(cumap, results[i], attribute_in[i]); } @@ -160,11 +160,10 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon } case CD_PROP_COLOR: { const CurveMapping *cumap = (CurveMapping *)node_storage.curve_rgb; - GVArray_Typed<ColorGeometry4f> attribute_in = - component.attribute_get_for_read<ColorGeometry4f>( - input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f)); + VArray<ColorGeometry4f> attribute_in = component.attribute_get_for_read<ColorGeometry4f>( + input_name, result_domain, ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f)); MutableSpan<ColorGeometry4f> results = attribute_result.as_span<ColorGeometry4f>(); - threading::parallel_for(IndexRange(attribute_in.size()), 512, [&](IndexRange range) { + threading::parallel_for(attribute_in.index_range(), 512, [&](IndexRange range) { for (const int i : range) { BKE_curvemapping_evaluateRGBF(cumap, results[i], attribute_in[i]); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc index 978c75187fe..1dc2d9457e6 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc @@ -362,7 +362,7 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP const AttributeDomain domain = get_result_domain(component, input_name, result_name); - GVArrayPtr attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type); + GVArray attribute_input = component.attribute_try_get_for_read(input_name, domain, data_type); if (!attribute_input) { params.error_message_add(NodeWarningType::Error, @@ -381,12 +381,12 @@ static void map_range_attribute(GeometryComponent &component, const GeoNodeExecP switch (data_type) { case CD_PROP_FLOAT: { - map_range_float(attribute_input->typed<float>(), attribute_result.as_span<float>(), params); + map_range_float(attribute_input.typed<float>(), attribute_result.as_span<float>(), params); break; } case CD_PROP_FLOAT3: { map_range_float3( - attribute_input->typed<float3>(), attribute_result.as_span<float3>(), params); + attribute_input.typed<float3>(), attribute_result.as_span<float3>(), params); break; } default: diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc index 55d35f87cda..b01936c9929 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc @@ -250,7 +250,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP return; } - GVArray_Typed<float> attribute_a = params.get_input_attribute<float>( + VArray<float> attribute_a = params.get_input_attribute<float>( "A", component, result_domain, 0.0f); MutableSpan<float> result_span = attribute_result.as_span(); @@ -258,10 +258,10 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP /* Note that passing the data with `get_internal_span<float>()` works * because the attributes were accessed with #CD_PROP_FLOAT. */ if (operation_use_input_b(operation)) { - GVArray_Typed<float> attribute_b = params.get_input_attribute<float>( + VArray<float> attribute_b = params.get_input_attribute<float>( "B", component, result_domain, 0.0f); if (operation_use_input_c(operation)) { - GVArray_Typed<float> attribute_c = params.get_input_attribute<float>( + VArray<float> attribute_c = params.get_input_attribute<float>( "C", component, result_domain, 0.0f); do_math_operation(attribute_a, attribute_b, attribute_c, result_span, operation); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc index b4205bc91b7..36ac6e040ee 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc @@ -144,25 +144,28 @@ static void do_mix_operation(const CustomDataType result_type, GVMutableArray &attribute_result) { if (result_type == CD_PROP_FLOAT) { + VMutableArray<float> result = attribute_result.typed<float>(); do_mix_operation_float(blend_mode, attribute_factor, attribute_a.typed<float>(), attribute_b.typed<float>(), - attribute_result.typed<float>()); + result); } else if (result_type == CD_PROP_FLOAT3) { + VMutableArray<float3> result = attribute_result.typed<float3>(); do_mix_operation_float3(blend_mode, attribute_factor, attribute_a.typed<float3>(), attribute_b.typed<float3>(), - attribute_result.typed<float3>()); + result); } else if (result_type == CD_PROP_COLOR) { + VMutableArray<ColorGeometry4f> result = attribute_result.typed<ColorGeometry4f>(); do_mix_operation_color4f(blend_mode, attribute_factor, attribute_a.typed<ColorGeometry4f>(), attribute_b.typed<ColorGeometry4f>(), - attribute_result.typed<ColorGeometry4f>()); + result); } } @@ -203,19 +206,19 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa return; } - GVArray_Typed<float> attribute_factor = params.get_input_attribute<float>( + VArray<float> attribute_factor = params.get_input_attribute<float>( "Factor", component, result_domain, 0.5f); - GVArrayPtr attribute_a = params.get_input_attribute( + GVArray attribute_a = params.get_input_attribute( "A", component, result_domain, result_type, nullptr); - GVArrayPtr attribute_b = params.get_input_attribute( + GVArray attribute_b = params.get_input_attribute( "B", component, result_domain, result_type, nullptr); do_mix_operation(result_type, node_storage->blend_type, attribute_factor, - *attribute_a, - *attribute_b, - *attribute_result); + attribute_a, + attribute_b, + attribute_result.varray()); attribute_result.save(); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc index 9e3a7984c53..0122f9b7598 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc @@ -153,7 +153,7 @@ static void attribute_calc_proximity(GeometryComponent &component, if (!position_attribute || (!distance_attribute && !location_attribute)) { return; } - GVArray_Typed<float3> positions{*position_attribute.varray}; + VArray<float3> positions = position_attribute.varray.typed<float3>(); const NodeGeometryAttributeProximity &storage = *(const NodeGeometryAttributeProximity *)params.node().storage; diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc index 2901472d661..71bb7eb6b79 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc @@ -180,13 +180,13 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo const int domain_size = component.attribute_domain_size(domain); /* Hash the reserved name attribute "id" as a (hopefully) stable seed for each point. */ - GVArrayPtr hash_attribute = component.attribute_try_get_for_read("id", domain); + GVArray hash_attribute = component.attribute_try_get_for_read("id", domain); Array<uint32_t> hashes(domain_size); if (hash_attribute) { - BLI_assert(hashes.size() == hash_attribute->size()); - const CPPType &cpp_type = hash_attribute->type(); + BLI_assert(hashes.size() == hash_attribute.size()); + const CPPType &cpp_type = hash_attribute.type(); BLI_assert(cpp_type.is_hashable()); - GVArray_GSpan items{*hash_attribute}; + GVArray_GSpan items{hash_attribute}; threading::parallel_for(hashes.index_range(), 512, [&](IndexRange range) { for (const int i : range) { hashes[i] = cpp_type.hash(items[i]); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc index 19d6ced6eb6..9748ca3f2ad 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc @@ -82,7 +82,7 @@ static void execute_on_component(GeometryComponent &component, const GeoNodeExec return; } - GVArray_Typed<float3> mapping_attribute = component.attribute_get_for_read<float3>( + VArray<float3> mapping_attribute = component.attribute_get_for_read<float3>( mapping_name, result_domain, {0, 0, 0}); MutableSpan<ColorGeometry4f> colors = attribute_out.as_span(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc index 809e75e73a3..5d3d2e241d9 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc @@ -106,9 +106,9 @@ static void separate_attribute(GeometryComponent &component, const GeoNodeExecPa const AttributeDomain result_domain = get_result_domain( component, params, result_name_x, result_name_y, result_name_z); - GVArray_Typed<float3> attribute_input = params.get_input_attribute<float3>( + VArray<float3> attribute_input = params.get_input_attribute<float3>( "Vector", component, result_domain, {0, 0, 0}); - VArray_Span<float3> input_span{*attribute_input}; + VArray_Span<float3> input_span{attribute_input}; OutputAttribute_Typed<float> attribute_result_x = component.attribute_try_get_for_output_only<float>(result_name_x, result_domain); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc index 3a9cd52661a..b8827f82efc 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc @@ -407,13 +407,13 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry, if (pointcloud_distances_sq[i] < mesh_distances_sq[i]) { /* Point-cloud point is closer. */ const int index = pointcloud_indices[i]; - pointcloud_src_attribute.varray->get(index, buffer); + pointcloud_src_attribute.varray.get(index, buffer); dst_attribute->set_by_relocate(i, buffer); } else { /* Mesh element is closer. */ const int index = mesh_indices[i]; - mesh_src_attribute.varray->get(index, buffer); + mesh_src_attribute.varray.get(index, buffer); dst_attribute->set_by_relocate(i, buffer); } } @@ -424,7 +424,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry, src_name, data_type); for (const int i : IndexRange(tot_samples)) { const int index = pointcloud_indices[i]; - src_attribute.varray->get(index, buffer); + src_attribute.varray.get(index, buffer); dst_attribute->set_by_relocate(i, buffer); } } @@ -434,7 +434,7 @@ static void transfer_attribute_nearest(const GeometrySet &src_geometry, data_type); for (const int i : IndexRange(tot_samples)) { const int index = mesh_indices[i]; - src_attribute.varray->get(index, buffer); + src_attribute.varray.get(index, buffer); dst_attribute->set_by_relocate(i, buffer); } } @@ -460,7 +460,7 @@ static void transfer_attribute(const GeoNodeExecParams ¶ms, const AttributeDomain dst_domain = (input_domain == ATTR_DOMAIN_AUTO) ? auto_domain : input_domain; - GVArray_Typed<float3> dst_positions = dst_component.attribute_get_for_read<float3>( + VArray<float3> dst_positions = dst_component.attribute_get_for_read<float3>( "position", dst_domain, {0, 0, 0}); switch (mapping) { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc index 4c351846243..2b28a50f4b5 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc @@ -187,7 +187,7 @@ static void geo_node_attribute_vector_math_update(bNodeTree *UNUSED(ntree), bNod static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a, const VArray<float3> &input_b, - VMutableArray<float3> &result, + const VMutableArray<float3> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -218,7 +218,7 @@ static void do_math_operation_fl3_fl3_to_fl3(const VArray<float3> &input_a, static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a, const VArray<float3> &input_b, const VArray<float3> &input_c, - VMutableArray<float3> &result, + const VMutableArray<float3> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -251,7 +251,7 @@ static void do_math_operation_fl3_fl3_fl3_to_fl3(const VArray<float3> &input_a, static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a, const VArray<float3> &input_b, const VArray<float> &input_c, - VMutableArray<float3> &result, + const VMutableArray<float3> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -283,7 +283,7 @@ static void do_math_operation_fl3_fl3_fl_to_fl3(const VArray<float3> &input_a, static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a, const VArray<float3> &input_b, - VMutableArray<float> &result, + const VMutableArray<float> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -313,7 +313,7 @@ static void do_math_operation_fl3_fl3_to_fl(const VArray<float3> &input_a, static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a, const VArray<float> &input_b, - VMutableArray<float3> &result, + const VMutableArray<float3> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -342,7 +342,7 @@ static void do_math_operation_fl3_fl_to_fl3(const VArray<float3> &input_a, } static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a, - VMutableArray<float3> &result, + const VMutableArray<float3> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -369,7 +369,7 @@ static void do_math_operation_fl3_to_fl3(const VArray<float3> &input_a, } static void do_math_operation_fl3_to_fl(const VArray<float3> &input_a, - VMutableArray<float> &result, + const VMutableArray<float> &result, const NodeVectorMathOperation operation) { const int size = input_a.size(); @@ -437,13 +437,13 @@ static void attribute_vector_math_calc(GeometryComponent &component, const AttributeDomain result_domain = get_result_domain( component, params, operation, result_name); - GVArrayPtr attribute_a = params.get_input_attribute( + GVArray attribute_a = params.get_input_attribute( "A", component, result_domain, read_type_a, nullptr); if (!attribute_a) { return; } - GVArrayPtr attribute_b; - GVArrayPtr attribute_c; + GVArray attribute_b; + GVArray attribute_c; if (use_input_b) { attribute_b = params.get_input_attribute("B", component, result_domain, read_type_b, nullptr); if (!attribute_b) { @@ -476,26 +476,26 @@ static void attribute_vector_math_calc(GeometryComponent &component, case NODE_VECTOR_MATH_MODULO: case NODE_VECTOR_MATH_MINIMUM: case NODE_VECTOR_MATH_MAXIMUM: - do_math_operation_fl3_fl3_to_fl3(attribute_a->typed<float3>(), - attribute_b->typed<float3>(), - attribute_result->typed<float3>(), + do_math_operation_fl3_fl3_to_fl3(attribute_a.typed<float3>(), + attribute_b.typed<float3>(), + attribute_result.varray().typed<float3>(), operation); break; case NODE_VECTOR_MATH_DOT_PRODUCT: case NODE_VECTOR_MATH_DISTANCE: - do_math_operation_fl3_fl3_to_fl(attribute_a->typed<float3>(), - attribute_b->typed<float3>(), - attribute_result->typed<float>(), + do_math_operation_fl3_fl3_to_fl(attribute_a.typed<float3>(), + attribute_b.typed<float3>(), + attribute_result.varray().typed<float>(), operation); break; case NODE_VECTOR_MATH_LENGTH: do_math_operation_fl3_to_fl( - attribute_a->typed<float3>(), attribute_result->typed<float>(), operation); + attribute_a.typed<float3>(), attribute_result.varray().typed<float>(), operation); break; case NODE_VECTOR_MATH_SCALE: - do_math_operation_fl3_fl_to_fl3(attribute_a->typed<float3>(), - attribute_b->typed<float>(), - attribute_result->typed<float3>(), + do_math_operation_fl3_fl_to_fl3(attribute_a.typed<float3>(), + attribute_b.typed<float>(), + attribute_result.varray().typed<float3>(), operation); break; case NODE_VECTOR_MATH_NORMALIZE: @@ -507,22 +507,22 @@ static void attribute_vector_math_calc(GeometryComponent &component, case NODE_VECTOR_MATH_COSINE: case NODE_VECTOR_MATH_TANGENT: do_math_operation_fl3_to_fl3( - attribute_a->typed<float3>(), attribute_result->typed<float3>(), operation); + attribute_a.typed<float3>(), attribute_result.varray().typed<float3>(), operation); break; case NODE_VECTOR_MATH_WRAP: case NODE_VECTOR_MATH_FACEFORWARD: case NODE_VECTOR_MATH_MULTIPLY_ADD: - do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a->typed<float3>(), - attribute_b->typed<float3>(), - attribute_c->typed<float3>(), - attribute_result->typed<float3>(), + do_math_operation_fl3_fl3_fl3_to_fl3(attribute_a.typed<float3>(), + attribute_b.typed<float3>(), + attribute_c.typed<float3>(), + attribute_result.varray().typed<float3>(), operation); break; case NODE_VECTOR_MATH_REFRACT: - do_math_operation_fl3_fl3_fl_to_fl3(attribute_a->typed<float3>(), - attribute_b->typed<float3>(), - attribute_c->typed<float>(), - attribute_result->typed<float3>(), + do_math_operation_fl3_fl3_fl_to_fl3(attribute_a.typed<float3>(), + attribute_b.typed<float3>(), + attribute_c.typed<float>(), + attribute_result.varray().typed<float3>(), operation); break; } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc index 9ab8ec25fb6..298ca40abc1 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc @@ -220,12 +220,12 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon const AttributeDomain result_domain = get_result_domain(component, params, result_name); const bool invert = params.get_input<bool>("Invert"); - GVArrayPtr attribute_vector = params.get_input_attribute( + GVArray attribute_vector = params.get_input_attribute( "Vector", component, result_domain, CD_PROP_FLOAT3, nullptr); if (!attribute_vector) { return; } - GVArrayPtr attribute_center = params.get_input_attribute( + GVArray attribute_center = params.get_input_attribute( "Center", component, result_domain, CD_PROP_FLOAT3, nullptr); if (!attribute_center) { return; @@ -238,21 +238,21 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon } if (mode == GEO_NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { - GVArrayPtr attribute_rotation = params.get_input_attribute( + GVArray attribute_rotation = params.get_input_attribute( "Rotation", component, result_domain, CD_PROP_FLOAT3, nullptr); if (!attribute_rotation) { return; } - do_vector_rotate_euler(attribute_vector->typed<float3>(), - attribute_center->typed<float3>(), - attribute_rotation->typed<float3>(), + do_vector_rotate_euler(attribute_vector.typed<float3>(), + attribute_center.typed<float3>(), + attribute_rotation.typed<float3>(), attribute_result.as_span<float3>(), invert); attribute_result.save(); return; } - GVArrayPtr attribute_angle = params.get_input_attribute( + GVArray attribute_angle = params.get_input_attribute( "Angle", component, result_domain, CD_PROP_FLOAT, nullptr); if (!attribute_angle) { return; @@ -260,40 +260,40 @@ static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryCompon switch (mode) { case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS: { - GVArrayPtr attribute_axis = params.get_input_attribute( + GVArray attribute_axis = params.get_input_attribute( "Axis", component, result_domain, CD_PROP_FLOAT3, nullptr); if (!attribute_axis) { return; } - do_vector_rotate_around_axis(attribute_vector->typed<float3>(), - attribute_center->typed<float3>(), - attribute_axis->typed<float3>(), - attribute_angle->typed<float>(), + do_vector_rotate_around_axis(attribute_vector.typed<float3>(), + attribute_center.typed<float3>(), + attribute_axis.typed<float3>(), + attribute_angle.typed<float>(), attribute_result.as_span<float3>(), invert); } break; case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_X: - do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(), - attribute_center->typed<float3>(), + do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(), + attribute_center.typed<float3>(), float3(1.0f, 0.0f, 0.0f), - attribute_angle->typed<float>(), + attribute_angle.typed<float>(), attribute_result.as_span<float3>(), invert); break; case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Y: - do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(), - attribute_center->typed<float3>(), + do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(), + attribute_center.typed<float3>(), float3(0.0f, 1.0f, 0.0f), - attribute_angle->typed<float>(), + attribute_angle.typed<float>(), attribute_result.as_span<float3>(), invert); break; case GEO_NODE_VECTOR_ROTATE_TYPE_AXIS_Z: - do_vector_rotate_around_fixed_axis(attribute_vector->typed<float3>(), - attribute_center->typed<float3>(), + do_vector_rotate_around_fixed_axis(attribute_vector.typed<float3>(), + attribute_center.typed<float3>(), float3(0.0f, 0.0f, 1.0f), - attribute_angle->typed<float>(), + attribute_angle.typed<float>(), attribute_result.as_span<float3>(), invert); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc index 8b81008ff34..67c8200a9c2 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc @@ -61,7 +61,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, if (meta_data.domain != ATTR_DOMAIN_CURVE) { return true; } - GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( + GVArray spline_attribute = curve_component.attribute_get_for_read( attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type); OutputAttribute result_attribute = points.attribute_try_get_for_output_only( @@ -70,7 +70,7 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, /* Only copy the attributes of splines in the offsets. */ for (const int i : offsets.index_range()) { - spline_attribute->get(offsets[i], result[i]); + spline_attribute.get(offsets[i], result[i]); } result_attribute.save(); @@ -130,7 +130,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines, BLI_assert(spline.attributes.get_for_read(attribute_id)); GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - blender::fn::GVArray_For_GSpan(spline_span).get(0, point_span[i]); + spline_span.type().copy_assign(spline_span[0], point_span[i]); } for (const auto item : end_data.point_attributes.items()) { @@ -139,7 +139,7 @@ static void copy_endpoint_attributes(Span<SplinePtr> splines, BLI_assert(spline.attributes.get_for_read(attribute_id)); GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - blender::fn::GVArray_For_GSpan(spline_span).get(spline.size() - 1, point_span[i]); + spline_span.type().copy_assign(spline_span[spline.size() - 1], point_span[i]); } } }); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc index ba76fafe3e6..bc4612e2b8b 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc @@ -44,7 +44,7 @@ static void geo_node_curve_reverse_exec(GeoNodeExecParams params) MutableSpan<SplinePtr> splines = curve.splines(); const std::string selection_name = params.extract_input<std::string>("Selection"); - GVArray_Typed<bool> selection = curve_component.attribute_get_for_read( + VArray<bool> selection = curve_component.attribute_get_for_read( selection_name, ATTR_DOMAIN_CURVE, true); threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc index 4bac9cb976e..b92db315d94 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc @@ -84,7 +84,7 @@ static void geo_node_curve_set_handles_exec(GeoNodeExecParams params) MutableSpan<SplinePtr> splines = curve.splines(); const std::string selection_name = params.extract_input<std::string>("Selection"); - GVArray_Typed<bool> selection = curve_component.attribute_get_for_read( + VArray<bool> selection = curve_component.attribute_get_for_read( selection_name, ATTR_DOMAIN_POINT, true); const BezierSpline::HandleType new_handle_type = handle_type_from_input_type(type); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc index df53c96e6ca..36d4519cac3 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc @@ -255,7 +255,7 @@ static void geo_node_legacy_curve_spline_type_exec(GeoNodeExecParams params) const CurveEval &curve = *curve_component->get_for_read(); const std::string selection_name = params.extract_input<std::string>("Selection"); - GVArray_Typed<bool> selection = curve_component->attribute_get_for_read( + VArray<bool> selection = curve_component->attribute_get_for_read( selection_name, ATTR_DOMAIN_CURVE, true); std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc index f9b0a9d128e..5b6be344a1d 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc @@ -25,10 +25,6 @@ #include "node_geometry_util.hh" -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_For_Span; -using blender::fn::GVArray_Typed; - namespace blender::nodes { static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b) @@ -363,14 +359,13 @@ static void geo_node_subdivide_exec(GeoNodeExecParams params) } const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>(); - GVArray_Typed<int> cuts = params.get_input_attribute<int>( - "Cuts", component, ATTR_DOMAIN_POINT, 0); - if (cuts->is_single() && cuts->get_internal_single() < 1) { + VArray<int> cuts = params.get_input_attribute<int>("Cuts", component, ATTR_DOMAIN_POINT, 0); + if (cuts.is_single() && cuts.get_internal_single() < 1) { params.set_output("Geometry", geometry_set); return; } - std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), *cuts); + std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts); params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release())); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc index c171d485a6a..035077ad3f4 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc @@ -121,7 +121,7 @@ static GMutableSpan create_attribute_and_retrieve_span(PointCloudComponent &poin points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault()); WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id); BLI_assert(attribute); - return attribute.varray->get_internal_span(); + return attribute.varray.get_internal_span(); } template<typename T> @@ -177,8 +177,8 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, const int size = offsets[i + 1] - offsets[i]; data.positions.slice(offset, size).copy_from(spline.evaluated_positions()); - spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size)); - spline.interpolate_to_evaluated(spline.tilts())->materialize(data.tilts.slice(offset, size)); + spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size)); + spline.interpolate_to_evaluated(spline.tilts()).materialize(data.tilts.slice(offset, size)); for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) { const AttributeIDRef attribute_id = item.key; @@ -188,7 +188,7 @@ static void copy_evaluated_point_attributes(Span<SplinePtr> splines, GSpan spline_span = *spline.attributes.get_for_read(attribute_id); spline.interpolate_to_evaluated(spline_span) - ->materialize(point_span.slice(offset, size).data()); + .materialize(point_span.slice(offset, size).data()); } data.tangents.slice(offset, size).copy_from(spline.evaluated_tangents()); @@ -230,7 +230,7 @@ static void copy_uniform_sample_point_attributes(Span<SplinePtr> splines, BLI_assert(spline.attributes.get_for_read(attribute_id)); GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span), + spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span), uniform_samples, point_span.slice(offset, size)); } @@ -263,20 +263,20 @@ static void copy_spline_domain_attributes(const CurveComponent &curve_component, if (meta_data.domain != ATTR_DOMAIN_CURVE) { return true; } - GVArrayPtr spline_attribute = curve_component.attribute_get_for_read( + GVArray spline_attribute = curve_component.attribute_get_for_read( attribute_id, ATTR_DOMAIN_CURVE, meta_data.data_type); - const CPPType &type = spline_attribute->type(); + const CPPType &type = spline_attribute.type(); OutputAttribute result_attribute = points.attribute_try_get_for_output_only( attribute_id, ATTR_DOMAIN_POINT, meta_data.data_type); GMutableSpan result = result_attribute.as_span(); - for (const int i : IndexRange(spline_attribute->size())) { + for (const int i : spline_attribute.index_range()) { const int offset = offsets[i]; const int size = offsets[i + 1] - offsets[i]; if (size != 0) { BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); - spline_attribute->get(i, buffer); + spline_attribute.get(i, buffer); type.fill_assign_n(buffer, result[offset], size); } } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc index 1d76a0532a1..f62a22d7934 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc @@ -137,7 +137,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve, Vector<int64_t> copied_splines; if (input_curve.attributes.get_for_read(name)) { - GVArray_Typed<bool> selection = input_curve.attributes.get_for_read<bool>(name, false); + VArray<bool> selection = input_curve.attributes.get_for_read<bool>(name, false); for (const int i : input_splines.index_range()) { if (selection[i] == invert) { output_curve->add_spline(input_splines[i]->copy()); @@ -151,7 +151,7 @@ static std::unique_ptr<CurveEval> curve_delete(const CurveEval &input_curve, for (const int i : input_splines.index_range()) { const Spline &spline = *input_splines[i]; - GVArray_Typed<bool> selection = spline.attributes.get_for_read<bool>(name, false); + VArray<bool> selection = spline.attributes.get_for_read<bool>(name, false); indices_to_copy.clear(); for (const int i_point : IndexRange(spline.size())) { @@ -202,7 +202,7 @@ static void delete_point_cloud_selection(const PointCloudComponent &in_component const StringRef selection_name, const bool invert) { - const GVArray_Typed<bool> selection_attribute = in_component.attribute_get_for_read<bool>( + const VArray<bool> selection_attribute = in_component.attribute_get_for_read<bool>( selection_name, ATTR_DOMAIN_POINT, false); VArray_Span<bool> selection{selection_attribute}; @@ -590,7 +590,7 @@ static void delete_mesh_selection(MeshComponent &component, const AttributeDomain selection_domain = get_mesh_selection_domain(component, selection_name); /* This already checks if the attribute exists, and displays a warning in that case. */ - GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>( + VArray<bool> selection = component.attribute_get_for_read<bool>( selection_name, selection_domain, false); /* Check if there is anything to delete. */ diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc index 333a17aa4e9..58374679a95 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc @@ -72,7 +72,7 @@ static void geo_node_legacy_material_assign_exec(GeoNodeExecParams params) MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); Mesh *mesh = mesh_component.get_for_write(); if (mesh != nullptr) { - GVArray_Typed<bool> face_mask = mesh_component.attribute_get_for_read<bool>( + VArray<bool> face_mask = mesh_component.attribute_get_for_read<bool>( mask_name, ATTR_DOMAIN_FACE, true); assign_material_to_faces(*mesh, face_mask, material); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc index 9167096fd3d..321de24a3dc 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc @@ -44,7 +44,7 @@ static void geo_node_legacy_mesh_to_curve_exec(GeoNodeExecParams params) params.error_message_add(NodeWarningType::Error, TIP_("No attribute with name \"") + selection_name + "\""); } - GVArray_Typed<bool> selection = component.attribute_get_for_read<bool>( + VArray<bool> selection = component.attribute_get_for_read<bool>( selection_name, ATTR_DOMAIN_EDGE, true); Vector<int64_t> selected_edge_indices; diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc index 210757f986d..73428c88235 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc @@ -106,9 +106,9 @@ static void sample_mesh_surface(const Mesh &mesh, float looptri_density_factor = 1.0f; if (density_factors != nullptr) { - const float v0_density_factor = std::max(0.0f, density_factors->get(v0_loop)); - const float v1_density_factor = std::max(0.0f, density_factors->get(v1_loop)); - const float v2_density_factor = std::max(0.0f, density_factors->get(v2_loop)); + const float v0_density_factor = std::max(0.0f, (*density_factors)[v0_loop]); + const float v1_density_factor = std::max(0.0f, (*density_factors)[v1_loop]); + const float v2_density_factor = std::max(0.0f, (*density_factors)[v2_loop]); looptri_density_factor = (v0_density_factor + v1_density_factor + v2_density_factor) / 3.0f; } const float area = area_tri_v3(v0_pos, v1_pos, v2_pos); @@ -315,7 +315,7 @@ BLI_NOINLINE static void interpolate_existing_attributes( } const AttributeDomain source_domain = attribute_info->domain; - GVArrayPtr source_attribute = source_component.attribute_get_for_read( + GVArray source_attribute = source_component.attribute_get_for_read( attribute_id, source_domain, output_data_type, nullptr); if (!source_attribute) { i_instance += set_group.transforms.size(); @@ -329,7 +329,7 @@ BLI_NOINLINE static void interpolate_existing_attributes( GMutableSpan instance_span = out_span.slice(offset, bary_coords.size()); interpolate_attribute( - mesh, bary_coords, looptri_indices, source_domain, *source_attribute, instance_span); + mesh, bary_coords, looptri_indices, source_domain, source_attribute, instance_span); i_instance++; } @@ -337,7 +337,7 @@ BLI_NOINLINE static void interpolate_existing_attributes( attribute_math::convert_to_static_type(output_data_type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Span<T> source_span{*source_attribute}; + VArray_Span source_span{source_attribute.typed<T>()}; }); } @@ -445,7 +445,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups, for (const GeometryInstanceGroup &set_group : set_groups) { const GeometrySet &set = set_group.geometry_set; const MeshComponent &component = *set.get_component_for_read<MeshComponent>(); - GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>( + VArray<float> density_factors = component.attribute_get_for_read<float>( density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f); const Mesh &mesh = *component.get_for_read(); for (const float4x4 &transform : set_group.transforms) { @@ -455,7 +455,7 @@ static void distribute_points_random(Span<GeometryInstanceGroup> set_groups, sample_mesh_surface(mesh, transform, density, - &*density_factors, + &density_factors, seed, positions, bary_coords, @@ -514,7 +514,7 @@ static void distribute_points_poisson_disk(Span<GeometryInstanceGroup> set_group const GeometrySet &set = set_group.geometry_set; const MeshComponent &component = *set.get_component_for_read<MeshComponent>(); const Mesh &mesh = *component.get_for_read(); - const GVArray_Typed<float> density_factors = component.attribute_get_for_read<float>( + const VArray<float> density_factors = component.attribute_get_for_read<float>( density_attribute_name, ATTR_DOMAIN_CORNER, use_one_default ? 1.0f : 0.0f); for (const int UNUSED(i_set_instance) : set_group.transforms.index_range()) { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc index ffb2a0dd7ac..27875ce457f 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc @@ -171,13 +171,12 @@ static void add_instances_from_component(InstancesComponent &instances, const int domain_size = src_geometry.attribute_domain_size(domain); - GVArray_Typed<float3> positions = src_geometry.attribute_get_for_read<float3>( + VArray<float3> positions = src_geometry.attribute_get_for_read<float3>( "position", domain, {0, 0, 0}); - GVArray_Typed<float3> rotations = src_geometry.attribute_get_for_read<float3>( + VArray<float3> rotations = src_geometry.attribute_get_for_read<float3>( "rotation", domain, {0, 0, 0}); - GVArray_Typed<float3> scales = src_geometry.attribute_get_for_read<float3>( - "scale", domain, {1, 1, 1}); - GVArray_Typed<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1); + VArray<float3> scales = src_geometry.attribute_get_for_read<float3>("scale", domain, {1, 1, 1}); + VArray<int> id_attribute = src_geometry.attribute_get_for_read<int>("id", domain, -1); /* The initial size of the component might be non-zero if there are two component types. */ const int start_len = instances.instances_amount(); diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc index 54d36dab98d..977099d47db 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc @@ -169,9 +169,9 @@ static void point_rotate_on_component(GeometryComponent &component, const int domain_size = rotations.size(); if (storage.type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) { - GVArray_Typed<float3> axis = params.get_input_attribute<float3>( + VArray<float3> axis = params.get_input_attribute<float3>( "Axis", component, ATTR_DOMAIN_POINT, {0, 0, 1}); - GVArray_Typed<float> angles = params.get_input_attribute<float>( + VArray<float> angles = params.get_input_attribute<float>( "Angle", component, ATTR_DOMAIN_POINT, 0); if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) { @@ -182,7 +182,7 @@ static void point_rotate_on_component(GeometryComponent &component, } } else { - GVArray_Typed<float3> eulers = params.get_input_attribute<float3>( + VArray<float3> eulers = params.get_input_attribute<float3>( "Rotation", component, ATTR_DOMAIN_POINT, {0, 0, 0}); if (storage.space == GEO_NODE_POINT_ROTATE_SPACE_OBJECT) { diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc index 934442ee8a3..0869c4a6a09 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc @@ -78,7 +78,7 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co const CustomDataType data_type = (input_type == GEO_NODE_ATTRIBUTE_INPUT_FLOAT) ? CD_PROP_FLOAT : CD_PROP_FLOAT3; - GVArrayPtr attribute = params.get_input_attribute( + GVArray attribute = params.get_input_attribute( "Factor", component, ATTR_DOMAIN_POINT, data_type, nullptr); if (!attribute) { return; @@ -86,13 +86,13 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co MutableSpan<float3> scale_span = scale_attribute.as_span(); if (data_type == CD_PROP_FLOAT) { - GVArray_Typed<float> factors{*attribute}; + VArray<float> factors = attribute.typed<float>(); for (const int i : scale_span.index_range()) { scale_span[i] = scale_span[i] * factors[i]; } } else if (data_type == CD_PROP_FLOAT3) { - GVArray_Typed<float3> factors{*attribute}; + VArray<float3> factors = attribute.typed<float3>(); for (const int i : scale_span.index_range()) { scale_span[i] = scale_span[i] * factors[i]; } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc index accdaf78439..3539fe2de64 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc @@ -55,7 +55,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, { for (const AttributeIDRef &attribute_id : in_component.attribute_ids()) { ReadAttributeLookup attribute = in_component.attribute_try_get_for_read(attribute_id); - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type()); + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); /* Only copy point attributes. Theoretically this could interpolate attributes on other * domains to the point domain, but that would conflict with attributes that are built-in @@ -69,7 +69,7 @@ void copy_point_attributes_based_on_mask(const GeometryComponent &in_component, attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Span<T> span{*attribute.varray}; + VArray_Span span{attribute.varray.typed<T>()}; MutableSpan<T> out_span = result_attribute.as_span<T>(); copy_data_based_on_mask(span, masks, invert, out_span); }); @@ -103,7 +103,7 @@ static void separate_points_from_component(const GeometryComponent &in_component return; } - const GVArray_Typed<bool> mask_attribute = in_component.attribute_get_for_read<bool>( + const VArray<bool> mask_attribute = in_component.attribute_get_for_read<bool>( mask_name, ATTR_DOMAIN_POINT, false); VArray_Span<bool> masks{mask_attribute}; diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc index 34f7641995f..3c67c3f3985 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc @@ -43,10 +43,10 @@ static void execute_on_component(GeoNodeExecParams params, GeometryComponent &co if (!position_attribute) { return; } - GVArray_Typed<float3> attribute = params.get_input_attribute<float3>( + VArray<float3> attribute = params.get_input_attribute<float3>( "Translation", component, ATTR_DOMAIN_POINT, {0, 0, 0}); - for (const int i : IndexRange(attribute.size())) { + for (const int i : attribute.index_range()) { position_attribute->set(i, position_attribute->get(i) + attribute[i]); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc index cf7f466c2a6..5ad7f187c18 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc @@ -172,12 +172,12 @@ static void gather_point_data_from_component(const GeoNodeExecParams ¶ms, Vector<float3> &r_positions, Vector<float> &r_radii) { - GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>( + VArray<float3> positions = component.attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - GVArray_Typed<float> radii = params.get_input_attribute<float>( + VArray<float> radii = params.get_input_attribute<float>( "Radius", component, ATTR_DOMAIN_POINT, 0.0f); - for (const int i : IndexRange(positions.size())) { + for (const int i : positions.index_range()) { r_positions.append(positions[i]); r_radii.append(radii[i]); } diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc index e6a81fc9627..a3e1e4e60c6 100644 --- a/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc +++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc @@ -197,11 +197,11 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms, (GeometryNodeRaycastMapMode)storage.mapping); const AttributeDomain result_domain = ATTR_DOMAIN_POINT; - GVArray_Typed<float3> ray_origins = dst_component.attribute_get_for_read<float3>( + VArray<float3> ray_origins = dst_component.attribute_get_for_read<float3>( "position", result_domain, {0, 0, 0}); - GVArray_Typed<float3> ray_directions = params.get_input_attribute<float3>( + VArray<float3> ray_directions = params.get_input_attribute<float3>( "Ray Direction", dst_component, result_domain, {0, 0, 0}); - GVArray_Typed<float> ray_lengths = params.get_input_attribute<float>( + VArray<float> ray_lengths = params.get_input_attribute<float>( "Ray Length", dst_component, result_domain, 0); OutputAttribute_Typed<bool> hit_attribute = @@ -218,10 +218,10 @@ static void raycast_from_points(const GeoNodeExecParams ¶ms, Array<int> hit_indices; Array<float3> hit_positions_internal; if (!hit_attribute_names.is_empty()) { - hit_indices.reinitialize(ray_origins->size()); + hit_indices.reinitialize(ray_origins.size()); if (!hit_position_attribute) { - hit_positions_internal.reinitialize(ray_origins->size()); + hit_positions_internal.reinitialize(ray_origins.size()); } } const MutableSpan<bool> is_hit = hit_attribute ? hit_attribute.as_span() : MutableSpan<bool>(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc index 3cf682e161c..221fb421ab4 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc @@ -169,10 +169,10 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) span_count++; const PointCloudComponent *component = geometry_set.get_component_for_read<PointCloudComponent>(); - GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>( + VArray<float3> varray = component->attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - total_size += varray->size(); - positions_span = varray->get_internal_span(); + total_size += varray.size(); + positions_span = varray.get_internal_span(); } if (geometry_set.has_curve()) { @@ -200,18 +200,18 @@ static Mesh *compute_hull(const GeometrySet &geometry_set) if (geometry_set.has_mesh()) { const MeshComponent *component = geometry_set.get_component_for_read<MeshComponent>(); - GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>( + VArray<float3> varray = component->attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - varray->materialize(positions.as_mutable_span().slice(offset, varray.size())); + varray.materialize(positions.as_mutable_span().slice(offset, varray.size())); offset += varray.size(); } if (geometry_set.has_pointcloud()) { const PointCloudComponent *component = geometry_set.get_component_for_read<PointCloudComponent>(); - GVArray_Typed<float3> varray = component->attribute_get_for_read<float3>( + VArray<float3> varray = component->attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); - varray->materialize(positions.as_mutable_span().slice(offset, varray.size())); + varray.materialize(positions.as_mutable_span().slice(offset, varray.size())); offset += varray.size(); } @@ -235,16 +235,16 @@ static void read_positions(const GeometryComponent &component, Span<float4x4> transforms, Vector<float3> *r_coords) { - GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>( + VArray<float3> positions = component.attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); /* NOTE: could use convex hull operation here to * cut out some vertices, before accumulating, * but can also be done by the user beforehand. */ - r_coords->reserve(r_coords->size() + positions.size() * transforms.size()); + r_coords->reserve(r_coords->size() + positions->size() * transforms.size()); for (const float4x4 &transform : transforms) { - for (const int i : positions.index_range()) { + for (const int i : positions->index_range()) { const float3 position = positions[i]; const float3 transformed_position = transform * position; r_coords->append(transformed_position); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc index 42d88cdb1e7..c41b76412e9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc @@ -64,9 +64,9 @@ class EndpointFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask UNUSED(mask), - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &UNUSED(scope)) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -111,9 +111,9 @@ class EndpointFieldInput final : public fn::FieldInput { } current_point += spline->size(); } - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection)); + return VArray<bool>::ForContainer(std::move(selection)); } - return nullptr; + return {}; }; uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc index 27d7d22b106..f53557035bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc @@ -59,10 +59,10 @@ struct FilletParam { GeometryNodeCurveFilletMode mode; /* Number of points to be added. */ - const VArray<int> *counts; + VArray<int> counts; /* Radii for fillet arc at all vertices. */ - const VArray<float> *radii; + VArray<float> radii; /* Whether or not fillets are allowed to overlap. */ bool limit_radius; @@ -160,7 +160,7 @@ static Array<int> calculate_counts(const FilletParam &fillet_param, Array<int> counts(size, 1); if (fillet_param.mode == GEO_NODE_CURVE_FILLET_POLY) { for (const int i : IndexRange(size)) { - counts[i] = (*fillet_param.counts)[spline_offset + i]; + counts[i] = fillet_param.counts[spline_offset + i]; } } if (!cyclic) { @@ -178,12 +178,12 @@ static Array<float> calculate_radii(const FilletParam &fillet_param, Array<float> radii(size, 0.0f); if (fillet_param.limit_radius) { for (const int i : IndexRange(size)) { - radii[i] = std::max((*fillet_param.radii)[spline_offset + i], 0.0f); + radii[i] = std::max(fillet_param.radii[spline_offset + i], 0.0f); } } else { for (const int i : IndexRange(size)) { - radii[i] = (*fillet_param.radii)[spline_offset + i]; + radii[i] = fillet_param.radii[spline_offset + i]; } } @@ -590,13 +590,13 @@ static void calculate_curve_fillet(GeometrySet &geometry_set, field_evaluator.evaluate(); - fillet_param.radii = &field_evaluator.get_evaluated<float>(0); - if (fillet_param.radii->is_single() && fillet_param.radii->get_internal_single() < 0.0f) { + fillet_param.radii = field_evaluator.get_evaluated<float>(0); + if (fillet_param.radii.is_single() && fillet_param.radii.get_internal_single() < 0.0f) { return; } if (mode == GEO_NODE_CURVE_FILLET_POLY) { - fillet_param.counts = &field_evaluator.get_evaluated<int>(1); + fillet_param.counts = field_evaluator.get_evaluated<int>(1); } fillet_param.limit_radius = limit_radius; diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc index e48c72b68d9..5fb17270301 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc @@ -96,9 +96,9 @@ class HandleTypeFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &UNUSED(scope)) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -106,22 +106,22 @@ class HandleTypeFieldInput final : public fn::FieldInput { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); if (component.type() != GEO_COMPONENT_TYPE_CURVE) { - return nullptr; + return {}; } const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); const CurveEval *curve = curve_component.get_for_read(); if (curve == nullptr) { - return nullptr; + return {}; } if (domain == ATTR_DOMAIN_POINT) { Array<bool> selection(mask.min_array_size()); select_by_handle_type(*curve, type_, mode_, selection); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection)); + return VArray<bool>::ForContainer(std::move(selection)); } } - return nullptr; + return {}; }; uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc index ee7a78ccf71..63518b38090 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc @@ -129,10 +129,9 @@ static Array<float> curve_length_point_domain(const CurveEval &curve) return lengths; } -static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve, - const IndexMask mask, - const AttributeDomain domain, - ResourceScope &scope) +static VArray<float> construct_curve_parameter_varray(const CurveEval &curve, + const IndexMask mask, + const AttributeDomain domain) { if (domain == ATTR_DOMAIN_POINT) { Span<SplinePtr> splines = curve.splines(); @@ -147,7 +146,7 @@ static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve, values[offsets[i_spline] + i] *= spline_length_inv; } } - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(values)); + return VArray<float>::ForContainer(std::move(values)); } if (domain == ATTR_DOMAIN_CURVE) { @@ -156,32 +155,31 @@ static const GVArray *construct_curve_parameter_gvarray(const CurveEval &curve, for (const int i : mask) { values[i] *= total_length_inv; } - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(values)); + return VArray<float>::ForContainer(std::move(values)); } - return nullptr; + return {}; } -static const GVArray *construct_curve_length_gvarray(const CurveEval &curve, - const IndexMask mask, - const AttributeDomain domain, - ResourceScope &scope) +static VArray<float> construct_curve_length_varray(const CurveEval &curve, + const IndexMask mask, + const AttributeDomain domain) { if (domain == ATTR_DOMAIN_POINT) { Array<float> lengths = curve_length_point_domain(curve); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(lengths)); + return VArray<float>::ForContainer(std::move(lengths)); } if (domain == ATTR_DOMAIN_CURVE) { if (curve.splines().size() == 1) { Array<float> lengths(1, 0.0f); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(lengths)); + return VArray<float>::ForContainer(std::move(lengths)); } Array<float> lengths = curve_length_spline_domain(curve, mask); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float>>>(std::move(lengths)); + return VArray<float>::ForContainer(std::move(lengths)); } - return nullptr; + return {}; } class CurveParameterFieldInput final : public fn::FieldInput { @@ -191,9 +189,9 @@ class CurveParameterFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &UNUSED(scope)) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -205,11 +203,11 @@ class CurveParameterFieldInput final : public fn::FieldInput { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); const CurveEval *curve = curve_component.get_for_read(); if (curve) { - return construct_curve_parameter_gvarray(*curve, mask, domain, scope); + return construct_curve_parameter_varray(*curve, mask, domain); } } } - return nullptr; + return {}; } uint64_t hash() const override @@ -231,9 +229,9 @@ class CurveLengthFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &UNUSED(scope)) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -244,11 +242,11 @@ class CurveLengthFieldInput final : public fn::FieldInput { const CurveComponent &curve_component = static_cast<const CurveComponent &>(component); const CurveEval *curve = curve_component.get_for_read(); if (curve) { - return construct_curve_length_gvarray(*curve, mask, domain, scope); + return construct_curve_length_varray(*curve, mask, domain); } } } - return nullptr; + return {}; } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc index 4dad3d22283..a5d5ab756bd 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc @@ -26,10 +26,6 @@ #include "node_geometry_util.hh" -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_For_Span; -using blender::fn::GVArray_Typed; - namespace blender::nodes { static void geo_node_curve_resample_declare(NodeDeclarationBuilder &b) @@ -124,7 +120,7 @@ static SplinePtr resample_spline(const Spline &src, const int count) std::optional<GMutableSpan> output_attribute = dst->attributes.get_for_write( attribute_id); if (output_attribute) { - src.sample_with_index_factors(*src.interpolate_to_evaluated(*input_attribute), + src.sample_with_index_factors(src.interpolate_to_evaluated(*input_attribute), uniform_samples, *output_attribute); return true; @@ -147,8 +143,8 @@ static SplinePtr resample_spline_evaluated(const Spline &src) dst->positions().copy_from(src.evaluated_positions()); dst->positions().copy_from(src.evaluated_positions()); - src.interpolate_to_evaluated(src.radii())->materialize(dst->radii()); - src.interpolate_to_evaluated(src.tilts())->materialize(dst->tilts()); + src.interpolate_to_evaluated(src.radii()).materialize(dst->radii()); + src.interpolate_to_evaluated(src.tilts()).materialize(dst->tilts()); src.attributes.foreach_attribute( [&](const AttributeIDRef &attribute_id, const AttributeMetaData &meta_data) { @@ -156,7 +152,7 @@ static SplinePtr resample_spline_evaluated(const Spline &src) if (dst->attributes.create(attribute_id, meta_data.data_type)) { std::optional<GMutableSpan> dst_attribute = dst->attributes.get_for_write(attribute_id); if (dst_attribute) { - src.interpolate_to_evaluated(*src_attribute)->materialize(dst_attribute->data()); + src.interpolate_to_evaluated(*src_attribute).materialize(dst_attribute->data()); return true; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc index b52de822c22..7c4c17e69e0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc @@ -25,10 +25,6 @@ #include "node_geometry_util.hh" -using blender::fn::GVArray_For_GSpan; -using blender::fn::GVArray_For_Span; -using blender::fn::GVArray_Typed; - namespace blender::nodes { static void geo_node_curve_subdivide_declare(NodeDeclarationBuilder &b) diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index 38d7fb99e87..060dadcb93d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -113,7 +113,7 @@ static GMutableSpan ensure_point_attribute(PointCloudComponent &points, points.attribute_try_create(attribute_id, ATTR_DOMAIN_POINT, data_type, AttributeInitDefault()); WriteAttributeLookup attribute = points.attribute_try_get_for_write(attribute_id); BLI_assert(attribute); - return attribute.varray->get_internal_span(); + return attribute.varray.get_internal_span(); } template<typename T> @@ -194,7 +194,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines, const int size = offsets[i + 1] - offsets[i]; data.positions.slice(offset, size).copy_from(spline.evaluated_positions()); - spline.interpolate_to_evaluated(spline.radii())->materialize(data.radii.slice(offset, size)); + spline.interpolate_to_evaluated(spline.radii()).materialize(data.radii.slice(offset, size)); for (const Map<AttributeIDRef, GMutableSpan>::Item item : data.point_attributes.items()) { const AttributeIDRef attribute_id = item.key; @@ -203,7 +203,7 @@ static void copy_evaluated_point_attributes(const Span<SplinePtr> splines, BLI_assert(spline.attributes.get_for_read(attribute_id)); GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - spline.interpolate_to_evaluated(spline_span)->materialize(dst.slice(offset, size).data()); + spline.interpolate_to_evaluated(spline_span).materialize(dst.slice(offset, size).data()); } if (!data.tangents.is_empty()) { @@ -233,7 +233,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines, spline.sample_with_index_factors<float3>( spline.evaluated_positions(), uniform_samples, data.positions.slice(offset, size)); - spline.sample_with_index_factors<float>(*spline.interpolate_to_evaluated(spline.radii()), + spline.sample_with_index_factors<float>(spline.interpolate_to_evaluated(spline.radii()), uniform_samples, data.radii.slice(offset, size)); @@ -244,7 +244,7 @@ static void copy_uniform_sample_point_attributes(const Span<SplinePtr> splines, BLI_assert(spline.attributes.get_for_read(attribute_id)); GSpan spline_span = *spline.attributes.get_for_read(attribute_id); - spline.sample_with_index_factors(*spline.interpolate_to_evaluated(spline_span), + spline.sample_with_index_factors(spline.interpolate_to_evaluated(spline_span), uniform_samples, dst.slice(offset, size)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc index 4e1a2910c7c..7a04191c319 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc @@ -216,9 +216,9 @@ static PolySpline trim_nurbs_spline(const Spline &spline, attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { using T = decltype(dummy); - GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>()); + VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>()); linear_trim_to_output_data<T>( - start, end, eval_data->get_internal_span(), dst->typed<T>()); + start, end, eval_data.get_internal_span(), dst->typed<T>()); }); return true; }, @@ -227,13 +227,13 @@ static PolySpline trim_nurbs_spline(const Spline &spline, linear_trim_to_output_data<float3>( start, end, spline.evaluated_positions(), new_spline.positions()); - GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii()); + VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii()); linear_trim_to_output_data<float>( - start, end, evaluated_radii->get_internal_span(), new_spline.radii()); + start, end, evaluated_radii.get_internal_span(), new_spline.radii()); - GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts()); + VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts()); linear_trim_to_output_data<float>( - start, end, evaluated_tilts->get_internal_span(), new_spline.tilts()); + start, end, evaluated_tilts.get_internal_span(), new_spline.tilts()); return new_spline; } @@ -427,8 +427,8 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look std::optional<GMutableSpan> dst = new_spline.attributes.get_for_write(attribute_id); attribute_math::convert_to_static_type(src->type(), [&](auto dummy) { using T = decltype(dummy); - GVArray_Typed<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>()); - to_single_point_data<T>(trim, eval_data->get_internal_span(), dst->typed<T>()); + VArray<T> eval_data = spline.interpolate_to_evaluated<T>(src->typed<T>()); + to_single_point_data<T>(trim, eval_data.get_internal_span(), dst->typed<T>()); }); return true; }, @@ -436,11 +436,11 @@ static PolySpline to_single_point_nurbs(const Spline &spline, const Spline::Look to_single_point_data<float3>(trim, spline.evaluated_positions(), new_spline.positions()); - GVArray_Typed<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii()); - to_single_point_data<float>(trim, evaluated_radii->get_internal_span(), new_spline.radii()); + VArray<float> evaluated_radii = spline.interpolate_to_evaluated(spline.radii()); + to_single_point_data<float>(trim, evaluated_radii.get_internal_span(), new_spline.radii()); - GVArray_Typed<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts()); - to_single_point_data<float>(trim, evaluated_tilts->get_internal_span(), new_spline.tilts()); + VArray<float> evaluated_tilts = spline.interpolate_to_evaluated(spline.tilts()); + to_single_point_data<float>(trim, evaluated_tilts.get_internal_span(), new_spline.tilts()); return new_spline; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc index e0a3faaefb0..d07644f8403 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc @@ -138,7 +138,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes if (!domains.contains(attribute.domain)) { continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type()); + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( attribute_id, attribute.domain, data_type); @@ -149,7 +149,7 @@ static void copy_attributes(const Map<AttributeIDRef, AttributeKind> &attributes attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Span<T> span{*attribute.varray}; + VArray_Span<T> span{attribute.varray.typed<T>()}; MutableSpan<T> out_span = result_attribute.as_span<T>(); out_span.copy_from(span); }); @@ -178,7 +178,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin if (domain != attribute.domain) { continue; } - const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray->type()); + const CustomDataType data_type = bke::cpp_type_to_custom_data_type(attribute.varray.type()); OutputAttribute result_attribute = result_component.attribute_try_get_for_output_only( attribute_id, attribute.domain, data_type); @@ -189,7 +189,7 @@ static void copy_attributes_based_on_mask(const Map<AttributeIDRef, AttributeKin attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Span<T> span{*attribute.varray}; + VArray_Span<T> span{attribute.varray.typed<T>()}; MutableSpan<T> out_span = result_attribute.as_span<T>(); copy_data(span, out_span, mask); }); diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index 115ad09a9e6..cdde6d510a3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -313,7 +313,7 @@ BLI_NOINLINE static void propagate_existing_attributes( bary_coords, looptri_indices, source_attribute.domain, - *source_attribute.varray, + source_attribute.varray, out_span); attribute_out.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc b/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc index 92b89313d23..6c95ad73bf7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_normal.cc @@ -31,19 +31,18 @@ static void geo_node_input_normal_declare(NodeDeclarationBuilder &b) b.add_output<decl::Vector>(N_("Normal")).field_source(); } -static GVArrayPtr mesh_face_normals(const Mesh &mesh, - const Span<MVert> verts, - const Span<MPoly> polys, - const Span<MLoop> loops, - const IndexMask mask) +static VArray<float3> mesh_face_normals(const Mesh &mesh, + const Span<MVert> verts, + const Span<MPoly> polys, + const Span<MLoop> loops, + const IndexMask mask) { /* Use existing normals to avoid unnecessarily recalculating them, if possible. */ if (!(mesh.runtime.cd_dirty_poly & CD_MASK_NORMAL) && CustomData_has_layer(&mesh.pdata, CD_NORMAL)) { const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL); - return std::make_unique<fn::GVArray_For_Span<float3>>( - Span<float3>((const float3 *)data, polys.size())); + return VArray<float3>::ForSpan({(const float3 *)data, polys.size()}); } auto normal_fn = [verts, polys, loops](const int i) -> float3 { @@ -53,24 +52,21 @@ static GVArrayPtr mesh_face_normals(const Mesh &mesh, return normal; }; - return std::make_unique< - fn::GVArray_For_EmbeddedVArray<float3, VArray_For_Func<float3, decltype(normal_fn)>>>( - mask.min_array_size(), mask.min_array_size(), normal_fn); + return VArray<float3>::ForFunc(mask.min_array_size(), normal_fn); } -static GVArrayPtr mesh_vertex_normals(const Mesh &mesh, - const Span<MVert> verts, - const Span<MPoly> polys, - const Span<MLoop> loops, - const IndexMask mask) +static VArray<float3> mesh_vertex_normals(const Mesh &mesh, + const Span<MVert> verts, + const Span<MPoly> polys, + const Span<MLoop> loops, + const IndexMask mask) { /* Use existing normals to avoid unnecessarily recalculating them, if possible. */ if (!(mesh.runtime.cd_dirty_vert & CD_MASK_NORMAL) && CustomData_has_layer(&mesh.vdata, CD_NORMAL)) { const void *data = CustomData_get_layer(&mesh.pdata, CD_NORMAL); - return std::make_unique<fn::GVArray_For_Span<float3>>( - Span<float3>((const float3 *)data, mesh.totvert)); + return VArray<float3>::ForSpan({(const float3 *)data, mesh.totvert}); } /* If the normals are dirty, they must be recalculated for the output of this node's field @@ -91,14 +87,14 @@ static GVArrayPtr mesh_vertex_normals(const Mesh &mesh, nullptr, (float(*)[3])normals.data()); - return std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals)); + return VArray<float3>::ForContainer(std::move(normals)); } -static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_component, +static VArray<float3> construct_mesh_normals_gvarray(const MeshComponent &mesh_component, const Mesh &mesh, const IndexMask mask, const AttributeDomain domain, - ResourceScope &scope) + ResourceScope &UNUSED(scope)) { Span<MVert> verts{mesh.mvert, mesh.totvert}; Span<MEdge> edges{mesh.medge, mesh.totedge}; @@ -107,18 +103,18 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c switch (domain) { case ATTR_DOMAIN_FACE: { - return scope.add_value(mesh_face_normals(mesh, verts, polys, loops, mask)).get(); + return mesh_face_normals(mesh, verts, polys, loops, mask); } case ATTR_DOMAIN_POINT: { - return scope.add_value(mesh_vertex_normals(mesh, verts, polys, loops, mask)).get(); + return mesh_vertex_normals(mesh, verts, polys, loops, mask); } case ATTR_DOMAIN_EDGE: { /* In this case, start with vertex normals and convert to the edge domain, since the * conversion from edges to vertices is very simple. Use the full mask since the edges * might use the vertex normal from any index. */ - GVArrayPtr vert_normals = mesh_vertex_normals( + GVArray vert_normals = mesh_vertex_normals( mesh, verts, polys, loops, IndexRange(verts.size())); - Span<float3> vert_normals_span = vert_normals->get_internal_span().typed<float3>(); + Span<float3> vert_normals_span = vert_normals.get_internal_span().typed<float3>(); Array<float3> edge_normals(mask.min_array_size()); /* Use "manual" domain interpolation instead of the GeometryComponent API to avoid @@ -130,23 +126,21 @@ static const GVArray *construct_mesh_normals_gvarray(const MeshComponent &mesh_c .normalized(); } - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>( - std::move(edge_normals)); + return VArray<float3>::ForContainer(std::move(edge_normals)); } case ATTR_DOMAIN_CORNER: { /* The normals on corners are just the mesh's face normals, so start with the face normal * array and copy the face normal for each of its corners. */ - GVArrayPtr face_normals = mesh_face_normals( + VArray<float3> face_normals = mesh_face_normals( mesh, verts, polys, loops, IndexRange(polys.size())); /* In this case using the mesh component's generic domain interpolation is fine, the data * will still be normalized, since the face normal is just copied to every corner. */ - GVArrayPtr loop_normals = mesh_component.attribute_try_adapt_domain( + return mesh_component.attribute_try_adapt_domain<float3>( std::move(face_normals), ATTR_DOMAIN_FACE, ATTR_DOMAIN_CORNER); - return scope.add_value(std::move(loop_normals)).get(); } default: - return nullptr; + return {}; } } @@ -204,9 +198,9 @@ static Array<float3> curve_normal_point_domain(const CurveEval &curve) return normals; } -static const GVArray *construct_curve_normal_gvarray(const CurveComponent &component, +static VArray<float3> construct_curve_normal_gvarray(const CurveComponent &component, const AttributeDomain domain, - ResourceScope &scope) + ResourceScope &UNUSED(scope)) { const CurveEval *curve = component.get_for_read(); if (curve == nullptr) { @@ -220,20 +214,18 @@ static const GVArray *construct_curve_normal_gvarray(const CurveComponent &compo * This is only possible when there is only one poly spline. */ if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) { const PolySpline &spline = static_cast<PolySpline &>(*splines.first()); - return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_normals()); + return VArray<float3>::ForSpan(spline.evaluated_normals()); } Array<float3> normals = curve_normal_point_domain(*curve); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(normals)); + return VArray<float3>::ForContainer(std::move(normals)); } if (domain == ATTR_DOMAIN_CURVE) { Array<float3> point_normals = curve_normal_point_domain(*curve); - GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>( - std::move(point_normals)); - GVArrayPtr spline_normals = component.attribute_try_adapt_domain( - std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); - return scope.add_value(std::move(spline_normals)).get(); + VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals)); + return component.attribute_try_adapt_domain<float3>( + std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); } return nullptr; @@ -246,9 +238,9 @@ class NormalFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &scope) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -260,7 +252,7 @@ class NormalFieldInput final : public fn::FieldInput { const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); const Mesh *mesh = mesh_component.get_for_read(); if (mesh == nullptr) { - return nullptr; + return {}; } return construct_mesh_normals_gvarray(mesh_component, *mesh, mask, domain, scope); @@ -270,7 +262,7 @@ class NormalFieldInput final : public fn::FieldInput { return construct_curve_normal_gvarray(curve_component, domain, scope); } } - return nullptr; + return {}; } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc index 895efa6f0ed..a976e0b193f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc @@ -25,31 +25,25 @@ static void geo_node_input_spline_length_declare(NodeDeclarationBuilder &b) b.add_output<decl::Float>(N_("Length")).field_source(); } -static const GVArray *construct_spline_length_gvarray(const CurveComponent &component, - const AttributeDomain domain, - ResourceScope &scope) +static VArray<float> construct_spline_length_gvarray(const CurveComponent &component, + const AttributeDomain domain, + ResourceScope &UNUSED(scope)) { const CurveEval *curve = component.get_for_read(); if (curve == nullptr) { - return nullptr; + return {}; } Span<SplinePtr> splines = curve->splines(); auto length_fn = [splines](int i) { return splines[i]->length(); }; if (domain == ATTR_DOMAIN_CURVE) { - return &scope.construct< - fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>( - splines.size(), splines.size(), length_fn); + return VArray<float>::ForFunc(splines.size(), length_fn); } if (domain == ATTR_DOMAIN_POINT) { - GVArrayPtr length = std::make_unique< - fn::GVArray_For_EmbeddedVArray<float, VArray_For_Func<float, decltype(length_fn)>>>( - splines.size(), splines.size(), length_fn); - return scope - .add_value(component.attribute_try_adapt_domain( - std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT)) - .get(); + VArray<float> length = VArray<float>::ForFunc(splines.size(), length_fn); + return component.attribute_try_adapt_domain<float>( + std::move(length), ATTR_DOMAIN_CURVE, ATTR_DOMAIN_POINT); } return nullptr; @@ -62,9 +56,9 @@ class SplineLengthFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask UNUSED(mask), - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &scope) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -76,7 +70,7 @@ class SplineLengthFieldInput final : public fn::FieldInput { return construct_spline_length_gvarray(curve_component, domain, scope); } } - return nullptr; + return {}; } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc index 6b1736fe2ac..49885f29d44 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc @@ -84,9 +84,9 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve) return tangents; } -static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &component, +static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component, const AttributeDomain domain, - ResourceScope &scope) + ResourceScope &UNUSED(scope)) { const CurveEval *curve = component.get_for_read(); if (curve == nullptr) { @@ -100,20 +100,19 @@ static const GVArray *construct_curve_tangent_gvarray(const CurveComponent &comp * This is only possible when there is only one poly spline. */ if (splines.size() == 1 && splines.first()->type() == Spline::Type::Poly) { const PolySpline &spline = static_cast<PolySpline &>(*splines.first()); - return &scope.construct<fn::GVArray_For_Span<float3>>(spline.evaluated_tangents()); + return VArray<float3>::ForSpan(spline.evaluated_tangents()); } Array<float3> tangents = curve_tangent_point_domain(*curve); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<float3>>>(std::move(tangents)); + return VArray<float3>::ForContainer(std::move(tangents)); } if (domain == ATTR_DOMAIN_CURVE) { Array<float3> point_tangents = curve_tangent_point_domain(*curve); - GVArrayPtr gvarray = std::make_unique<fn::GVArray_For_ArrayContainer<Array<float3>>>( - std::move(point_tangents)); - GVArrayPtr spline_tangents = component.attribute_try_adapt_domain( - std::move(gvarray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE); - return scope.add_value(std::move(spline_tangents)).get(); + return component.attribute_try_adapt_domain<float3>( + VArray<float3>::ForContainer(std::move(point_tangents)), + ATTR_DOMAIN_POINT, + ATTR_DOMAIN_CURVE); } return nullptr; @@ -126,9 +125,9 @@ class TangentFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask UNUSED(mask), - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask UNUSED(mask), + ResourceScope &scope) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { @@ -141,7 +140,7 @@ class TangentFieldInput final : public fn::FieldInput { return construct_curve_tangent_gvarray(curve_component, domain, scope); } } - return nullptr; + return {}; } uint64_t hash() const override diff --git a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc index aff29d973d4..2a68030aba7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc @@ -80,10 +80,10 @@ static void add_instances_from_component(InstancesComponent &dst_component, select_len); FieldEvaluator field_evaluator{field_context, domain_size}; - const VArray<bool> *pick_instance = nullptr; - const VArray<int> *indices = nullptr; - const VArray<float3> *rotations = nullptr; - const VArray<float3> *scales = nullptr; + VArray<bool> pick_instance; + VArray<int> indices; + VArray<float3> rotations; + VArray<float3> scales; /* The evaluator could use the component's stable IDs as a destination directly, but only the * selected indices should be copied. */ field_evaluator.add(params.get_input<Field<bool>>("Pick Instance"), &pick_instance); @@ -92,7 +92,7 @@ static void add_instances_from_component(InstancesComponent &dst_component, field_evaluator.add(params.get_input<Field<float3>>("Scale"), &scales); field_evaluator.evaluate(); - GVArray_Typed<float3> positions = src_component.attribute_get_for_read<float3>( + VArray<float3> positions = src_component.attribute_get_for_read<float3>( "position", domain, {0, 0, 0}); const InstancesComponent *src_instances = instance.get_component_for_read<InstancesComponent>(); @@ -101,7 +101,7 @@ static void add_instances_from_component(InstancesComponent &dst_component, Array<int> handle_mapping; /* Only fill #handle_mapping when it may be used below. */ if (src_instances != nullptr && - (!pick_instance->is_single() || pick_instance->get_internal_single())) { + (!pick_instance.is_single() || pick_instance.get_internal_single())) { Span<InstanceReference> src_references = src_instances->references(); handle_mapping.reinitialize(src_references.size()); for (const int src_instance_handle : src_references.index_range()) { @@ -121,17 +121,16 @@ static void add_instances_from_component(InstancesComponent &dst_component, /* Compute base transform for every instances. */ float4x4 &dst_transform = dst_transforms[range_i]; - dst_transform = float4x4::from_loc_eul_scale( - positions[i], rotations->get(i), scales->get(i)); + dst_transform = float4x4::from_loc_eul_scale(positions[i], rotations[i], scales[i]); /* Reference that will be used by this new instance. */ int dst_handle = empty_reference_handle; - const bool use_individual_instance = pick_instance->get(i); + const bool use_individual_instance = pick_instance[i]; if (use_individual_instance) { if (src_instances != nullptr) { const int src_instances_amount = src_instances->instances_amount(); - const int original_index = indices->get(i); + const int original_index = indices[i]; /* Use #mod_i instead of `%` to get the desirable wrap around behavior where -1 * refers to the last element. */ const int index = mod_i(original_index, std::max(src_instances_amount, 1)); @@ -155,10 +154,10 @@ static void add_instances_from_component(InstancesComponent &dst_component, } }); - GVArrayPtr id_attribute = src_component.attribute_try_get_for_read( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); - if (id_attribute) { - GVArray_Typed<int> ids{*id_attribute}; + VArray<int> ids = src_component + .attribute_try_get_for_read("id", ATTR_DOMAIN_POINT, CD_PROP_INT32) + .typed<int>(); + if (ids) { VArray_Span<int> ids_span{ids}; MutableSpan<int> dst_ids = dst_component.instance_ids_ensure(); for (const int64_t i : selection.index_range()) { @@ -166,8 +165,8 @@ static void add_instances_from_component(InstancesComponent &dst_component, } } - if (pick_instance->is_single()) { - if (pick_instance->get_internal_single()) { + if (pick_instance.is_single()) { + if (pick_instance.get_internal_single()) { if (instance.has_realized_data()) { params.error_message_add( NodeWarningType::Info, diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 9d363bd1af4..fcdf7c2da01 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -27,8 +27,6 @@ #include "node_geometry_util.hh" -using blender::fn::GVArray_For_GSpan; - namespace blender::nodes { static void geo_node_join_geometry_declare(NodeDeclarationBuilder &b) @@ -190,10 +188,10 @@ static void fill_new_attribute(Span<const GeometryComponent *> src_components, if (domain_size == 0) { continue; } - GVArrayPtr read_attribute = component->attribute_get_for_read( + GVArray read_attribute = component->attribute_get_for_read( attribute_id, domain, data_type, nullptr); - GVArray_GSpan src_span{*read_attribute}; + GVArray_GSpan src_span{read_attribute}; const void *src_buffer = src_span.data(); void *dst_buffer = dst_span[offset]; cpp_type->copy_assign_n(src_buffer, dst_buffer, domain_size); @@ -319,8 +317,7 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id, spline->size() * type.size(), type.alignment(), __func__); const DataTypeConversions &conversions = blender::nodes::get_implicit_type_conversions(); - conversions.try_convert(std::make_unique<GVArray_For_GSpan>(*attribute), type) - ->materialize(converted_buffer); + conversions.try_convert(GVArray::ForSpan(*attribute), type).materialize(converted_buffer); spline->attributes.remove(attribute_id); spline->attributes.create_by_move(attribute_id, data_type, converted_buffer); @@ -333,14 +330,14 @@ static void ensure_control_point_attribute(const AttributeIDRef &attribute_id, /* In this case the attribute did not exist, but there is a spline domain attribute * we can retrieve a value from, as a spline to point domain conversion. So fill the * new attribute with the value for this spline. */ - GVArrayPtr current_curve_attribute = current_curve->attributes.get_for_read( + GVArray current_curve_attribute = current_curve->attributes.get_for_read( attribute_id, data_type, nullptr); BLI_assert(spline->attributes.get_for_read(attribute_id)); std::optional<GMutableSpan> new_attribute = spline->attributes.get_for_write(attribute_id); BUFFER_FOR_CPP_TYPE_VALUE(type, buffer); - current_curve_attribute->get(spline_index_in_component, buffer); + current_curve_attribute.get(spline_index_in_component, buffer); type.fill_assign_n(buffer, new_attribute->data(), new_attribute->size()); } } @@ -397,8 +394,8 @@ static void ensure_spline_attribute(const AttributeIDRef &attribute_id, if (size == 0) { continue; } - GVArrayPtr read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr); - GVArray_GSpan src_span{*read_attribute}; + GVArray read_attribute = curve.attributes.get_for_read(attribute_id, data_type, nullptr); + GVArray_GSpan src_span{read_attribute}; const void *src_buffer = src_span.data(); type.copy_assign_n(src_buffer, result_attribute[offset], size); diff --git a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc index 06c770820ee..12ffa21762e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_material_selection.cc @@ -64,36 +64,33 @@ class MaterialSelectionFieldInput final : public fn::FieldInput { category_ = Category::Generated; } - const GVArray *get_varray_for_context(const fn::FieldContext &context, - IndexMask mask, - ResourceScope &scope) const final + GVArray get_varray_for_context(const fn::FieldContext &context, + IndexMask mask, + ResourceScope &UNUSED(scope)) const final { if (const GeometryComponentFieldContext *geometry_context = dynamic_cast<const GeometryComponentFieldContext *>(&context)) { const GeometryComponent &component = geometry_context->geometry_component(); const AttributeDomain domain = geometry_context->domain(); if (component.type() != GEO_COMPONENT_TYPE_MESH) { - return nullptr; + return {}; } const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); const Mesh *mesh = mesh_component.get_for_read(); if (mesh == nullptr) { - return nullptr; + return {}; } if (domain == ATTR_DOMAIN_FACE) { Array<bool> selection(mask.min_array_size()); select_mesh_by_material(*mesh, material_, mask, selection); - return &scope.construct<fn::GVArray_For_ArrayContainer<Array<bool>>>(std::move(selection)); + return VArray<bool>::ForContainer(std::move(selection)); } Array<bool> selection(mesh->totpoly); select_mesh_by_material(*mesh, material_, IndexMask(mesh->totpoly), selection); - GVArrayPtr face_selection = std::make_unique<fn::GVArray_For_ArrayContainer<Array<bool>>>( - std::move(selection)); - GVArrayPtr final_selection = mesh_component.attribute_try_adapt_domain( - std::move(face_selection), ATTR_DOMAIN_FACE, domain); - return scope.add_value(std::move(final_selection)).get(); + return mesh_component.attribute_try_adapt_domain<bool>( + VArray<bool>::ForContainer(std::move(selection)), ATTR_DOMAIN_FACE, domain); } return nullptr; diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc index 92911e89f59..a37e3e34777 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc @@ -113,14 +113,14 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set, for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; const CustomDataType data_type = entry.value.data_type; - GVArrayPtr src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type); + GVArray src = mesh_component->attribute_get_for_read(attribute_id, domain, data_type); OutputAttribute dst = point_component.attribute_try_get_for_output_only( attribute_id, ATTR_DOMAIN_POINT, data_type); if (dst && src) { attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Typed<T> src_typed{*src}; - copy_attribute_to_points(*src_typed, selection, dst.as_span().typed<T>()); + VArray<T> src_typed = src.typed<T>(); + copy_attribute_to_points(src_typed, selection, dst.as_span().typed<T>()); }); dst.save(); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc index 3e0096824d3..5a6a3b25a45 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc @@ -74,15 +74,15 @@ static void geometry_set_points_to_vertices(GeometrySet &geometry_set, for (Map<AttributeIDRef, AttributeKind>::Item entry : attributes.items()) { const AttributeIDRef attribute_id = entry.key; const CustomDataType data_type = entry.value.data_type; - GVArrayPtr src = point_component->attribute_get_for_read( + GVArray src = point_component->attribute_get_for_read( attribute_id, ATTR_DOMAIN_POINT, data_type); OutputAttribute dst = mesh_component.attribute_try_get_for_output_only( attribute_id, ATTR_DOMAIN_POINT, data_type); if (dst && src) { attribute_math::convert_to_static_type(data_type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Typed<T> src_typed{*src}; - VArray_Span<T> src_typed_span{*src_typed}; + VArray<T> src_typed = src.typed<T>(); + VArray_Span<T> src_typed_span{src_typed}; copy_attribute_to_vertices(src_typed_span, selection, dst.as_span().typed<T>()); }); dst.save(); diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc index 18d674a38a4..cf2518cbd01 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -165,7 +165,7 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms, Vector<float3> &r_positions, Vector<float> &r_radii) { - GVArray_Typed<float3> positions = component.attribute_get_for_read<float3>( + VArray<float3> positions = component.attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); Field<float> radius_field = params.get_input<Field<float>>("Radius"); @@ -173,7 +173,7 @@ static void gather_point_data_from_component(GeoNodeExecParams ¶ms, const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); r_positions.resize(r_positions.size() + domain_size); - positions->materialize(r_positions.as_mutable_span().take_back(domain_size)); + positions.materialize(r_positions.as_mutable_span().take_back(domain_size)); r_radii.resize(r_radii.size() + domain_size); fn::FieldEvaluator evaluator{field_context, domain_size}; diff --git a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc index 9754b3f81a0..ea522cf4bfc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc @@ -541,10 +541,10 @@ class NearestTransferFunction : public fn::MultiFunction { attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) { using T = decltype(dummy); if (use_mesh_ && use_points_) { - GVArray_Typed<T> src_mesh{*mesh_data_}; - GVArray_Typed<T> src_point{*point_data_}; - copy_with_indices_and_comparison(*src_mesh, - *src_point, + VArray<T> src_mesh = mesh_data_->typed<T>(); + VArray<T> src_point = point_data_->typed<T>(); + copy_with_indices_and_comparison(src_mesh, + src_point, mesh_distances, point_distances, mask, @@ -553,12 +553,12 @@ class NearestTransferFunction : public fn::MultiFunction { dst.typed<T>()); } else if (use_points_) { - GVArray_Typed<T> src_point{*point_data_}; - copy_with_indices(*src_point, mask, point_indices, dst.typed<T>()); + VArray<T> src_point = point_data_->typed<T>(); + copy_with_indices(src_point, mask, point_indices, dst.typed<T>()); } else if (use_mesh_) { - GVArray_Typed<T> src_mesh{*mesh_data_}; - copy_with_indices(*src_mesh, mask, mesh_indices, dst.typed<T>()); + VArray<T> src_mesh = mesh_data_->typed<T>(); + copy_with_indices(src_mesh, mask, mesh_indices, dst.typed<T>()); } }); } @@ -667,8 +667,7 @@ class IndexTransferFunction : public fn::MultiFunction { attribute_math::convert_to_static_type(type, [&](auto dummy) { using T = decltype(dummy); - GVArray_Typed<T> src{*src_data_}; - copy_with_indices_clamped(*src, mask, indices, dst.typed<T>()); + copy_with_indices_clamped(src_data_->typed<T>(), mask, indices, dst.typed<T>()); }); } }; diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 27bc206187d..faa4337ba7e 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -113,11 +113,11 @@ const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name return nullptr; } -GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name, - const GeometryComponent &component, - const AttributeDomain domain, - const CustomDataType type, - const void *default_value) const +GVArray GeoNodeExecParams::get_input_attribute(const StringRef name, + const GeometryComponent &component, + const AttributeDomain domain, + const CustomDataType type, + const void *default_value) const { const bNodeSocket *found_socket = this->find_available_socket(name); BLI_assert(found_socket != nullptr); /* There should always be available socket for the name. */ @@ -129,13 +129,13 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name, } if (found_socket == nullptr) { - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value); + return GVArray::ForSingle(*cpp_type, domain_size, default_value); } if (found_socket->type == SOCK_STRING) { const std::string name = this->get_input<std::string>(found_socket->identifier); /* Try getting the attribute without the default value. */ - GVArrayPtr attribute = component.attribute_try_get_for_read(name, domain, type); + GVArray attribute = component.attribute_try_get_for_read(name, domain, type); if (attribute) { return attribute; } @@ -147,36 +147,36 @@ GVArrayPtr GeoNodeExecParams::get_input_attribute(const StringRef name, this->error_message_add(NodeWarningType::Error, TIP_("No attribute with name \"") + name + "\""); } - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value); + return GVArray::ForSingle(*cpp_type, domain_size, default_value); } const DataTypeConversions &conversions = get_implicit_type_conversions(); if (found_socket->type == SOCK_FLOAT) { const float value = this->get_input<float>(found_socket->identifier); BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer); conversions.convert_to_uninitialized(CPPType::get<float>(), *cpp_type, &value, buffer); - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer); + return GVArray::ForSingle(*cpp_type, domain_size, buffer); } if (found_socket->type == SOCK_INT) { const int value = this->get_input<int>(found_socket->identifier); BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer); conversions.convert_to_uninitialized(CPPType::get<int>(), *cpp_type, &value, buffer); - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer); + return GVArray::ForSingle(*cpp_type, domain_size, buffer); } if (found_socket->type == SOCK_VECTOR) { const float3 value = this->get_input<float3>(found_socket->identifier); BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer); conversions.convert_to_uninitialized(CPPType::get<float3>(), *cpp_type, &value, buffer); - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer); + return GVArray::ForSingle(*cpp_type, domain_size, buffer); } if (found_socket->type == SOCK_RGBA) { const ColorGeometry4f value = this->get_input<ColorGeometry4f>(found_socket->identifier); BUFFER_FOR_CPP_TYPE_VALUE(*cpp_type, buffer); conversions.convert_to_uninitialized( CPPType::get<ColorGeometry4f>(), *cpp_type, &value, buffer); - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, buffer); + return GVArray::ForSingle(*cpp_type, domain_size, buffer); } BLI_assert(false); - return std::make_unique<fn::GVArray_For_SingleValue>(*cpp_type, domain_size, default_value); + return GVArray::ForSingle(*cpp_type, domain_size, default_value); } CustomDataType GeoNodeExecParams::get_input_attribute_data_type( diff --git a/source/blender/nodes/intern/type_conversions.cc b/source/blender/nodes/intern/type_conversions.cc index 1a71a3418a5..b1611679ced 100644 --- a/source/blender/nodes/intern/type_conversions.cc +++ b/source/blender/nodes/intern/type_conversions.cc @@ -24,9 +24,6 @@ namespace blender::nodes { -using fn::GVArrayPtr; -using fn::GVMutableArray; -using fn::GVMutableArrayPtr; using fn::MFDataType; template<typename From, typename To, To (*ConversionF)(const From &)> @@ -242,107 +239,108 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type, functions->convert_single_to_uninitialized(from_value, to_value); } -class GVArray_For_ConvertedGVArray : public GVArray { +class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl { private: - GVArrayPtr varray_; + fn::GVArray varray_; const CPPType &from_type_; ConversionFunctions old_to_new_conversions_; public: - GVArray_For_ConvertedGVArray(GVArrayPtr varray, + GVArray_For_ConvertedGVArray(fn::GVArray varray, const CPPType &to_type, const DataTypeConversions &conversions) - : GVArray(to_type, varray->size()), varray_(std::move(varray)), from_type_(varray_->type()) + : fn::GVArrayImpl(to_type, varray.size()), + varray_(std::move(varray)), + from_type_(varray_.type()) { old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type); } private: - void get_impl(const int64_t index, void *r_value) const override + void get(const int64_t index, void *r_value) const override { BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer); - varray_->get(index, buffer); + varray_.get(index, buffer); old_to_new_conversions_.convert_single_to_initialized(buffer, r_value); from_type_.destruct(buffer); } - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override + void get_to_uninitialized(const int64_t index, void *r_value) const override { BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer); - varray_->get(index, buffer); + varray_.get(index, buffer); old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value); from_type_.destruct(buffer); } }; -class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArray { +class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl { private: - GVMutableArrayPtr varray_; + fn::GVMutableArray varray_; const CPPType &from_type_; ConversionFunctions old_to_new_conversions_; ConversionFunctions new_to_old_conversions_; public: - GVMutableArray_For_ConvertedGVMutableArray(GVMutableArrayPtr varray, + GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray, const CPPType &to_type, const DataTypeConversions &conversions) - : GVMutableArray(to_type, varray->size()), + : fn::GVMutableArrayImpl(to_type, varray.size()), varray_(std::move(varray)), - from_type_(varray_->type()) + from_type_(varray_.type()) { old_to_new_conversions_ = *conversions.get_conversion_functions(from_type_, to_type); new_to_old_conversions_ = *conversions.get_conversion_functions(to_type, from_type_); } private: - void get_impl(const int64_t index, void *r_value) const override + void get(const int64_t index, void *r_value) const override { BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer); - varray_->get(index, buffer); + varray_.get(index, buffer); old_to_new_conversions_.convert_single_to_initialized(buffer, r_value); from_type_.destruct(buffer); } - void get_to_uninitialized_impl(const int64_t index, void *r_value) const override + void get_to_uninitialized(const int64_t index, void *r_value) const override { BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer); - varray_->get(index, buffer); + varray_.get(index, buffer); old_to_new_conversions_.convert_single_to_uninitialized(buffer, r_value); from_type_.destruct(buffer); } - void set_by_move_impl(const int64_t index, void *value) override + void set_by_move(const int64_t index, void *value) override { BUFFER_FOR_CPP_TYPE_VALUE(from_type_, buffer); new_to_old_conversions_.convert_single_to_uninitialized(value, buffer); - varray_->set_by_relocate(index, buffer); + varray_.set_by_relocate(index, buffer); } }; -fn::GVArrayPtr DataTypeConversions::try_convert(fn::GVArrayPtr varray, - const CPPType &to_type) const +fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const { - const CPPType &from_type = varray->type(); + const CPPType &from_type = varray.type(); if (from_type == to_type) { return varray; } if (!this->is_convertible(from_type, to_type)) { return {}; } - return std::make_unique<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this); + return fn::GVArray::For<GVArray_For_ConvertedGVArray>(std::move(varray), to_type, *this); } -fn::GVMutableArrayPtr DataTypeConversions::try_convert(fn::GVMutableArrayPtr varray, - const CPPType &to_type) const +fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray, + const CPPType &to_type) const { - const CPPType &from_type = varray->type(); + const CPPType &from_type = varray.type(); if (from_type == to_type) { return varray; } if (!this->is_convertible(from_type, to_type)) { return {}; } - return std::make_unique<GVMutableArray_For_ConvertedGVMutableArray>( + return fn::GVMutableArray::For<GVMutableArray_For_ConvertedGVMutableArray>( std::move(varray), to_type, *this); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc index 81f9cd735eb..c290c4d2a82 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc @@ -199,28 +199,28 @@ class MusgraveFunction : public fn::MultiFunction { void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override { - auto get_vector = [&](int param_index) -> const VArray<float3> & { + auto get_vector = [&](int param_index) -> VArray<float3> { return params.readonly_single_input<float3>(param_index, "Vector"); }; - auto get_w = [&](int param_index) -> const VArray<float> & { + auto get_w = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "W"); }; - auto get_scale = [&](int param_index) -> const VArray<float> & { + auto get_scale = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Scale"); }; - auto get_detail = [&](int param_index) -> const VArray<float> & { + auto get_detail = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Detail"); }; - auto get_dimension = [&](int param_index) -> const VArray<float> & { + auto get_dimension = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Dimension"); }; - auto get_lacunarity = [&](int param_index) -> const VArray<float> & { + auto get_lacunarity = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Lacunarity"); }; - auto get_offset = [&](int param_index) -> const VArray<float> & { + auto get_offset = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Offset"); }; - auto get_gain = [&](int param_index) -> const VArray<float> & { + auto get_gain = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Gain"); }; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc index 422268b98c3..9a483120709 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc +++ b/source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc @@ -220,22 +220,22 @@ class VoronoiMinowskiFunction : public fn::MultiFunction { void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override { - auto get_vector = [&](int param_index) -> const VArray<float3> & { + auto get_vector = [&](int param_index) -> VArray<float3> { return params.readonly_single_input<float3>(param_index, "Vector"); }; - auto get_w = [&](int param_index) -> const VArray<float> & { + auto get_w = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "W"); }; - auto get_scale = [&](int param_index) -> const VArray<float> & { + auto get_scale = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Scale"); }; - auto get_smoothness = [&](int param_index) -> const VArray<float> & { + auto get_smoothness = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Smoothness"); }; - auto get_exponent = [&](int param_index) -> const VArray<float> & { + auto get_exponent = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Exponent"); }; - auto get_randomness = [&](int param_index) -> const VArray<float> & { + auto get_randomness = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Randomness"); }; auto get_r_distance = [&](int param_index) -> MutableSpan<float> { @@ -651,19 +651,19 @@ class VoronoiMetricFunction : public fn::MultiFunction { void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override { - auto get_vector = [&](int param_index) -> const VArray<float3> & { + auto get_vector = [&](int param_index) -> VArray<float3> { return params.readonly_single_input<float3>(param_index, "Vector"); }; - auto get_w = [&](int param_index) -> const VArray<float> & { + auto get_w = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "W"); }; - auto get_scale = [&](int param_index) -> const VArray<float> & { + auto get_scale = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Scale"); }; - auto get_smoothness = [&](int param_index) -> const VArray<float> & { + auto get_smoothness = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Smoothness"); }; - auto get_randomness = [&](int param_index) -> const VArray<float> & { + auto get_randomness = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Randomness"); }; auto get_r_distance = [&](int param_index) -> MutableSpan<float> { @@ -1153,16 +1153,16 @@ class VoronoiEdgeFunction : public fn::MultiFunction { void call(IndexMask mask, fn::MFParams params, fn::MFContext UNUSED(context)) const override { - auto get_vector = [&](int param_index) -> const VArray<float3> & { + auto get_vector = [&](int param_index) -> VArray<float3> { return params.readonly_single_input<float3>(param_index, "Vector"); }; - auto get_w = [&](int param_index) -> const VArray<float> & { + auto get_w = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "W"); }; - auto get_scale = [&](int param_index) -> const VArray<float> & { + auto get_scale = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Scale"); }; - auto get_randomness = [&](int param_index) -> const VArray<float> & { + auto get_randomness = [&](int param_index) -> VArray<float> { return params.readonly_single_input<float>(param_index, "Randomness"); }; auto get_r_distance = [&](int param_index) -> MutableSpan<float> { |