[Bf-blender-cvs] [320639740d5] temp-gpu-image-engine: Geometry Nodes: support instance attributes when realizing instances

Jacques Lucke noreply at git.blender.org
Wed Dec 15 14:37:51 CET 2021


Commit: 320639740d58693cbd656b44a4c7fc7f74cd26f4
Author: Jacques Lucke
Date:   Tue Dec 14 15:57:58 2021 +0100
Branches: temp-gpu-image-engine
https://developer.blender.org/rB320639740d58693cbd656b44a4c7fc7f74cd26f4

Geometry Nodes: support instance attributes when realizing instances

This patch refactors the instance-realization code and adds new functionality.
* Named and anonymous attributes are propagated from instances to the
  realized geometry. If the same attribute exists on the geometry and on an
  instance, the attribute on the geometry has precedence.
* The id attribute has special handling to avoid creating the same id on many
  output points. This is necessary to make e.g. the Random Value node work
  as expected afterwards.

Realizing instance attributes has an effect on existing files, especially due to the
id attribute. To avoid breaking existing files, the Realize Instances node now has
a legacy option that is enabled for all already existing Realize Instances nodes.
Removing this legacy behavior does affect some existing files (although not many).
We can decide whether it's worth to remove the old behavior as a separate step.

This refactor also improves performance when realizing instances. That is mainly
due to multi-threading. See D13446 to get the file used for benchmarking. The
curve code is not as optimized as it could be yet. That's mainly because the storage
for these attributes might change soonish and it wasn't worth optimizing for the
current storage format right now.

```
1,000,000 x mesh vertex:       530 ms -> 130 ms
1,000,000 x simple cube:      1290 ms -> 190 ms
1,000,000 x point:            1000 ms -> 150 ms
1,000,000 x curve spiral:     1740 ms -> 330 ms
1,000,000 x curve line:       1110 ms -> 210 ms
10,000 x subdivided cylinder:  170 ms ->  40 ms
10 x subdivided spiral:        180 ms -> 180 ms
```

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

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

M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenkernel/BKE_geometry_set_instances.hh
M	source/blender/blenkernel/BKE_spline.hh
M	source/blender/blenkernel/BKE_type_conversions.hh
M	source/blender/blenkernel/intern/curve_eval.cc
M	source/blender/blenkernel/intern/geometry_set.cc
M	source/blender/blenkernel/intern/geometry_set_instances.cc
M	source/blender/blenkernel/intern/type_conversions.cc
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/geometry/CMakeLists.txt
A	source/blender/geometry/GEO_realize_instances.hh
A	source/blender/geometry/intern/realize_instances.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/modifiers/CMakeLists.txt
M	source/blender/nodes/NOD_geometry_exec.hh
M	source/blender/nodes/NOD_static_types.h
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_align_rotation_to_vector.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_clamp.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_color_ramp.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_combine_xyz.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_compare.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_convert.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_curve_map.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_fill.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_math.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_mix.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_proximity.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_randomize.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_sample_texture.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_separate_xyz.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_transfer.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_math.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_attribute_vector_rotate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_edge_split.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_material_assign.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_instance.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_rotate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_scale.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_separate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_point_translate.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_points_to_volume.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_raycast.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_select_by_material.cc
M	source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_subdivision_surface.cc
M	source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc
M	source/blender/nodes/geometry/nodes/node_geo_realize_instances.cc

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

diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 83429b58faf..d0ab8be9a29 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
 
 /* Blender file format version. */
 #define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 4
+#define BLENDER_FILE_SUBVERSION 5
 
 /* Minimum Blender version that supports reading file written with the current
  * version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index 414cb750937..98120b07f2d 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -57,8 +57,6 @@ struct GeometryInstanceGroup {
 void geometry_set_gather_instances(const GeometrySet &geometry_set,
                                    Vector<GeometryInstanceGroup> &r_instance_groups);
 
-GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
-
 /**
  * Add information about all the attributes on every component of the type. The resulting info
  * will contain the highest complexity data type and the highest priority domain among every
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 2073ec065fa..ebdc4a0ca0b 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -705,6 +705,7 @@ struct CurveEval {
    * \warning Call #reallocate on the spline's attributes after adding all splines.
    */
   void add_spline(SplinePtr spline);
