From 3e16f3b3ef4b8f385b30fe4a1e00860620f610ee Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Sat, 19 Mar 2022 08:26:29 +0100 Subject: BLI: move generic data structures to blenlib This is a follow up to rB2252bc6a5527cd7360d1ccfe7a2d1bc640a8dfa6. --- source/blender/blenkernel/BKE_attribute_access.hh | 30 +- source/blender/blenkernel/BKE_curves.hh | 13 +- source/blender/blenkernel/BKE_geometry_set.hh | 48 +- source/blender/blenkernel/BKE_mesh_sample.hh | 7 +- source/blender/blenkernel/BKE_spline.hh | 22 +- source/blender/blenkernel/BKE_type_conversions.hh | 6 +- .../blender/blenkernel/intern/attribute_access.cc | 46 +- .../blender/blenkernel/intern/curve_catmull_rom.cc | 4 +- source/blender/blenkernel/intern/curve_eval.cc | 4 +- source/blender/blenkernel/intern/curve_nurbs.cc | 4 +- .../blenkernel/intern/curve_to_mesh_convert.cc | 3 - .../blender/blenkernel/intern/curves_geometry.cc | 6 +- .../blenkernel/intern/geometry_component_curve.cc | 8 +- .../blenkernel/intern/geometry_component_curves.cc | 2 +- .../intern/geometry_component_instances.cc | 4 +- .../blenkernel/intern/geometry_component_mesh.cc | 4 +- source/blender/blenkernel/intern/spline_base.cc | 11 +- source/blender/blenkernel/intern/spline_bezier.cc | 2 +- source/blender/blenkernel/intern/spline_nurbs.cc | 2 +- source/blender/blenkernel/intern/spline_poly.cc | 2 +- .../blender/blenkernel/intern/type_conversions.cc | 31 +- source/blender/blenlib/BLI_generic_array.hh | 255 ++++++ source/blender/blenlib/BLI_generic_pointer.hh | 123 +++ source/blender/blenlib/BLI_generic_span.hh | 169 ++++ source/blender/blenlib/BLI_generic_value_map.hh | 111 +++ source/blender/blenlib/BLI_generic_vector_array.hh | 147 ++++ .../blender/blenlib/BLI_generic_virtual_array.hh | 877 ++++++++++++++++++++ .../blenlib/BLI_generic_virtual_vector_array.hh | 173 ++++ source/blender/blenlib/BLI_virtual_array.hh | 10 +- source/blender/blenlib/CMakeLists.txt | 13 + .../blender/blenlib/intern/generic_vector_array.cc | 96 +++ .../blenlib/intern/generic_virtual_array.cc | 724 +++++++++++++++++ .../blenlib/intern/generic_virtual_vector_array.cc | 53 ++ .../blenlib/tests/BLI_generic_array_test.cc | 117 +++ .../blender/blenlib/tests/BLI_generic_span_test.cc | 53 ++ .../blenlib/tests/BLI_generic_vector_array_test.cc | 43 + .../editors/geometry/geometry_attributes.cc | 3 - source/blender/editors/space_node/node_draw.cc | 2 +- .../space_spreadsheet/spreadsheet_column_values.hh | 9 +- .../spreadsheet_data_source_geometry.cc | 14 +- .../spreadsheet_data_source_geometry.hh | 4 +- .../space_spreadsheet/spreadsheet_layout.cc | 2 +- .../space_spreadsheet/spreadsheet_row_filter.cc | 2 +- source/blender/functions/CMakeLists.txt | 13 - source/blender/functions/FN_field.hh | 2 +- source/blender/functions/FN_generic_array.hh | 256 ------ source/blender/functions/FN_generic_pointer.hh | 123 --- source/blender/functions/FN_generic_span.hh | 169 ---- source/blender/functions/FN_generic_value_map.hh | 112 --- .../blender/functions/FN_generic_vector_array.hh | 148 ---- .../blender/functions/FN_generic_virtual_array.hh | 878 --------------------- .../functions/FN_generic_virtual_vector_array.hh | 174 ---- source/blender/functions/FN_multi_function.hh | 2 - .../blender/functions/FN_multi_function_params.hh | 6 +- .../functions/intern/generic_vector_array.cc | 98 --- .../functions/intern/generic_virtual_array.cc | 724 ----------------- .../intern/generic_virtual_vector_array.cc | 53 -- .../functions/tests/FN_generic_array_test.cc | 118 --- .../functions/tests/FN_generic_span_test.cc | 53 -- .../tests/FN_generic_vector_array_test.cc | 43 - .../geometry/intern/mesh_to_curve_convert.cc | 4 +- .../blender/geometry/intern/realize_instances.cc | 7 +- source/blender/modifiers/intern/MOD_nodes.cc | 7 +- .../modifiers/intern/MOD_nodes_evaluator.cc | 4 +- .../modifiers/intern/MOD_nodes_evaluator.hh | 5 +- source/blender/nodes/NOD_geometry_exec.hh | 8 - .../blender/nodes/NOD_geometry_nodes_eval_log.hh | 6 +- .../geometry/nodes/node_geo_transfer_attribute.cc | 4 +- 68 files changed, 3108 insertions(+), 3168 deletions(-) create mode 100644 source/blender/blenlib/BLI_generic_array.hh create mode 100644 source/blender/blenlib/BLI_generic_pointer.hh create mode 100644 source/blender/blenlib/BLI_generic_span.hh create mode 100644 source/blender/blenlib/BLI_generic_value_map.hh create mode 100644 source/blender/blenlib/BLI_generic_vector_array.hh create mode 100644 source/blender/blenlib/BLI_generic_virtual_array.hh create mode 100644 source/blender/blenlib/BLI_generic_virtual_vector_array.hh create mode 100644 source/blender/blenlib/intern/generic_vector_array.cc create mode 100644 source/blender/blenlib/intern/generic_virtual_array.cc create mode 100644 source/blender/blenlib/intern/generic_virtual_vector_array.cc create mode 100644 source/blender/blenlib/tests/BLI_generic_array_test.cc create mode 100644 source/blender/blenlib/tests/BLI_generic_span_test.cc create mode 100644 source/blender/blenlib/tests/BLI_generic_vector_array_test.cc delete mode 100644 source/blender/functions/FN_generic_array.hh delete mode 100644 source/blender/functions/FN_generic_pointer.hh delete mode 100644 source/blender/functions/FN_generic_span.hh delete mode 100644 source/blender/functions/FN_generic_value_map.hh delete mode 100644 source/blender/functions/FN_generic_vector_array.hh delete mode 100644 source/blender/functions/FN_generic_virtual_array.hh delete mode 100644 source/blender/functions/FN_generic_virtual_vector_array.hh delete mode 100644 source/blender/functions/intern/generic_vector_array.cc delete mode 100644 source/blender/functions/intern/generic_virtual_array.cc delete mode 100644 source/blender/functions/intern/generic_virtual_vector_array.cc delete mode 100644 source/blender/functions/tests/FN_generic_array_test.cc delete mode 100644 source/blender/functions/tests/FN_generic_span_test.cc delete mode 100644 source/blender/functions/tests/FN_generic_vector_array_test.cc (limited to 'source') diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index e36163878a5..36f29c7fbb7 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -4,14 +4,13 @@ #include -#include "FN_generic_span.hh" -#include "FN_generic_virtual_array.hh" - #include "BKE_anonymous_attribute.hh" #include "BKE_attribute.h" #include "BLI_color.hh" #include "BLI_function_ref.hh" +#include "BLI_generic_span.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_math_vec_types.hh" /** @@ -132,9 +131,9 @@ struct AttributeInitDefault : public AttributeInit { * Note that this can be used to fill the new attribute with the default */ struct AttributeInitVArray : public AttributeInit { - blender::fn::GVArray varray; + blender::GVArray varray; - AttributeInitVArray(blender::fn::GVArray varray) + AttributeInitVArray(blender::GVArray varray) : AttributeInit(Type::VArray), varray(std::move(varray)) { } @@ -165,9 +164,6 @@ using AttributeForeachCallback = blender::FunctionRef data_types); @@ -237,7 +233,7 @@ class OutputAttribute { GVMutableArray varray_; AttributeDomain domain_ = ATTR_DOMAIN_AUTO; SaveFn save_; - std::unique_ptr optional_span_varray_; + std::unique_ptr optional_span_varray_; bool ignore_old_values_ = false; bool save_has_been_called_ = false; @@ -254,13 +250,13 @@ class OutputAttribute { operator bool() const; GVMutableArray &operator*(); - fn::GVMutableArray *operator->(); + GVMutableArray *operator->(); GVMutableArray &varray(); AttributeDomain domain() const; const CPPType &cpp_type() const; CustomDataType custom_data_type() const; - fn::GMutableSpan as_span(); + GMutableSpan as_span(); template MutableSpan as_span(); void save(); @@ -374,16 +370,16 @@ class CustomDataAttributes { void clear(); - std::optional get_for_read(const AttributeIDRef &attribute_id) const; + std::optional get_for_read(const AttributeIDRef &attribute_id) const; /** * Return a virtual array for a stored attribute, or a single value virtual array with the * default value if the attribute doesn't exist. If no default value is provided, the default * value for the type will be used. */ - blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id, - const CustomDataType data_type, - const void *default_value) const; + blender::GVArray get_for_read(const AttributeIDRef &attribute_id, + const CustomDataType data_type, + const void *default_value) const; template blender::VArray get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const @@ -394,7 +390,7 @@ class CustomDataAttributes { return varray.typed(); } - std::optional get_for_write(const AttributeIDRef &attribute_id); + std::optional get_for_write(const AttributeIDRef &attribute_id); bool create(const AttributeIDRef &attribute_id, const CustomDataType data_type); bool create_by_move(const AttributeIDRef &attribute_id, const CustomDataType data_type, @@ -514,7 +510,7 @@ inline GVMutableArray &OutputAttribute::operator*() return varray_; } -inline fn::GVMutableArray *OutputAttribute::operator->() +inline GVMutableArray *OutputAttribute::operator->() { return &varray_; } diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 93b98a01fce..ea378c5a0a5 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -12,6 +12,7 @@ #include #include "BLI_float4x4.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_index_mask.hh" #include "BLI_math_vec_types.hh" #include "BLI_span.hh" @@ -21,8 +22,6 @@ #include "BKE_attribute_access.hh" -#include "FN_generic_virtual_array.hh" - namespace blender::bke { template)> @@ -287,9 +286,7 @@ class CurvesGeometry : public ::CurvesGeometry { * Attributes. */ - fn::GVArray adapt_domain(const fn::GVArray &varray, - AttributeDomain from, - AttributeDomain to) const; + GVArray adapt_domain(const GVArray &varray, AttributeDomain from, AttributeDomain to) const; }; namespace curves { @@ -375,7 +372,7 @@ int calculate_evaluated_size(int size, bool cyclic, int resolution); * Evaluate the Catmull Rom curve. The length of the #dst span should be calculated with * #calculate_evaluated_size and is expected to divide evenly by the #src span's segment size. */ -void interpolate_to_evaluated(fn::GSpan src, bool cyclic, int resolution, fn::GMutableSpan dst); +void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst); } // namespace catmull_rom @@ -439,8 +436,8 @@ void calculate_basis_cache(int size, void interpolate_to_evaluated(const BasisCache &basis_cache, int8_t order, Span control_weights, - fn::GSpan src, - fn::GMutableSpan dst); + GSpan src, + GMutableSpan dst); } // namespace nurbs diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 372922a24d2..bd392057436 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -131,9 +131,9 @@ class GeometryComponent { * interpolate from one domain to another. * \return null if the interpolation is not implemented. */ - blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray, - const AttributeDomain from_domain, - const AttributeDomain to_domain) const + blender::GVArray attribute_try_adapt_domain(const blender::GVArray &varray, + const AttributeDomain from_domain, + const AttributeDomain to_domain) const { return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain); } @@ -177,17 +177,17 @@ class GeometryComponent { * and converted to the data type. Returns null when the attribute does not exist or cannot be * interpolated or converted. */ - blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id, - AttributeDomain domain, - const CustomDataType data_type) const; + blender::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + AttributeDomain domain, + const CustomDataType data_type) const; /** * Get a virtual array that refers to the data of an attribute, interpolated to the given domain. * The data type is left unchanged. Returns null when the attribute does not exist or cannot be * interpolated. */ - blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id, - AttributeDomain domain) const; + blender::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + AttributeDomain domain) const; /** * Get a virtual array that refers to the data of an attribute converted to the given data type. @@ -202,10 +202,10 @@ class GeometryComponent { * and converted to the data type. If that is not possible, the returned virtual array will * contain a default value. This never returns null. */ - blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id, - AttributeDomain domain, - const CustomDataType data_type, - const void *default_value = nullptr) const; + blender::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id, + AttributeDomain domain, + const CustomDataType data_type, + const void *default_value = nullptr) const; /* Use instead of the method above when the type is known at compile time for type safety. */ template blender::VArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id, @@ -268,9 +268,9 @@ 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, - AttributeDomain from_domain, - AttributeDomain to_domain) const; + virtual blender::GVArray attribute_try_adapt_domain_impl(const blender::GVArray &varray, + AttributeDomain from_domain, + AttributeDomain to_domain) const; }; template @@ -568,9 +568,9 @@ 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, - AttributeDomain from_domain, - AttributeDomain to_domain) const final; + blender::GVArray attribute_try_adapt_domain_impl(const blender::GVArray &varray, + AttributeDomain from_domain, + AttributeDomain to_domain) const final; }; /** @@ -672,9 +672,9 @@ class CurveComponentLegacy : 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, - AttributeDomain from_domain, - AttributeDomain to_domain) const final; + blender::GVArray attribute_try_adapt_domain_impl(const blender::GVArray &varray, + AttributeDomain from_domain, + AttributeDomain to_domain) const final; }; /** @@ -729,9 +729,9 @@ 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, - AttributeDomain from_domain, - AttributeDomain to_domain) const final; + blender::GVArray attribute_try_adapt_domain_impl(const blender::GVArray &varray, + AttributeDomain from_domain, + AttributeDomain to_domain) const final; }; /** diff --git a/source/blender/blenkernel/BKE_mesh_sample.hh b/source/blender/blenkernel/BKE_mesh_sample.hh index a51dc7eef2f..a942f3bb7ed 100644 --- a/source/blender/blenkernel/BKE_mesh_sample.hh +++ b/source/blender/blenkernel/BKE_mesh_sample.hh @@ -6,8 +6,7 @@ * \ingroup bke */ -#include "FN_generic_virtual_array.hh" - +#include "BLI_generic_virtual_array.hh" #include "BLI_math_vec_types.hh" #include "BKE_attribute.h" @@ -21,10 +20,6 @@ class OutputAttribute; namespace blender::bke::mesh_surface_sample { -using fn::GMutableSpan; -using fn::GSpan; -using fn::GVArray; - void sample_point_attribute(const Mesh &mesh, Span looptri_indices, Span bary_coords, diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index 87f4ad6dc61..32330244c08 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -8,11 +8,10 @@ #include -#include "FN_generic_virtual_array.hh" - #include "DNA_curves_types.h" #include "BLI_float4x4.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_math_vec_types.hh" #include "BLI_vector.hh" @@ -205,16 +204,16 @@ class Spline { * points) to arbitrary parameters in between the evaluated points. The interpolation is quite * simple, but this handles the cyclic and end point special cases. */ - void sample_with_index_factors(const blender::fn::GVArray &src, + void sample_with_index_factors(const blender::GVArray &src, blender::Span index_factors, - blender::fn::GMutableSpan dst) const; + blender::GMutableSpan dst) const; template void sample_with_index_factors(const blender::VArray &src, blender::Span index_factors, blender::MutableSpan dst) const { this->sample_with_index_factors( - blender::fn::GVArray(src), index_factors, blender::fn::GMutableSpan(dst)); + blender::GVArray(src), index_factors, blender::GMutableSpan(dst)); } template void sample_with_index_factors(blender::Span src, @@ -229,11 +228,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::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const = 0; - blender::fn::GVArray interpolate_to_evaluated(blender::fn::GSpan data) const; + virtual blender::GVArray interpolate_to_evaluated(const blender::GVArray &src) const = 0; + blender::GVArray interpolate_to_evaluated(blender::GSpan data) const; template blender::VArray interpolate_to_evaluated(blender::Span data) const { - return this->interpolate_to_evaluated(blender::fn::GSpan(data)).typed(); + return this->interpolate_to_evaluated(blender::GSpan(data)).typed(); } protected: @@ -386,8 +385,7 @@ class BezierSpline final : public Spline { */ InterpolationData interpolation_data_from_index_factor(float index_factor) const; - virtual blender::fn::GVArray interpolate_to_evaluated( - const blender::fn::GVArray &src) const override; + virtual blender::GVArray interpolate_to_evaluated(const blender::GVArray &src) const override; void evaluate_segment(int index, int next_index, @@ -541,7 +539,7 @@ class NURBSpline final : public Spline { blender::Span evaluated_positions() const final; - blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final; + blender::GVArray interpolate_to_evaluated(const blender::GVArray &src) const final; protected: void correct_end_tangents() const final; @@ -599,7 +597,7 @@ class PolySpline final : public Spline { * the original data. Therefore the lifetime of the returned virtual array must not be longer * than the source data. */ - blender::fn::GVArray interpolate_to_evaluated(const blender::fn::GVArray &src) const final; + blender::GVArray interpolate_to_evaluated(const blender::GVArray &src) const final; protected: void correct_end_tangents() const final; diff --git a/source/blender/blenkernel/BKE_type_conversions.hh b/source/blender/blenkernel/BKE_type_conversions.hh index 8d3b2730a9c..5152989d137 100644 --- a/source/blender/blenkernel/BKE_type_conversions.hh +++ b/source/blender/blenkernel/BKE_type_conversions.hh @@ -56,11 +56,11 @@ class DataTypeConversions { const void *from_value, void *to_value) const; - void convert_to_initialized_n(fn::GSpan from_span, fn::GMutableSpan to_span) const; + void convert_to_initialized_n(GSpan from_span, GMutableSpan to_span) const; - fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const; + GVArray try_convert(GVArray varray, const CPPType &to_type) const; - fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const; + GVMutableArray try_convert(GVMutableArray varray, const CPPType &to_type) const; }; const DataTypeConversions &get_implicit_type_conversions(); diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index f79e8ee7653..50e35c3c7c2 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -28,14 +28,14 @@ static CLG_LogRef LOG = {"bke.attribute_access"}; using blender::float3; +using blender::GMutableSpan; +using blender::GSpan; +using blender::GVArrayImpl_For_GSpan; using blender::Set; using blender::StringRef; using blender::StringRefNull; using blender::bke::AttributeIDRef; using blender::bke::OutputAttribute; -using blender::fn::GMutableSpan; -using blender::fn::GSpan; -using blender::fn::GVArrayImpl_For_GSpan; namespace blender::bke { @@ -191,14 +191,14 @@ AttributeDomain attribute_domain_highest_priority(Span domains) return highest_priority_domain; } -fn::GMutableSpan OutputAttribute::as_span() +GMutableSpan OutputAttribute::as_span() { if (!optional_span_varray_) { const bool materialize_old_values = !ignore_old_values_; - optional_span_varray_ = std::make_unique(varray_, - materialize_old_values); + optional_span_varray_ = std::make_unique(varray_, + materialize_old_values); } - fn::GVMutableArray_GSpan &span_varray = *optional_span_varray_; + GVMutableArray_GSpan &span_varray = *optional_span_varray_; return span_varray; } @@ -917,8 +917,8 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( return {}; } -blender::fn::GVArray GeometryComponent::attribute_try_adapt_domain_impl( - const blender::fn::GVArray &varray, +blender::GVArray GeometryComponent::attribute_try_adapt_domain_impl( + const blender::GVArray &varray, const AttributeDomain from_domain, const AttributeDomain to_domain) const { @@ -1101,15 +1101,15 @@ std::optional GeometryComponent::attribute_get_meta_data( return result; } -static blender::fn::GVArray try_adapt_data_type(blender::fn::GVArray varray, - const blender::CPPType &to_type) +static blender::GVArray try_adapt_data_type(blender::GVArray varray, + const blender::CPPType &to_type) { const blender::bke::DataTypeConversions &conversions = blender::bke::get_implicit_type_conversions(); return conversions.try_convert(std::move(varray), to_type); } -blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( +blender::GVArray GeometryComponent::attribute_try_get_for_read( const AttributeIDRef &attribute_id, const AttributeDomain domain, const CustomDataType data_type) const @@ -1119,7 +1119,7 @@ blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( return {}; } - blender::fn::GVArray varray = std::move(attribute.varray); + blender::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) { @@ -1139,8 +1139,8 @@ blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( return varray; } -blender::fn::GVArray GeometryComponent::attribute_try_get_for_read( - const AttributeIDRef &attribute_id, const AttributeDomain domain) const +blender::GVArray GeometryComponent::attribute_try_get_for_read(const AttributeIDRef &attribute_id, + const AttributeDomain domain) const { if (!this->attribute_domain_supported(domain)) { return {}; @@ -1175,12 +1175,12 @@ blender::bke::ReadAttributeLookup GeometryComponent::attribute_try_get_for_read( return {conversions.try_convert(std::move(attribute.varray), *type), attribute.domain}; } -blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeIDRef &attribute_id, - const AttributeDomain domain, - const CustomDataType data_type, - const void *default_value) const +blender::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 varray = this->attribute_try_get_for_read(attribute_id, domain, data_type); + blender::GVArray varray = this->attribute_try_get_for_read(attribute_id, domain, data_type); if (varray) { return varray; } @@ -1189,10 +1189,10 @@ blender::fn::GVArray GeometryComponent::attribute_get_for_read(const AttributeID default_value = type->default_value(); } const int domain_size = this->attribute_domain_size(domain); - return blender::fn::GVArray::ForSingle(*type, domain_size, default_value); + return blender::GVArray::ForSingle(*type, domain_size, default_value); } -class GVMutableAttribute_For_OutputAttribute : public blender::fn::GVArrayImpl_For_GSpan { +class GVMutableAttribute_For_OutputAttribute : public blender::GVArrayImpl_For_GSpan { public: GeometryComponent *component; std::string attribute_name; @@ -1201,7 +1201,7 @@ class GVMutableAttribute_For_OutputAttribute : public blender::fn::GVArrayImpl_F GVMutableAttribute_For_OutputAttribute(GMutableSpan data, GeometryComponent &component, const AttributeIDRef &attribute_id) - : blender::fn::GVArrayImpl_For_GSpan(data), component(&component) + : blender::GVArrayImpl_For_GSpan(data), component(&component) { if (attribute_id.is_named()) { this->attribute_name = attribute_id.name(); diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc index a247c67066b..27687eb736f 100644 --- a/source/blender/blenkernel/intern/curve_catmull_rom.cc +++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc @@ -96,10 +96,10 @@ static void interpolate_to_evaluated(const Span src, }); } -void interpolate_to_evaluated(const fn::GSpan src, +void interpolate_to_evaluated(const GSpan src, const bool cyclic, const int resolution, - fn::GMutableSpan dst) + GMutableSpan dst) { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index 191a510947e..b2399f25638 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -20,6 +20,8 @@ using blender::Array; using blender::float3; using blender::float4x4; +using blender::GVArray; +using blender::GVArray_GSpan; using blender::IndexRange; using blender::Map; using blender::MutableSpan; @@ -32,8 +34,6 @@ using blender::bke::AttributeIDRef; using blender::bke::OutputAttribute; using blender::bke::OutputAttribute_Typed; using blender::bke::ReadAttributeLookup; -using blender::fn::GVArray; -using blender::fn::GVArray_GSpan; blender::Span CurveEval::splines() const { diff --git a/source/blender/blenkernel/intern/curve_nurbs.cc b/source/blender/blenkernel/intern/curve_nurbs.cc index 3bec01520e8..a4cdbbca654 100644 --- a/source/blender/blenkernel/intern/curve_nurbs.cc +++ b/source/blender/blenkernel/intern/curve_nurbs.cc @@ -230,8 +230,8 @@ static void interpolate_to_evaluated_rational(const BasisCache &basis_cache, void interpolate_to_evaluated(const BasisCache &basis_cache, const int8_t order, const Span control_weights, - const fn::GSpan src, - fn::GMutableSpan dst) + const GSpan src, + GMutableSpan dst) { BLI_assert(dst.size() == basis_cache.start_indices.size()); diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 5d80ef47908..9b22a4c9726 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -16,9 +16,6 @@ #include "BKE_curve_to_mesh.hh" -using blender::fn::GMutableSpan; -using blender::fn::GSpan; - namespace blender::bke { /** Information about the creation of one curve spline and profile spline combination. */ diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index ff24720e5e5..45f3bf36381 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -1055,9 +1055,9 @@ static GVArray adapt_curve_domain_curve_to_point(const CurvesGeometry &curves, return new_varray; } -fn::GVArray CurvesGeometry::adapt_domain(const fn::GVArray &varray, - const AttributeDomain from, - const AttributeDomain to) const +GVArray CurvesGeometry::adapt_domain(const GVArray &varray, + const AttributeDomain from, + const AttributeDomain to) const { if (!varray) { return {}; diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index 0926d65b306..f409389e463 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -14,10 +14,10 @@ #include "attribute_access_intern.hh" -using blender::fn::GMutableSpan; -using blender::fn::GSpan; -using blender::fn::GVArray; -using blender::fn::GVArray_GSpan; +using blender::GMutableSpan; +using blender::GSpan; +using blender::GVArray; +using blender::GVArray_GSpan; /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc index 86cbea9a9bb..7cf6fc5a03e 100644 --- a/source/blender/blenkernel/intern/geometry_component_curves.cc +++ b/source/blender/blenkernel/intern/geometry_component_curves.cc @@ -15,7 +15,7 @@ #include "attribute_access_intern.hh" -using blender::fn::GVArray; +using blender::GVArray; /* -------------------------------------------------------------------- */ /** \name Geometry Component Implementation diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc index 75384b5c420..0dc6f486d28 100644 --- a/source/blender/blenkernel/intern/geometry_component_instances.cc +++ b/source/blender/blenkernel/intern/geometry_component_instances.cc @@ -23,13 +23,13 @@ #include "BLI_cpp_type_make.hh" using blender::float4x4; +using blender::GSpan; using blender::IndexMask; using blender::Map; using blender::MutableSpan; using blender::Set; using blender::Span; using blender::VectorSet; -using blender::fn::GSpan; BLI_CPP_TYPE_MAKE(InstanceReference, InstanceReference, CPPTypeFlags::None) @@ -164,7 +164,7 @@ void InstancesComponent::remove_instances(const IndexMask mask) GSpan src = *src_attributes.get_for_read(id); dst_attributes.create(id, meta_data.data_type); - fn::GMutableSpan dst = *dst_attributes.get_for_write(id); + GMutableSpan dst = *dst_attributes.get_for_write(id); attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc index a07957e999c..76c8a0054b3 100644 --- a/source/blender/blenkernel/intern/geometry_component_mesh.cc +++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc @@ -746,8 +746,8 @@ static GVArray adapt_mesh_domain_edge_to_face(const Mesh &mesh, const GVArray &v } // namespace blender::bke -blender::fn::GVArray MeshComponent::attribute_try_adapt_domain_impl( - const blender::fn::GVArray &varray, +blender::GVArray MeshComponent::attribute_try_adapt_domain_impl( + const blender::GVArray &varray, const AttributeDomain from_domain, const AttributeDomain to_domain) const { diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc index dc5b1d28539..eecb374cd63 100644 --- a/source/blender/blenkernel/intern/spline_base.cc +++ b/source/blender/blenkernel/intern/spline_base.cc @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_array.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_span.hh" #include "BLI_task.hh" #include "BLI_timeit.hh" @@ -9,19 +10,17 @@ #include "BKE_attribute_math.hh" #include "BKE_spline.hh" -#include "FN_generic_virtual_array.hh" - using blender::Array; using blender::float3; +using blender::GMutableSpan; +using blender::GSpan; +using blender::GVArray; 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; CurveType Spline::type() const { @@ -100,7 +99,7 @@ void Spline::reverse() this->attributes.foreach_attribute( [&](const AttributeIDRef &id, const AttributeMetaData &meta_data) { - std::optional attribute = this->attributes.get_for_write(id); + std::optional attribute = this->attributes.get_for_write(id); if (!attribute) { BLI_assert_unreachable(); return false; diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index e9ae51b16f8..8e207f93bf5 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -8,11 +8,11 @@ using blender::Array; using blender::float3; +using blender::GVArray; using blender::IndexRange; using blender::MutableSpan; using blender::Span; using blender::VArray; -using blender::fn::GVArray; void BezierSpline::copy_settings(Spline &dst) const { diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index a8a17b7aee6..9d1d5a53a43 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -9,11 +9,11 @@ using blender::Array; using blender::float3; +using blender::GVArray; using blender::IndexRange; using blender::MutableSpan; using blender::Span; using blender::VArray; -using blender::fn::GVArray; void NURBSpline::copy_settings(Spline &dst) const { diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc index a5d3fd47ede..122f7f6c059 100644 --- a/source/blender/blenkernel/intern/spline_poly.cc +++ b/source/blender/blenkernel/intern/spline_poly.cc @@ -6,9 +6,9 @@ #include "BKE_spline.hh" using blender::float3; +using blender::GVArray; using blender::MutableSpan; using blender::Span; -using blender::fn::GVArray; void PolySpline::copy_settings(Spline &UNUSED(dst)) const { diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc index 2e8b5b3433b..d10979eeee9 100644 --- a/source/blender/blenkernel/intern/type_conversions.cc +++ b/source/blender/blenkernel/intern/type_conversions.cc @@ -288,8 +288,7 @@ void DataTypeConversions::convert_to_uninitialized(const CPPType &from_type, functions->convert_single_to_uninitialized(from_value, to_value); } -void DataTypeConversions::convert_to_initialized_n(fn::GSpan from_span, - fn::GMutableSpan to_span) const +void DataTypeConversions::convert_to_initialized_n(GSpan from_span, GMutableSpan to_span) const { const CPPType &from_type = from_span.type(); const CPPType &to_type = to_span.type(); @@ -305,19 +304,17 @@ void DataTypeConversions::convert_to_initialized_n(fn::GSpan from_span, fn->call_auto(IndexRange(from_span.size()), params, context); } -class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl { +class GVArray_For_ConvertedGVArray : public GVArrayImpl { private: - fn::GVArray varray_; + GVArray varray_; const CPPType &from_type_; ConversionFunctions old_to_new_conversions_; public: - GVArray_For_ConvertedGVArray(fn::GVArray varray, + GVArray_For_ConvertedGVArray(GVArray varray, const CPPType &to_type, const DataTypeConversions &conversions) - : fn::GVArrayImpl(to_type, varray.size()), - varray_(std::move(varray)), - from_type_(varray_.type()) + : 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); } @@ -340,18 +337,18 @@ class GVArray_For_ConvertedGVArray : public fn::GVArrayImpl { } }; -class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl { +class GVMutableArray_For_ConvertedGVMutableArray : public GVMutableArrayImpl { private: - fn::GVMutableArray varray_; + GVMutableArray varray_; const CPPType &from_type_; ConversionFunctions old_to_new_conversions_; ConversionFunctions new_to_old_conversions_; public: - GVMutableArray_For_ConvertedGVMutableArray(fn::GVMutableArray varray, + GVMutableArray_For_ConvertedGVMutableArray(GVMutableArray varray, const CPPType &to_type, const DataTypeConversions &conversions) - : fn::GVMutableArrayImpl(to_type, varray.size()), + : GVMutableArrayImpl(to_type, varray.size()), varray_(std::move(varray)), from_type_(varray_.type()) { @@ -384,7 +381,7 @@ class GVMutableArray_For_ConvertedGVMutableArray : public fn::GVMutableArrayImpl } }; -fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType &to_type) const +GVArray DataTypeConversions::try_convert(GVArray varray, const CPPType &to_type) const { const CPPType &from_type = varray.type(); if (from_type == to_type) { @@ -393,11 +390,11 @@ fn::GVArray DataTypeConversions::try_convert(fn::GVArray varray, const CPPType & if (!this->is_convertible(from_type, to_type)) { return {}; } - return fn::GVArray::For(std::move(varray), to_type, *this); + return GVArray::For(std::move(varray), to_type, *this); } -fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray, - const CPPType &to_type) const +GVMutableArray DataTypeConversions::try_convert(GVMutableArray varray, + const CPPType &to_type) const { const CPPType &from_type = varray.type(); if (from_type == to_type) { @@ -406,7 +403,7 @@ fn::GVMutableArray DataTypeConversions::try_convert(fn::GVMutableArray varray, if (!this->is_convertible(from_type, to_type)) { return {}; } - return fn::GVMutableArray::For( + return GVMutableArray::For( std::move(varray), to_type, *this); } diff --git a/source/blender/blenlib/BLI_generic_array.hh b/source/blender/blenlib/BLI_generic_array.hh new file mode 100644 index 00000000000..e1b6b29874a --- /dev/null +++ b/source/blender/blenlib/BLI_generic_array.hh @@ -0,0 +1,255 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * This is a generic counterpart to #blender::Array, used when the type is not known at runtime. + * + * `GArray` should generally only be used for passing data around in dynamic contexts. + * It does not support a few things that #blender::Array supports: + * - Small object optimization / inline buffer. + * - Exception safety and various more specific constructors. + */ + +#include "BLI_allocator.hh" +#include "BLI_cpp_type.hh" +#include "BLI_generic_span.hh" + +namespace blender { + +template< + /** + * The allocator used by this array. Should rarely be changed, except when you don't want that + * MEM_* functions are used internally. + */ + typename Allocator = GuardedAllocator> +class GArray { + protected: + /** The type of the data in the array, will be null after the array is default constructed, + * but a value should be assigned before any other interaction with the array. */ + const CPPType *type_ = nullptr; + void *data_ = nullptr; + int64_t size_ = 0; + + Allocator allocator_; + + public: + /** + * The default constructor creates an empty array, the only situation in which the type is + * allowed to be null. This default constructor exists so `GArray` can be used in containers, + * but the type should be supplied before doing anything else to the array. + */ + GArray(Allocator allocator = {}) noexcept : allocator_(allocator) + { + } + + GArray(NoExceptConstructor, Allocator allocator = {}) noexcept : GArray(allocator) + { + } + + /** + * Create and allocate a new array, with elements default constructed + * (which does not do anything for trivial types). + */ + GArray(const CPPType &type, int64_t size, Allocator allocator = {}) : GArray(type, allocator) + { + BLI_assert(size >= 0); + size_ = size; + data_ = this->allocate(size_); + type_->default_construct_n(data_, size_); + } + + /** + * Create an empty array with just a type. + */ + GArray(const CPPType &type, Allocator allocator = {}) : GArray(allocator) + { + type_ = &type; + } + + /** + * Take ownership of a buffer with a provided size. The buffer should be + * allocated with the same allocator provided to the constructor. + */ + GArray(const CPPType &type, void *buffer, int64_t size, Allocator allocator = {}) + : GArray(type, allocator) + { + BLI_assert(size >= 0); + BLI_assert(buffer != nullptr || size == 0); + BLI_assert(type_->pointer_has_valid_alignment(buffer)); + + data_ = buffer; + size_ = size; + } + + /** + * Create an array by copying values from a generic span. + */ + GArray(const GSpan span, Allocator allocator = {}) : GArray(span.type(), span.size(), allocator) + { + if (span.data() != nullptr) { + BLI_assert(span.size() != 0); + /* Use copy assign rather than construct since the memory is already initialized. */ + type_->copy_assign_n(span.data(), data_, size_); + } + } + + /** + * Create an array by copying values from another generic array. + */ + GArray(const GArray &other) : GArray(other.as_span(), other.allocator()) + { + } + + /** + * Create an array by taking ownership of another array's data, clearing the data in the other. + */ + GArray(GArray &&other) : GArray(other.type(), other.data(), other.size(), other.allocator()) + { + other.data_ = nullptr; + other.size_ = 0; + } + + ~GArray() + { + if (data_ != nullptr) { + type_->destruct_n(data_, size_); + this->deallocate(data_); + } + } + + GArray &operator=(const GArray &other) + { + return copy_assign_container(*this, other); + } + + GArray &operator=(GArray &&other) + { + return move_assign_container(*this, std::move(other)); + } + + const CPPType &type() const + { + BLI_assert(type_ != nullptr); + return *type_; + } + + bool is_empty() const + { + return size_ == 0; + } + + /** + * Return the number of elements in the array (not the size in bytes). + */ + int64_t size() const + { + return size_; + } + + /** + * Get a pointer to the beginning of the array. + */ + const void *data() const + { + return data_; + } + void *data() + { + return data_; + } + + const void *operator[](int64_t index) const + { + BLI_assert(index < size_); + return POINTER_OFFSET(data_, type_->size() * index); + } + + void *operator[](int64_t index) + { + BLI_assert(index < size_); + return POINTER_OFFSET(data_, type_->size() * index); + } + + operator GSpan() const + { + BLI_assert(type_ != nullptr); + return GSpan(*type_, data_, size_); + } + + operator GMutableSpan() + { + BLI_assert(type_ != nullptr); + return GMutableSpan(*type_, data_, size_); + } + + GSpan as_span() const + { + return *this; + } + + GMutableSpan as_mutable_span() + { + return *this; + } + + /** + * Access the allocator used by this array. + */ + Allocator &allocator() + { + return allocator_; + } + const Allocator &allocator() const + { + return allocator_; + } + + /** + * Destruct values and create a new array of the given size. The values in the new array are + * default constructed. + */ + void reinitialize(const int64_t new_size) + { + BLI_assert(new_size >= 0); + int64_t old_size = size_; + + type_->destruct_n(data_, size_); + size_ = 0; + + if (new_size <= old_size) { + type_->default_construct_n(data_, new_size); + } + else { + void *new_data = this->allocate(new_size); + try { + type_->default_construct_n(new_data, new_size); + } + catch (...) { + this->deallocate(new_data); + throw; + } + this->deallocate(data_); + data_ = new_data; + } + + size_ = new_size; + } + + private: + void *allocate(int64_t size) + { + const int64_t item_size = type_->size(); + const int64_t alignment = type_->alignment(); + return allocator_.allocate(static_cast(size) * item_size, alignment, AT); + } + + void deallocate(void *ptr) + { + allocator_.deallocate(ptr); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_generic_pointer.hh b/source/blender/blenlib/BLI_generic_pointer.hh new file mode 100644 index 00000000000..226f76c3d33 --- /dev/null +++ b/source/blender/blenlib/BLI_generic_pointer.hh @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BLI_cpp_type.hh" + +namespace blender { + +/** + * A generic non-const pointer whose type is only known at runtime. + */ +class GMutablePointer { + private: + const CPPType *type_ = nullptr; + void *data_ = nullptr; + + public: + GMutablePointer() = default; + + GMutablePointer(const CPPType *type, void *data = nullptr) : type_(type), data_(data) + { + /* If there is data, there has to be a type. */ + BLI_assert(data_ == nullptr || type_ != nullptr); + } + + GMutablePointer(const CPPType &type, void *data = nullptr) : GMutablePointer(&type, data) + { + } + + template GMutablePointer(T *data) : GMutablePointer(&CPPType::get(), data) + { + } + + void *get() const + { + return data_; + } + + const CPPType *type() const + { + return type_; + } + + template T *get() const + { + BLI_assert(this->is_type()); + return static_cast(data_); + } + + template bool is_type() const + { + return type_ != nullptr && type_->is(); + } + + template T relocate_out() + { + BLI_assert(this->is_type()); + T value; + type_->relocate_assign(data_, &value); + data_ = nullptr; + type_ = nullptr; + return value; + } + + void destruct() + { + BLI_assert(data_ != nullptr); + type_->destruct(data_); + } +}; + +/** + * A generic const pointer whose type is only known at runtime. + */ +class GPointer { + private: + const CPPType *type_ = nullptr; + const void *data_ = nullptr; + + public: + GPointer() = default; + + GPointer(GMutablePointer ptr) : type_(ptr.type()), data_(ptr.get()) + { + } + + GPointer(const CPPType *type, const void *data = nullptr) : type_(type), data_(data) + { + /* If there is data, there has to be a type. */ + BLI_assert(data_ == nullptr || type_ != nullptr); + } + + GPointer(const CPPType &type, const void *data = nullptr) : type_(&type), data_(data) + { + } + + template GPointer(T *data) : GPointer(&CPPType::get(), data) + { + } + + const void *get() const + { + return data_; + } + + const CPPType *type() const + { + return type_; + } + + template const T *get() const + { + BLI_assert(this->is_type()); + return static_cast(data_); + } + + template bool is_type() const + { + return type_ != nullptr && type_->is(); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_generic_span.hh b/source/blender/blenlib/BLI_generic_span.hh new file mode 100644 index 00000000000..f4f93735e06 --- /dev/null +++ b/source/blender/blenlib/BLI_generic_span.hh @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + */ + +#include "BLI_cpp_type.hh" +#include "BLI_span.hh" + +namespace blender { + +/** + * A generic span. It behaves just like a blender::Span, but the type is only known at run-time. + */ +class GSpan { + protected: + const CPPType *type_; + const void *data_; + int64_t size_; + + public: + GSpan(const CPPType &type, const void *buffer, int64_t size) + : type_(&type), data_(buffer), size_(size) + { + BLI_assert(size >= 0); + BLI_assert(buffer != nullptr || size == 0); + BLI_assert(type.pointer_has_valid_alignment(buffer)); + } + + GSpan(const CPPType &type) : GSpan(type, nullptr, 0) + { + } + + template + GSpan(Span array) + : GSpan(CPPType::get(), static_cast(array.data()), array.size()) + { + } + + const CPPType &type() const + { + return *type_; + } + + bool is_empty() const + { + return size_ == 0; + } + + int64_t size() const + { + return size_; + } + + const void *data() const + { + return data_; + } + + const void *operator[](int64_t index) const + { + BLI_assert(index < size_); + return POINTER_OFFSET(data_, type_->size() * index); + } + + template Span typed() const + { + BLI_assert(type_->is()); + return Span(static_cast(data_), size_); + } + + GSpan slice(const int64_t start, int64_t size) const + { + BLI_assert(start >= 0); + BLI_assert(size >= 0); + const int64_t new_size = std::max(0, std::min(size, size_ - start)); + return GSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size); + } + + GSpan slice(const IndexRange range) const + { + return this->slice(range.start(), range.size()); + } +}; + +/** + * A generic mutable span. It behaves just like a blender::MutableSpan, but the type is only + * known at run-time. + */ +class GMutableSpan { + protected: + const CPPType *type_; + void *data_; + int64_t size_; + + public: + GMutableSpan(const CPPType &type, void *buffer, int64_t size) + : type_(&type), data_(buffer), size_(size) + { + BLI_assert(size >= 0); + BLI_assert(buffer != nullptr || size == 0); + BLI_assert(type.pointer_has_valid_alignment(buffer)); + } + + GMutableSpan(const CPPType &type) : GMutableSpan(type, nullptr, 0) + { + } + + template + GMutableSpan(MutableSpan array) + : GMutableSpan(CPPType::get(), static_cast(array.begin()), array.size()) + { + } + + operator GSpan() const + { + return GSpan(*type_, data_, size_); + } + + const CPPType &type() const + { + return *type_; + } + + bool is_empty() const + { + return size_ == 0; + } + + int64_t size() const + { + return size_; + } + + void *data() const + { + return data_; + } + + void *operator[](int64_t index) const + { + BLI_assert(index >= 0); + BLI_assert(index < size_); + return POINTER_OFFSET(data_, type_->size() * index); + } + + template MutableSpan typed() const + { + BLI_assert(type_->is()); + return MutableSpan(static_cast(data_), size_); + } + + GMutableSpan slice(const int64_t start, int64_t size) const + { + BLI_assert(start >= 0); + BLI_assert(size >= 0); + const int64_t new_size = std::max(0, std::min(size, size_ - start)); + return GMutableSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size); + } + + GMutableSpan slice(IndexRange range) const + { + return this->slice(range.start(), range.size()); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_generic_value_map.hh b/source/blender/blenlib/BLI_generic_value_map.hh new file mode 100644 index 00000000000..bd8408526b8 --- /dev/null +++ b/source/blender/blenlib/BLI_generic_value_map.hh @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +#include "BLI_generic_pointer.hh" +#include "BLI_linear_allocator.hh" +#include "BLI_map.hh" + +namespace blender { + +/** + * This is a map that stores key-value-pairs. What makes it special is that the type of values does + * not have to be known at compile time. There just has to be a corresponding CPPType. + */ +template class GValueMap { + private: + /* Used to allocate values owned by this container. */ + LinearAllocator<> &allocator_; + Map values_; + + public: + GValueMap(LinearAllocator<> &allocator) : allocator_(allocator) + { + } + + ~GValueMap() + { + /* Destruct all values that are still in the map. */ + for (GMutablePointer value : values_.values()) { + value.destruct(); + } + } + + /* Add a value to the container. The container becomes responsible for destructing the value that + * is passed in. The caller remains responsible for freeing the value after it has been + * destructed. */ + template void add_new_direct(ForwardKey &&key, GMutablePointer value) + { + values_.add_new_as(std::forward(key), value); + } + + /* Add a value to the container that is move constructed from the given value. The caller remains + * responsible for destructing and freeing the given value. */ + template void add_new_by_move(ForwardKey &&key, GMutablePointer value) + { + const CPPType &type = *value.type(); + void *buffer = allocator_.allocate(type.size(), type.alignment()); + type.move_construct(value.get(), buffer); + values_.add_new_as(std::forward(key), GMutablePointer{type, buffer}); + } + + /* Add a value to the container that is copy constructed from the given value. The caller remains + * responsible for destructing and freeing the given value. */ + template void add_new_by_copy(ForwardKey &&key, GPointer value) + { + const CPPType &type = *value.type(); + void *buffer = allocator_.allocate(type.size(), type.alignment()); + type.copy_construct(value.get(), buffer); + values_.add_new_as(std::forward(key), GMutablePointer{type, buffer}); + } + + /* Add a value to the container. */ + template void add_new(ForwardKey &&key, T &&value) + { + if constexpr (std::is_rvalue_reference_v) { + this->add_new_by_move(std::forward(key), &value); + } + else { + this->add_new_by_copy(std::forward(key), &value); + } + } + + /* Remove the value for the given name from the container and remove it. The caller is + * responsible for freeing it. The lifetime of the referenced memory might be bound to lifetime + * of the container. */ + template GMutablePointer extract(const ForwardKey &key) + { + return values_.pop_as(key); + } + + template GPointer lookup(const ForwardKey &key) const + { + return values_.lookup_as(key); + } + + /* Remove the value for the given name from the container and remove it. */ + template T extract(const ForwardKey &key) + { + GMutablePointer value = values_.pop_as(key); + const CPPType &type = *value.type(); + BLI_assert(type.is()); + T return_value; + type.relocate_assign(value.get(), &return_value); + return return_value; + } + + template const T &lookup(const ForwardKey &key) const + { + GMutablePointer value = values_.lookup_as(key); + BLI_assert(value.is_type()); + BLI_assert(value.get() != nullptr); + return *(const T *)value.get(); + } + + template bool contains(const ForwardKey &key) const + { + return values_.contains_as(key); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_generic_vector_array.hh b/source/blender/blenlib/BLI_generic_vector_array.hh new file mode 100644 index 00000000000..c98817df4e3 --- /dev/null +++ b/source/blender/blenlib/BLI_generic_vector_array.hh @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * A`GVectorArray` is a container for a fixed amount of dynamically growing vectors with a generic + * data type. Its main use case is to store many small vectors with few separate allocations. Using + * this structure is generally more efficient than allocating each vector separately. + */ + +#include "BLI_array.hh" +#include "BLI_generic_virtual_vector_array.hh" +#include "BLI_linear_allocator.hh" + +namespace blender { + +/* An array of vectors containing elements of a generic type. */ +class GVectorArray : NonCopyable, NonMovable { + private: + struct Item { + void *start = nullptr; + int64_t length = 0; + int64_t capacity = 0; + }; + + /* Use a linear allocator to pack many small vectors together. Currently, memory from reallocated + * vectors is not reused. This can be improved in the future. */ + LinearAllocator<> allocator_; + /* The data type of individual elements. */ + const CPPType &type_; + /* The size of an individual element. This is inlined from `type_.size()` for easier access. */ + const int64_t element_size_; + /* The individual vectors. */ + Array items_; + + public: + GVectorArray() = delete; + + GVectorArray(const CPPType &type, int64_t array_size); + + ~GVectorArray(); + + int64_t size() const + { + return items_.size(); + } + + bool is_empty() const + { + return items_.is_empty(); + } + + const CPPType &type() const + { + return type_; + } + + void append(int64_t index, const void *value); + + /* Add multiple elements to a single vector. */ + void extend(int64_t index, const GVArray &values); + void extend(int64_t index, GSpan values); + + /* Add multiple elements to multiple vectors. */ + void extend(IndexMask mask, const GVVectorArray &values); + void extend(IndexMask mask, const GVectorArray &values); + + void clear(IndexMask mask); + + GMutableSpan operator[](int64_t index); + GSpan operator[](int64_t index) const; + + private: + void realloc_to_at_least(Item &item, int64_t min_capacity); +}; + +/* A non-owning typed mutable reference to an `GVectorArray`. It simplifies access when the type of + * the data is known at compile time. */ +template class GVectorArray_TypedMutableRef { + private: + GVectorArray *vector_array_; + + public: + GVectorArray_TypedMutableRef(GVectorArray &vector_array) : vector_array_(&vector_array) + { + BLI_assert(vector_array_->type().is()); + } + + int64_t size() const + { + return vector_array_->size(); + } + + bool is_empty() const + { + return vector_array_->is_empty(); + } + + void append(const int64_t index, const T &value) + { + vector_array_->append(index, &value); + } + + void extend(const int64_t index, const Span values) + { + vector_array_->extend(index, values); + } + + void extend(const int64_t index, const VArray &values) + { + vector_array_->extend(index, values); + } + + MutableSpan operator[](const int64_t index) + { + return (*vector_array_)[index].typed(); + } +}; + +/* A generic virtual vector array implementation for a `GVectorArray`. */ +class GVVectorArray_For_GVectorArray : public GVVectorArray { + private: + const GVectorArray &vector_array_; + + public: + GVVectorArray_For_GVectorArray(const GVectorArray &vector_array) + : GVVectorArray(vector_array.type(), vector_array.size()), vector_array_(vector_array) + { + } + + protected: + int64_t get_vector_size_impl(const int64_t index) const override + { + return vector_array_[index].size(); + } + + void get_vector_element_impl(const int64_t index, + const int64_t index_in_vector, + void *r_value) const override + { + type_->copy_assign(vector_array_[index][index_in_vector], r_value); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh new file mode 100644 index 00000000000..f4c9e745cf9 --- /dev/null +++ b/source/blender/blenlib/BLI_generic_virtual_array.hh @@ -0,0 +1,877 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * A generic virtual array is the same as a virtual array, except for the fact that the data type + * is only known at runtime. + */ + +#include "BLI_generic_array.hh" +#include "BLI_generic_span.hh" +#include "BLI_timeit.hh" +#include "BLI_virtual_array.hh" + +namespace blender { + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl and #GVMutableArrayImpl. + * \{ */ + +class GVArray; +class GVArrayImpl; +class GVMutableArray; +class GVMutableArrayImpl; + +/* A generically typed version of #VArrayImpl. */ +class GVArrayImpl { + protected: + const CPPType *type_; + int64_t size_; + + public: + GVArrayImpl(const CPPType &type, int64_t size); + virtual ~GVArrayImpl() = default; + + const CPPType &type() const; + + int64_t size() const; + + virtual void get(int64_t index, void *r_value) const; + virtual void get_to_uninitialized(int64_t index, void *r_value) const = 0; + + virtual bool is_span() const; + virtual GSpan get_internal_span() const; + + virtual bool is_single() const; + virtual void get_internal_single(void *UNUSED(r_value)) const; + + virtual void materialize(const IndexMask mask, void *dst) const; + virtual void materialize_to_uninitialized(const IndexMask mask, void *dst) const; + + virtual bool try_assign_VArray(void *varray) const; + virtual bool may_have_ownership() const; +}; + +/* A generic version of #VMutableArrayImpl. */ +class GVMutableArrayImpl : public GVArrayImpl { + public: + GVMutableArrayImpl(const CPPType &type, int64_t size); + + virtual void set_by_copy(int64_t index, const void *value); + virtual void set_by_relocate(int64_t index, void *value); + virtual void set_by_move(int64_t index, void *value) = 0; + + virtual void set_all(const void *src); + + virtual bool try_assign_VMutableArray(void *varray) const; +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArray and #GVMutableArray + * \{ */ + +namespace detail { +struct GVArrayAnyExtraInfo { + const GVArrayImpl *(*get_varray)(const void *buffer) = + [](const void *UNUSED(buffer)) -> const GVArrayImpl * { return nullptr; }; + + template static GVArrayAnyExtraInfo get(); +}; +} // namespace detail + +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: + /** + * 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; + + const GVArrayImpl *impl_ = nullptr; + Storage storage_; + + protected: + GVArrayCommon(); + GVArrayCommon(const GVArrayCommon &other); + GVArrayCommon(GVArrayCommon &&other) noexcept; + GVArrayCommon(const GVArrayImpl *impl); + GVArrayCommon(std::shared_ptr impl); + ~GVArrayCommon(); + + template void emplace(Args &&...args); + + void copy_from(const GVArrayCommon &other); + void move_from(GVArrayCommon &&other) noexcept; + + const GVArrayImpl *impl_from_storage() const; + + public: + const CPPType &type() const; + operator bool() const; + + int64_t size() const; + bool is_empty() const; + IndexRange index_range() const; + + template bool try_assign_VArray(VArray &varray) const; + bool may_have_ownership() 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; + + /** + * Returns true when the virtual array is stored as a span internally. + */ + bool is_span() const; + /** + * Returns the internally used span of the virtual array. This invokes undefined behavior if the + * virtual array is not stored as a span internally. + */ + GSpan get_internal_span() const; + + /** + * Returns true when the virtual array returns the same value for every index. + */ + bool is_single() const; + /** + * 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; + /** + * Same as `get_internal_single`, but `r_value` points to initialized memory. + */ + void get_internal_single_to_uninitialized(void *r_value) const; + + void get(int64_t index, void *r_value) const; + /** + * Returns a copy of the value at the given index. Usually a typed virtual array should + * be used instead, but sometimes this is simpler when only a few indices are needed. + */ + template T get(int64_t index) const; + void get_to_uninitialized(int64_t index, void *r_value) const; +}; + +/** Generic version of #VArray. */ +class GVArray : public GVArrayCommon { + private: + friend GVMutableArray; + + public: + GVArray() = default; + + GVArray(const GVArray &other); + GVArray(GVArray &&other) noexcept; + GVArray(const GVArrayImpl *impl); + GVArray(std::shared_ptr impl); + + template GVArray(const VArray &varray); + template VArray typed() const; + + template static GVArray For(Args &&...args); + + static GVArray ForSingle(const CPPType &type, int64_t size, const void *value); + static GVArray ForSingleRef(const CPPType &type, int64_t size, const void *value); + static GVArray ForSingleDefault(const CPPType &type, int64_t size); + static GVArray ForSpan(GSpan span); + static GVArray ForGArray(GArray<> array); + static GVArray ForEmpty(const CPPType &type); + + GVArray slice(IndexRange slice) const; + + GVArray &operator=(const GVArray &other); + GVArray &operator=(GVArray &&other) noexcept; + + const GVArrayImpl *get_implementation() const + { + return impl_; + } +}; + +/** Generic version of #VMutableArray. */ +class GVMutableArray : public GVArrayCommon { + public: + GVMutableArray() = default; + GVMutableArray(const GVMutableArray &other); + GVMutableArray(GVMutableArray &&other) noexcept; + GVMutableArray(GVMutableArrayImpl *impl); + GVMutableArray(std::shared_ptr impl); + + template GVMutableArray(const VMutableArray &varray); + template VMutableArray typed() const; + + template static GVMutableArray For(Args &&...args); + + static GVMutableArray ForSpan(GMutableSpan span); + + operator GVArray() const &; + operator GVArray() &&noexcept; + + GVMutableArray &operator=(const GVMutableArray &other); + GVMutableArray &operator=(GVMutableArray &&other) noexcept; + + GMutableSpan get_internal_span() const; + + template bool try_assign_VMutableArray(VMutableArray &varray) const; + + void set_by_copy(int64_t index, const void *value); + void set_by_move(int64_t index, void *value); + void set_by_relocate(int64_t index, void *value); + + void fill(const void *value); + /** + * Copy the values from the source buffer to all elements in the virtual array. + */ + void set_all(const void *src); + + GVMutableArrayImpl *get_implementation() const; + + private: + GVMutableArrayImpl *get_impl() const; +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \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(); +}; + +/* 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(); +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Conversions between generic and typed virtual arrays. + * \{ */ + +/* Used to convert a typed virtual array into a generic one. */ +template class GVArrayImpl_For_VArray : public GVArrayImpl { + protected: + VArray varray_; + + public: + GVArrayImpl_For_VArray(VArray varray) + : GVArrayImpl(CPPType::get(), varray.size()), varray_(std::move(varray)) + { + } + + protected: + void get(const int64_t index, void *r_value) const override + { + *(T *)r_value = varray_[index]; + } + + void get_to_uninitialized(const int64_t index, void *r_value) const override + { + new (r_value) T(varray_[index]); + } + + bool is_span() const override + { + return varray_.is_span(); + } + + GSpan get_internal_span() const override + { + return GSpan(varray_.get_internal_span()); + } + + bool is_single() const override + { + return varray_.is_single(); + } + + void get_internal_single(void *r_value) const override + { + *(T *)r_value = varray_.get_internal_single(); + } + + void materialize(const IndexMask mask, void *dst) const override + { + varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); + } + + void materialize_to_uninitialized(const IndexMask mask, void *dst) const override + { + varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); + } + + bool try_assign_VArray(void *varray) const override + { + *(VArray *)varray = varray_; + return true; + } + + bool may_have_ownership() const override + { + return varray_.may_have_ownership(); + } +}; + +/* Used to convert any generic virtual array into a typed one. */ +template class VArrayImpl_For_GVArray : public VArrayImpl { + protected: + GVArray varray_; + + public: + VArrayImpl_For_GVArray(GVArray varray) : VArrayImpl(varray.size()), varray_(std::move(varray)) + { + BLI_assert(varray_); + BLI_assert(varray_.type().template is()); + } + + protected: + T get(const int64_t index) const override + { + T value; + varray_.get(index, &value); + return value; + } + + bool is_span() const override + { + return varray_.is_span(); + } + + Span get_internal_span() const override + { + return varray_.get_internal_span().template typed(); + } + + bool is_single() const override + { + return varray_.is_single(); + } + + T get_internal_single() const override + { + T value; + varray_.get_internal_single(&value); + return value; + } + + bool try_assign_GVArray(GVArray &varray) const override + { + varray = varray_; + return true; + } + + bool may_have_ownership() const override + { + return varray_.may_have_ownership(); + } +}; + +/* Used to convert any typed virtual mutable array into a generic one. */ +template class GVMutableArrayImpl_For_VMutableArray : public GVMutableArrayImpl { + protected: + VMutableArray varray_; + + public: + GVMutableArrayImpl_For_VMutableArray(VMutableArray varray) + : GVMutableArrayImpl(CPPType::get(), varray.size()), varray_(std::move(varray)) + { + } + + protected: + void get(const int64_t index, void *r_value) const override + { + *(T *)r_value = varray_[index]; + } + + void get_to_uninitialized(const int64_t index, void *r_value) const override + { + new (r_value) T(varray_[index]); + } + + bool is_span() const override + { + return varray_.is_span(); + } + + GSpan get_internal_span() const override + { + Span span = varray_.get_internal_span(); + return span; + } + + bool is_single() const override + { + return varray_.is_single(); + } + + void get_internal_single(void *r_value) const override + { + *(T *)r_value = varray_.get_internal_single(); + } + + void set_by_copy(const int64_t index, const void *value) override + { + const T &value_ = *(const T *)value; + varray_.set(index, value_); + } + + void set_by_relocate(const int64_t index, void *value) override + { + T &value_ = *(T *)value; + varray_.set(index, std::move(value_)); + value_.~T(); + } + + void set_by_move(const int64_t index, void *value) override + { + T &value_ = *(T *)value; + varray_.set(index, std::move(value_)); + } + + void set_all(const void *src) override + { + varray_.set_all(Span((T *)src, size_)); + } + + void materialize(const IndexMask mask, void *dst) const override + { + varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); + } + + void materialize_to_uninitialized(const IndexMask mask, void *dst) const override + { + varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); + } + + bool try_assign_VArray(void *varray) const override + { + *(VArray *)varray = varray_; + return true; + } + + bool try_assign_VMutableArray(void *varray) const override + { + *(VMutableArray *)varray = varray_; + return true; + } + + bool may_have_ownership() const override + { + return varray_.may_have_ownership(); + } +}; + +/* Used to convert an generic mutable virtual array into a typed one. */ +template class VMutableArrayImpl_For_GVMutableArray : public VMutableArrayImpl { + protected: + GVMutableArray varray_; + + public: + VMutableArrayImpl_For_GVMutableArray(GVMutableArray varray) + : VMutableArrayImpl(varray.size()), varray_(varray) + { + BLI_assert(varray_); + BLI_assert(varray_.type().template is()); + } + + private: + T get(const int64_t index) const override + { + T value; + varray_.get(index, &value); + return value; + } + + void set(const int64_t index, T value) override + { + varray_.set_by_relocate(index, &value); + } + + bool is_span() const override + { + return varray_.is_span(); + } + + Span get_internal_span() const override + { + return varray_.get_internal_span().template typed(); + } + + bool is_single() const override + { + return varray_.is_single(); + } + + T get_internal_single() const override + { + T value; + varray_.get_internal_single(&value); + return value; + } + + bool try_assign_GVArray(GVArray &varray) const override + { + varray = varray_; + return true; + } + + bool try_assign_GVMutableArray(GVMutableArray &varray) const override + { + varray = varray_; + return true; + } + + bool may_have_ownership() const override + { + return varray_.may_have_ownership(); + } +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl_For_GSpan. + * \{ */ + +class GVArrayImpl_For_GSpan : public GVMutableArrayImpl { + protected: + void *data_ = nullptr; + const int64_t element_size_; + + public: + GVArrayImpl_For_GSpan(const GMutableSpan span); + + protected: + GVArrayImpl_For_GSpan(const CPPType &type, int64_t size); + + public: + void get(int64_t index, void *r_value) const override; + void get_to_uninitialized(int64_t index, void *r_value) const override; + + void set_by_copy(int64_t index, const void *value) override; + void set_by_move(int64_t index, void *value) override; + void set_by_relocate(int64_t index, void *value) override; + + bool is_span() const override; + GSpan get_internal_span() const override; +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \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); +} + +template +inline bool GVMutableArray::try_assign_VMutableArray(VMutableArray &varray) const +{ + BLI_assert(impl_->type().is()); + return this->get_impl()->try_assign_VMutableArray(&varray); +} + +inline GVMutableArrayImpl *GVMutableArray::get_impl() const +{ + return (GVMutableArrayImpl *)impl_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVArrayCommon. + * \{ */ + +template inline void GVArrayCommon::emplace(Args &&...args) +{ + static_assert(std::is_base_of_v); + if constexpr (std::is_copy_constructible_v && Storage::template is_inline_v) { + impl_ = &storage_.template emplace(std::forward(args)...); + } + else { + std::shared_ptr ptr = std::make_shared(std::forward(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); +} + +template inline T GVArrayCommon::get(const int64_t index) const +{ + BLI_assert(index >= 0); + BLI_assert(index < this->size()); + BLI_assert(this->type().is()); + T value{}; + impl_->get(index, &value); + return 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 inline bool GVArrayCommon::try_assign_VArray(VArray &varray) const +{ + BLI_assert(impl_->type().is()); + 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 inline GVArrayAnyExtraInfo GVArrayAnyExtraInfo::get() +{ + static_assert(std::is_base_of_v || + is_same_any_v>); + + if constexpr (std::is_base_of_v) { + return {[](const void *buffer) { + return static_cast((const StorageT *)buffer); + }}; + } + else if constexpr (std::is_same_v) { + return {[](const void *buffer) { return *(const StorageT *)buffer; }}; + } + else if constexpr (std::is_same_v>) { + return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }}; + } + else { + BLI_assert_unreachable(); + return {}; + } +} +} // namespace detail + +template inline GVArray GVArray::For(Args &&...args) +{ + static_assert(std::is_base_of_v); + GVArray varray; + varray.template emplace(std::forward(args)...); + return varray; +} + +template inline GVArray::GVArray(const VArray &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>(varray); + } + else if (varray.is_span()) { + Span 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(), varray.size(), &value); + } + else { + *this = GVArray::For>(varray); + } +} + +template inline VArray GVArray::typed() const +{ + if (!*this) { + return {}; + } + BLI_assert(impl_->type().is()); + VArray varray; + if (this->try_assign_VArray(varray)) { + return varray; + } + if (this->may_have_ownership()) { + return VArray::template For>(*this); + } + if (this->is_span()) { + const Span span = this->get_internal_span().typed(); + return VArray::ForSpan(span); + } + if (this->is_single()) { + T value; + this->get_internal_single(&value); + return VArray::ForSingle(value, this->size()); + } + return VArray::template For>(*this); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Inline methods for #GVMutableArray. + * \{ */ + +template +inline GVMutableArray GVMutableArray::For(Args &&...args) +{ + static_assert(std::is_base_of_v); + GVMutableArray varray; + varray.emplace(std::forward(args)...); + return varray; +} + +template inline GVMutableArray::GVMutableArray(const VMutableArray &varray) +{ + if (!varray) { + return; + } + if (varray.try_assign_GVMutableArray(*this)) { + return; + } + if (varray.may_have_ownership()) { + *this = GVMutableArray::For>(varray); + } + else if (varray.is_span()) { + MutableSpan data = varray.get_internal_span(); + *this = GVMutableArray::ForSpan(data); + } + else { + *this = GVMutableArray::For>(varray); + } +} + +template inline VMutableArray GVMutableArray::typed() const +{ + if (!*this) { + return {}; + } + BLI_assert(this->type().is()); + VMutableArray varray; + if (this->try_assign_VMutableArray(varray)) { + return varray; + } + if (this->may_have_ownership()) { + return VMutableArray::template For>(*this); + } + if (this->is_span()) { + const MutableSpan span = this->get_internal_span().typed(); + return VMutableArray::ForSpan(span); + } + return VMutableArray::template For>(*this); +} + +/** \} */ + +} // namespace blender diff --git a/source/blender/blenlib/BLI_generic_virtual_vector_array.hh b/source/blender/blenlib/BLI_generic_virtual_vector_array.hh new file mode 100644 index 00000000000..364b1ab33c7 --- /dev/null +++ b/source/blender/blenlib/BLI_generic_virtual_vector_array.hh @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup bli + * + * A generic virtual vector array is essentially the same as a virtual vector array, but its data + * type is only known at runtime. + */ + +#include "BLI_generic_virtual_array.hh" +#include "BLI_virtual_vector_array.hh" + +namespace blender { + +/* A generically typed version of `VVectorArray`. */ +class GVVectorArray { + protected: + const CPPType *type_; + int64_t size_; + + public: + GVVectorArray(const CPPType &type, const int64_t size) : type_(&type), size_(size) + { + } + + virtual ~GVVectorArray() = default; + + /* Returns the number of vectors in the vector array. */ + int64_t size() const + { + return size_; + } + + /* Returns true when there is no vector in the vector array. */ + bool is_empty() const + { + return size_ == 0; + } + + const CPPType &type() const + { + return *type_; + } + + /* Returns the size of the vector at the given index. */ + int64_t get_vector_size(const int64_t index) const + { + BLI_assert(index >= 0); + BLI_assert(index < size_); + return this->get_vector_size_impl(index); + } + + /* Copies an element from one of the vectors into `r_value`, which is expected to point to + * initialized memory. */ + void get_vector_element(const int64_t index, const int64_t index_in_vector, void *r_value) const + { + BLI_assert(index >= 0); + BLI_assert(index < size_); + BLI_assert(index_in_vector >= 0); + BLI_assert(index_in_vector < this->get_vector_size(index)); + this->get_vector_element_impl(index, index_in_vector, r_value); + } + + /* Returns true when the same vector is used at every index. */ + bool is_single_vector() const + { + if (size_ == 1) { + return true; + } + return this->is_single_vector_impl(); + } + + protected: + virtual int64_t get_vector_size_impl(int64_t index) const = 0; + + virtual void get_vector_element_impl(int64_t index, + int64_t index_in_vector, + void *r_value) const = 0; + + virtual bool is_single_vector_impl() const + { + return false; + } +}; + +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) + : GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)), + vector_array_(vector_array), + index_(index) + { + } + + protected: + void get(int64_t index_in_vector, void *r_value) const override; + void get_to_uninitialized(int64_t index_in_vector, void *r_value) const override; +}; + +class GVVectorArray_For_SingleGVArray : public GVVectorArray { + private: + GVArray varray_; + + public: + GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size) + : GVVectorArray(varray.type(), size), varray_(std::move(varray)) + { + } + + protected: + int64_t get_vector_size_impl(int64_t index) const override; + void get_vector_element_impl(int64_t index, + int64_t index_in_vector, + void *r_value) const override; + + bool is_single_vector_impl() const override; +}; + +class GVVectorArray_For_SingleGSpan : public GVVectorArray { + private: + const GSpan span_; + + public: + GVVectorArray_For_SingleGSpan(const GSpan span, const int64_t size) + : GVVectorArray(span.type(), size), span_(span) + { + } + + protected: + int64_t get_vector_size_impl(int64_t UNUSED(index)) const override; + void get_vector_element_impl(int64_t UNUSED(index), + int64_t index_in_vector, + void *r_value) const override; + + bool is_single_vector_impl() const override; +}; + +template class VVectorArray_For_GVVectorArray : public VVectorArray { + private: + const GVVectorArray &vector_array_; + + public: + VVectorArray_For_GVVectorArray(const GVVectorArray &vector_array) + : VVectorArray(vector_array.size()), vector_array_(vector_array) + { + } + + protected: + int64_t get_vector_size_impl(const int64_t index) const override + { + return vector_array_.get_vector_size(index); + } + + T get_vector_element_impl(const int64_t index, const int64_t index_in_vector) const override + { + T value; + vector_array_.get_vector_element(index, index_in_vector, &value); + return value; + } + + bool is_single_vector_impl() const override + { + return vector_array_.is_single_vector(); + } +}; + +} // namespace blender diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 16fd706c99d..3aa25bf6819 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -31,10 +31,8 @@ namespace blender { /** 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 @@ -154,7 +152,7 @@ template class VArrayImpl { * 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 + virtual bool try_assign_GVArray(GVArray &UNUSED(varray)) const { return false; } @@ -211,7 +209,7 @@ template class VMutableArrayImpl : public VArrayImpl { /** * Similar to #VArrayImpl::try_assign_GVArray but for mutable virtual arrays. */ - virtual bool try_assign_GVMutableArray(fn::GVMutableArray &UNUSED(varray)) const + virtual bool try_assign_GVMutableArray(GVMutableArray &UNUSED(varray)) const { return false; } @@ -743,7 +741,7 @@ template class VArrayCommon { } /** See #GVArrayImpl::try_assign_GVArray. */ - bool try_assign_GVArray(fn::GVArray &varray) const + bool try_assign_GVArray(GVArray &varray) const { return impl_->try_assign_GVArray(varray); } @@ -960,7 +958,7 @@ template class VMutableArray : public VArrayCommon { } /** See #GVMutableArrayImpl::try_assign_GVMutableArray. */ - bool try_assign_GVMutableArray(fn::GVMutableArray &varray) const + bool try_assign_GVMutableArray(GVMutableArray &varray) const { return this->get_impl()->try_assign_GVMutableArray(varray); } diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 057d94a6f39..6c216f873de 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -65,6 +65,9 @@ set(SRC intern/filereader_memory.c intern/filereader_zstd.c intern/fnmatch.c + intern/generic_vector_array.cc + intern/generic_virtual_array.cc + intern/generic_virtual_vector_array.cc intern/gsqueue.c intern/hash_md5.c intern/hash_mm2a.c @@ -195,6 +198,13 @@ set(SRC BLI_float4x4.hh BLI_fnmatch.h BLI_function_ref.hh + BLI_generic_array.hh + BLI_generic_pointer.hh + BLI_generic_span.hh + BLI_generic_value_map.hh + BLI_generic_vector_array.hh + BLI_generic_virtual_array.hh + BLI_generic_virtual_vector_array.hh BLI_ghash.h BLI_gsqueue.h BLI_hash.h @@ -413,6 +423,9 @@ if(WITH_GTESTS) tests/BLI_expr_pylike_eval_test.cc tests/BLI_fileops_test.cc tests/BLI_function_ref_test.cc + tests/BLI_generic_array_test.cc + tests/BLI_generic_span_test.cc + tests/BLI_generic_vector_array_test.cc tests/BLI_ghash_test.cc tests/BLI_hash_mm2a_test.cc tests/BLI_heap_simple_test.cc diff --git a/source/blender/blenlib/intern/generic_vector_array.cc b/source/blender/blenlib/intern/generic_vector_array.cc new file mode 100644 index 00000000000..b32236bfada --- /dev/null +++ b/source/blender/blenlib/intern/generic_vector_array.cc @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_generic_vector_array.hh" + +namespace blender { + +GVectorArray::GVectorArray(const CPPType &type, const int64_t array_size) + : type_(type), element_size_(type.size()), items_(array_size) +{ +} + +GVectorArray::~GVectorArray() +{ + if (type_.is_trivially_destructible()) { + return; + } + for (Item &item : items_) { + type_.destruct_n(item.start, item.length); + } +} + +void GVectorArray::append(const int64_t index, const void *value) +{ + Item &item = items_[index]; + if (item.length == item.capacity) { + this->realloc_to_at_least(item, item.capacity + 1); + } + + void *dst = POINTER_OFFSET(item.start, element_size_ * item.length); + type_.copy_construct(value, dst); + item.length++; +} + +void GVectorArray::extend(const int64_t index, const GVArray &values) +{ + BLI_assert(values.type() == type_); + for (const int i : IndexRange(values.size())) { + BUFFER_FOR_CPP_TYPE_VALUE(type_, buffer); + values.get(i, buffer); + this->append(index, buffer); + type_.destruct(buffer); + } +} + +void GVectorArray::extend(const int64_t index, const GSpan values) +{ + 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, GVArray(&array)); + } +} + +void GVectorArray::extend(IndexMask mask, const GVectorArray &values) +{ + GVVectorArray_For_GVectorArray virtual_values{values}; + this->extend(mask, virtual_values); +} + +void GVectorArray::clear(IndexMask mask) +{ + for (const int64_t i : mask) { + Item &item = items_[i]; + type_.destruct_n(item.start, item.length); + item.length = 0; + } +} + +GMutableSpan GVectorArray::operator[](const int64_t index) +{ + Item &item = items_[index]; + return GMutableSpan{type_, item.start, item.length}; +} + +GSpan GVectorArray::operator[](const int64_t index) const +{ + const Item &item = items_[index]; + return GSpan{type_, item.start, item.length}; +} + +void GVectorArray::realloc_to_at_least(Item &item, int64_t min_capacity) +{ + const int64_t new_capacity = std::max(min_capacity, item.length * 2); + + void *new_buffer = allocator_.allocate(element_size_ * new_capacity, type_.alignment()); + type_.relocate_assign_n(item.start, new_buffer, item.length); + + item.start = new_buffer; + item.capacity = new_capacity; +} + +} // namespace blender diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc new file mode 100644 index 00000000000..c6abf3624e1 --- /dev/null +++ b/source/blender/blenlib/intern/generic_virtual_array.cc @@ -0,0 +1,724 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_generic_virtual_array.hh" + +namespace blender { + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl + * \{ */ + +void GVArrayImpl::materialize(const IndexMask mask, void *dst) const +{ + for (const int64_t i : mask) { + void *elem_dst = POINTER_OFFSET(dst, type_->size() * i); + this->get(i, elem_dst); + } +} + +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); + this->get_to_uninitialized(i, elem_dst); + } +} + +void GVArrayImpl::get(const int64_t index, void *r_value) const +{ + type_->destruct(r_value); + this->get_to_uninitialized(index, r_value); +} + +bool GVArrayImpl::is_span() const +{ + return false; +} + +GSpan GVArrayImpl::get_internal_span() const +{ + BLI_assert(false); + return GSpan(*type_); +} + +bool GVArrayImpl::is_single() const +{ + return false; +} + +void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const +{ + BLI_assert(false); +} + +bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const +{ + return false; +} + +bool GVArrayImpl::may_have_ownership() const +{ + /* 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 #GVMutableArrayImpl + * \{ */ + +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(index, buffer); + type_->destruct(buffer); +} + +void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value) +{ + this->set_by_move(index, value); + type_->destruct(value); +} + +void GVMutableArrayImpl::set_all(const void *src) +{ + if (this->is_span()) { + const GSpan span = this->get_internal_span(); + type_->copy_assign_n(src, const_cast(span.data()), size_); + } + else { + for (int64_t i : IndexRange(size_)) { + this->set_by_copy(i, POINTER_OFFSET(src, type_->size() * i)); + } + } +} + +void GVMutableArray::fill(const void *value) +{ + if (this->is_span()) { + const GSpan span = this->get_internal_span(); + this->type().fill_assign_n(value, const_cast(span.data()), this->size()); + } + else { + 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 #GVArrayImpl_For_GSpan + * \{ */ + +GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GMutableSpan span) + : GVMutableArrayImpl(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) + : GVMutableArrayImpl(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 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); +} + +void GVArrayImpl_For_GSpan::set_by_copy(const int64_t index, const void *value) +{ + type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index)); +} + +void GVArrayImpl_For_GSpan::set_by_move(const int64_t index, void *value) +{ + type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index)); +} + +void GVArrayImpl_For_GSpan::set_by_relocate(const int64_t index, void *value) +{ + type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index)); +} + +bool GVArrayImpl_For_GSpan::is_span() const +{ + return true; +} + +GSpan GVArrayImpl_For_GSpan::get_internal_span() const +{ + return GSpan(*type_, data_, size_); +} + +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 #GVArrayImpl_For_SingleValueRef + * \{ */ + +/* 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; + + public: + GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value) + : GVArrayImpl(type, size), value_(value) + { + } + + protected: + GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size) + { + } + + 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 is_span() const override + { + return size_ == 1; + } + GSpan get_internal_span() const override + { + return GSpan{*type_, value_, 1}; + } + + 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 #GVArrayImpl_For_SingleValue + * \{ */ + +/* 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_); + } + + ~GVArrayImpl_For_SingleValue() override + { + type_->destruct((void *)value_); + MEM_freeN((void *)value_); + } +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl_For_SmallTrivialSingleValue + * \{ */ + +/** + * Contains an inline buffer that can store a single value of a trivial type. + * This avoids the allocation that would be done by #GVArrayImpl_For_SingleValue. + */ +template class GVArrayImpl_For_SmallTrivialSingleValue : public GVArrayImpl { + private: + AlignedBuffer buffer_; + + public: + GVArrayImpl_For_SmallTrivialSingleValue(const CPPType &type, + const int64_t size, + const void *value) + : GVArrayImpl(type, size) + { + BLI_assert(type.is_trivial()); + BLI_assert(type.alignment() <= 8); + BLI_assert(type.size() <= BufferSize); + type.copy_construct(value, &buffer_); + } + + private: + void get(const int64_t UNUSED(index), void *r_value) const override + { + this->copy_value_to(r_value); + } + void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override + { + this->copy_value_to(r_value); + } + + bool is_single() const override + { + return true; + } + void get_internal_single(void *r_value) const override + { + this->copy_value_to(r_value); + } + + void copy_value_to(void *dst) const + { + memcpy(dst, &buffer_, type_->size()); + } +}; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArray_GSpan + * \{ */ + +GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) +{ + size_ = varray_.size(); + if (varray_.is_span()) { + data_ = varray_.get_internal_span().data(); + } + else { + owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__); + varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_); + data_ = owned_data_; + } +} + +GVArray_GSpan::~GVArray_GSpan() +{ + if (owned_data_ != nullptr) { + type_->destruct_n(owned_data_, size_); + MEM_freeN(owned_data_); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVMutableArray_GSpan + * \{ */ + +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()) { + data_ = varray_.get_internal_span().data(); + } + else { + owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__); + if (copy_values_to_span) { + varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_); + } + else { + type_->default_construct_n(owned_data_, size_); + } + data_ = owned_data_; + } +} + +GVMutableArray_GSpan::~GVMutableArray_GSpan() +{ + if (show_not_saved_warning_) { + if (!save_has_been_called_) { + std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n"; + } + } + if (owned_data_ != nullptr) { + type_->destruct_n(owned_data_, size_); + MEM_freeN(owned_data_); + } +} + +void GVMutableArray_GSpan::save() +{ + save_has_been_called_ = true; + if (data_ != owned_data_) { + return; + } + const int64_t element_size = type_->size(); + for (int64_t i : IndexRange(size_)) { + varray_.set_by_copy(i, POINTER_OFFSET(owned_data_, element_size * i)); + } +} + +void GVMutableArray_GSpan::disable_not_applied_warning() +{ + show_not_saved_warning_ = false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name #GVArrayImpl_For_SlicedGVArray + * \{ */ + +class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl { + protected: + GVArray varray_; + int64_t offset_; + IndexRange slice_; + + public: + GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice) + : GVArrayImpl(varray.type(), slice.size()), + varray_(std::move(varray)), + offset_(slice.start()), + slice_(slice) + { + 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); + } + + bool is_span() const override + { + return varray_.is_span(); + } + GSpan get_internal_span() const override + { + return varray_.get_internal_span().slice(slice_); + } + + bool is_single() const override + { + return varray_.is_single(); + } + void get_internal_single(void *r_value) const override + { + varray_.get_internal_single(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 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; +} + +bool GVArrayCommon::is_span() const +{ + return impl_->is_span(); +} + +GSpan GVArrayCommon::get_internal_span() const +{ + BLI_assert(this->is_span()); + return impl_->get_internal_span(); +} + +bool GVArrayCommon::is_single() const +{ + return impl_->is_single(); +} + +void GVArrayCommon::get_internal_single(void *r_value) const +{ + BLI_assert(this->is_single()); + impl_->get_internal_single(r_value); +} + +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 + * \{ */ + +GVArray::GVArray(const GVArray &other) = default; + +GVArray::GVArray(GVArray &&other) noexcept = default; + +GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl) +{ +} + +GVArray::GVArray(std::shared_ptr impl) : GVArrayCommon(std::move(impl)) +{ +} + +GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value) +{ + if (type.is_trivial() && type.size() <= 16 && type.alignment() <= 8) { + return GVArray::For>(type, size, value); + } + return GVArray::For(type, size, value); +} + +GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value) +{ + return GVArray::For(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) +{ + /* Use const-cast because the underlying virtual array implementation is shared between const + * and non const data. */ + GMutableSpan mutable_span{span.type(), const_cast(span.data()), span.size()}; + return GVArray::For(mutable_span); +} + +class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan { + protected: + GArray<> array_; + + public: + GVArrayImpl_For_GArray(GArray<> array) + : GVArrayImpl_For_GSpan(array.as_mutable_span()), array_(std::move(array)) + { + } +}; + +GVArray GVArray::ForGArray(GArray<> array) +{ + return GVArray::For(array); +} + +GVArray GVArray::ForEmpty(const CPPType &type) +{ + return GVArray::ForSpan(GSpan(type)); +} + +GVArray GVArray::slice(IndexRange slice) const +{ + return GVArray::For(*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 impl) + : GVArrayCommon(std::move(impl)) +{ +} + +GVMutableArray GVMutableArray::ForSpan(GMutableSpan span) +{ + return GVMutableArray::For(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(); +} + +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(span.data()), span.size()); +} + +/** \} */ + +} // namespace blender diff --git a/source/blender/blenlib/intern/generic_virtual_vector_array.cc b/source/blender/blenlib/intern/generic_virtual_vector_array.cc new file mode 100644 index 00000000000..8fd1fb50b72 --- /dev/null +++ b/source/blender/blenlib/intern/generic_virtual_vector_array.cc @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "BLI_generic_virtual_vector_array.hh" + +namespace blender { + +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(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); +} + +int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const +{ + 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 +{ + varray_.get(index_in_vector, r_value); +} + +bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const +{ + return true; +} + +int64_t GVVectorArray_For_SingleGSpan::get_vector_size_impl(const int64_t UNUSED(index)) const +{ + return span_.size(); +} + +void GVVectorArray_For_SingleGSpan::get_vector_element_impl(const int64_t UNUSED(index), + const int64_t index_in_vector, + void *r_value) const +{ + type_->copy_assign(span_[index_in_vector], r_value); +} + +bool GVVectorArray_For_SingleGSpan::is_single_vector_impl() const +{ + return true; +} + +} // namespace blender diff --git a/source/blender/blenlib/tests/BLI_generic_array_test.cc b/source/blender/blenlib/tests/BLI_generic_array_test.cc new file mode 100644 index 00000000000..52bc7728a6a --- /dev/null +++ b/source/blender/blenlib/tests/BLI_generic_array_test.cc @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_array.hh" +#include "BLI_generic_array.hh" + +namespace blender::tests { + +TEST(generic_array, TypeConstructor) +{ + GArray array(CPPType::get()); + EXPECT_TRUE(array.data() == nullptr); + EXPECT_EQ(array.size(), 0); + EXPECT_EQ(array.as_span().typed().size(), 0); + EXPECT_TRUE(array.is_empty()); +} + +TEST(generic_array, MoveConstructor) +{ + GArray array_a(CPPType::get(), (int64_t)10); + GMutableSpan span_a = array_a.as_mutable_span(); + MutableSpan typed_span_a = span_a.typed(); + typed_span_a.fill(42); + + const GArray array_b = std::move(array_a); + Span typed_span_b = array_b.as_span().typed(); + EXPECT_FALSE(array_b.data() == nullptr); + EXPECT_EQ(array_b.size(), 10); + EXPECT_EQ(typed_span_b[4], 42); + + /* Make sure the copy constructor cleaned up the original, but it shouldn't clear the type. */ + EXPECT_TRUE(array_a.data() == nullptr); /* NOLINT: bugprone-use-after-move */ + EXPECT_EQ(array_a.size(), 0); /* NOLINT: bugprone-use-after-move */ + EXPECT_TRUE(array_a.is_empty()); /* NOLINT: bugprone-use-after-move */ + EXPECT_EQ(array_b.type(), array_a.type()); /* NOLINT: bugprone-use-after-move */ +} + +TEST(generic_array, CopyConstructor) +{ + GArray array_a(CPPType::get(), (int64_t)10); + GMutableSpan span_a = array_a.as_mutable_span(); + MutableSpan typed_span_a = span_a.typed(); + typed_span_a.fill(42); + + /* From span directly. */ + const GArray array_b = array_a.as_span(); + Span typed_span_b = array_b.as_span().typed(); + EXPECT_FALSE(array_b.data() == nullptr); + EXPECT_EQ(array_b.size(), 10); + EXPECT_EQ(typed_span_b[4], 42); + EXPECT_FALSE(array_a.is_empty()); + + /* From array. */ + const GArray array_c = array_a; + Span typed_span_c = array_c.as_span().typed(); + EXPECT_FALSE(array_c.data() == nullptr); + EXPECT_EQ(array_c.size(), 10); + EXPECT_EQ(typed_span_c[4], 42); + EXPECT_FALSE(array_a.is_empty()); +} + +TEST(generic_array, BufferAndSizeConstructor) +{ + int32_t *values = (int32_t *)MEM_malloc_arrayN(12, sizeof(int32_t), __func__); + void *buffer = (void *)values; + GArray array(CPPType::get(), buffer, 4); + EXPECT_FALSE(array.data() == nullptr); + EXPECT_EQ(array.size(), 4); + EXPECT_FALSE(array.is_empty()); + EXPECT_EQ(array.as_span().typed().size(), 4); + EXPECT_EQ(array[0], &values[0]); + EXPECT_EQ(array[1], &values[1]); + EXPECT_EQ(array[2], &values[2]); + EXPECT_EQ(array[3], &values[3]); +} + +TEST(generic_array, Reinitialize) +{ + GArray array(CPPType::get(), (int64_t)5); + EXPECT_FALSE(array.data() == nullptr); + GMutableSpan span = array.as_mutable_span(); + MutableSpan typed_span = span.typed(); + typed_span.fill(77); + EXPECT_FALSE(typed_span.data() == nullptr); + typed_span[2] = 8; + EXPECT_EQ(array[2], &typed_span[2]); + EXPECT_EQ(typed_span[0], 77); + EXPECT_EQ(typed_span[1], 77); + + array.reinitialize(10); + EXPECT_EQ(array.size(), 10); + span = array.as_mutable_span(); + EXPECT_EQ(span.size(), 10); + + typed_span = span.typed(); + EXPECT_FALSE(typed_span.data() == nullptr); + + array.reinitialize(0); + EXPECT_EQ(array.size(), 0); +} + +TEST(generic_array, InContainer) +{ + blender::Array> arrays; + for (GArray<> &array : arrays) { + array = GArray(CPPType::get(), (int64_t)5); + array.as_mutable_span().typed().fill(55); + } + for (GArray<> &array : arrays) { + EXPECT_EQ(array.as_span().typed()[3], 55); + } +} + +} // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_generic_span_test.cc b/source/blender/blenlib/tests/BLI_generic_span_test.cc new file mode 100644 index 00000000000..fe07a67d63b --- /dev/null +++ b/source/blender/blenlib/tests/BLI_generic_span_test.cc @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "BLI_generic_span.hh" + +namespace blender::tests { + +TEST(generic_span, TypeConstructor) +{ + GSpan span(CPPType::get()); + EXPECT_EQ(span.size(), 0); + EXPECT_EQ(span.typed().size(), 0); + EXPECT_TRUE(span.is_empty()); +} + +TEST(generic_span, BufferAndSizeConstructor) +{ + int values[4] = {6, 7, 3, 2}; + void *buffer = (void *)values; + GSpan span(CPPType::get(), buffer, 4); + EXPECT_EQ(span.size(), 4); + EXPECT_FALSE(span.is_empty()); + EXPECT_EQ(span.typed().size(), 4); + EXPECT_EQ(span[0], &values[0]); + EXPECT_EQ(span[1], &values[1]); + EXPECT_EQ(span[2], &values[2]); + EXPECT_EQ(span[3], &values[3]); +} + +TEST(generic_mutable_span, TypeConstructor) +{ + GMutableSpan span(CPPType::get()); + EXPECT_EQ(span.size(), 0); + EXPECT_TRUE(span.is_empty()); +} + +TEST(generic_mutable_span, BufferAndSizeConstructor) +{ + int values[4] = {4, 7, 3, 5}; + void *buffer = (void *)values; + GMutableSpan span(CPPType::get(), buffer, 4); + EXPECT_EQ(span.size(), 4); + EXPECT_FALSE(span.is_empty()); + EXPECT_EQ(span.typed().size(), 4); + EXPECT_EQ(values[2], 3); + *(int *)span[2] = 10; + EXPECT_EQ(values[2], 10); + span.typed()[2] = 20; + EXPECT_EQ(values[2], 20); +} + +} // namespace blender::tests diff --git a/source/blender/blenlib/tests/BLI_generic_vector_array_test.cc b/source/blender/blenlib/tests/BLI_generic_vector_array_test.cc new file mode 100644 index 00000000000..105f3603914 --- /dev/null +++ b/source/blender/blenlib/tests/BLI_generic_vector_array_test.cc @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "testing/testing.h" + +#include "BLI_generic_vector_array.hh" + +namespace blender::tests { + +TEST(generic_vector_array, Construct) +{ + GVectorArray vector_array{CPPType::get(), 4}; + EXPECT_EQ(vector_array.size(), 4); + EXPECT_FALSE(vector_array.is_empty()); +} + +TEST(generic_vector_array, Append) +{ + GVectorArray vector_array{CPPType::get(), 3}; + int value1 = 2; + vector_array.append(1, &value1); + vector_array.append(1, &value1); + int value2 = 3; + vector_array.append(0, &value2); + vector_array.append(1, &value2); + + EXPECT_EQ(vector_array[0].size(), 1); + EXPECT_EQ(vector_array[1].size(), 3); + EXPECT_EQ(vector_array[2].size(), 0); +} + +TEST(generic_vector_array, Extend) +{ + GVectorArray vector_array{CPPType::get(), 3}; + vector_array.extend(0, Span({1, 4, 6, 4})); + vector_array.extend(1, Span()); + vector_array.extend(0, Span({10, 20, 30})); + + EXPECT_EQ(vector_array[0].size(), 7); + EXPECT_EQ(vector_array[1].size(), 0); + EXPECT_EQ(vector_array[2].size(), 0); +} + +} // namespace blender::tests diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc index 28efc5be2e9..6225a68f53c 100644 --- a/source/blender/editors/geometry/geometry_attributes.cc +++ b/source/blender/editors/geometry/geometry_attributes.cc @@ -36,9 +36,6 @@ namespace blender::ed::geometry { -using fn::GArray; -using fn::GVArray; - /*********************** Attribute Operators ************************/ static bool geometry_attributes_poll(bContext *C) diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index b8d8335d47c..7f0c426922b 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -73,10 +73,10 @@ #include "node_intern.hh" /* own include */ +using blender::GPointer; using blender::fn::FieldCPPType; using blender::fn::FieldInput; using blender::fn::GField; -using blender::fn::GPointer; namespace geo_log = blender::nodes::geometry_nodes_eval_log; extern "C" { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh index f4d07255e2d..7cf9238d34e 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_column_values.hh @@ -4,10 +4,9 @@ #include "DNA_space_types.h" +#include "BLI_generic_virtual_array.hh" #include "BLI_string_ref.hh" -#include "FN_generic_virtual_array.hh" - namespace blender::ed::spreadsheet { struct CellDrawParams; @@ -22,10 +21,10 @@ class ColumnValues final { protected: std::string name_; - fn::GVArray data_; + GVArray data_; public: - ColumnValues(std::string name, fn::GVArray data) : name_(std::move(name)), data_(std::move(data)) + ColumnValues(std::string name, GVArray data) : name_(std::move(name)), data_(std::move(data)) { /* The array should not be empty. */ BLI_assert(data_); @@ -48,7 +47,7 @@ class ColumnValues final { return data_.size(); } - const fn::GVArray &data() const + const GVArray &data() const { return data_; } 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 3c94c466da1..0ad64db1b6d 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -53,11 +53,11 @@ void ExtraColumns::foreach_default_column_ids( std::unique_ptr ExtraColumns::get_column_values( const SpreadsheetColumnID &column_id) const { - const fn::GSpan *values = columns_.lookup_ptr(column_id.name); + const GSpan *values = columns_.lookup_ptr(column_id.name); if (values == nullptr) { return {}; } - return std::make_unique(column_id.name, fn::GVArray::ForSpan(*values)); + return std::make_unique(column_id.name, GVArray::ForSpan(*values)); } void GeometryDataSource::foreach_default_column_ids( @@ -199,7 +199,7 @@ std::unique_ptr GeometryDataSource::get_column_values( if (!attribute) { return {}; } - fn::GVArray varray = std::move(attribute.varray); + GVArray varray = std::move(attribute.varray); if (attribute.domain != domain_) { return {}; } @@ -462,7 +462,7 @@ static void find_fields_to_evaluate(const SpaceSpreadsheet *sspreadsheet, } if (const geo_log::GenericValueLog *generic_value_log = dynamic_cast(value_log)) { - fn::GPointer value = generic_value_log->value(); + GPointer value = generic_value_log->value(); r_fields.add("Viewer", fn::make_constant_field(*value.type(), value.get())); } } @@ -508,7 +508,7 @@ class GeometryComponentCacheValue : public SpreadsheetCache::Value { public: /* Stores the result of fields evaluated on a geometry component. Without this, fields would have * to be reevaluated on every redraw. */ - Map, fn::GArray<>> arrays; + Map, GArray<>> arrays; }; static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet, @@ -529,8 +529,8 @@ static void add_fields_as_extra_columns(SpaceSpreadsheet *sspreadsheet, const GField &field = item.value; /* Use the cached evaluated array if it exists, otherwise evaluate the field now. */ - fn::GArray<> &evaluated_array = cache.arrays.lookup_or_add_cb({domain, field}, [&]() { - fn::GArray<> evaluated_array(field.cpp_type(), domain_size); + GArray<> &evaluated_array = cache.arrays.lookup_or_add_cb({domain, field}, [&]() { + GArray<> evaluated_array(field.cpp_type(), domain_size); bke::GeometryComponentFieldContext field_context{component, domain}; fn::FieldEvaluator field_evaluator{field_context, domain_size}; diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh index 303f495e3df..8b281e5a558 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh @@ -21,10 +21,10 @@ namespace blender::ed::spreadsheet { class ExtraColumns { private: /** Maps column names to their data. The data is actually stored in the spreadsheet cache. */ - Map columns_; + Map columns_; public: - void add(std::string name, fn::GSpan data) + void add(std::string name, GSpan data) { columns_.add(std::move(name), data); } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc index 33fd7329e6d..db466f8ccf3 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc @@ -89,7 +89,7 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { return; } - const fn::GVArray &data = column.data(); + const GVArray &data = column.data(); if (data.type().is()) { const int value = data.get(real_index); diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc index 1fddd751d78..e45317c2a5c 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_row_filter.cc @@ -42,7 +42,7 @@ static void apply_row_filter(const SpreadsheetRowFilter &row_filter, Vector &new_indices) { const ColumnValues &column = *columns.lookup(row_filter.column_name); - const fn::GVArray &column_data = column.data(); + const GVArray &column_data = column.data(); if (column_data.type().is()) { const float value = row_filter.value_float; switch (row_filter.operation) { diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt index eef5b1e3ea6..f1298a7f5b7 100644 --- a/source/blender/functions/CMakeLists.txt +++ b/source/blender/functions/CMakeLists.txt @@ -13,9 +13,6 @@ set(INC_SYS set(SRC intern/cpp_types.cc intern/field.cc - intern/generic_vector_array.cc - intern/generic_virtual_array.cc - intern/generic_virtual_vector_array.cc intern/multi_function.cc intern/multi_function_builder.cc intern/multi_function_params.cc @@ -26,13 +23,6 @@ set(SRC FN_field.hh FN_field_cpp_type.hh - FN_generic_array.hh - FN_generic_pointer.hh - FN_generic_span.hh - FN_generic_value_map.hh - FN_generic_vector_array.hh - FN_generic_virtual_array.hh - FN_generic_virtual_vector_array.hh FN_multi_function.hh FN_multi_function_builder.hh FN_multi_function_context.hh @@ -71,9 +61,6 @@ blender_add_lib(bf_functions "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") if(WITH_GTESTS) set(TEST_SRC tests/FN_field_test.cc - tests/FN_generic_array_test.cc - tests/FN_generic_span_test.cc - tests/FN_generic_vector_array_test.cc tests/FN_multi_function_procedure_test.cc tests/FN_multi_function_test.cc diff --git a/source/blender/functions/FN_field.hh b/source/blender/functions/FN_field.hh index 957b395e633..5a27cda0787 100644 --- a/source/blender/functions/FN_field.hh +++ b/source/blender/functions/FN_field.hh @@ -33,11 +33,11 @@ */ #include "BLI_function_ref.hh" +#include "BLI_generic_virtual_array.hh" #include "BLI_string_ref.hh" #include "BLI_vector.hh" #include "BLI_vector_set.hh" -#include "FN_generic_virtual_array.hh" #include "FN_multi_function_builder.hh" namespace blender::fn { diff --git a/source/blender/functions/FN_generic_array.hh b/source/blender/functions/FN_generic_array.hh deleted file mode 100644 index c5388d27585..00000000000 --- a/source/blender/functions/FN_generic_array.hh +++ /dev/null @@ -1,256 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup fn - * - * This is a generic counterpart to #blender::Array, used when the type is not known at runtime. - * - * `GArray` should generally only be used for passing data around in dynamic contexts. - * It does not support a few things that #blender::Array supports: - * - Small object optimization / inline buffer. - * - Exception safety and various more specific constructors. - */ - -#include "BLI_allocator.hh" -#include "BLI_cpp_type.hh" - -#include "FN_generic_span.hh" - -namespace blender::fn { - -template< - /** - * The allocator used by this array. Should rarely be changed, except when you don't want that - * MEM_* functions are used internally. - */ - typename Allocator = GuardedAllocator> -class GArray { - protected: - /** The type of the data in the array, will be null after the array is default constructed, - * but a value should be assigned before any other interaction with the array. */ - const CPPType *type_ = nullptr; - void *data_ = nullptr; - int64_t size_ = 0; - - Allocator allocator_; - - public: - /** - * The default constructor creates an empty array, the only situation in which the type is - * allowed to be null. This default constructor exists so `GArray` can be used in containers, - * but the type should be supplied before doing anything else to the array. - */ - GArray(Allocator allocator = {}) noexcept : allocator_(allocator) - { - } - - GArray(NoExceptConstructor, Allocator allocator = {}) noexcept : GArray(allocator) - { - } - - /** - * Create and allocate a new array, with elements default constructed - * (which does not do anything for trivial types). - */ - GArray(const CPPType &type, int64_t size, Allocator allocator = {}) : GArray(type, allocator) - { - BLI_assert(size >= 0); - size_ = size; - data_ = this->allocate(size_); - type_->default_construct_n(data_, size_); - } - - /** - * Create an empty array with just a type. - */ - GArray(const CPPType &type, Allocator allocator = {}) : GArray(allocator) - { - type_ = &type; - } - - /** - * Take ownership of a buffer with a provided size. The buffer should be - * allocated with the same allocator provided to the constructor. - */ - GArray(const CPPType &type, void *buffer, int64_t size, Allocator allocator = {}) - : GArray(type, allocator) - { - BLI_assert(size >= 0); - BLI_assert(buffer != nullptr || size == 0); - BLI_assert(type_->pointer_has_valid_alignment(buffer)); - - data_ = buffer; - size_ = size; - } - - /** - * Create an array by copying values from a generic span. - */ - GArray(const GSpan span, Allocator allocator = {}) : GArray(span.type(), span.size(), allocator) - { - if (span.data() != nullptr) { - BLI_assert(span.size() != 0); - /* Use copy assign rather than construct since the memory is already initialized. */ - type_->copy_assign_n(span.data(), data_, size_); - } - } - - /** - * Create an array by copying values from another generic array. - */ - GArray(const GArray &other) : GArray(other.as_span(), other.allocator()) - { - } - - /** - * Create an array by taking ownership of another array's data, clearing the data in the other. - */ - GArray(GArray &&other) : GArray(other.type(), other.data(), other.size(), other.allocator()) - { - other.data_ = nullptr; - other.size_ = 0; - } - - ~GArray() - { - if (data_ != nullptr) { - type_->destruct_n(data_, size_); - this->deallocate(data_); - } - } - - GArray &operator=(const GArray &other) - { - return copy_assign_container(*this, other); - } - - GArray &operator=(GArray &&other) - { - return move_assign_container(*this, std::move(other)); - } - - const CPPType &type() const - { - BLI_assert(type_ != nullptr); - return *type_; - } - - bool is_empty() const - { - return size_ == 0; - } - - /** - * Return the number of elements in the array (not the size in bytes). - */ - int64_t size() const - { - return size_; - } - - /** - * Get a pointer to the beginning of the array. - */ - const void *data() const - { - return data_; - } - void *data() - { - return data_; - } - - const void *operator[](int64_t index) const - { - BLI_assert(index < size_); - return POINTER_OFFSET(data_, type_->size() * index); - } - - void *operator[](int64_t index) - { - BLI_assert(index < size_); - return POINTER_OFFSET(data_, type_->size() * index); - } - - operator GSpan() const - { - BLI_assert(type_ != nullptr); - return GSpan(*type_, data_, size_); - } - - operator GMutableSpan() - { - BLI_assert(type_ != nullptr); - return GMutableSpan(*type_, data_, size_); - } - - GSpan as_span() const - { - return *this; - } - - GMutableSpan as_mutable_span() - { - return *this; - } - - /** - * Access the allocator used by this array. - */ - Allocator &allocator() - { - return allocator_; - } - const Allocator &allocator() const - { - return allocator_; - } - - /** - * Destruct values and create a new array of the given size. The values in the new array are - * default constructed. - */ - void reinitialize(const int64_t new_size) - { - BLI_assert(new_size >= 0); - int64_t old_size = size_; - - type_->destruct_n(data_, size_); - size_ = 0; - - if (new_size <= old_size) { - type_->default_construct_n(data_, new_size); - } - else { - void *new_data = this->allocate(new_size); - try { - type_->default_construct_n(new_data, new_size); - } - catch (...) { - this->deallocate(new_data); - throw; - } - this->deallocate(data_); - data_ = new_data; - } - - size_ = new_size; - } - - private: - void *allocate(int64_t size) - { - const int64_t item_size = type_->size(); - const int64_t alignment = type_->alignment(); - return allocator_.allocate(static_cast(size) * item_size, alignment, AT); - } - - void deallocate(void *ptr) - { - allocator_.deallocate(ptr); - } -}; - -} // namespace blender::fn diff --git a/source/blender/functions/FN_generic_pointer.hh b/source/blender/functions/FN_generic_pointer.hh deleted file mode 100644 index 382d882e3f7..00000000000 --- a/source/blender/functions/FN_generic_pointer.hh +++ /dev/null @@ -1,123 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -#include "BLI_cpp_type.hh" - -namespace blender::fn { - -/** - * A generic non-const pointer whose type is only known at runtime. - */ -class GMutablePointer { - private: - const CPPType *type_ = nullptr; - void *data_ = nullptr; - - public: - GMutablePointer() = default; - - GMutablePointer(const CPPType *type, void *data = nullptr) : type_(type), data_(data) - { - /* If there is data, there has to be a type. */ - BLI_assert(data_ == nullptr || type_ != nullptr); - } - - GMutablePointer(const CPPType &type, void *data = nullptr) : GMutablePointer(&type, data) - { - } - - template GMutablePointer(T *data) : GMutablePointer(&CPPType::get(), data) - { - } - - void *get() const - { - return data_; - } - - const CPPType *type() const - { - return type_; - } - - template T *get() const - { - BLI_assert(this->is_type()); - return static_cast(data_); - } - - template bool is_type() const - { - return type_ != nullptr && type_->is(); - } - - template T relocate_out() - { - BLI_assert(this->is_type()); - T value; - type_->relocate_assign(data_, &value); - data_ = nullptr; - type_ = nullptr; - return value; - } - - void destruct() - { - BLI_assert(data_ != nullptr); - type_->destruct(data_); - } -}; - -/** - * A generic const pointer whose type is only known at runtime. - */ -class GPointer { - private: - const CPPType *type_ = nullptr; - const void *data_ = nullptr; - - public: - GPointer() = default; - - GPointer(GMutablePointer ptr) : type_(ptr.type()), data_(ptr.get()) - { - } - - GPointer(const CPPType *type, const void *data = nullptr) : type_(type), data_(data) - { - /* If there is data, there has to be a type. */ - BLI_assert(data_ == nullptr || type_ != nullptr); - } - - GPointer(const CPPType &type, const void *data = nullptr) : type_(&type), data_(data) - { - } - - template GPointer(T *data) : GPointer(&CPPType::get(), data) - { - } - - const void *get() const - { - return data_; - } - - const CPPType *type() const - { - return type_; - } - - template const T *get() const - { - BLI_assert(this->is_type()); - return static_cast(data_); - } - - template bool is_type() const - { - return type_ != nullptr && type_->is(); - } -}; - -} // namespace blender::fn diff --git a/source/blender/functions/FN_generic_span.hh b/source/blender/functions/FN_generic_span.hh deleted file mode 100644 index c79cece138f..00000000000 --- a/source/blender/functions/FN_generic_span.hh +++ /dev/null @@ -1,169 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup fn - */ - -#include "BLI_cpp_type.hh" -#include "BLI_span.hh" - -namespace blender::fn { - -/** - * A generic span. It behaves just like a blender::Span, but the type is only known at run-time. - */ -class GSpan { - protected: - const CPPType *type_; - const void *data_; - int64_t size_; - - public: - GSpan(const CPPType &type, const void *buffer, int64_t size) - : type_(&type), data_(buffer), size_(size) - { - BLI_assert(size >= 0); - BLI_assert(buffer != nullptr || size == 0); - BLI_assert(type.pointer_has_valid_alignment(buffer)); - } - - GSpan(const CPPType &type) : GSpan(type, nullptr, 0) - { - } - - template - GSpan(Span array) - : GSpan(CPPType::get(), static_cast(array.data()), array.size()) - { - } - - const CPPType &type() const - { - return *type_; - } - - bool is_empty() const - { - return size_ == 0; - } - - int64_t size() const - { - return size_; - } - - const void *data() const - { - return data_; - } - - const void *operator[](int64_t index) const - { - BLI_assert(index < size_); - return POINTER_OFFSET(data_, type_->size() * index); - } - - template Span typed() const - { - BLI_assert(type_->is()); - return Span(static_cast(data_), size_); - } - - GSpan slice(const int64_t start, int64_t size) const - { - BLI_assert(start >= 0); - BLI_assert(size >= 0); - const int64_t new_size = std::max(0, std::min(size, size_ - start)); - return GSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size); - } - - GSpan slice(const IndexRange range) const - { - return this->slice(range.start(), range.size()); - } -}; - -/** - * A generic mutable span. It behaves just like a blender::MutableSpan, but the type is only - * known at run-time. - */ -class GMutableSpan { - protected: - const CPPType *type_; - void *data_; - int64_t size_; - - public: - GMutableSpan(const CPPType &type, void *buffer, int64_t size) - : type_(&type), data_(buffer), size_(size) - { - BLI_assert(size >= 0); - BLI_assert(buffer != nullptr || size == 0); - BLI_assert(type.pointer_has_valid_alignment(buffer)); - } - - GMutableSpan(const CPPType &type) : GMutableSpan(type, nullptr, 0) - { - } - - template - GMutableSpan(MutableSpan array) - : GMutableSpan(CPPType::get(), static_cast(array.begin()), array.size()) - { - } - - operator GSpan() const - { - return GSpan(*type_, data_, size_); - } - - const CPPType &type() const - { - return *type_; - } - - bool is_empty() const - { - return size_ == 0; - } - - int64_t size() const - { - return size_; - } - - void *data() const - { - return data_; - } - - void *operator[](int64_t index) const - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - return POINTER_OFFSET(data_, type_->size() * index); - } - - template MutableSpan typed() const - { - BLI_assert(type_->is()); - return MutableSpan(static_cast(data_), size_); - } - - GMutableSpan slice(const int64_t start, int64_t size) const - { - BLI_assert(start >= 0); - BLI_assert(size >= 0); - const int64_t new_size = std::max(0, std::min(size, size_ - start)); - return GMutableSpan(*type_, POINTER_OFFSET(data_, type_->size() * start), new_size); - } - - GMutableSpan slice(IndexRange range) const - { - return this->slice(range.start(), range.size()); - } -}; - -} // namespace blender::fn diff --git a/source/blender/functions/FN_generic_value_map.hh b/source/blender/functions/FN_generic_value_map.hh deleted file mode 100644 index 3807ada1c3c..00000000000 --- a/source/blender/functions/FN_generic_value_map.hh +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -#include "BLI_linear_allocator.hh" -#include "BLI_map.hh" - -#include "FN_generic_pointer.hh" - -namespace blender::fn { - -/** - * This is a map that stores key-value-pairs. What makes it special is that the type of values does - * not have to be known at compile time. There just has to be a corresponding CPPType. - */ -template class GValueMap { - private: - /* Used to allocate values owned by this container. */ - LinearAllocator<> &allocator_; - Map values_; - - public: - GValueMap(LinearAllocator<> &allocator) : allocator_(allocator) - { - } - - ~GValueMap() - { - /* Destruct all values that are still in the map. */ - for (GMutablePointer value : values_.values()) { - value.destruct(); - } - } - - /* Add a value to the container. The container becomes responsible for destructing the value that - * is passed in. The caller remains responsible for freeing the value after it has been - * destructed. */ - template void add_new_direct(ForwardKey &&key, GMutablePointer value) - { - values_.add_new_as(std::forward(key), value); - } - - /* Add a value to the container that is move constructed from the given value. The caller remains - * responsible for destructing and freeing the given value. */ - template void add_new_by_move(ForwardKey &&key, GMutablePointer value) - { - const CPPType &type = *value.type(); - void *buffer = allocator_.allocate(type.size(), type.alignment()); - type.move_construct(value.get(), buffer); - values_.add_new_as(std::forward(key), GMutablePointer{type, buffer}); - } - - /* Add a value to the container that is copy constructed from the given value. The caller remains - * responsible for destructing and freeing the given value. */ - template void add_new_by_copy(ForwardKey &&key, GPointer value) - { - const CPPType &type = *value.type(); - void *buffer = allocator_.allocate(type.size(), type.alignment()); - type.copy_construct(value.get(), buffer); - values_.add_new_as(std::forward(key), GMutablePointer{type, buffer}); - } - - /* Add a value to the container. */ - template void add_new(ForwardKey &&key, T &&value) - { - if constexpr (std::is_rvalue_reference_v) { - this->add_new_by_move(std::forward(key), &value); - } - else { - this->add_new_by_copy(std::forward(key), &value); - } - } - - /* Remove the value for the given name from the container and remove it. The caller is - * responsible for freeing it. The lifetime of the referenced memory might be bound to lifetime - * of the container. */ - template GMutablePointer extract(const ForwardKey &key) - { - return values_.pop_as(key); - } - - template GPointer lookup(const ForwardKey &key) const - { - return values_.lookup_as(key); - } - - /* Remove the value for the given name from the container and remove it. */ - template T extract(const ForwardKey &key) - { - GMutablePointer value = values_.pop_as(key); - const CPPType &type = *value.type(); - BLI_assert(type.is()); - T return_value; - type.relocate_assign(value.get(), &return_value); - return return_value; - } - - template const T &lookup(const ForwardKey &key) const - { - GMutablePointer value = values_.lookup_as(key); - BLI_assert(value.is_type()); - BLI_assert(value.get() != nullptr); - return *(const T *)value.get(); - } - - template bool contains(const ForwardKey &key) const - { - return values_.contains_as(key); - } -}; - -} // namespace blender::fn diff --git a/source/blender/functions/FN_generic_vector_array.hh b/source/blender/functions/FN_generic_vector_array.hh deleted file mode 100644 index d7416a0f5b9..00000000000 --- a/source/blender/functions/FN_generic_vector_array.hh +++ /dev/null @@ -1,148 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup fn - * - * A`GVectorArray` is a container for a fixed amount of dynamically growing vectors with a generic - * data type. Its main use case is to store many small vectors with few separate allocations. Using - * this structure is generally more efficient than allocating each vector separately. - */ - -#include "BLI_array.hh" -#include "BLI_linear_allocator.hh" - -#include "FN_generic_virtual_vector_array.hh" - -namespace blender::fn { - -/* An array of vectors containing elements of a generic type. */ -class GVectorArray : NonCopyable, NonMovable { - private: - struct Item { - void *start = nullptr; - int64_t length = 0; - int64_t capacity = 0; - }; - - /* Use a linear allocator to pack many small vectors together. Currently, memory from reallocated - * vectors is not reused. This can be improved in the future. */ - LinearAllocator<> allocator_; - /* The data type of individual elements. */ - const CPPType &type_; - /* The size of an individual element. This is inlined from `type_.size()` for easier access. */ - const int64_t element_size_; - /* The individual vectors. */ - Array items_; - - public: - GVectorArray() = delete; - - GVectorArray(const CPPType &type, int64_t array_size); - - ~GVectorArray(); - - int64_t size() const - { - return items_.size(); - } - - bool is_empty() const - { - return items_.is_empty(); - } - - const CPPType &type() const - { - return type_; - } - - void append(int64_t index, const void *value); - - /* Add multiple elements to a single vector. */ - void extend(int64_t index, const GVArray &values); - void extend(int64_t index, GSpan values); - - /* Add multiple elements to multiple vectors. */ - void extend(IndexMask mask, const GVVectorArray &values); - void extend(IndexMask mask, const GVectorArray &values); - - void clear(IndexMask mask); - - GMutableSpan operator[](int64_t index); - GSpan operator[](int64_t index) const; - - private: - void realloc_to_at_least(Item &item, int64_t min_capacity); -}; - -/* A non-owning typed mutable reference to an `GVectorArray`. It simplifies access when the type of - * the data is known at compile time. */ -template class GVectorArray_TypedMutableRef { - private: - GVectorArray *vector_array_; - - public: - GVectorArray_TypedMutableRef(GVectorArray &vector_array) : vector_array_(&vector_array) - { - BLI_assert(vector_array_->type().is()); - } - - int64_t size() const - { - return vector_array_->size(); - } - - bool is_empty() const - { - return vector_array_->is_empty(); - } - - void append(const int64_t index, const T &value) - { - vector_array_->append(index, &value); - } - - void extend(const int64_t index, const Span values) - { - vector_array_->extend(index, values); - } - - void extend(const int64_t index, const VArray &values) - { - vector_array_->extend(index, values); - } - - MutableSpan operator[](const int64_t index) - { - return (*vector_array_)[index].typed(); - } -}; - -/* A generic virtual vector array implementation for a `GVectorArray`. */ -class GVVectorArray_For_GVectorArray : public GVVectorArray { - private: - const GVectorArray &vector_array_; - - public: - GVVectorArray_For_GVectorArray(const GVectorArray &vector_array) - : GVVectorArray(vector_array.type(), vector_array.size()), vector_array_(vector_array) - { - } - - protected: - int64_t get_vector_size_impl(const int64_t index) const override - { - return vector_array_[index].size(); - } - - void get_vector_element_impl(const int64_t index, - const int64_t index_in_vector, - void *r_value) const override - { - type_->copy_assign(vector_array_[index][index_in_vector], r_value); - } -}; - -} // namespace blender::fn diff --git a/source/blender/functions/FN_generic_virtual_array.hh b/source/blender/functions/FN_generic_virtual_array.hh deleted file mode 100644 index ced0c2b9546..00000000000 --- a/source/blender/functions/FN_generic_virtual_array.hh +++ /dev/null @@ -1,878 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup fn - * - * A generic virtual array is the same as a virtual array from blenlib, except for the fact that - * the data type is only known at runtime. - */ - -#include "BLI_timeit.hh" -#include "BLI_virtual_array.hh" - -#include "FN_generic_array.hh" -#include "FN_generic_span.hh" - -namespace blender::fn { - -/* -------------------------------------------------------------------- */ -/** \name #GVArrayImpl and #GVMutableArrayImpl. - * \{ */ - -class GVArray; -class GVArrayImpl; -class GVMutableArray; -class GVMutableArrayImpl; - -/* A generically typed version of #VArrayImpl. */ -class GVArrayImpl { - protected: - const CPPType *type_; - int64_t size_; - - public: - GVArrayImpl(const CPPType &type, int64_t size); - virtual ~GVArrayImpl() = default; - - const CPPType &type() const; - - int64_t size() const; - - virtual void get(int64_t index, void *r_value) const; - virtual void get_to_uninitialized(int64_t index, void *r_value) const = 0; - - virtual bool is_span() const; - virtual GSpan get_internal_span() const; - - virtual bool is_single() const; - virtual void get_internal_single(void *UNUSED(r_value)) const; - - virtual void materialize(const IndexMask mask, void *dst) const; - virtual void materialize_to_uninitialized(const IndexMask mask, void *dst) const; - - virtual bool try_assign_VArray(void *varray) const; - virtual bool may_have_ownership() const; -}; - -/* A generic version of #VMutableArrayImpl. */ -class GVMutableArrayImpl : public GVArrayImpl { - public: - GVMutableArrayImpl(const CPPType &type, int64_t size); - - virtual void set_by_copy(int64_t index, const void *value); - virtual void set_by_relocate(int64_t index, void *value); - virtual void set_by_move(int64_t index, void *value) = 0; - - virtual void set_all(const void *src); - - virtual bool try_assign_VMutableArray(void *varray) const; -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVArray and #GVMutableArray - * \{ */ - -namespace detail { -struct GVArrayAnyExtraInfo { - const GVArrayImpl *(*get_varray)(const void *buffer) = - [](const void *UNUSED(buffer)) -> const GVArrayImpl * { return nullptr; }; - - template static GVArrayAnyExtraInfo get(); -}; -} // namespace detail - -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: - /** - * 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; - - const GVArrayImpl *impl_ = nullptr; - Storage storage_; - - protected: - GVArrayCommon(); - GVArrayCommon(const GVArrayCommon &other); - GVArrayCommon(GVArrayCommon &&other) noexcept; - GVArrayCommon(const GVArrayImpl *impl); - GVArrayCommon(std::shared_ptr impl); - ~GVArrayCommon(); - - template void emplace(Args &&...args); - - void copy_from(const GVArrayCommon &other); - void move_from(GVArrayCommon &&other) noexcept; - - const GVArrayImpl *impl_from_storage() const; - - public: - const CPPType &type() const; - operator bool() const; - - int64_t size() const; - bool is_empty() const; - IndexRange index_range() const; - - template bool try_assign_VArray(VArray &varray) const; - bool may_have_ownership() 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; - - /** - * Returns true when the virtual array is stored as a span internally. - */ - bool is_span() const; - /** - * Returns the internally used span of the virtual array. This invokes undefined behavior if the - * virtual array is not stored as a span internally. - */ - GSpan get_internal_span() const; - - /** - * Returns true when the virtual array returns the same value for every index. - */ - bool is_single() const; - /** - * 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; - /** - * Same as `get_internal_single`, but `r_value` points to initialized memory. - */ - void get_internal_single_to_uninitialized(void *r_value) const; - - void get(int64_t index, void *r_value) const; - /** - * Returns a copy of the value at the given index. Usually a typed virtual array should - * be used instead, but sometimes this is simpler when only a few indices are needed. - */ - template T get(int64_t index) const; - void get_to_uninitialized(int64_t index, void *r_value) const; -}; - -/** Generic version of #VArray. */ -class GVArray : public GVArrayCommon { - private: - friend GVMutableArray; - - public: - GVArray() = default; - - GVArray(const GVArray &other); - GVArray(GVArray &&other) noexcept; - GVArray(const GVArrayImpl *impl); - GVArray(std::shared_ptr impl); - - template GVArray(const VArray &varray); - template VArray typed() const; - - template static GVArray For(Args &&...args); - - static GVArray ForSingle(const CPPType &type, int64_t size, const void *value); - static GVArray ForSingleRef(const CPPType &type, int64_t size, const void *value); - static GVArray ForSingleDefault(const CPPType &type, int64_t size); - static GVArray ForSpan(GSpan span); - static GVArray ForGArray(GArray<> array); - static GVArray ForEmpty(const CPPType &type); - - GVArray slice(IndexRange slice) const; - - GVArray &operator=(const GVArray &other); - GVArray &operator=(GVArray &&other) noexcept; - - const GVArrayImpl *get_implementation() const - { - return impl_; - } -}; - -/** Generic version of #VMutableArray. */ -class GVMutableArray : public GVArrayCommon { - public: - GVMutableArray() = default; - GVMutableArray(const GVMutableArray &other); - GVMutableArray(GVMutableArray &&other) noexcept; - GVMutableArray(GVMutableArrayImpl *impl); - GVMutableArray(std::shared_ptr impl); - - template GVMutableArray(const VMutableArray &varray); - template VMutableArray typed() const; - - template static GVMutableArray For(Args &&...args); - - static GVMutableArray ForSpan(GMutableSpan span); - - operator GVArray() const &; - operator GVArray() &&noexcept; - - GVMutableArray &operator=(const GVMutableArray &other); - GVMutableArray &operator=(GVMutableArray &&other) noexcept; - - GMutableSpan get_internal_span() const; - - template bool try_assign_VMutableArray(VMutableArray &varray) const; - - void set_by_copy(int64_t index, const void *value); - void set_by_move(int64_t index, void *value); - void set_by_relocate(int64_t index, void *value); - - void fill(const void *value); - /** - * Copy the values from the source buffer to all elements in the virtual array. - */ - void set_all(const void *src); - - GVMutableArrayImpl *get_implementation() const; - - private: - GVMutableArrayImpl *get_impl() const; -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \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(); -}; - -/* 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(); -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Conversions between generic and typed virtual arrays. - * \{ */ - -/* Used to convert a typed virtual array into a generic one. */ -template class GVArrayImpl_For_VArray : public GVArrayImpl { - protected: - VArray varray_; - - public: - GVArrayImpl_For_VArray(VArray varray) - : GVArrayImpl(CPPType::get(), varray.size()), varray_(std::move(varray)) - { - } - - protected: - void get(const int64_t index, void *r_value) const override - { - *(T *)r_value = varray_[index]; - } - - void get_to_uninitialized(const int64_t index, void *r_value) const override - { - new (r_value) T(varray_[index]); - } - - bool is_span() const override - { - return varray_.is_span(); - } - - GSpan get_internal_span() const override - { - return GSpan(varray_.get_internal_span()); - } - - bool is_single() const override - { - return varray_.is_single(); - } - - void get_internal_single(void *r_value) const override - { - *(T *)r_value = varray_.get_internal_single(); - } - - void materialize(const IndexMask mask, void *dst) const override - { - varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); - } - - void materialize_to_uninitialized(const IndexMask mask, void *dst) const override - { - varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); - } - - bool try_assign_VArray(void *varray) const override - { - *(VArray *)varray = varray_; - return true; - } - - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } -}; - -/* Used to convert any generic virtual array into a typed one. */ -template class VArrayImpl_For_GVArray : public VArrayImpl { - protected: - GVArray varray_; - - public: - VArrayImpl_For_GVArray(GVArray varray) : VArrayImpl(varray.size()), varray_(std::move(varray)) - { - BLI_assert(varray_); - BLI_assert(varray_.type().template is()); - } - - protected: - T get(const int64_t index) const override - { - T value; - varray_.get(index, &value); - return value; - } - - bool is_span() const override - { - return varray_.is_span(); - } - - Span get_internal_span() const override - { - return varray_.get_internal_span().template typed(); - } - - bool is_single() const override - { - return varray_.is_single(); - } - - T get_internal_single() const override - { - T value; - varray_.get_internal_single(&value); - return value; - } - - bool try_assign_GVArray(GVArray &varray) const override - { - varray = varray_; - return true; - } - - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } -}; - -/* Used to convert any typed virtual mutable array into a generic one. */ -template class GVMutableArrayImpl_For_VMutableArray : public GVMutableArrayImpl { - protected: - VMutableArray varray_; - - public: - GVMutableArrayImpl_For_VMutableArray(VMutableArray varray) - : GVMutableArrayImpl(CPPType::get(), varray.size()), varray_(std::move(varray)) - { - } - - protected: - void get(const int64_t index, void *r_value) const override - { - *(T *)r_value = varray_[index]; - } - - void get_to_uninitialized(const int64_t index, void *r_value) const override - { - new (r_value) T(varray_[index]); - } - - bool is_span() const override - { - return varray_.is_span(); - } - - GSpan get_internal_span() const override - { - Span span = varray_.get_internal_span(); - return span; - } - - bool is_single() const override - { - return varray_.is_single(); - } - - void get_internal_single(void *r_value) const override - { - *(T *)r_value = varray_.get_internal_single(); - } - - void set_by_copy(const int64_t index, const void *value) override - { - const T &value_ = *(const T *)value; - varray_.set(index, value_); - } - - void set_by_relocate(const int64_t index, void *value) override - { - T &value_ = *(T *)value; - varray_.set(index, std::move(value_)); - value_.~T(); - } - - void set_by_move(const int64_t index, void *value) override - { - T &value_ = *(T *)value; - varray_.set(index, std::move(value_)); - } - - void set_all(const void *src) override - { - varray_.set_all(Span((T *)src, size_)); - } - - void materialize(const IndexMask mask, void *dst) const override - { - varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); - } - - void materialize_to_uninitialized(const IndexMask mask, void *dst) const override - { - varray_.materialize_to_uninitialized(mask, MutableSpan((T *)dst, mask.min_array_size())); - } - - bool try_assign_VArray(void *varray) const override - { - *(VArray *)varray = varray_; - return true; - } - - bool try_assign_VMutableArray(void *varray) const override - { - *(VMutableArray *)varray = varray_; - return true; - } - - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } -}; - -/* Used to convert an generic mutable virtual array into a typed one. */ -template class VMutableArrayImpl_For_GVMutableArray : public VMutableArrayImpl { - protected: - GVMutableArray varray_; - - public: - VMutableArrayImpl_For_GVMutableArray(GVMutableArray varray) - : VMutableArrayImpl(varray.size()), varray_(varray) - { - BLI_assert(varray_); - BLI_assert(varray_.type().template is()); - } - - private: - T get(const int64_t index) const override - { - T value; - varray_.get(index, &value); - return value; - } - - void set(const int64_t index, T value) override - { - varray_.set_by_relocate(index, &value); - } - - bool is_span() const override - { - return varray_.is_span(); - } - - Span get_internal_span() const override - { - return varray_.get_internal_span().template typed(); - } - - bool is_single() const override - { - return varray_.is_single(); - } - - T get_internal_single() const override - { - T value; - varray_.get_internal_single(&value); - return value; - } - - bool try_assign_GVArray(GVArray &varray) const override - { - varray = varray_; - return true; - } - - bool try_assign_GVMutableArray(GVMutableArray &varray) const override - { - varray = varray_; - return true; - } - - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVArrayImpl_For_GSpan. - * \{ */ - -class GVArrayImpl_For_GSpan : public GVMutableArrayImpl { - protected: - void *data_ = nullptr; - const int64_t element_size_; - - public: - GVArrayImpl_For_GSpan(const GMutableSpan span); - - protected: - GVArrayImpl_For_GSpan(const CPPType &type, int64_t size); - - public: - void get(int64_t index, void *r_value) const override; - void get_to_uninitialized(int64_t index, void *r_value) const override; - - void set_by_copy(int64_t index, const void *value) override; - void set_by_move(int64_t index, void *value) override; - void set_by_relocate(int64_t index, void *value) override; - - bool is_span() const override; - GSpan get_internal_span() const override; -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \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); -} - -template -inline bool GVMutableArray::try_assign_VMutableArray(VMutableArray &varray) const -{ - BLI_assert(impl_->type().is()); - return this->get_impl()->try_assign_VMutableArray(&varray); -} - -inline GVMutableArrayImpl *GVMutableArray::get_impl() const -{ - return (GVMutableArrayImpl *)impl_; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Inline methods for #GVArrayCommon. - * \{ */ - -template inline void GVArrayCommon::emplace(Args &&...args) -{ - static_assert(std::is_base_of_v); - if constexpr (std::is_copy_constructible_v && Storage::template is_inline_v) { - impl_ = &storage_.template emplace(std::forward(args)...); - } - else { - std::shared_ptr ptr = std::make_shared(std::forward(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); -} - -template inline T GVArrayCommon::get(const int64_t index) const -{ - BLI_assert(index >= 0); - BLI_assert(index < this->size()); - BLI_assert(this->type().is()); - T value{}; - impl_->get(index, &value); - return 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 inline bool GVArrayCommon::try_assign_VArray(VArray &varray) const -{ - BLI_assert(impl_->type().is()); - 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 inline GVArrayAnyExtraInfo GVArrayAnyExtraInfo::get() -{ - static_assert(std::is_base_of_v || - is_same_any_v>); - - if constexpr (std::is_base_of_v) { - return {[](const void *buffer) { - return static_cast((const StorageT *)buffer); - }}; - } - else if constexpr (std::is_same_v) { - return {[](const void *buffer) { return *(const StorageT *)buffer; }}; - } - else if constexpr (std::is_same_v>) { - return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }}; - } - else { - BLI_assert_unreachable(); - return {}; - } -} -} // namespace detail - -template inline GVArray GVArray::For(Args &&...args) -{ - static_assert(std::is_base_of_v); - GVArray varray; - varray.template emplace(std::forward(args)...); - return varray; -} - -template inline GVArray::GVArray(const VArray &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>(varray); - } - else if (varray.is_span()) { - Span 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(), varray.size(), &value); - } - else { - *this = GVArray::For>(varray); - } -} - -template inline VArray GVArray::typed() const -{ - if (!*this) { - return {}; - } - BLI_assert(impl_->type().is()); - VArray varray; - if (this->try_assign_VArray(varray)) { - return varray; - } - if (this->may_have_ownership()) { - return VArray::template For>(*this); - } - if (this->is_span()) { - const Span span = this->get_internal_span().typed(); - return VArray::ForSpan(span); - } - if (this->is_single()) { - T value; - this->get_internal_single(&value); - return VArray::ForSingle(value, this->size()); - } - return VArray::template For>(*this); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Inline methods for #GVMutableArray. - * \{ */ - -template -inline GVMutableArray GVMutableArray::For(Args &&...args) -{ - static_assert(std::is_base_of_v); - GVMutableArray varray; - varray.emplace(std::forward(args)...); - return varray; -} - -template inline GVMutableArray::GVMutableArray(const VMutableArray &varray) -{ - if (!varray) { - return; - } - if (varray.try_assign_GVMutableArray(*this)) { - return; - } - if (varray.may_have_ownership()) { - *this = GVMutableArray::For>(varray); - } - else if (varray.is_span()) { - MutableSpan data = varray.get_internal_span(); - *this = GVMutableArray::ForSpan(data); - } - else { - *this = GVMutableArray::For>(varray); - } -} - -template inline VMutableArray GVMutableArray::typed() const -{ - if (!*this) { - return {}; - } - BLI_assert(this->type().is()); - VMutableArray varray; - if (this->try_assign_VMutableArray(varray)) { - return varray; - } - if (this->may_have_ownership()) { - return VMutableArray::template For>(*this); - } - if (this->is_span()) { - const MutableSpan span = this->get_internal_span().typed(); - return VMutableArray::ForSpan(span); - } - return VMutableArray::template For>(*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 deleted file mode 100644 index 1f40366da04..00000000000 --- a/source/blender/functions/FN_generic_virtual_vector_array.hh +++ /dev/null @@ -1,174 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#pragma once - -/** \file - * \ingroup fn - * - * A generic virtual vector array is essentially the same as a virtual vector array from blenlib, - * but its data type is only known at runtime. - */ - -#include "FN_generic_virtual_array.hh" - -#include "BLI_virtual_vector_array.hh" - -namespace blender::fn { - -/* A generically typed version of `VVectorArray`. */ -class GVVectorArray { - protected: - const CPPType *type_; - int64_t size_; - - public: - GVVectorArray(const CPPType &type, const int64_t size) : type_(&type), size_(size) - { - } - - virtual ~GVVectorArray() = default; - - /* Returns the number of vectors in the vector array. */ - int64_t size() const - { - return size_; - } - - /* Returns true when there is no vector in the vector array. */ - bool is_empty() const - { - return size_ == 0; - } - - const CPPType &type() const - { - return *type_; - } - - /* Returns the size of the vector at the given index. */ - int64_t get_vector_size(const int64_t index) const - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - return this->get_vector_size_impl(index); - } - - /* Copies an element from one of the vectors into `r_value`, which is expected to point to - * initialized memory. */ - void get_vector_element(const int64_t index, const int64_t index_in_vector, void *r_value) const - { - BLI_assert(index >= 0); - BLI_assert(index < size_); - BLI_assert(index_in_vector >= 0); - BLI_assert(index_in_vector < this->get_vector_size(index)); - this->get_vector_element_impl(index, index_in_vector, r_value); - } - - /* Returns true when the same vector is used at every index. */ - bool is_single_vector() const - { - if (size_ == 1) { - return true; - } - return this->is_single_vector_impl(); - } - - protected: - virtual int64_t get_vector_size_impl(int64_t index) const = 0; - - virtual void get_vector_element_impl(int64_t index, - int64_t index_in_vector, - void *r_value) const = 0; - - virtual bool is_single_vector_impl() const - { - return false; - } -}; - -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) - : GVArrayImpl(vector_array.type(), vector_array.get_vector_size(index)), - vector_array_(vector_array), - index_(index) - { - } - - protected: - void get(int64_t index_in_vector, void *r_value) const override; - void get_to_uninitialized(int64_t index_in_vector, void *r_value) const override; -}; - -class GVVectorArray_For_SingleGVArray : public GVVectorArray { - private: - GVArray varray_; - - public: - GVVectorArray_For_SingleGVArray(GVArray varray, const int64_t size) - : GVVectorArray(varray.type(), size), varray_(std::move(varray)) - { - } - - protected: - int64_t get_vector_size_impl(int64_t index) const override; - void get_vector_element_impl(int64_t index, - int64_t index_in_vector, - void *r_value) const override; - - bool is_single_vector_impl() const override; -}; - -class GVVectorArray_For_SingleGSpan : public GVVectorArray { - private: - const GSpan span_; - - public: - GVVectorArray_For_SingleGSpan(const GSpan span, const int64_t size) - : GVVectorArray(span.type(), size), span_(span) - { - } - - protected: - int64_t get_vector_size_impl(int64_t UNUSED(index)) const override; - void get_vector_element_impl(int64_t UNUSED(index), - int64_t index_in_vector, - void *r_value) const override; - - bool is_single_vector_impl() const override; -}; - -template class VVectorArray_For_GVVectorArray : public VVectorArray { - private: - const GVVectorArray &vector_array_; - - public: - VVectorArray_For_GVVectorArray(const GVVectorArray &vector_array) - : VVectorArray(vector_array.size()), vector_array_(vector_array) - { - } - - protected: - int64_t get_vector_size_impl(const int64_t index) const override - { - return vector_array_.get_vector_size(index); - } - - T get_vector_element_impl(const int64_t index, const int64_t index_in_vector) const override - { - T value; - vector_array_.get_vector_element(index, index_in_vector, &value); - return value; - } - - bool is_single_vector_impl() const override - { - return vector_array_.is_single_vector(); - } -}; - -} // namespace blender::fn diff --git a/source/blender/functions/FN_multi_function.hh b/source/blender/functions/FN_multi_function.hh index edeb1fed27e..015df179ef0 100644 --- a/source/blender/functions/FN_multi_function.hh +++ b/source/blender/functions/FN_multi_function.hh @@ -154,8 +154,6 @@ inline MFParamsBuilder::MFParamsBuilder(const MultiFunction &fn, const IndexMask } namespace multi_function_types { -using fn::GMutableSpan; -using fn::GSpan; using fn::MFContext; using fn::MFContextBuilder; using fn::MFDataType; diff --git a/source/blender/functions/FN_multi_function_params.hh b/source/blender/functions/FN_multi_function_params.hh index 38736527771..67f31a61dc4 100644 --- a/source/blender/functions/FN_multi_function_params.hh +++ b/source/blender/functions/FN_multi_function_params.hh @@ -13,11 +13,11 @@ #include +#include "BLI_generic_pointer.hh" +#include "BLI_generic_vector_array.hh" +#include "BLI_generic_virtual_vector_array.hh" #include "BLI_resource_scope.hh" -#include "FN_generic_pointer.hh" -#include "FN_generic_vector_array.hh" -#include "FN_generic_virtual_vector_array.hh" #include "FN_multi_function_signature.hh" namespace blender::fn { diff --git a/source/blender/functions/intern/generic_vector_array.cc b/source/blender/functions/intern/generic_vector_array.cc deleted file mode 100644 index b188b31b087..00000000000 --- a/source/blender/functions/intern/generic_vector_array.cc +++ /dev/null @@ -1,98 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "FN_generic_vector_array.hh" -#include "FN_multi_function_params.hh" -#include "FN_multi_function_signature.hh" - -namespace blender::fn { - -GVectorArray::GVectorArray(const CPPType &type, const int64_t array_size) - : type_(type), element_size_(type.size()), items_(array_size) -{ -} - -GVectorArray::~GVectorArray() -{ - if (type_.is_trivially_destructible()) { - return; - } - for (Item &item : items_) { - type_.destruct_n(item.start, item.length); - } -} - -void GVectorArray::append(const int64_t index, const void *value) -{ - Item &item = items_[index]; - if (item.length == item.capacity) { - this->realloc_to_at_least(item, item.capacity + 1); - } - - void *dst = POINTER_OFFSET(item.start, element_size_ * item.length); - type_.copy_construct(value, dst); - item.length++; -} - -void GVectorArray::extend(const int64_t index, const GVArray &values) -{ - BLI_assert(values.type() == type_); - for (const int i : IndexRange(values.size())) { - BUFFER_FOR_CPP_TYPE_VALUE(type_, buffer); - values.get(i, buffer); - this->append(index, buffer); - type_.destruct(buffer); - } -} - -void GVectorArray::extend(const int64_t index, const GSpan values) -{ - 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, GVArray(&array)); - } -} - -void GVectorArray::extend(IndexMask mask, const GVectorArray &values) -{ - GVVectorArray_For_GVectorArray virtual_values{values}; - this->extend(mask, virtual_values); -} - -void GVectorArray::clear(IndexMask mask) -{ - for (const int64_t i : mask) { - Item &item = items_[i]; - type_.destruct_n(item.start, item.length); - item.length = 0; - } -} - -GMutableSpan GVectorArray::operator[](const int64_t index) -{ - Item &item = items_[index]; - return GMutableSpan{type_, item.start, item.length}; -} - -GSpan GVectorArray::operator[](const int64_t index) const -{ - const Item &item = items_[index]; - return GSpan{type_, item.start, item.length}; -} - -void GVectorArray::realloc_to_at_least(Item &item, int64_t min_capacity) -{ - const int64_t new_capacity = std::max(min_capacity, item.length * 2); - - void *new_buffer = allocator_.allocate(element_size_ * new_capacity, type_.alignment()); - type_.relocate_assign_n(item.start, new_buffer, item.length); - - item.start = new_buffer; - item.capacity = new_capacity; -} - -} // namespace blender::fn diff --git a/source/blender/functions/intern/generic_virtual_array.cc b/source/blender/functions/intern/generic_virtual_array.cc deleted file mode 100644 index 4644323bd1f..00000000000 --- a/source/blender/functions/intern/generic_virtual_array.cc +++ /dev/null @@ -1,724 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "FN_generic_virtual_array.hh" - -namespace blender::fn { - -/* -------------------------------------------------------------------- */ -/** \name #GVArrayImpl - * \{ */ - -void GVArrayImpl::materialize(const IndexMask mask, void *dst) const -{ - for (const int64_t i : mask) { - void *elem_dst = POINTER_OFFSET(dst, type_->size() * i); - this->get(i, elem_dst); - } -} - -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); - this->get_to_uninitialized(i, elem_dst); - } -} - -void GVArrayImpl::get(const int64_t index, void *r_value) const -{ - type_->destruct(r_value); - this->get_to_uninitialized(index, r_value); -} - -bool GVArrayImpl::is_span() const -{ - return false; -} - -GSpan GVArrayImpl::get_internal_span() const -{ - BLI_assert(false); - return GSpan(*type_); -} - -bool GVArrayImpl::is_single() const -{ - return false; -} - -void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const -{ - BLI_assert(false); -} - -bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const -{ - return false; -} - -bool GVArrayImpl::may_have_ownership() const -{ - /* 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 #GVMutableArrayImpl - * \{ */ - -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(index, buffer); - type_->destruct(buffer); -} - -void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value) -{ - this->set_by_move(index, value); - type_->destruct(value); -} - -void GVMutableArrayImpl::set_all(const void *src) -{ - if (this->is_span()) { - const GSpan span = this->get_internal_span(); - type_->copy_assign_n(src, const_cast(span.data()), size_); - } - else { - for (int64_t i : IndexRange(size_)) { - this->set_by_copy(i, POINTER_OFFSET(src, type_->size() * i)); - } - } -} - -void GVMutableArray::fill(const void *value) -{ - if (this->is_span()) { - const GSpan span = this->get_internal_span(); - this->type().fill_assign_n(value, const_cast(span.data()), this->size()); - } - else { - 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 #GVArrayImpl_For_GSpan - * \{ */ - -GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan(const GMutableSpan span) - : GVMutableArrayImpl(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) - : GVMutableArrayImpl(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 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); -} - -void GVArrayImpl_For_GSpan::set_by_copy(const int64_t index, const void *value) -{ - type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index)); -} - -void GVArrayImpl_For_GSpan::set_by_move(const int64_t index, void *value) -{ - type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index)); -} - -void GVArrayImpl_For_GSpan::set_by_relocate(const int64_t index, void *value) -{ - type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index)); -} - -bool GVArrayImpl_For_GSpan::is_span() const -{ - return true; -} - -GSpan GVArrayImpl_For_GSpan::get_internal_span() const -{ - return GSpan(*type_, data_, size_); -} - -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 #GVArrayImpl_For_SingleValueRef - * \{ */ - -/* 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; - - public: - GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value) - : GVArrayImpl(type, size), value_(value) - { - } - - protected: - GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size) : GVArrayImpl(type, size) - { - } - - 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 is_span() const override - { - return size_ == 1; - } - GSpan get_internal_span() const override - { - return GSpan{*type_, value_, 1}; - } - - 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 #GVArrayImpl_For_SingleValue - * \{ */ - -/* 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_); - } - - ~GVArrayImpl_For_SingleValue() override - { - type_->destruct((void *)value_); - MEM_freeN((void *)value_); - } -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVArrayImpl_For_SmallTrivialSingleValue - * \{ */ - -/** - * Contains an inline buffer that can store a single value of a trivial type. - * This avoids the allocation that would be done by #GVArrayImpl_For_SingleValue. - */ -template class GVArrayImpl_For_SmallTrivialSingleValue : public GVArrayImpl { - private: - AlignedBuffer buffer_; - - public: - GVArrayImpl_For_SmallTrivialSingleValue(const CPPType &type, - const int64_t size, - const void *value) - : GVArrayImpl(type, size) - { - BLI_assert(type.is_trivial()); - BLI_assert(type.alignment() <= 8); - BLI_assert(type.size() <= BufferSize); - type.copy_construct(value, &buffer_); - } - - private: - void get(const int64_t UNUSED(index), void *r_value) const override - { - this->copy_value_to(r_value); - } - void get_to_uninitialized(const int64_t UNUSED(index), void *r_value) const override - { - this->copy_value_to(r_value); - } - - bool is_single() const override - { - return true; - } - void get_internal_single(void *r_value) const override - { - this->copy_value_to(r_value); - } - - void copy_value_to(void *dst) const - { - memcpy(dst, &buffer_, type_->size()); - } -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVArray_GSpan - * \{ */ - -GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) -{ - size_ = varray_.size(); - if (varray_.is_span()) { - data_ = varray_.get_internal_span().data(); - } - else { - owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__); - varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_); - data_ = owned_data_; - } -} - -GVArray_GSpan::~GVArray_GSpan() -{ - if (owned_data_ != nullptr) { - type_->destruct_n(owned_data_, size_); - MEM_freeN(owned_data_); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVMutableArray_GSpan - * \{ */ - -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()) { - data_ = varray_.get_internal_span().data(); - } - else { - owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__); - if (copy_values_to_span) { - varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_); - } - else { - type_->default_construct_n(owned_data_, size_); - } - data_ = owned_data_; - } -} - -GVMutableArray_GSpan::~GVMutableArray_GSpan() -{ - if (show_not_saved_warning_) { - if (!save_has_been_called_) { - std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n"; - } - } - if (owned_data_ != nullptr) { - type_->destruct_n(owned_data_, size_); - MEM_freeN(owned_data_); - } -} - -void GVMutableArray_GSpan::save() -{ - save_has_been_called_ = true; - if (data_ != owned_data_) { - return; - } - const int64_t element_size = type_->size(); - for (int64_t i : IndexRange(size_)) { - varray_.set_by_copy(i, POINTER_OFFSET(owned_data_, element_size * i)); - } -} - -void GVMutableArray_GSpan::disable_not_applied_warning() -{ - show_not_saved_warning_ = false; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name #GVArrayImpl_For_SlicedGVArray - * \{ */ - -class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl { - protected: - GVArray varray_; - int64_t offset_; - IndexRange slice_; - - public: - GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice) - : GVArrayImpl(varray.type(), slice.size()), - varray_(std::move(varray)), - offset_(slice.start()), - slice_(slice) - { - 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); - } - - bool is_span() const override - { - return varray_.is_span(); - } - GSpan get_internal_span() const override - { - return varray_.get_internal_span().slice(slice_); - } - - bool is_single() const override - { - return varray_.is_single(); - } - void get_internal_single(void *r_value) const override - { - varray_.get_internal_single(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 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; -} - -bool GVArrayCommon::is_span() const -{ - return impl_->is_span(); -} - -GSpan GVArrayCommon::get_internal_span() const -{ - BLI_assert(this->is_span()); - return impl_->get_internal_span(); -} - -bool GVArrayCommon::is_single() const -{ - return impl_->is_single(); -} - -void GVArrayCommon::get_internal_single(void *r_value) const -{ - BLI_assert(this->is_single()); - impl_->get_internal_single(r_value); -} - -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 - * \{ */ - -GVArray::GVArray(const GVArray &other) = default; - -GVArray::GVArray(GVArray &&other) noexcept = default; - -GVArray::GVArray(const GVArrayImpl *impl) : GVArrayCommon(impl) -{ -} - -GVArray::GVArray(std::shared_ptr impl) : GVArrayCommon(std::move(impl)) -{ -} - -GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value) -{ - if (type.is_trivial() && type.size() <= 16 && type.alignment() <= 8) { - return GVArray::For>(type, size, value); - } - return GVArray::For(type, size, value); -} - -GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value) -{ - return GVArray::For(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) -{ - /* Use const-cast because the underlying virtual array implementation is shared between const - * and non const data. */ - GMutableSpan mutable_span{span.type(), const_cast(span.data()), span.size()}; - return GVArray::For(mutable_span); -} - -class GVArrayImpl_For_GArray : public GVArrayImpl_For_GSpan { - protected: - GArray<> array_; - - public: - GVArrayImpl_For_GArray(GArray<> array) - : GVArrayImpl_For_GSpan(array.as_mutable_span()), array_(std::move(array)) - { - } -}; - -GVArray GVArray::ForGArray(GArray<> array) -{ - return GVArray::For(array); -} - -GVArray GVArray::ForEmpty(const CPPType &type) -{ - return GVArray::ForSpan(GSpan(type)); -} - -GVArray GVArray::slice(IndexRange slice) const -{ - return GVArray::For(*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 impl) - : GVArrayCommon(std::move(impl)) -{ -} - -GVMutableArray GVMutableArray::ForSpan(GMutableSpan span) -{ - return GVMutableArray::For(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(); -} - -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(span.data()), span.size()); -} - -/** \} */ - -} // namespace blender::fn diff --git a/source/blender/functions/intern/generic_virtual_vector_array.cc b/source/blender/functions/intern/generic_virtual_vector_array.cc deleted file mode 100644 index 7dc728a4460..00000000000 --- a/source/blender/functions/intern/generic_virtual_vector_array.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "FN_generic_virtual_vector_array.hh" - -namespace blender::fn { - -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(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); -} - -int64_t GVVectorArray_For_SingleGVArray::get_vector_size_impl(const int64_t UNUSED(index)) const -{ - 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 -{ - varray_.get(index_in_vector, r_value); -} - -bool GVVectorArray_For_SingleGVArray::is_single_vector_impl() const -{ - return true; -} - -int64_t GVVectorArray_For_SingleGSpan::get_vector_size_impl(const int64_t UNUSED(index)) const -{ - return span_.size(); -} - -void GVVectorArray_For_SingleGSpan::get_vector_element_impl(const int64_t UNUSED(index), - const int64_t index_in_vector, - void *r_value) const -{ - type_->copy_assign(span_[index_in_vector], r_value); -} - -bool GVVectorArray_For_SingleGSpan::is_single_vector_impl() const -{ - return true; -} - -} // namespace blender::fn diff --git a/source/blender/functions/tests/FN_generic_array_test.cc b/source/blender/functions/tests/FN_generic_array_test.cc deleted file mode 100644 index 5420a809ffc..00000000000 --- a/source/blender/functions/tests/FN_generic_array_test.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include "testing/testing.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_array.hh" - -#include "FN_generic_array.hh" - -namespace blender::fn::tests { - -TEST(generic_array, TypeConstructor) -{ - GArray array(CPPType::get()); - EXPECT_TRUE(array.data() == nullptr); - EXPECT_EQ(array.size(), 0); - EXPECT_EQ(array.as_span().typed().size(), 0); - EXPECT_TRUE(array.is_empty()); -} - -TEST(generic_array, MoveConstructor) -{ - GArray array_a(CPPType::get(), (int64_t)10); - GMutableSpan span_a = array_a.as_mutable_span(); - MutableSpan typed_span_a = span_a.typed(); - typed_span_a.fill(42); - - const GArray array_b = std::move(array_a); - Span typed_span_b = array_b.as_span().typed(); - EXPECT_FALSE(array_b.data() == nullptr); - EXPECT_EQ(array_b.size(), 10); - EXPECT_EQ(typed_span_b[4], 42); - - /* Make sure the copy constructor cleaned up the original, but it shouldn't clear the type. */ - EXPECT_TRUE(array_a.data() == nullptr); /* NOLINT: bugprone-use-after-move */ - EXPECT_EQ(array_a.size(), 0); /* NOLINT: bugprone-use-after-move */ - EXPECT_TRUE(array_a.is_empty()); /* NOLINT: bugprone-use-after-move */ - EXPECT_EQ(array_b.type(), array_a.type()); /* NOLINT: bugprone-use-after-move */ -} - -TEST(generic_array, CopyConstructor) -{ - GArray array_a(CPPType::get(), (int64_t)10); - GMutableSpan span_a = array_a.as_mutable_span(); - MutableSpan typed_span_a = span_a.typed(); - typed_span_a.fill(42); - - /* From span directly. */ - const GArray array_b = array_a.as_span(); - Span typed_span_b = array_b.as_span().typed(); - EXPECT_FALSE(array_b.data() == nullptr); - EXPECT_EQ(array_b.size(), 10); - EXPECT_EQ(typed_span_b[4], 42); - EXPECT_FALSE(array_a.is_empty()); - - /* From array. */ - const GArray array_c = array_a; - Span typed_span_c = array_c.as_span().typed(); - EXPECT_FALSE(array_c.data() == nullptr); - EXPECT_EQ(array_c.size(), 10); - EXPECT_EQ(typed_span_c[4], 42); - EXPECT_FALSE(array_a.is_empty()); -} - -TEST(generic_array, BufferAndSizeConstructor) -{ - int32_t *values = (int32_t *)MEM_malloc_arrayN(12, sizeof(int32_t), __func__); - void *buffer = (void *)values; - GArray array(CPPType::get(), buffer, 4); - EXPECT_FALSE(array.data() == nullptr); - EXPECT_EQ(array.size(), 4); - EXPECT_FALSE(array.is_empty()); - EXPECT_EQ(array.as_span().typed().size(), 4); - EXPECT_EQ(array[0], &values[0]); - EXPECT_EQ(array[1], &values[1]); - EXPECT_EQ(array[2], &values[2]); - EXPECT_EQ(array[3], &values[3]); -} - -TEST(generic_array, Reinitialize) -{ - GArray array(CPPType::get(), (int64_t)5); - EXPECT_FALSE(array.data() == nullptr); - GMutableSpan span = array.as_mutable_span(); - MutableSpan typed_span = span.typed(); - typed_span.fill(77); - EXPECT_FALSE(typed_span.data() == nullptr); - typed_span[2] = 8; - EXPECT_EQ(array[2], &typed_span[2]); - EXPECT_EQ(typed_span[0], 77); - EXPECT_EQ(typed_span[1], 77); - - array.reinitialize(10); - EXPECT_EQ(array.size(), 10); - span = array.as_mutable_span(); - EXPECT_EQ(span.size(), 10); - - typed_span = span.typed(); - EXPECT_FALSE(typed_span.data() == nullptr); - - array.reinitialize(0); - EXPECT_EQ(array.size(), 0); -} - -TEST(generic_array, InContainer) -{ - blender::Array> arrays; - for (GArray<> &array : arrays) { - array = GArray(CPPType::get(), (int64_t)5); - array.as_mutable_span().typed().fill(55); - } - for (GArray<> &array : arrays) { - EXPECT_EQ(array.as_span().typed()[3], 55); - } -} - -} // namespace blender::fn::tests diff --git a/source/blender/functions/tests/FN_generic_span_test.cc b/source/blender/functions/tests/FN_generic_span_test.cc deleted file mode 100644 index 19b3ceaf44e..00000000000 --- a/source/blender/functions/tests/FN_generic_span_test.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include "testing/testing.h" - -#include "FN_generic_span.hh" - -namespace blender::fn::tests { - -TEST(generic_span, TypeConstructor) -{ - GSpan span(CPPType::get()); - EXPECT_EQ(span.size(), 0); - EXPECT_EQ(span.typed().size(), 0); - EXPECT_TRUE(span.is_empty()); -} - -TEST(generic_span, BufferAndSizeConstructor) -{ - int values[4] = {6, 7, 3, 2}; - void *buffer = (void *)values; - GSpan span(CPPType::get(), buffer, 4); - EXPECT_EQ(span.size(), 4); - EXPECT_FALSE(span.is_empty()); - EXPECT_EQ(span.typed().size(), 4); - EXPECT_EQ(span[0], &values[0]); - EXPECT_EQ(span[1], &values[1]); - EXPECT_EQ(span[2], &values[2]); - EXPECT_EQ(span[3], &values[3]); -} - -TEST(generic_mutable_span, TypeConstructor) -{ - GMutableSpan span(CPPType::get()); - EXPECT_EQ(span.size(), 0); - EXPECT_TRUE(span.is_empty()); -} - -TEST(generic_mutable_span, BufferAndSizeConstructor) -{ - int values[4] = {4, 7, 3, 5}; - void *buffer = (void *)values; - GMutableSpan span(CPPType::get(), buffer, 4); - EXPECT_EQ(span.size(), 4); - EXPECT_FALSE(span.is_empty()); - EXPECT_EQ(span.typed().size(), 4); - EXPECT_EQ(values[2], 3); - *(int *)span[2] = 10; - EXPECT_EQ(values[2], 10); - span.typed()[2] = 20; - EXPECT_EQ(values[2], 20); -} - -} // namespace blender::fn::tests diff --git a/source/blender/functions/tests/FN_generic_vector_array_test.cc b/source/blender/functions/tests/FN_generic_vector_array_test.cc deleted file mode 100644 index 6a83e6094b4..00000000000 --- a/source/blender/functions/tests/FN_generic_vector_array_test.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include "testing/testing.h" - -#include "FN_generic_vector_array.hh" - -namespace blender::fn::tests { - -TEST(generic_vector_array, Construct) -{ - GVectorArray vector_array{CPPType::get(), 4}; - EXPECT_EQ(vector_array.size(), 4); - EXPECT_FALSE(vector_array.is_empty()); -} - -TEST(generic_vector_array, Append) -{ - GVectorArray vector_array{CPPType::get(), 3}; - int value1 = 2; - vector_array.append(1, &value1); - vector_array.append(1, &value1); - int value2 = 3; - vector_array.append(0, &value2); - vector_array.append(1, &value2); - - EXPECT_EQ(vector_array[0].size(), 1); - EXPECT_EQ(vector_array[1].size(), 3); - EXPECT_EQ(vector_array[2].size(), 0); -} - -TEST(generic_vector_array, Extend) -{ - GVectorArray vector_array{CPPType::get(), 3}; - vector_array.extend(0, Span({1, 4, 6, 4})); - vector_array.extend(1, Span()); - vector_array.extend(0, Span({10, 20, 30})); - - EXPECT_EQ(vector_array[0].size(), 7); - EXPECT_EQ(vector_array[1].size(), 0); - EXPECT_EQ(vector_array[2].size(), 0); -} - -} // namespace blender::fn::tests diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index dad2612cabd..5ba9bc066fd 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -59,8 +59,8 @@ static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_componen continue; } - const fn::GVArray mesh_attribute = mesh_component.attribute_try_get_for_read( - attribute_id, ATTR_DOMAIN_POINT); + const 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. */ if (!mesh_attribute) { diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 96291be7a96..502f5f0232e 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -29,11 +29,6 @@ using blender::bke::object_get_evaluated_geometry_set; using blender::bke::OutputAttribute; using blender::bke::OutputAttribute_Typed; using blender::bke::ReadAttributeLookup; -using blender::fn::GArray; -using blender::fn::GMutableSpan; -using blender::fn::GSpan; -using blender::fn::GVArray; -using blender::fn::GVArray_GSpan; /** * An ordered set of attribute ids. Attributes are ordered to avoid name lookups in many places. @@ -272,7 +267,7 @@ static void threaded_copy(const GSpan src, GMutableSpan dst) }); } -static void threaded_fill(const fn::GPointer value, GMutableSpan dst) +static void threaded_fill(const GPointer value, GMutableSpan dst) { BLI_assert(*value.type() == dst.type()); threading::parallel_for(IndexRange(dst.size()), 1024, [&](const IndexRange range) { diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 5b41d46443a..e94f8e50fec 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -93,6 +93,10 @@ using blender::CPPType; using blender::destruct_ptr; using blender::float3; using blender::FunctionRef; +using blender::GMutablePointer; +using blender::GMutableSpan; +using blender::GPointer; +using blender::GVArray; using blender::IndexRange; using blender::Map; using blender::MultiValueMap; @@ -105,9 +109,6 @@ using blender::Vector; using blender::bke::OutputAttribute; using blender::fn::Field; using blender::fn::GField; -using blender::fn::GMutablePointer; -using blender::fn::GPointer; -using blender::fn::GVArray; using blender::fn::ValueOrField; using blender::fn::ValueOrFieldCPPType; using blender::nodes::FieldInferencingInterface; diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 398f7cb3cf8..8e5f9dc429f 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -11,12 +11,12 @@ #include "FN_field.hh" #include "FN_field_cpp_type.hh" -#include "FN_generic_value_map.hh" #include "FN_multi_function.hh" #include "BLT_translation.h" #include "BLI_enumerable_thread_specific.hh" +#include "BLI_generic_value_map.hh" #include "BLI_stack.hh" #include "BLI_task.h" #include "BLI_task.hh" @@ -28,8 +28,6 @@ namespace blender::modifiers::geometry_nodes { using fn::Field; using fn::GField; -using fn::GValueMap; -using fn::GVArray; using fn::ValueOrField; using fn::ValueOrFieldCPPType; using nodes::GeoNodeExecParams; diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh index e981157da41..cbcbcab5679 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh @@ -2,14 +2,13 @@ #pragma once +#include "BLI_generic_pointer.hh" #include "BLI_map.hh" #include "NOD_derived_node_tree.hh" #include "NOD_geometry_nodes_eval_log.hh" #include "NOD_multi_function.hh" -#include "FN_generic_pointer.hh" - #include "DNA_modifier_types.h" #include "FN_multi_function.hh" @@ -19,8 +18,6 @@ namespace geo_log = blender::nodes::geometry_nodes_eval_log; namespace blender::modifiers::geometry_nodes { using namespace nodes::derived_node_tree_types; -using fn::GMutablePointer; -using fn::GPointer; struct GeometryNodesEvaluationParams { blender::LinearAllocator<> allocator; diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index ce0c027da25..dc0965f5d71 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -38,14 +38,6 @@ using fn::FieldEvaluator; using fn::FieldInput; using fn::FieldOperation; using fn::GField; -using fn::GMutablePointer; -using fn::GMutableSpan; -using fn::GPointer; -using fn::GSpan; -using fn::GVArray; -using fn::GVArray_GSpan; -using fn::GVMutableArray; -using fn::GVMutableArray_GSpan; using fn::ValueOrField; using geometry_nodes_eval_log::NodeWarningType; diff --git a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh index 492c67a236f..319fcdeebb7 100644 --- a/source/blender/nodes/NOD_geometry_nodes_eval_log.hh +++ b/source/blender/nodes/NOD_geometry_nodes_eval_log.hh @@ -18,13 +18,12 @@ #include "BLI_enumerable_thread_specific.hh" #include "BLI_function_ref.hh" +#include "BLI_generic_pointer.hh" #include "BLI_linear_allocator.hh" #include "BLI_map.hh" #include "BKE_geometry_set.hh" -#include "FN_generic_pointer.hh" - #include "NOD_derived_node_tree.hh" #include @@ -34,9 +33,6 @@ struct SpaceSpreadsheet; namespace blender::nodes::geometry_nodes_eval_log { -using fn::GMutablePointer; -using fn::GPointer; - /** Contains information about a value that has been computed during geometry nodes evaluation. */ class ValueLog { public: 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 2d5b0e58367..7f0ba950490 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_generic_array.hh" #include "BLI_kdopbvh.h" #include "BLI_task.hh" @@ -12,8 +13,6 @@ #include "BKE_mesh_runtime.h" #include "BKE_mesh_sample.hh" -#include "FN_generic_array.hh" - #include "UI_interface.h" #include "UI_resources.h" @@ -24,7 +23,6 @@ namespace blender::nodes::node_geo_transfer_attribute_cc { using namespace blender::bke::mesh_surface_sample; -using blender::fn::GArray; NODE_STORAGE_FUNCS(NodeGeometryTransferAttribute) -- cgit v1.2.3