[Bf-blender-cvs] [3d209d16198] master: Mesh: Multithread some boolean domain interpolation logic
Iliya Katueshenock
noreply at git.blender.org
Sat Oct 8 00:54:50 CEST 2022
Commit: 3d209d161988d6000c2f99fa4051f9a117ffbfd5
Author: Iliya Katueshenock
Date: Fri Oct 7 17:54:05 2022 -0500
Branches: master
https://developer.blender.org/rB3d209d161988d6000c2f99fa4051f9a117ffbfd5
Mesh: Multithread some boolean domain interpolation logic
This can improve performance by 3-10x in some simple test cases,
when reading a boolean attribute on a different domain from the
one it's stored on.
Differential Revision: https://developer.blender.org/D16054
===================================================================
M source/blender/blenkernel/intern/geometry_component_mesh.cc
===================================================================
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 228c27cedf7..8fb33198fc1 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -213,11 +213,15 @@ void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh,
}
/* Deselect loose vertices without corners that are still selected from the 'true' default. */
- for (const int vert_index : IndexRange(mesh.totvert)) {
- if (loose_verts[vert_index]) {
- r_values[vert_index] = false;
+ /* The record fact says that the value is true.
+ *Writing to the array from different threads is okay because each thread sets the same value. */
+ threading::parallel_for(loose_verts.index_range(), 2048, [&](const IndexRange range) {
+ for (const int vert_index : range) {
+ if (loose_verts[vert_index]) {
+ r_values[vert_index] = false;
+ }
}
- }
+ });
}
static GVArray adapt_mesh_domain_corner_to_point(const Mesh &mesh, const GVArray &varray)
@@ -413,16 +417,16 @@ void adapt_mesh_domain_face_to_point_impl(const Mesh &mesh,
const Span<MLoop> loops = mesh.loops();
r_values.fill(false);
- for (const int poly_index : polys.index_range()) {
- const MPoly &poly = polys[poly_index];
- if (old_values[poly_index]) {
- for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
- const MLoop &loop = loops[loop_index];
- const int vert_index = loop.v;
- r_values[vert_index] = true;
+ threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
+ for (const int poly_index : range) {
+ if (old_values[poly_index]) {
+ const MPoly &poly = polys[poly_index];
+ for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
+ r_values[loop.v] = true;
+ }
}
}
- }
+ });
}
static GVArray adapt_mesh_domain_face_to_point(const Mesh &mesh, const GVArray &varray)
@@ -502,16 +506,16 @@ void adapt_mesh_domain_face_to_edge_impl(const Mesh &mesh,
const Span<MLoop> loops = mesh.loops();
r_values.fill(false);
- for (const int poly_index : polys.index_range()) {
- const MPoly &poly = polys[poly_index];
- if (old_values[poly_index]) {
- for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
- const MLoop &loop = loops[loop_index];
- const int edge_index = loop.e;
- r_values[edge_index] = true;
+ threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
+ for (const int poly_index : range) {
+ if (old_values[poly_index]) {
+ const MPoly &poly = polys[poly_index];
+ for (const MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
+ r_values[loop.e] = true;
+ }
}
}
- }
+ });
}
static GVArray adapt_mesh_domain_face_to_edge(const Mesh &mesh, const GVArray &varray)
@@ -642,17 +646,19 @@ void adapt_mesh_domain_edge_to_corner_impl(const Mesh &mesh,
r_values.fill(false);
- for (const int poly_index : polys.index_range()) {
- const MPoly &poly = polys[poly_index];
- for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
- const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop;
- const MLoop &loop = loops[loop_index];
- const MLoop &loop_prev = loops[loop_index_prev];
- if (old_values[loop.e] && old_values[loop_prev.e]) {
- r_values[loop_index] = true;
+ threading::parallel_for(polys.index_range(), 2048, [&](const IndexRange range) {
+ for (const int poly_index : range) {
+ const MPoly &poly = polys[poly_index];
+ for (const int loop_index : IndexRange(poly.loopstart, poly.totloop)) {
+ const int loop_index_prev = loop_index - 1 + (loop_index == poly.loopstart) * poly.totloop;
+ const MLoop &loop = loops[loop_index];
+ const MLoop &loop_prev = loops[loop_index_prev];
+ if (old_values[loop.e] && old_values[loop_prev.e]) {
+ r_values[loop_index] = true;
+ }
}
}
- }
+ });
}
static GVArray adapt_mesh_domain_edge_to_corner(const Mesh &mesh, const GVArray &varray)
@@ -697,14 +703,18 @@ void adapt_mesh_domain_edge_to_point_impl(const Mesh &mesh,
BLI_assert(r_values.size() == mesh.totvert);
const Span<MEdge> edges = mesh.edges();
+ /* Multiple threads can write to the same index here, but they are only
+ * writing true, and writing to single bytes is expected to be threadsafe. */
r_values.fill(false);
- for (const int edge_index : edges.index_range()) {
- const MEdge &edge = edges[edge_index];
- if (old_values[edge_index]) {
- r_values[edge.v1] = true;
- r_values[edge.v2] = true;
+ threading::parallel_for(edges.index_range(), 4096, [&](const IndexRange range) {
+ for (const int edge_index : range) {
+ if (old_values[edge_index]) {
+ const MEdge &edge = edges[edge_index];
+ r_values[edge.v1] = true;
+ r_values[edge.v2] = true;
+ }
}
- }
+ });
}
static GVArray adapt_mesh_domain_edge_to_point(const Mesh &mesh, const GVArray &varray)
More information about the Bf-blender-cvs
mailing list