+  void add_splines(blender::MutableSpan<SplinePtr> splines);
   void remove_splines(blender::IndexMask mask);
 
   void translate(const blender::float3 &translation);
diff --git a/source/blender/blenkernel/BKE_type_conversions.hh b/source/blender/blenkernel/BKE_type_conversions.hh
index 27419b32de6..ebfb13cd08f 100644
--- a/source/blender/blenkernel/BKE_type_conversions.hh
+++ b/source/blender/blenkernel/BKE_type_conversions.hh
@@ -72,6 +72,8 @@ class DataTypeConversions {
                                 const void *from_value,
                                 void *to_value) const;
 
+  void convert_to_initialized_n(fn::GSpan from_span, fn::GMutableSpan to_span) const;
+
   fn::GVArray try_convert(fn::GVArray varray, const CPPType &to_type) const;
 
   fn::GVMutableArray try_convert(fn::GVMutableArray varray, const CPPType &to_type) const;
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index 02abb097175..38f736e6907 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -71,6 +71,13 @@ void CurveEval::add_spline(SplinePtr spline)
   splines_.append(std::move(spline));
 }
 
+void CurveEval::add_splines(MutableSpan<SplinePtr> splines)
+{
+  for (SplinePtr &spline : splines) {
+    this->add_spline(std::move(spline));
+  }
+}
+
 void CurveEval::remove_splines(blender::IndexMask mask)
 {
   for (int i = mask.size() - 1; i >= 0; i--) {
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 7830e897109..ef5609ec9a8 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -481,13 +481,18 @@ void GeometrySet::gather_attributes_for_propagation(
           return;
         }
 
+        AttributeDomain domain = meta_data.domain;
+        if (dst_component_type != GEO_COMPONENT_TYPE_INSTANCES && domain == ATTR_DOMAIN_INSTANCE) {
+          domain = ATTR_DOMAIN_POINT;
+        }
+
         auto add_info = [&](AttributeKind *attribute_kind) {
-          attribute_kind->domain = meta_data.domain;
+          attribute_kind->domain = domain;
           attribute_kind->data_type = meta_data.data_type;
         };
         auto modify_info = [&](AttributeKind *attribute_kind) {
           attribute_kind->domain = bke::attribute_domain_highest_priority(
-              {attribute_kind->domain, meta_data.domain});
+              {attribute_kind->domain, domain});
           attribute_kind->data_type = bke::attribute_data_type_highest_complexity(
               {attribute_kind->data_type, meta_data.data_type});
         };
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 6d50dcd3c8c..4d84d5d899d 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -207,375 +207,6 @@ void geometry_set_gather_instances_attribute_info(Span<GeometryInstanceGroup> se
   }
 }
 
