Sculpt: Only re-upload mask attribute data

Similar to the previous commits, previously all GPU buffers
were recreated when only masks changed. Now only
that masks are re-uploaded, using the same mechanism.

Part of #118145.
This commit is contained in:
Hans Goudey
2024-09-13 22:25:27 -04:00
parent 30c1475dfd
commit 76c322047e
12 changed files with 195 additions and 97 deletions

View File

@@ -179,6 +179,7 @@ class DrawCache {
virtual ~DrawCache() = default;
virtual void tag_positions_changed(const IndexMask &node_mask) = 0;
virtual void tag_face_sets_changed(const IndexMask &node_mask) = 0;
virtual void tag_masks_changed(const IndexMask &node_mask) = 0;
virtual void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) = 0;
};
@@ -240,6 +241,9 @@ class Tree {
/** Tag nodes where face sets have changed, causing refresh of derived data. */
void tag_face_sets_changed(const IndexMask &node_mask);
/** Tag nodes where mask values have changed, causing refresh of derived data. */
void tag_masks_changed(const IndexMask &node_mask);
/**
* Tag nodes where generic attribute data has changed (not positions, masks, or face sets).
*/
@@ -406,7 +410,6 @@ bool bmesh_update_topology(BMesh &bm,
/* Node Access */
void BKE_pbvh_node_mark_update(blender::bke::pbvh::Node &node);
void BKE_pbvh_node_mark_update_mask(blender::bke::pbvh::Node &node);
void BKE_pbvh_node_mark_update_visibility(blender::bke::pbvh::Node &node);
void BKE_pbvh_node_mark_rebuild_draw(blender::bke::pbvh::Node &node);
void BKE_pbvh_node_mark_redraw(blender::bke::pbvh::Node &node);

View File

@@ -571,6 +571,13 @@ void Tree::tag_face_sets_changed(const IndexMask &node_mask)
}
}
void Tree::tag_masks_changed(const IndexMask &node_mask)
{
if (this->draw_data) {
this->draw_data->tag_masks_changed(node_mask);
}
}
void Tree::tag_attribute_changed(const IndexMask &node_mask, const StringRef attribute_name)
{
if (this->draw_data) {
@@ -1512,11 +1519,6 @@ void BKE_pbvh_node_mark_update(blender::bke::pbvh::Node &node)
node.flag_ |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw | PBVH_RebuildPixels;
}
void BKE_pbvh_node_mark_update_mask(blender::bke::pbvh::Node &node)
{
node.flag_ |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
}
void BKE_pbvh_mark_rebuild_pixels(blender::bke::pbvh::Tree &pbvh)
{
std::visit(

View File

@@ -141,6 +141,7 @@ class DrawCacheImpl : public DrawCache {
void tag_all_attributes_dirty(const IndexMask &node_mask) override;
void tag_positions_changed(const IndexMask &node_mask) override;
void tag_face_sets_changed(const IndexMask &node_mask) override;
void tag_masks_changed(const IndexMask &node_mask) override;
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) override;
Span<gpu::Batch *> ensure_tris_batches(const Object &object,
@@ -212,6 +213,13 @@ void DrawCacheImpl::tag_face_sets_changed(const IndexMask &node_mask)
}
}
void DrawCacheImpl::tag_masks_changed(const IndexMask &node_mask)
{
if (DrawCacheImpl::AttributeData *data = attribute_vbos_.lookup_ptr(CustomRequest::Mask)) {
data->tag_dirty(node_mask);
}
}
void DrawCacheImpl::tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
{
for (const auto &[data_request, data] : attribute_vbos_.items()) {

View File

@@ -245,7 +245,6 @@ void do_mask_brush(const Depsgraph &depsgraph,
tls,
mask.span);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
mask.finish();
@@ -261,7 +260,6 @@ void do_mask_brush(const Depsgraph &depsgraph,
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, object, brush, bstrength, nodes[i], tls);
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
@@ -275,11 +273,12 @@ void do_mask_brush(const Depsgraph &depsgraph,
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, object, brush, bstrength, nodes[i], tls);
bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
}
}
pbvh.tag_masks_changed(node_mask);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -172,10 +172,10 @@ static void do_smooth_brush_mesh(const Depsgraph &depsgraph,
tls,
new_masks.as_span().slice(node_vert_offsets[pos]),
mask.span);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
}
bke::pbvh::update_mask_mesh(mesh, node_mask, pbvh);
pbvh.tag_masks_changed(node_mask);
mask.finish();
}
@@ -306,13 +306,12 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_grids(depsgraph, object, brush, strength, nodes[i], tls);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
node_mask.slice(range).foreach_index(
[&](const int i) { calc_grids(depsgraph, object, brush, strength, nodes[i], tls); });
});
}
bke::pbvh::update_mask_grids(*ss.subdiv_ccg, node_mask, pbvh);
pbvh.tag_masks_changed(node_mask);
break;
}
case bke::pbvh::Type::BMesh: {
@@ -327,13 +326,14 @@ void do_smooth_mask_brush(const Depsgraph &depsgraph,
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
calc_bmesh(depsgraph, object, mask_offset, brush, strength, nodes[i], tls);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
}
bke::pbvh::update_mask_bmesh(*ss.bm, node_mask, pbvh);
pbvh.tag_masks_changed(node_mask);
break;
}
}
}
} // namespace blender::ed::sculpt_paint

