[Bf-blender-cvs] [d4c868da9f9] master: Geometry Nodes: refactor virtual array system

Jacques Lucke noreply at git.blender.org
Tue Nov 16 10:16:40 CET 2021


Commit: d4c868da9f97a06c3457b8eafd344a23ed704874
Author: Jacques Lucke
Date:   Tue Nov 16 10:15:51 2021 +0100
Branches: master
https://developer.blender.org/rBd4c868da9f97a06c3457b8eafd344a23ed704874

Geometry Nodes: refactor virtual array system

Goals of this refactor:
* Simplify creating virtual arrays.
* Simplify passing virtual arrays around.
* Simplify converting between typed and generic virtual arrays.
* Reduce memory allocations.

As a quick reminder, a virtual arrays is a data structure that behaves like an
array (i.e. it can be accessed using an index). However, it may not actually
be stored as array internally. The two most important implementations
of virtual arrays are those that correspond to an actual plain array and those
that have the same value for every index. However, many more
implementations exist for various reasons (interfacing with legacy attributes,
unified iterator over all points in multiple splines, ...).

With this refactor the core types (`VArray`, `GVArray`, `VMutableArray` and
`GVMutableArray`) can be used like "normal values". They typically live
on the stack. Before, they were usually inside a `std::unique_ptr`. This makes
passing them around much easier. Creation of new virtual arrays is also
much simpler now due to some constructors. Memory allocations are
reduced by making use of small object optimization inside the core types.

Previously, `VArray` was a class with virtual methods that had to be overridden
to change the behavior of a the virtual array. Now,`VArray` has a fixed size
and has no virtual methods. Instead it contains a `VArrayImpl` that is
similar to the old `VArray`. `VArrayImpl` should rarely ever be used directly,
unless a new virtual array implementation is added.

To support the small object optimization for many `VArrayImpl` classes,
a new `blender::Any` type is added. It is similar to `std::any` with two
additional features. It has an adjustable inline buffer size and alignment.
The inline buffer size of `std::any` can't be relied on and is usually too
small for our use case here. Furthermore, `blender::Any` can store
additional user-defined type information without increasing the
stack size.

Differential Revision: https://developer.blender.org/D12986

===================================================================

