Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-09-12 19:35:33 +0300
committerHans Goudey <h.goudey@me.com>2022-09-12 19:35:33 +0300
commit9088a1f4764f371f7f22384e7d7e2c8971d5c9f0 (patch)
treecd67c66c9c00cf09e6ea70804c0bece324b29678
parent225b5a3491d9593639a80c9a34bcc017862eb2b2 (diff)
Geometry: Avoid unnecessary initialization when resizing data arrays
When resizing mesh and curves attribute storage, avoid initializing the new memory for basic types. Also, avoid skipping "no free" layers; all layers should be reallocated to the new size since they may be accessed. The semantics introduced in 25237d2625078c6d1 are essential for this change, because otherwise we don't have a way to construct non-trivial types in the new memory. In a basic test of the extrude node, I observed a performance improvement of about 30%, from 55ms to 42ms. Differential Revision: https://developer.blender.org/D15818
-rw-r--r--source/blender/blenkernel/BKE_customdata.h10
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc16
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc4
-rw-r--r--source/blender/blenkernel/intern/customdata.cc34
-rw-r--r--source/blender/blenkernel/intern/mesh.cc4
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc11
-rw-r--r--source/blender/blenkernel/intern/pointcloud.cc8
-rw-r--r--source/blender/geometry/intern/add_curves_on_mesh.cc22
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc26
9 files changed, 99 insertions, 36 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 09d37682b3c..24fa5f0e87a 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -178,13 +178,11 @@ bool CustomData_merge_mesh_to_bmesh(const struct CustomData *source,
int totelem);
/**
- * Reallocate custom data to a new element count.
- * Only affects on data layers which are owned by the CustomData itself,
- * referenced data is kept unchanged,
- *
- * \note Take care of referenced layers by yourself!
+ * Reallocate custom data to a new element count. If the new size is larger, the new values use
+ * the #CD_CONSTRUCT behavior, so trivial types must be initialized by the caller. After being
+ * resized, the #CustomData does not contain any referenced layers.
*/
-void CustomData_realloc(struct CustomData *data, int totelem);
+void CustomData_realloc(struct CustomData *data, int old_size, int new_size);
/**
* BMesh version of CustomData_merge; merges the layouts of source and `dest`,
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index 69f3e5bb389..27c54a3d4a7 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -726,8 +726,22 @@ bool CustomDataAttributes::remove(const AttributeIDRef &attribute_id)
void CustomDataAttributes::reallocate(const int size)
{
+ const int old_size = size_;
size_ = size;
- CustomData_realloc(&data, size);
+ CustomData_realloc(&data, old_size, size_);
+ if (size_ > old_size) {
+ /* Fill default new values. */
+ const int new_elements_num = size_ - old_size;
+ this->foreach_attribute(
+ [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData /*meta_data*/) {
+ GMutableSpan new_data = this->get_for_write(id)->take_back(new_elements_num);
+ const CPPType &type = new_data.type();
+ type.fill_assign_n(type.default_value(), new_data.data(), new_data.size());
+ return true;
+ },
+ /* Dummy. */
+ ATTR_DOMAIN_POINT);
+ }
}
void CustomDataAttributes::clear()
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 35b209179d3..d192c10912f 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -963,11 +963,11 @@ void CurvesGeometry::ensure_can_interpolate_to_evaluated() const
void CurvesGeometry::resize(const int points_num, const int curves_num)
{
if (points_num != this->point_num) {
- CustomData_realloc(&this->point_data, points_num);
+ CustomData_realloc(&this->point_data, this->points_num(), points_num);
this->point_num = points_num;
}
if (curves_num != this->curve_num) {
- CustomData_realloc(&this->curve_data, curves_num);
+ CustomData_realloc(&this->curve_data, this->curves_num(), curves_num);
this->curve_num = curves_num;
this->curve_offsets = (int *)MEM_reallocN(this->curve_offsets, sizeof(int) * (curves_num + 1));
}
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 24373053896..82a1a2aa8f6 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -2408,19 +2408,37 @@ bool CustomData_merge_mesh_to_bmesh(const CustomData *source,
return result;
}
-void CustomData_realloc(CustomData *data, const int totelem)
+void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
{
- BLI_assert(totelem >= 0);
+ BLI_assert(new_size >= 0);
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
- const LayerTypeInfo *typeInfo;
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
+
+ const int64_t old_size_in_bytes = int64_t(old_size) * typeInfo->size;
+ const int64_t new_size_in_bytes = int64_t(new_size) * typeInfo->size;
if (layer->flag & CD_FLAG_NOFREE) {
- continue;
+ const void *old_data = layer->data;
+ layer->data = MEM_malloc_arrayN(new_size, typeInfo->size, __func__);
+ if (typeInfo->copy) {
+ typeInfo->copy(old_data, layer->data, std::min(old_size, new_size));
+ }
+ else {
+ std::memcpy(layer->data, old_data, std::min(old_size_in_bytes, new_size_in_bytes));
+ }
+ layer->flag &= ~CD_FLAG_NOFREE;
+ }
+ else {
+ layer->data = MEM_reallocN(layer->data, new_size_in_bytes);
+ }
+
+ if (new_size > old_size) {
+ /* Initialize new values for non-trivial types. */
+ if (typeInfo->construct) {
+ const int new_elements_num = new_size - old_size;
+ typeInfo->construct(POINTER_OFFSET(layer->data, old_size_in_bytes), new_elements_num);
+ }
}
- typeInfo = layerType_getInfo(layer->type);
- /* Use calloc to avoid the need to manually initialize new data in layers.
- * Useful for types like #MDeformVert which contain a pointer. */
- layer->data = MEM_recallocN(layer->data, (size_t)totelem * typeInfo->size);
}
}
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index a0548b7efd4..636be0dc032 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -2095,11 +2095,11 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
const bool do_edges = (num_new_edges > 0);
/* Reallocate all vert and edge related data. */
+ CustomData_realloc(&mesh->vdata, mesh->totvert, mesh->totvert + num_new_verts);
mesh->totvert += num_new_verts;
- CustomData_realloc(&mesh->vdata, mesh->totvert);
if (do_edges) {
+ CustomData_realloc(&mesh->edata, mesh->totedge, mesh->totedge + num_new_edges);
mesh->totedge += num_new_edges;
- CustomData_realloc(&mesh->edata, mesh->totedge);
}
/* Update normals manually to avoid recalculation after this operation. */
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index b7d8972aa7b..e56df0e3fe3 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -105,8 +105,9 @@ static void make_edges_mdata_extend(Mesh &mesh)
#endif
if (totedge_new) {
- CustomData_realloc(&mesh.edata, totedge + totedge_new);
-
+ /* The only layer should be edges, so no other layers need to be initialized. */
+ BLI_assert(mesh.edata.totlayer == 1);
+ CustomData_realloc(&mesh.edata, totedge, totedge + totedge_new);
mesh.totedge += totedge_new;
MutableSpan<MEdge> edges = mesh.edges_for_write();
MEdge *medge = &edges[totedge];
@@ -634,9 +635,11 @@ void BKE_pointcloud_from_mesh(Mesh *me, PointCloud *pointcloud)
using namespace blender;
BLI_assert(me != nullptr);
-
+ /* The pointcloud should only contain the position attribute, otherwise more attributes would
+ * need to be initialized below. */
+ BLI_assert(pointcloud->attributes().all_ids().size() == 1);
+ CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint, me->totvert);
pointcloud->totpoint = me->totvert;
- CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint);
/* Copy over all attributes. */
CustomData_merge(&me->vdata, &pointcloud->pdata, CD_MASK_PROP_ALL, CD_DUPLICATE, me->totvert);
diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc
index fe6353bc72d..b45e164b594 100644
--- a/source/blender/blenkernel/intern/pointcloud.cc
+++ b/source/blender/blenkernel/intern/pointcloud.cc
@@ -189,8 +189,9 @@ IDTypeInfo IDType_ID_PT = {
static void pointcloud_random(PointCloud *pointcloud)
{
+ BLI_assert(pointcloud->totpoint == 0);
pointcloud->totpoint = 400;
- CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint);
+ CustomData_realloc(&pointcloud->pdata, 0, pointcloud->totpoint);
RNG *rng = BLI_rng_new(0);
@@ -238,9 +239,6 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint)
nullptr, ID_PT, BKE_idtype_idcode_to_name(ID_PT), LIB_ID_CREATE_LOCALIZE));
pointcloud_init_data(&pointcloud->id);
-
- pointcloud->totpoint = totpoint;
-
CustomData_add_layer_named(&pointcloud->pdata,
CD_PROP_FLOAT,
CD_SET_DEFAULT,
@@ -248,8 +246,8 @@ PointCloud *BKE_pointcloud_new_nomain(const int totpoint)
pointcloud->totpoint,
POINTCLOUD_ATTR_RADIUS);
+ CustomData_realloc(&pointcloud->pdata, 0, totpoint);
pointcloud->totpoint = totpoint;
- CustomData_realloc(&pointcloud->pdata, pointcloud->totpoint);
return pointcloud;
}
diff --git a/source/blender/geometry/intern/add_curves_on_mesh.cc b/source/blender/geometry/intern/add_curves_on_mesh.cc
index e06ee55afa0..bb5e2a0a28a 100644
--- a/source/blender/geometry/intern/add_curves_on_mesh.cc
+++ b/source/blender/geometry/intern/add_curves_on_mesh.cc
@@ -372,6 +372,28 @@ AddCurvesOnMeshOutputs add_curves_on_mesh(CurvesGeometry &curves,
curves.fill_curve_types(new_curves_range, CURVE_TYPE_CATMULL_ROM);
+ /* Explicitly set all other attributes besides those processed above to default values. */
+ bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
+ Set<std::string> attributes_to_skip{{"position",
+ "curve_type",
+ "surface_uv_coordinate",
+ ".selection_point_float",
+ ".selection_curve_float"}};
+ attributes.for_all(
+ [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData /*meta_data*/) {
+ if (id.is_named() && attributes_to_skip.contains(id.name())) {
+ return true;
+ }
+ bke::GSpanAttributeWriter attribute = attributes.lookup_for_write_span(id);
+ const int new_elements_num = attribute.domain == ATTR_DOMAIN_POINT ? new_points_num :
+ new_curves_num;
+ const CPPType &type = attribute.span.type();
+ GMutableSpan new_data = attribute.span.take_back(new_elements_num);
+ type.fill_assign_n(type.default_value(), new_data.data(), new_data.size());
+ attribute.finish();
+ return true;
+ });
+
return outputs;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
index 64779494e3e..c7f4b78946d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc
@@ -94,24 +94,24 @@ static void expand_mesh(Mesh &mesh,
const int loop_expand)
{
if (vert_expand != 0) {
- CustomData_duplicate_referenced_layers(&mesh.vdata, mesh.totvert);
+ const int old_verts_num = mesh.totvert;
mesh.totvert += vert_expand;
- CustomData_realloc(&mesh.vdata, mesh.totvert);
+ CustomData_realloc(&mesh.vdata, old_verts_num, mesh.totvert);
}
if (edge_expand != 0) {
- CustomData_duplicate_referenced_layers(&mesh.edata, mesh.totedge);
+ const int old_edges_num = mesh.totedge;
mesh.totedge += edge_expand;
- CustomData_realloc(&mesh.edata, mesh.totedge);
+ CustomData_realloc(&mesh.edata, old_edges_num, mesh.totedge);
}
if (poly_expand != 0) {
- CustomData_duplicate_referenced_layers(&mesh.pdata, mesh.totpoly);
+ const int old_polys_num = mesh.totpoly;
mesh.totpoly += poly_expand;
- CustomData_realloc(&mesh.pdata, mesh.totpoly);
+ CustomData_realloc(&mesh.pdata, old_polys_num, mesh.totpoly);
}
if (loop_expand != 0) {
- CustomData_duplicate_referenced_layers(&mesh.ldata, mesh.totloop);
+ const int old_loops_num = mesh.totloop;
mesh.totloop += loop_expand;
- CustomData_realloc(&mesh.ldata, mesh.totloop);
+ CustomData_realloc(&mesh.ldata, old_loops_num, mesh.totloop);
}
}
@@ -147,6 +147,7 @@ static MEdge new_edge(const int v1, const int v2)
MEdge edge;
edge.v1 = v1;
edge.v2 = v2;
+ edge.crease = 0;
edge.flag = (ME_EDGEDRAW | ME_EDGERENDER);
return edge;
}
@@ -156,6 +157,7 @@ static MEdge new_loose_edge(const int v1, const int v2)
MEdge edge;
edge.v1 = v1;
edge.v2 = v2;
+ edge.crease = 0;
edge.flag = ME_LOOSEEDGE;
return edge;
}
@@ -286,6 +288,7 @@ static void extrude_mesh_vertices(Mesh &mesh,
for (const int i : range) {
const float3 offset = offsets[selection[i]];
add_v3_v3(new_verts[i].co, offset);
+ new_verts[i].flag = 0;
}
});
});
@@ -608,6 +611,7 @@ static void extrude_mesh_edges(Mesh &mesh,
threading::parallel_for(new_verts.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
add_v3_v3(new_verts[i].co, offset);
+ new_verts[i].flag = 0;
}
});
}
@@ -615,6 +619,7 @@ static void extrude_mesh_edges(Mesh &mesh,
threading::parallel_for(new_verts.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
add_v3_v3(new_verts[i].co, vert_offsets[new_vert_indices[i]]);
+ new_verts[i].flag = 0;
}
});
}
@@ -996,6 +1001,10 @@ static void extrude_mesh_face_regions(Mesh &mesh,
});
}
+ for (MVert &vert : verts.slice(new_vert_range)) {
+ vert.flag = 0;
+ }
+
MutableSpan<int> vert_orig_indices = get_orig_index_layer(mesh, ATTR_DOMAIN_POINT);
vert_orig_indices.slice(new_vert_range).fill(ORIGINDEX_NONE);
@@ -1253,6 +1262,7 @@ static void extrude_individual_mesh_faces(Mesh &mesh,
const IndexRange poly_corner_range = selected_corner_range(index_offsets, i_selection);
for (MVert &vert : new_verts.slice(poly_corner_range)) {
add_v3_v3(vert.co, poly_offset[poly_selection[i_selection]]);
+ vert.flag = 0;
}
}
});