Sculpt: Only re-upload face set data when changed

Similar to the previous commit, previously all GPU buffers
were recreated when only face sets changed. Now only face
sets are re-uploaded, using the same mechanism.

Part of #118145.
This commit is contained in:
Hans Goudey
2024-09-13 16:36:05 -04:00
parent 0c677e9494
commit 60ab232afb
8 changed files with 62 additions and 66 deletions

View File

@@ -177,6 +177,7 @@ class DrawCache {
public:
virtual ~DrawCache() = default;
virtual void tag_positions_changed(const IndexMask &node_mask) = 0;
virtual void tag_face_sets_changed(const IndexMask &node_mask) = 0;
};
/**
@@ -233,6 +234,9 @@ class Tree {
* \warning Must not be called from multiple threads in parallel.
*/
void tag_positions_changed(const IndexMask &node_mask);
/** Tag nodes where face sets have changed, causing refresh of derived data. */
void tag_face_sets_changed(const IndexMask &node_mask);
};
} // namespace blender::bke::pbvh
@@ -397,7 +401,6 @@ bool bmesh_update_topology(BMesh &bm,
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_color(blender::bke::pbvh::Node &node);
void BKE_pbvh_node_mark_update_face_sets(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

@@ -560,6 +560,13 @@ void Tree::tag_positions_changed(const IndexMask &node_mask)
}
}
void Tree::tag_face_sets_changed(const IndexMask &node_mask)
{
if (this->draw_data) {
this->draw_data->tag_face_sets_changed(node_mask);
}
}
static bool tree_is_empty(const Tree &pbvh)
{
return std::visit([](const auto &nodes) { return nodes.is_empty(); }, pbvh.nodes_);
@@ -1540,11 +1547,6 @@ void BKE_pbvh_node_mark_update_color(blender::bke::pbvh::Node &node)
node.flag_ |= PBVH_UpdateColor | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
}
void BKE_pbvh_node_mark_update_face_sets(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

@@ -140,6 +140,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;
Span<gpu::Batch *> ensure_tris_batches(const Object &object,
const ViewportRequest &request,
@@ -203,6 +204,13 @@ void DrawCacheImpl::tag_positions_changed(const IndexMask &node_mask)
}
}
void DrawCacheImpl::tag_face_sets_changed(const IndexMask &node_mask)
{
if (DrawCacheImpl::AttributeData *data = attribute_vbos_.lookup_ptr(CustomRequest::FaceSet)) {
data->tag_dirty(node_mask);
}
}
DrawCache &ensure_draw_data(std::unique_ptr<bke::pbvh::DrawCache> &ptr)
{
if (!ptr) {

View File

@@ -195,10 +195,9 @@ static void do_draw_face_sets_brush_mesh(const Depsgraph &depsgraph,
face_indices,
tls,
face_sets.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
});
});
pbvh.tag_face_sets_changed(node_mask);
face_sets.finish();
}

View File

@@ -1313,6 +1313,8 @@ static void restore_face_set_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>();
@@ -1323,7 +1325,7 @@ static void restore_face_set_from_undo_step(Object &object)
nodes[i]))
{
scatter_data_mesh(*orig_data, nodes[i].faces(), attribute.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
}
});
attribute.finish();
@@ -1343,7 +1345,7 @@ static void restore_face_set_from_undo_step(Object &object)
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
subdiv_ccg, nodes[i], tls);
scatter_data_mesh(*orig_data, faces, attribute.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
}
});
attribute.finish();
@@ -1352,6 +1354,8 @@ static void restore_face_set_from_undo_step(Object &object)
case bke::pbvh::Type::BMesh:
break;
}
pbvh.tag_face_sets_changed(IndexMask::from_bools(node_changed, memory));
}
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)

View File