View File

@@ -201,6 +201,8 @@ void update_mask_mesh(const Depsgraph &depsgraph,
Vector<float> mask;
};
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::EnumerableThreadSpecific<LocalData> all_tls;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
LocalData &tls = all_tls.local();
@@ -215,10 +217,13 @@ void update_mask_mesh(const Depsgraph &depsgraph,
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_mesh(tls.mask.as_span(), verts, mask.span);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
BKE_pbvh_node_mark_redraw(nodes[i]);
node_changed[i] = true;
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
mask.finish();
}
@@ -350,21 +355,21 @@ static bool try_remove_mask_mesh(const Depsgraph &depsgraph,
return false;
}
/* Store undo data for nodes with changed mask. */
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> verts = nodes[i].verts();
if (std::all_of(verts.begin(), verts.end(), [&](const int i) { return mask[i] == 0.0f; })) {
return;
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
BKE_pbvh_node_mark_redraw(nodes[i]);
});
IndexMaskMemory memory;
const IndexMask changed_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1), memory, [&](const int i) {
const Span<int> verts = nodes[i].verts();
return std::any_of(
verts.begin(), verts.end(), [&](const int i) { return mask[i] != 0.0f; });
});
undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::Mask);
attributes.remove(".sculpt_mask");
node_mask.foreach_index([&](const int i) {
changed_nodes.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], false);
BKE_pbvh_node_fully_unmasked_set(nodes[i], true);
});
pbvh.tag_masks_changed(changed_nodes);
return true;
}
@@ -388,6 +393,8 @@ static void fill_mask_mesh(const Depsgraph &depsgraph,
bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
".sculpt_mask", bke::AttrDomain::Point);
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::EnumerableThreadSpecific<Vector<int>> all_index_data;
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
Vector<int> &index_data = all_index_data.local();
@@ -398,12 +405,16 @@ static void fill_mask_mesh(const Depsgraph &depsgraph,
}
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
mask.span.fill_indices(verts, value);
BKE_pbvh_node_mark_redraw(nodes[i]);
node_changed[i] = true;
});
});
IndexMaskMemory memory;
const IndexMask changed_nodes = IndexMask::from_bools(node_mask, node_changed, memory);
pbvh.tag_masks_changed(changed_nodes);
mask.finish();
node_mask.foreach_index([&](const int i) {
changed_nodes.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f);
});
@@ -433,8 +444,9 @@ static void fill_mask_grids(Main &bmain,
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
Array<bool> node_changed(node_mask.min_array_size(), false);
MutableSpan<float> masks = subdiv_ccg.masks;
bool any_changed = false;
node_mask.foreach_index(GrainSize(1), [&](const int i) {
const Span<int> grid_indices = nodes[i].grids();
if (std::all_of(grid_indices.begin(), grid_indices.end(), [&](const int grid) {
@@ -459,14 +471,17 @@ static void fill_mask_grids(Main &bmain,
bits::foreach_0_index(grid_hidden[grid], [&](const int i) { grid_masks[i] = value; });
}
}
BKE_pbvh_node_mark_redraw(nodes[i]);
any_changed = true;
node_changed[i] = true;
});
if (any_changed) {
multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED);
IndexMaskMemory memory;
const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
if (node_changed.is_empty()) {
return;
}
node_mask.foreach_index([&](const int i) {
pbvh.tag_masks_changed(changed_nodes);
multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED);
changed_nodes.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f);
});
@@ -492,22 +507,31 @@ static void fill_mask_bmesh(const Depsgraph &depsgraph,
return;
}
undo::push_nodes(depsgraph, object, node_mask, undo::Type::Mask);
Array<bool> node_changed(node_mask.min_array_size(), false);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
bool redraw = false;
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
bool changed = false;
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
if (!BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
if (BM_ELEM_CD_GET_FLOAT(vert, offset) != value) {
BM_ELEM_CD_SET_FLOAT(vert, offset, value);
redraw = true;
changed = true;
}
}
}
if (redraw) {
BKE_pbvh_node_mark_redraw(nodes[i]);
if (changed) {
node_changed[i] = true;
}
});
node_mask.foreach_index([&](const int i) {
IndexMaskMemory memory;
const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
if (node_changed.is_empty()) {
return;
}
pbvh.tag_masks_changed(changed_nodes);
changed_nodes.foreach_index([&](const int i) {
BKE_pbvh_node_fully_masked_set(nodes[i], value == 1.0f);
BKE_pbvh_node_fully_unmasked_set(nodes[i], value == 0.0f);
});
@@ -569,9 +593,9 @@ static void invert_mask_grids(Main &bmain,
[&](const int i) { grid_masks[i] = 1.0f - grid_masks[i]; });
}
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
});
pbvh.tag_masks_changed(node_mask);
multires_mark_as_modified(&depsgraph, &object, MULTIRES_COORDS_MODIFIED);
}
@@ -596,9 +620,9 @@ static void invert_mask_bmesh(const Depsgraph &depsgraph,
BM_ELEM_CD_SET_FLOAT(vert, offset, 1.0f - BM_ELEM_CD_GET_FLOAT(vert, offset));
}
}
BKE_pbvh_node_mark_update_mask(nodes[i]);
bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
});
pbvh.tag_masks_changed(node_mask);
}
static void invert_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object)
@@ -747,6 +771,9 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
MutableSpan<float> masks = subdiv_ccg.masks;
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.slice(range).foreach_index([&](const int i) {
bool any_changed = false;
@@ -763,11 +790,16 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
mask = mask_gesture_get_new_value(mask, op.mode, op.value);
}
});
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
if (any_changed) {
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
node_changed[i] = true;
}
}
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
case bke::pbvh::Type::BMesh: {
@@ -775,6 +807,9 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *gesture_data.ss->bm;
const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
node_mask.slice(range).foreach_index([&](const int i) {
bool any_changed = false;
@@ -789,10 +824,15 @@ static void gesture_apply_for_symmetry_pass(bContext & /*C*/, gesture::GestureDa
BM_ELEM_CD_SET_FLOAT(vert, offset, new_mask);
}
}
bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
if (any_changed) {
bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
node_changed[i] = true;
}
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
}

View File

@@ -1212,6 +1212,8 @@ static void restore_mask_from_undo_step(Object &object)
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
Array<bool> node_changed(node_mask.min_array_size(), false);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
@@ -1226,7 +1228,7 @@ static void restore_mask_from_undo_step(Object &object)
const Span<int> verts = nodes[i].verts();
array_utils::scatter(*orig_data, verts, mask.span);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
node_changed[i] = true;
}
});
mask.finish();
@@ -1241,7 +1243,7 @@ static void restore_mask_from_undo_step(Object &object)
if (const float *orig_mask = BM_log_find_original_vert_mask(ss.bm_log, vert)) {
BM_ELEM_CD_SET_FLOAT(vert, offset, *orig_mask);
bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
node_changed[i] = true;
}
}
});
@@ -1269,12 +1271,13 @@ static void restore_mask_from_undo_step(Object &object)
}
}
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
node_changed[i] = true;
}
});
break;
}
}
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
}
static void restore_color_from_undo_step(Object &object)
@@ -1303,6 +1306,7 @@ static void restore_color_from_undo_step(Object &object)
verts[i],
(*orig_data)[i],
color_attribute.span);
// TODO
}
}
});
@@ -1466,6 +1470,7 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
break;
}
}
// TODO
pbvh.tag_positions_changed(node_mask);
/* Update normals for potentially-changed positions. Theoretically this may be unnecessary if

View File

@@ -1467,32 +1467,26 @@ static void write_mask_data(Object &object, const Span<float> mask)
bke::AttrDomain::Point,
bke::AttributeInitVArray(VArray<float>::ForSpan(mask)));
bke::pbvh::update_mask_mesh(mesh, node_mask, pbvh);
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ss.bm;
const int offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
BM_mesh_elem_table_ensure(&bm, BM_VERT);
for (const int i : mask.index_range()) {
BM_ELEM_CD_SET_FLOAT(BM_vert_at_index(&bm, i), offset, mask[i]);
}
bke::pbvh::update_mask_bmesh(bm, node_mask, pbvh);
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
subdiv_ccg.masks.as_mutable_span().copy_from(mask);
bke::pbvh::update_mask_grids(subdiv_ccg, node_mask, pbvh);
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_mask(nodes[i]); });
break;
}
}
pbvh.tag_masks_changed(node_mask);
}
/* Main function to restore the original state of the data to how it was before starting the expand
@@ -1572,7 +1566,7 @@ static void calc_new_mask_mesh(const SculptSession &ss,
mask::clamp_mask(mask);
}
static void update_mask_grids(const SculptSession &ss,
static bool update_mask_grids(const SculptSession &ss,
const BitSpan enabled_verts,
bke::pbvh::GridsNode &node,
SubdivCCG &subdiv_ccg)
@@ -1618,12 +1612,12 @@ static void update_mask_grids(const SculptSession &ss,
}
}
if (any_changed) {
BKE_pbvh_node_mark_update_mask(node);
bke::pbvh::node_update_mask_grids(key, masks, node);
}
return any_changed;
}
static void update_mask_bmesh(SculptSession &ss,
static bool update_mask_bmesh(SculptSession &ss,
const BitSpan enabled_verts,
const int mask_offset,
bke::pbvh::BMeshNode *node)
@@ -1665,9 +1659,9 @@ static void update_mask_bmesh(SculptSession &ss,
any_changed = true;
}
if (any_changed) {
BKE_pbvh_node_mark_update_mask(*node);
bke::pbvh::node_update_mask_bmesh(mask_offset, *node);
}
return any_changed;
}
/**
@@ -1866,19 +1860,29 @@ static void update_for_vert(bContext *C, Object &ob, const std::optional<int> ve
break;
}
case bke::pbvh::Type::Grids: {
Array<bool> node_changed(node_mask.min_array_size(), false);
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index(GrainSize(1), [&](const int i) {
update_mask_grids(ss, enabled_verts, nodes[i], *ss.subdiv_ccg);
node_changed[i] = update_mask_grids(ss, enabled_verts, nodes[i], *ss.subdiv_ccg);
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
case bke::pbvh::Type::BMesh: {
const int mask_offset = CustomData_get_offset_named(
&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
Array<bool> node_changed(node_mask.min_array_size(), false);
node_mask.foreach_index(GrainSize(1), [&](const int i) {
update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]);
node_changed[i] = update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]);
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
}

View File

@@ -117,6 +117,9 @@ static void apply_new_mask_mesh(const Depsgraph &depsgraph,
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
threading::EnumerableThreadSpecific<Vector<int>> all_tls;
Array<bool> node_changed(node_mask.min_array_size(), false);
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
Vector<int> &tls = all_tls.local();
const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, tls);
@@ -127,8 +130,11 @@ static void apply_new_mask_mesh(const Depsgraph &depsgraph,
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_mesh(new_node_mask, verts, mask);
bke::pbvh::node_update_mask_mesh(mask, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
node_changed[i] = true;
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
}
static void smooth_mask_mesh(const OffsetIndices<int> faces,
@@ -219,7 +225,7 @@ static void shrink_mask_mesh(const OffsetIndices<int> faces,
}
}
static void increase_contrast_mask_mesh(const Depsgraph &depsgraph,
static bool increase_contrast_mask_mesh(const Depsgraph &depsgraph,
const Object &object,
const Span<bool> hide_vert,
bke::pbvh::MeshNode &node,
@@ -235,16 +241,16 @@ static void increase_contrast_mask_mesh(const Depsgraph &depsgraph,
mask_increase_contrast(node_mask, new_mask);
if (node_mask == new_mask.as_span()) {
return;
return false;
}
undo::push_node(depsgraph, object, &node, undo::Type::Mask);
scatter_data_mesh(new_mask.as_span(), verts, mask);
bke::pbvh::node_update_mask_mesh(mask, node);
BKE_pbvh_node_mark_update_mask(node);
return true;
}
static void decrease_contrast_mask_mesh(const Depsgraph &depsgraph,
static bool decrease_contrast_mask_mesh(const Depsgraph &depsgraph,
const Object &object,
const Span<bool> hide_vert,
bke::pbvh::MeshNode &node,
@@ -260,13 +266,13 @@ static void decrease_contrast_mask_mesh(const Depsgraph &depsgraph,
mask_decrease_contrast(node_mask, new_mask);
if (node_mask == new_mask.as_span()) {
return;
return false;
}
undo::push_node(depsgraph, object, &node, undo::Type::Mask);
scatter_data_mesh(new_mask.as_span(), verts, mask);
bke::pbvh::node_update_mask_mesh(mask, node);
BKE_pbvh_node_mark_update_mask(node);
return true;
}
BLI_NOINLINE static void copy_old_hidden_mask_grids(const SubdivCCG &subdiv_ccg,
@@ -300,6 +306,8 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph,
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
MutableSpan<float> masks = subdiv_ccg.masks;
Array<bool> node_changed(node_mask.min_array_size(), false);
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
const Span<int> grids = nodes[i].grids();
const Span<float> new_node_mask = new_mask.slice(node_verts[pos]);
@@ -309,9 +317,12 @@ static void apply_new_mask_grids(const Depsgraph &depsgraph,
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_data_grids(subdiv_ccg, new_node_mask, grids, masks);
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
node_changed[i] = true;
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
/* New mask values need propagation across grid boundaries. */
BKE_subdiv_ccg_average_grids(subdiv_ccg);
}
@@ -412,7 +423,7 @@ static void shrink_mask_grids(const SubdivCCG &subdiv_ccg,
copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask);
}
static void increase_contrast_mask_grids(const Depsgraph &depsgraph,
static bool increase_contrast_mask_grids(const Depsgraph &depsgraph,
const Object &object,
bke::pbvh::GridsNode &node,
FilterLocalData &tls)
@@ -435,16 +446,16 @@ static void increase_contrast_mask_grids(const Depsgraph &depsgraph,
copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask);
if (node_mask.as_span() == new_mask.as_span()) {
return;
return false;
}
undo::push_node(depsgraph, object, &node, undo::Type::Mask);
scatter_data_grids(subdiv_ccg, new_mask.as_span(), grids, subdiv_ccg.masks.as_mutable_span());
bke::pbvh::node_update_mask_grids(key, subdiv_ccg.masks, node);
BKE_pbvh_node_mark_update_mask(node);
return true;
}
static void decrease_contrast_mask_grids(const Depsgraph &depsgraph,
static bool decrease_contrast_mask_grids(const Depsgraph &depsgraph,
const Object &object,
bke::pbvh::GridsNode &node,
FilterLocalData &tls)
@@ -467,13 +478,13 @@ static void decrease_contrast_mask_grids(const Depsgraph &depsgraph,
copy_old_hidden_mask_grids(subdiv_ccg, grids, new_mask);
if (node_mask.as_span() == new_mask.as_span()) {
return;
return false;
}
undo::push_node(depsgraph, object, &node, undo::Type::Mask);
scatter_data_grids(subdiv_ccg, new_mask.as_span(), grids, subdiv_ccg.masks.as_mutable_span());
bke::pbvh::node_update_mask_grids(key, subdiv_ccg.masks, node);
BKE_pbvh_node_mark_update_mask(node);
return true;
}
BLI_NOINLINE static void copy_old_hidden_mask_bmesh(const int mask_offset,
@@ -501,6 +512,8 @@ static void apply_new_mask_bmesh(const Depsgraph &depsgraph,
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
BMesh &bm = *ss.bm;
Array<bool> node_changed(node_mask.min_array_size(), false);
node_mask.foreach_index(GrainSize(1), [&](const int i, const int pos) {
const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(&nodes[i]);
const Span<float> new_node_mask = new_mask.slice(node_verts[pos]);
@@ -510,8 +523,11 @@ static void apply_new_mask_bmesh(const Depsgraph &depsgraph,
undo::push_node(depsgraph, object, &nodes[i], undo::Type::Mask);
scatter_mask_bmesh(new_node_mask, bm, verts);
bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
node_changed[i] = true;
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
}
static void smooth_mask_bmesh(const int mask_offset,
@@ -580,7 +596,7 @@ static void shrink_mask_bmesh(const int mask_offset,
copy_old_hidden_mask_bmesh(mask_offset, verts, new_mask);
}
static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph,
static bool increase_contrast_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const int mask_offset,
bke::pbvh::BMeshNode &node,
@@ -602,16 +618,16 @@ static void increase_contrast_mask_bmesh(const Depsgraph &depsgraph,
copy_old_hidden_mask_bmesh(mask_offset, verts, new_mask);
if (node_mask.as_span() == new_mask.as_span()) {
return;
return false;
}
undo::push_node(depsgraph, object, &node, undo::Type::Mask);
scatter_mask_bmesh(new_mask.as_span(), bm, verts);
bke::pbvh::node_update_mask_bmesh(mask_offset, node);
BKE_pbvh_node_mark_update_mask(node);
return true;
}
static void decrease_contrast_mask_bmesh(const Depsgraph &depsgraph,
static bool decrease_contrast_mask_bmesh(const Depsgraph &depsgraph,
Object &object,
const int mask_offset,
bke::pbvh::BMeshNode &node,
@@ -633,13 +649,13 @@ static void decrease_contrast_mask_bmesh(const Depsgraph &depsgraph,
copy_old_hidden_mask_bmesh(mask_offset, verts, new_mask);
if (node_mask.as_span() == new_mask.as_span()) {
return;
return false;
}
undo::push_node(depsgraph, object, &node, undo::Type::Mask);
scatter_mask_bmesh(new_mask.as_span(), bm, verts);
bke::pbvh::node_update_mask_bmesh(mask_offset, node);
BKE_pbvh_node_mark_update_mask(node);
return true;
}
static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
@@ -762,21 +778,29 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
break;
}
case FilterType::ContrastIncrease: {
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
increase_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span);
node_changed[i] = increase_contrast_mask_mesh(
*depsgraph, ob, hide_vert, nodes[i], tls, mask.span);
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
case FilterType::ContrastDecrease: {
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
decrease_contrast_mask_mesh(*depsgraph, ob, hide_vert, nodes[i], tls, mask.span);
node_changed[i] = decrease_contrast_mask_mesh(
*depsgraph, ob, hide_vert, nodes[i], tls, mask.span);
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
}
@@ -829,21 +853,27 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
break;
}
case FilterType::ContrastIncrease: {
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
increase_contrast_mask_grids(*depsgraph, ob, nodes[i], tls);
node_changed[i] = increase_contrast_mask_grids(*depsgraph, ob, nodes[i], tls);
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
case FilterType::ContrastDecrease: {
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
decrease_contrast_mask_grids(*depsgraph, ob, nodes[i], tls);
node_changed[i] = decrease_contrast_mask_grids(*depsgraph, ob, nodes[i], tls);
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
}
@@ -901,21 +931,29 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op)
break;
}
case FilterType::ContrastIncrease: {
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
increase_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls);
node_changed[i] = increase_contrast_mask_bmesh(
*depsgraph, ob, mask_offset, nodes[i], tls);
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
case FilterType::ContrastDecrease: {
Array<bool> node_changed(node_mask.min_array_size(), false);
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
FilterLocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
decrease_contrast_mask_bmesh(*depsgraph, ob, mask_offset, nodes[i], tls);
node_changed[i] = decrease_contrast_mask_bmesh(
*depsgraph, ob, mask_offset, nodes[i], tls);
});
});
IndexMaskMemory memory;
pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
break;
}
}

