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:
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user