@@ -1422,22 +1422,7 @@ static void restore_face_set_data(Object &object, Cache &expand_cache)
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::Grids: {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
break;
}
case bke::pbvh::Type::BMesh: {
BLI_assert_unreachable();
break;
}
}
pbvh.tag_face_sets_changed(node_mask);
}
static void restore_color_data(Object &ob, Cache &expand_cache)
@@ -1708,9 +1693,7 @@ static void face_sets_update(Object &object, Cache &expand_cache)
face_sets.finish();
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
expand_cache.node_mask.foreach_index(
[&](const int i) { BKE_pbvh_node_mark_update_face_sets(nodes[i]); });
pbvh.tag_face_sets_changed(expand_cache.node_mask);
}
/**

View File

@@ -294,6 +294,8 @@ static void face_sets_update(const Depsgraph &depsgraph,
Vector<int> new_face_sets;
};
Array<bool> node_changed(pbvh.nodes_num(), false);
threading::EnumerableThreadSpecific<TLS> all_tls;
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
@@ -312,7 +314,7 @@ static void face_sets_update(const Depsgraph &depsgraph,
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
});
});
}
@@ -334,11 +336,13 @@ static void face_sets_update(const Depsgraph &depsgraph,
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
array_utils::scatter(new_face_sets.as_span(), faces, face_sets.span);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
});
});
}
IndexMaskMemory memory;
pbvh.tag_face_sets_changed(IndexMask::from_bools(node_changed, memory));
face_sets.finish();
}
@@ -358,6 +362,9 @@ static void clear_face_sets(const Depsgraph &depsgraph, Object &object, const In
}
SculptSession &ss = *object.sculpt;
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
Array<bool> node_changed(pbvh.nodes_num(), false);
const int default_face_set = mesh.face_sets_color_default;
const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
@@ -369,7 +376,7 @@ static void clear_face_sets(const Depsgraph &depsgraph, Object &object, const In
}))
{
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
}
});
}
@@ -386,11 +393,13 @@ static void clear_face_sets(const Depsgraph &depsgraph, Object &object, const In
}))
{
undo::push_node(depsgraph, object, &nodes[i], undo::Type::FaceSet);
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
}
});
});
}
IndexMaskMemory memory;
pbvh.tag_face_sets_changed(IndexMask::from_bools(node_changed, memory));
attributes.remove(".sculpt_face_set");
}
@@ -774,14 +783,7 @@ static int init_op_exec(bContext *C, wmOperator *op)
undo::push_end(ob);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
pbvh.tag_face_sets_changed(node_mask);
SCULPT_tag_update_overlays(C);
@@ -1136,14 +1138,7 @@ static int randomize_colors_exec(bContext *C, wmOperator * /*op*/)
IndexMaskMemory memory;
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
else if (pbvh.type() == bke::pbvh::Type::Grids) {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_redraw(nodes[i]); });
}
pbvh.tag_face_sets_changed(node_mask);
SCULPT_tag_update_overlays(C);
@@ -1638,6 +1633,8 @@ static void gesture_apply_mesh(gesture::GestureData &gesture_data, const IndexMa
Vector<int> face_indices;
};
Array<bool> node_changed(pbvh.nodes_num(), false);
threading::EnumerableThreadSpecific<TLS> all_tls;
if (pbvh.type() == bke::pbvh::Type::Mesh) {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
@@ -1658,7 +1655,7 @@ static void gesture_apply_mesh(gesture::GestureData &gesture_data, const IndexMa
any_updated = true;
}
if (any_updated) {
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
}
});
}
@@ -1686,12 +1683,14 @@ static void gesture_apply_mesh(gesture::GestureData &gesture_data, const IndexMa
any_updated = true;
}
if (any_updated) {
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
node_changed[i] = true;
}
});
});
}
IndexMaskMemory memory;
pbvh.tag_face_sets_changed(IndexMask::from_bools(node_changed, memory));
face_sets.finish();
}

View File

@@ -1174,24 +1174,22 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
if (use_multires_undo(step_data, ss)) {
MutableSpan<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
Vector<int> faces_vector;
node_mask.foreach_index([&](const int i) {
faces_vector.clear();
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
subdiv_ccg, nodes[i], faces_vector);
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
const IndexMask changed_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1), memory, [&](const int i) {
Vector<int> faces_vector;
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
subdiv_ccg, nodes[i], faces_vector);
return indices_contain_true(modified_faces, faces);
});
pbvh.tag_face_sets_changed(changed_nodes);
}
else {
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
node_mask.foreach_index([&](const int i) {
const Span<int> faces = nodes[i].faces();
if (indices_contain_true(modified_faces, faces)) {
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
}
});
const IndexMask changed_nodes = IndexMask::from_predicate(
node_mask, GrainSize(1), memory, [&](const int i) {
return indices_contain_true(modified_faces, nodes[i].all_verts());
});
pbvh.tag_face_sets_changed(changed_nodes);
}
break;
}