Sculpt: Push multiple undo nodes at once for some operations

For the draw face set brush, dynamic topology remesh, and "Show All",
push all the affected nodes in one call. This helps to decrease overhead
from multithreading and data access.
This commit is contained in:
Hans Goudey
2024-09-04 13:10:31 -04:00
parent c21ec8221d
commit d7d19ec297
3 changed files with 53 additions and 53 deletions

View File

@@ -177,8 +177,9 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> corner_tris = mesh.corner_tri_faces();
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
MutableSpan<int> face_sets = attribute.span;
undo::push_nodes(depsgraph, object, node_mask, undo::Type::FaceSet);
bke::SpanAttributeWriter<int> face_sets = face_set::ensure_face_sets_mesh(object);
threading::EnumerableThreadSpecific<MeshLocalData> all_tls;
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
@@ -188,8 +189,6 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
const Span<int> face_indices = bke::pbvh::node_face_indices_calc_mesh(
corner_tris, nodes[i], tls.face_indices);
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
calc_faces(depsgraph,
object,
brush,
@@ -199,11 +198,11 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
nodes[i],
face_indices,
tls,
face_sets);
face_sets.span);
});
});
attribute.finish();
face_sets.finish();
}
struct GridLocalData {
@@ -278,16 +277,15 @@ static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph,
{
SculptSession &ss = *object.sculpt;
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
MutableSpan<int> face_sets = attribute.span;
undo::push_nodes(depsgraph, object, node_mask, undo::Type::FaceSet);
bke::SpanAttributeWriter<int> face_sets = face_set::ensure_face_sets_mesh(object);
threading::EnumerableThreadSpecific<GridLocalData> all_tls;
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
GridLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
calc_grids(depsgraph,
object,
brush,
@@ -295,10 +293,10 @@ static void do_draw_face_sets_brush_grids(const Depsgraph &depsgraph,
ss.cache->paint_face_set,
nodes[i],
tls,
face_sets);
face_sets.span);
});
});
attribute.finish();
face_sets.finish();
}
struct BMeshLocalData {
Vector<float3> positions;
@@ -409,6 +407,9 @@ static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph,
const IndexMask &node_mask)
{
SculptSession &ss = *object.sculpt;
undo::push_nodes(depsgraph, object, node_mask, undo::Type::FaceSet);
const int cd_offset = face_set::ensure_face_sets_bmesh(object);
threading::EnumerableThreadSpecific<BMeshLocalData> all_tls;
@@ -416,7 +417,6 @@ static void do_draw_face_sets_brush_bmesh(const Depsgraph &depsgraph,
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
BMeshLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
calc_bmesh(
object, brush, ss.cache->bstrength, ss.cache->paint_face_set, nodes[i], tls, cd_offset);
});

View File

@@ -128,20 +128,21 @@ void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
Mesh &mesh = *static_cast<Mesh *>(object.data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
if (const VArray<bool> attribute = *attributes.lookup<bool>(".hide_vert",
bke::AttrDomain::Point))
{
const VArraySpan hide_vert(attribute);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
if (std::any_of(verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; })) {
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
BKE_pbvh_node_mark_rebuild_draw(nodes[i]);
}
});
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); });
const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
if (!hide_vert.is_empty()) {
IndexMaskMemory memory;
const IndexMask changed_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1), memory, [&](const int i) {
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
return std::any_of(
verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; });
});
undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_mark_rebuild_draw(nodes[i]); });
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); });
attributes.remove(".hide_vert");
bke::mesh_hide_vert_flush(mesh);
}
@@ -152,25 +153,24 @@ void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
bool any_changed = false;
if (!grid_hidden.is_empty()) {
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
if (std::any_of(grids.begin(), grids.end(), [&](const int i) {
return bits::any_bit_set(grid_hidden[i]);
}))
{
any_changed = true;
undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
BKE_pbvh_node_mark_rebuild_draw(nodes[i]);
}
});
}
if (!any_changed) {
return;
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); });
if (!grid_hidden.is_empty()) {
IndexMaskMemory memory;
const IndexMask changed_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1), memory, [&](const int i) {
const Span<int> grids = bke::pbvh::node_grid_indices(nodes[i]);
return std::any_of(grids.begin(), grids.end(), [&](const int i) {
return bits::any_bit_set(grid_hidden[i]);
});
});
if (changed_nodes.is_empty()) {
return;
}
undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
changed_nodes.foreach_index([&](const int i) { BKE_pbvh_node_mark_rebuild_draw(nodes[i]); });
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_fully_hidden_set(nodes[i], false); });
BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg);
BKE_pbvh_sync_visibility_from_verts(object);
multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED);

View File

@@ -3275,15 +3275,15 @@ static void dynamic_topology_update(const Depsgraph &depsgraph,
}
}
node_mask.foreach_index([&](const int i) {
undo::push_node(depsgraph,
ob,
&nodes[i],
brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK ? undo::Type::Mask :
undo::Type::Position);
BKE_pbvh_node_mark_update(nodes[i]);
BKE_pbvh_node_mark_topology_update(nodes[i]);
if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK) {
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Mask);
}
else {
undo::push_nodes(depsgraph, ob, node_mask, undo::Type::Position);
}
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update(nodes[i]); });
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); });
node_mask.foreach_index(GrainSize(1), [&](const int i) {
BKE_pbvh_bmesh_node_save_orig(ss.bm, ss.bm_log, &nodes[i], false);
});