View File

@@ -71,10 +71,10 @@ void write_mask_mesh(const Depsgraph &depsgraph,
Vector<int> &index_data = all_index_data.local();
node_mask.slice(range).foreach_index(GrainSize(1), [&](const int i) {
write_fn(mask.span, hide::node_visible_verts(nodes[i], hide_vert, index_data));
BKE_pbvh_node_mark_redraw(nodes[i]);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
});
});
pbvh.tag_masks_changed(node_mask);
mask.finish();
}
@@ -104,8 +104,8 @@ static void init_mask_grids(
write_fn(grid_hidden, grid, masks.slice(bke::ccg::grid_range(key, grid)));
}
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
pbvh.tag_masks_changed(node_mask);
BKE_subdiv_ccg_average_grids(subdiv_ccg);
}
@@ -256,8 +256,8 @@ static int sculpt_mask_init_exec(bContext *C, wmOperator *op)
}
}
bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
pbvh.tag_masks_changed(node_mask);
break;
}
}

View File

@@ -1179,7 +1179,6 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
LocalData &tls = all_tls.local();
node_mask.slice(range).foreach_index([&](const int i) {
bake_mask_mesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls, mask.span);
BKE_pbvh_node_mark_update_mask(nodes[i]);
bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
});
});
@@ -1195,7 +1194,6 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
node_mask.slice(range).foreach_index([&](const int i) {
bake_mask_grids(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls);
bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
@@ -1209,7 +1207,6 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
node_mask.slice(range).foreach_index([&](const int i) {
bake_mask_bmesh(*depsgraph, ob, *automasking, mode, factor, nodes[i], tls);
bke::pbvh::node_update_mask_bmesh(mask_offset, nodes[i]);
BKE_pbvh_node_mark_update_mask(nodes[i]);
});
});
break;
@@ -1218,6 +1215,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
undo::push_end(ob);
pbvh.tag_masks_changed(node_mask);
flush_update_done(C, ob, UpdateType::Mask);
SCULPT_tag_update_overlays(C);

View File

@@ -735,8 +735,7 @@ static void bmesh_restore_generic(StepData &step_data, Object &object, SculptSes
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
MutableSpan<bke::pbvh::BMeshNode> nodes = pbvh.nodes<bke::pbvh::BMeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
pbvh.tag_masks_changed(node_mask);
}
else {
BKE_sculptsession_free_pbvh(object);
@@ -1139,6 +1138,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
return indices_contain_true(modified_grids, nodes[i].grids());
});
bke::pbvh::update_mask_grids(*ss.subdiv_ccg, changed_nodes, pbvh);
pbvh.tag_masks_changed(changed_nodes);
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
@@ -1152,6 +1152,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
return indices_contain_true(modified_verts, nodes[i].all_verts());
});
bke::pbvh::update_mask_mesh(mesh, changed_nodes, pbvh);
pbvh.tag_masks_changed(changed_nodes);
}
break;
}