-static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups)
-{
-  int totverts = 0;
-  int totloops = 0;
-  int totedges = 0;
-  int totpolys = 0;
-  int64_t cd_dirty_vert = 0;
-  int64_t cd_dirty_poly = 0;
-  int64_t cd_dirty_edge = 0;
-  int64_t cd_dirty_loop = 0;
-  VectorSet<Material *> materials;
-
-  for (const GeometryInstanceGroup &set_group : set_groups) {
-    const GeometrySet &set = set_group.geometry_set;
-    const int tot_transforms = set_group.transforms.size();
-    if (set.has_mesh()) {
-      const Mesh &mesh = *set.get_mesh_for_read();
-      totverts += mesh.totvert * tot_transforms;
-      totloops += mesh.totloop * tot_transforms;
-      totedges += mesh.totedge * tot_transforms;
-      totpolys += mesh.totpoly * tot_transforms;
-      cd_dirty_vert |= mesh.runtime.cd_dirty_vert;
-      cd_dirty_poly |= mesh.runtime.cd_dirty_poly;
-      cd_dirty_edge |= mesh.runtime.cd_dirty_edge;
-      cd_dirty_loop |= mesh.runtime.cd_dirty_loop;
-      for (const int slot_index : IndexRange(mesh.totcol)) {
-        Material *material = mesh.mat[slot_index];
-        materials.add(material);
-      }
-    }
-  }
-
-  /* Don't create an empty mesh. */
-  if ((totverts + totloops + totedges + totpolys) == 0) {
-    return nullptr;
-  }
-
-  Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys);
-  /* Copy settings from the first input geometry set with a mesh. */
-  for (const GeometryInstanceGroup &set_group : set_groups) {
-    const GeometrySet &set = set_group.geometry_set;
-    if (set.has_mesh()) {
-      const Mesh &mesh = *set.get_mesh_for_read();
-      BKE_mesh_copy_parameters_for_eval(new_mesh, &mesh);
-      break;
-    }
-  }
-  for (const int i : IndexRange(materials.size())) {
-    Material *material = materials[i];
-    BKE_id_material_eval_assign(&new_mesh->id, i + 1, material);
-  }
-  new_mesh->runtime.cd_dirty_vert = cd_dirty_vert;
-  new_mesh->runtime.cd_dirty_poly = cd_dirty_poly;
-  new_mesh->runtime.cd_dirty_edge = cd_dirty_edge;
-  new_mesh->runtime.cd_dirty_loop = cd_dirty_loop;
-
-  int vert_offset = 0;
-  int loop_offset = 0;
-  int edge_offset = 0;
-  int poly_offset = 0;
-  for (const GeometryInstanceGroup &set_group : set_groups) {
-    const GeometrySet &set = set_group.geometry_set;
-    if (set.has_mesh()) {
-      const Mesh &mesh = *set.get_mesh_for_read();
-
-      Array<int> material_index_map(mesh.totcol);
-      for (const int i : IndexRange(mesh.totcol)) {
-        Material *material = mesh.mat[i];
-        const int new_material_index = materials.index_of(material);
-        material_index_map[i] = new_material_index;
-      }
-
-      for (const float4x4 &transform : set_group.transforms) {
-        for (const int i : IndexRange(mesh.totvert)) {
-          const MVert &old_vert = mesh.mvert[i];
-          MVert &new_vert = new_mesh->mvert[vert_offset + i];
-
-          new_vert = old_vert;
-
-          const float3 new_position = transform * float3(old_vert.co);
-          copy_v3_v3(new_vert.co, new_position);
-        }
-        for (const int i : IndexRange(mesh.totedge)) {
-          const MEdge &old_edge = mesh.medge[i];
-          MEdge &new_edge = new_mesh->medge[edge_offset + i];
-          new_edge = old_edge;
-          new_edge.v1 += vert_offset;
-          new_edge.v2 += vert_offset;
-        }
-        for (const int i : IndexRange(mesh.totloop)) {
-          const MLoop &old_loop = mesh.mloop[i];
-          MLoop &new_loop = new_mesh->mloop[loop_offset + i];
-          new_loop = old_loop;
-          new_loop.v += vert_offset;
-          new_loop.e += edge_offset;
-        }
-        for (const int i : IndexRange(mesh.totpoly)) {
-          const MPoly &old_poly = mesh.mpoly[i];
-          MPoly &new_poly = new_mesh->mpoly[poly_offset + i];
-          new_poly = old_poly;
-          new_poly.loopstart += loop_offset;
-          if (old_poly.mat_nr >= 0 && old_poly.mat_nr < mesh.totcol) {
-            new_poly.mat_nr = material_index_map[new_poly.mat_nr];
-          }
-          else {
-            /* The material index was invalid before. */
-            new_poly.mat_nr = 0;
-          }
-        }
-
-        vert_offset += mesh.totvert;
-        loop_offset += mesh.totloop;
-        edge_offset += mesh.totedge;
-        poly_offset += mesh.totpoly;
-      }
-    }
-  }
-
-  /* A possible optimization is to only tag the normals dirty when there are transforms that change
-   * normals. */
-  BKE_mesh_normals_tag_dirty(new_mesh);
-
-  return new_mesh;
-}
-
-static void join_attributes(Span<GeometryInstanceGroup> set_groups,
-                            Span<GeometryComponentType> component_types,
-                            const Map<AttributeIDRef, AttributeKind> &attribute_info,
-                            GeometryComponent &result)
-{
-  for (Map<AttributeIDRef, AttributeKind>::Item entry : attribute_info.items()) {
-    const AttributeIDRef attribute_id = entry.key;
-    const AttributeDomain domain_output = entry.value.domain;
-    const CustomDataType data_type_output = entry.value.data_type;
-    const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type_output);
-    BLI_assert(cpp_type != nullptr);
-
-    result.attribute_try_create(
-        entry.key, domain_output, data_type_output, AttributeInitDefault());
-  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list