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:
authorIliya Katueshenock <Moder>2022-10-08 01:54:05 +0300
committerHans Goudey <h.goudey@me.com>2022-10-08 01:54:24 +0300
commit3d209d161988d6000c2f99fa4051f9a117ffbfd5 (patch)
tree6a71cae3b9ab485e6a98ebddd09932fe1f4ae2cc /source/blender/blenkernel/intern
parentaf288a09a529dc802effe104f09870a4fb48802a (diff)
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
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc80
1 files changed, 45 insertions, 35 deletions
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)