M	source/blender/blenkernel/BKE_attribute_access.hh
M	source/blender/blenkernel/BKE_geometry_set.hh
M	source/blender/blenkernel/BKE_spline.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/blenkernel/intern/attribute_access_intern.hh
M	source/blender/blenkernel/intern/curve_to_mesh_convert.cc
M	source/blender/blenkernel/intern/geometry_component_curve.cc
M	source/blender/blenkernel/intern/geometry_component_instances.cc
M	source/blender/blenkernel/intern/geometry_component_mesh.cc
M	source/blender/blenkernel/intern/geometry_component_pointcloud.cc
M	source/blender/blenkernel/intern/geometry_set_instances.cc
M	source/blender/blenkernel/intern/mesh_sample.cc
M	source/blender/blenkernel/intern/spline_base.cc
M	source/blender/blenkernel/intern/spline_bezier.cc
M	source/blender/blenkernel/intern/spline_nurbs.cc
M	source/blender/blenkernel/intern/spline_poly.cc
A	source/blender/blenlib/BLI_any.hh
M	source/blender/blenlib/BLI_virtual_array.hh
M	source/blender/blenlib/CMakeLists.txt
A	source/blender/blenlib/tests/BLI_any_test.cc
M	source/blender/blenlib/tests/BLI_virtual_array_test.cc
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
M	source/blender/functions/FN_field.hh
M	source/blender/functions/FN_generic_vector_array.hh
M	source/blender/functions/FN_generic_virtual_array.hh
M	source/blender/functions/FN_generic_virtual_vector_array.hh
M	source/blender/functions/FN_multi_function_params.hh
M	source/blender/functions/intern/field.cc
M	source/blender/functions/intern/generic_vector_array.cc
M	source/blender/functions/intern/generic_virtual_array.cc
M	source/blender/functions/intern/generic_virtual_vector_array.cc
M	source/blender/functions/intern/multi_function_parallel.cc
M	source/blender/functions/intern/multi_function_procedure_executor.cc
M	source/blender/functions/tests/FN_field_test.cc
M	source/blender/functions/tests/FN_multi_function_procedure_test.cc
M	source/blender/geometry/intern/mesh_to_curve_convert.cc
M	source/blender/nodes/NOD_geometry_exec.hh
M	source/blender/nodes/NOD_type_conversions.hh
M	source/blender/nodes/geometry/nodes/legacy/node_geo_align_rotation_to_vector.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_clamp.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_color_ramp.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_combine_xyz.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_compare.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_convert.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_curve_map.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_map_range.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_math.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_mix.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_proximity.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_randomize.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_sample_texture.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_separate_xyz.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_transfer.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_math.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_attribute_vector_rotate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_curve_endpoints.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_curve_reverse.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_curve_set_handles.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_curve_spline_type.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_curve_subdivide.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_curve_to_points.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_delete_geometry.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_material_assign.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_mesh_to_curve.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_point_distribute.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_point_instance.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_point_rotate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_point_scale.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_point_separate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_point_translate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_points_to_volume.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_raycast.cc
M	source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_parameter.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
M	source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc
M	source/blender/nodes/geometry/nodes/node_geo_input_normal.cc
M	source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
M	source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
M	source/blender/nodes/geometry/nodes/node_geo_instance_on_points.cc
M	source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_material_selection.cc
M	source/blender/nodes/geometry/nodes/node_geo_mesh_to_points.cc
M	source/blender/nodes/geometry/nodes/node_geo_points_to_vertices.cc
M	source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc
M	source/blender/nodes/geometry/nodes/node_geo_transfer_attribute.cc
M	source/blender/nodes/intern/node_geometry_exec.cc
M	source/blender/nodes/intern/type_conversions.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_musgrave.cc
M	source/blender/nodes/shader/nodes/node_shader_tex_voronoi.cc

===================================================================

diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh
index 6a87375e5e2..47f62b52a0f 100644
--- a/source/blender/blenkernel/BKE_attribute_access.hh
+++ b/source/blender/blenkernel/BKE_attribute_access.hh
@@ -115,10 +115,10 @@ struct AttributeInitDefault : public AttributeInit {
  * Note that this can be used to fill the new attribute with the default
  */
 struct AttributeInitVArray : public AttributeInit {
-  const blender::fn::GVArray *varray;
+  blender::fn::GVArray varray;
 
-  AttributeInitVArray(const blender::fn::GVArray *varray)
-      : AttributeInit(Type::VArray), varray(varray)
+  AttributeInitVArray(blender::fn::GVArray varray)
+      : AttributeInit(Type::VArray), varray(std::move(varray))
   {
   }
 };
@@ -150,9 +150,7 @@ namespace blender::bke {
 
 using fn::CPPType;
 using fn::GVArray;
-using fn::GVArrayPtr;
 using fn::GVMutableArray;
-using fn::GVMutableArrayPtr;
 
 const CPPType *custom_data_type_to_cpp_type(const CustomDataType type);
 CustomDataType cpp_type_to_custom_data_type(const CPPType &type);
@@ -164,14 +162,14 @@ AttributeDomain attribute_domain_highest_priority(Span<AttributeDomain> domains)
  */
 struct ReadAttributeLookup {
   /* The virtual array that is used to read from this attribute. */
-  GVArrayPtr varray;
+  GVArray varray;
   /* Domain the attribute lives on in the geometry. */
   AttributeDomain domain;
 
   /* Convenience function to check if the attribute has been found. */
   operator bool() const
   {
-    return this->varray.get() != nullptr;
+    return this->varray;
   }
 };
 
@@ -180,7 +178,7 @@ struct ReadAttributeLookup {
  */
 struct WriteAttributeLookup {
   /* The virtual array that is used to read from and write to the attribute. */
-  GVMutableArrayPtr varray;
+  GVMutableArray varray;
   /* Domain the attributes lives on in the geometry. */
   AttributeDomain domain;
   /* Call this after changing the attribute to invalidate caches that depend on this attribute. */
@@ -189,7 +187,7 @@ struct WriteAttributeLookup {
   /* Convenience function to check if the attribute has been found. */
   operator bool() const
   {
-    return this->varray.get() != nullptr;
+    return this->varray;
   }
 };
 
@@ -209,7 +207,7 @@ class OutputAttribute {
   using SaveFn = std::function<void(OutputAttribute &)>;
 
  private:
-  GVMutableArrayPtr varray_;
+  GVMutableArray varray_;
   AttributeDomain domain_ = ATTR_DOMAIN_AUTO;
   SaveFn save_;
   std::unique_ptr<fn::GVMutableArray_GSpan> optional_span_varray_;
@@ -219,7 +217,7 @@ class OutputAttribute {
  public:
   OutputAttribute();
   OutputAttribute(OutputAttribute &&other);
-  OutputAttribute(GVMutableArrayPtr varray,
+  OutputAttribute(GVMutableArray varray,
                   AttributeDomain domain,
                   SaveFn save,
                   const bool ignore_old_values);
@@ -229,7 +227,7 @@ class OutputAttribute {
   operator bool() const;
 
   GVMutableArray &operator*();
-  GVMutableArray *operator->();
+  fn::GVMutableArray *operator->();
   GVMutableArray &varray();
   AttributeDomain domain() const;
   const CPPType &cpp_type() const;
@@ -247,16 +245,14 @@ class OutputAttribute {
 template<typename T> class OutputAttribute_Typed {
  private:
   OutputAttribute attribute_;
-  std::unique_ptr<fn::GVMutableArray_Typed<T>> optional_varray_;
-  VMutableArray<T> *varray_ = nullptr;
+  VMutableArray<T> varray_;
 
  public:
   OutputAttribute_Typed();
   OutputAttribute_Typed(OutputAttribute attribute) : attribute_(std::move(attribute))
   {
     if (attribute_) {
-      optional_varray_ = std::make_unique<fn::GVMutableArray_Typed<T>>(attribute_.varray());
-      varray_ = &**optional_varray_;
+      varray_ = attribute_.varray().template typed<T>();
     }
   }
 
@@ -275,22 +271,22 @@ template<typename T> class OutputAttribute_Typed {
 
   operator bool() const
   {
-    return varray_ != nullptr;
+    return varray_;
   }
 
   VMutableArray<T> &operator*()
   {
-    return *varray_;
+    return varray_;
   }
 
   VMutableArray<T> *operator->()
   {
-    return varray_;
+    return &varray_;
   }
 
   VMutableArray<T> &varray()
   {
-    return *varray_;
+    return varray_;
   }
 
   AttributeDomain domain() const
@@ -351,18 +347,17 @@ class CustomDataAttributes {
 
   std::optional<blender::fn::GSpan> get_for_read(const AttributeIDRef &attribute_id) const;
 
-  blender::fn::GVArrayPtr get_for_read(const AttributeIDRef &attribute_id,
-                                       const CustomDataType data_type,
-                                       const void *default_value) const;
+  blender::fn::GVArray get_for_read(const AttributeIDRef &attribute_id,
+                                    const CustomDataType data_type,
+                                    const void *default_value) const;
 
   template<typename T>
-  blender::fn::GVArray_Typed<T> get_for_read(const AttributeIDRef &attribute_id,
-                                             const T &default_value) const
+  blender::VArray<T> get_for_read(const AttributeIDRef &attribute_id, const T &default_value) const
   {
     const blender::fn::CPPType &cpp_type = blender::fn::CPPType::get<T>();
     const CustomDataType type = blender::bke::cpp_type_to_custom_data_type(cpp_type);
-    GVArrayPtr varray = this->get_for_read(attribute_id, type, &default_value);
-    return blender::fn::GVArray_Typed<T>(std::move(varray));
+    GVArray varray = this->get_for_read(attribute_id, type, &default_value);
+    return varray.typed<T>();
   }
 
   std::optional<blender::fn::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
@@ -465,7 +460,7 @@ inline bool AttributeIDRef::should_be_kept() const
 inline OutputAttribute::OutputAttribute() = default;
 inline OutputAttribute::OutputAttribute(OutputAttribute &&other) = default;
 
-inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
+inline OutputAttribute::OutputAttribute(GVMutableArray varray,
                                         AttributeDomain domain,
                                         SaveFn save,
                                         const bool ignore_old_values)
@@ -478,22 +473,22 @@ inline OutputAttribute::OutputAttribute(GVMutableArrayPtr varray,
 
 inline OutputAttribute::operator bool() const
 {
-  return varray_.get() != nullptr;
+  return varray_;
 }
 
 inline GVMutableArray &OutputAttribute::operator*()
 {
-  return *varray_;
+  return varray_;
 }
 
-inline GVMutableArray *OutputAttribute::operator->()
+inline fn::GVMutableArray *OutputAttribute::operator->()
 {
-  return varray_.get();
+  return &varray_;
 }
 
 inline GVMutableArray &OutputAttribute::varray()
 {
-  return *varray_;
+  return varray_;
 }
 
 inline AttributeDomain OutputAttribute::domain() const
@@ -503,7 +498,7 @@ inline AttributeDomain OutputAttribute::domain() const
 
 inline const CPPType &OutputAttribute::cpp_type() const
 {
-  return varray_->type();
+  return varray_.type();
 }
 
 inline CustomDataType OutputAttribute::custom_data_type() const
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 58a89d0207a..63ada807c55 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -119,10 +119,21 @@ class GeometryComponent {
   /* Get a read-only attribute for the domain based on the given attribute. This can be used to
    * interpolate from one domain to another.
    * Returns null if the interpolation is not implemented. */
-  virtual std::unique_ptr<blender::fn::GVArray> attribute_try_adapt_domain(
-      std::unique_ptr<blender::fn::GVArray> varray,
-      const AttributeDomain from_domain,
-      const AttributeDomain to_domain) const;
+  blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray,
+                                                  const AttributeDomain from_domain,
+                                                  const AttributeDomain to_domain) const
+  {
+    return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain);
+  }
+
+  template<typename T>
+  blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray,
+                                                const AttributeDomain from_domain,
+                                                const AttributeDomain to_domain) const
+  {
+    return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain)
+        .template typed<T>();
+  }
 
   /* Returns true when the attribute has been deleted. */
   bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
@@ -146,16 +157,15 @@ class GeometryComponent {
   /* Get a virtual array to read the data of an attribute on the given domain and data type.
    * Returns null when the attribute does not exist or cannot be converted to the requested domain
    * and data type. */
-  std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
-      const blender::bke::AttributeIDRef &attribute_id,
-      const AttributeDomain domain,
-      const CustomDataType data_type) const;
+  blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
+                                                  const AttributeDomain domain,
+                                                  const CustomDataType data_type) const;
 
   /* Get a virtual array to read the data of an attribute on the given domain. The data type is
    * left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
    * requested domain. */
-  std::unique_ptr<blender::fn::GVArray> attribute_try_get_for_read(
-      const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain) const;
+  blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
+                                                  const AttributeDomain domain) const;
 
   /* Get a virtual array to read data of an attribute with the given data type. The domain is
    * left unchanged. Returns null when the attribute does not exist or cannot be converted to the
@@ -165,25 +175,22 @@ class GeometryComponent {
 
  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list