Sculpt: Only re-upload face color attribute data
Similar to the previous commit, previously all GPU buffers were recreated when only a color attribute changed. Now only that attribute is re-uploaded, using the same mechanism. Part of #118145.
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "BLI_offset_indices.hh"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
@@ -178,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_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -237,6 +239,11 @@ 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 generic attribute data has changed (not positions, masks, or face sets).
|
||||
*/
|
||||
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name);
|
||||
};
|
||||
|
||||
} // namespace blender::bke::pbvh
|
||||
@@ -400,7 +407,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_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);
|
||||
|
||||
@@ -567,6 +567,13 @@ void Tree::tag_face_sets_changed(const IndexMask &node_mask)
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::tag_attribute_changed(const IndexMask &node_mask, const StringRef attribute_name)
|
||||
{
|
||||
if (this->draw_data) {
|
||||
this->draw_data->tag_attribute_changed(node_mask, attribute_name);
|
||||
}
|
||||
}
|
||||
|
||||
static bool tree_is_empty(const Tree &pbvh)
|
||||
{
|
||||
return std::visit([](const auto &nodes) { return nodes.is_empty(); }, pbvh.nodes_);
|
||||
@@ -1542,11 +1549,6 @@ void BKE_pbvh_node_mark_update_mask(blender::bke::pbvh::Node &node)
|
||||
node.flag_ |= PBVH_UpdateMask | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_mark_update_color(blender::bke::pbvh::Node &node)
|
||||
{
|
||||
node.flag_ |= PBVH_UpdateColor | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
|
||||
}
|
||||
|
||||
void BKE_pbvh_mark_rebuild_pixels(blender::bke::pbvh::Tree &pbvh)
|
||||
{
|
||||
std::visit(
|
||||
|
||||
@@ -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_attribute_changed(const IndexMask &node_mask, StringRef attribute_name) override;
|
||||
|
||||
Span<gpu::Batch *> ensure_tris_batches(const Object &object,
|
||||
const ViewportRequest &request,
|
||||
@@ -211,6 +212,17 @@ void DrawCacheImpl::tag_face_sets_changed(const IndexMask &node_mask)
|
||||
}
|
||||
}
|
||||
|
||||
void DrawCacheImpl::tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
|
||||
{
|
||||
for (const auto &[data_request, data] : attribute_vbos_.items()) {
|
||||
if (const GenericRequest *request = std::get_if<GenericRequest>(&data_request)) {
|
||||
if (request->name == attribute_name) {
|
||||
data.tag_dirty(node_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawCache &ensure_draw_data(std::unique_ptr<bke::pbvh::DrawCache> &ptr)
|
||||
{
|
||||
if (!ptr) {
|
||||
|
||||
@@ -2316,10 +2316,11 @@ static int vertex_color_set_exec(bContext *C, wmOperator *op)
|
||||
|
||||
undo::push_nodes(depsgraph, obact, node_mask, undo::Type::Color);
|
||||
|
||||
Mesh &mesh = *static_cast<Mesh *>(obact.data);
|
||||
|
||||
fill_active_color(obact, paintcol, true, affect_alpha);
|
||||
|
||||
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
|
||||
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
undo::push_end(obact);
|
||||
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, &obact);
|
||||
|
||||
@@ -322,10 +322,10 @@ static void transform_active_color(bContext *C,
|
||||
const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
|
||||
undo::push_nodes(depsgraph, obact, node_mask, undo::Type::Color);
|
||||
|
||||
transform_active_color_data(*BKE_mesh_from_object(&obact), transform_fn);
|
||||
Mesh &mesh = *static_cast<Mesh *>(obact.data);
|
||||
transform_active_color_data(mesh, transform_fn);
|
||||
|
||||
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
|
||||
node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_update_color(nodes[i]); });
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
|
||||
undo::push_end(obact);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, &obact);
|
||||
|
||||
@@ -1447,8 +1447,8 @@ static void restore_color_data(Object &ob, Cache &expand_cache)
|
||||
expand_cache.original_colors[vert],
|
||||
color_attribute.span);
|
||||
}
|
||||
BKE_pbvh_node_mark_redraw(nodes[i]);
|
||||
});
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
color_attribute.finish();
|
||||
}
|
||||
|
||||
@@ -1699,7 +1699,7 @@ static void face_sets_update(Object &object, Cache &expand_cache)
|
||||
/**
|
||||
* Callback to update vertex colors per bke::pbvh::Tree node.
|
||||
*/
|
||||
static void colors_update_task(const Depsgraph &depsgraph,
|
||||
static bool colors_update_task(const Depsgraph &depsgraph,
|
||||
Object &object,
|
||||
const Span<float3> vert_positions,
|
||||
const OffsetIndices<int> faces,
|
||||
@@ -1762,9 +1762,7 @@ static void colors_update_task(const Depsgraph &depsgraph,
|
||||
|
||||
any_changed = true;
|
||||
}
|
||||
if (any_changed) {
|
||||
BKE_pbvh_node_mark_update_color(*node);
|
||||
}
|
||||
return any_changed;
|
||||
}
|
||||
|
||||
/* Store the original mesh data state in the expand cache. */
|
||||
@@ -1897,19 +1895,26 @@ static void update_for_vert(bContext *C, Object &ob, const std::optional<int> ve
|
||||
const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
|
||||
bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh);
|
||||
|
||||
Array<bool> node_changed(node_mask.min_array_size(), false);
|
||||
|
||||
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
|
||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||
colors_update_task(depsgraph,
|
||||
ob,
|
||||
vert_positions,
|
||||
faces,
|
||||
corner_verts,
|
||||
vert_to_face_map,
|
||||
hide_vert,
|
||||
mask,
|
||||
&nodes[i],
|
||||
color_attribute);
|
||||
node_changed[i] = colors_update_task(depsgraph,
|
||||
ob,
|
||||
vert_positions,
|
||||
faces,
|
||||
corner_verts,
|
||||
vert_to_face_map,
|
||||
hide_vert,
|
||||
mask,
|
||||
&nodes[i],
|
||||
color_attribute);
|
||||
});
|
||||
|
||||
IndexMaskMemory memory;
|
||||
pbvh.tag_attribute_changed(IndexMask::from_bools(node_changed, memory),
|
||||
mesh.active_color_attribute);
|
||||
|
||||
color_attribute.finish();
|
||||
flush_update_step(C, UpdateType::Color);
|
||||
break;
|
||||
|
||||
@@ -403,9 +403,9 @@ static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
|
||||
nodes[i],
|
||||
tls,
|
||||
color_attribute);
|
||||
BKE_pbvh_node_mark_update_color(nodes[i]);
|
||||
});
|
||||
});
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
color_attribute.finish();
|
||||
flush_update_step(C, UpdateType::Color);
|
||||
}
|
||||
|
||||
@@ -592,9 +592,9 @@ void do_paint_brush(const Scene &scene,
|
||||
nodes[i],
|
||||
tls,
|
||||
color_attribute);
|
||||
BKE_pbvh_node_mark_update_color(nodes[i]);
|
||||
});
|
||||
});
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
color_attribute.finish();
|
||||
return;
|
||||
}
|
||||
@@ -670,9 +670,9 @@ void do_paint_brush(const Scene &scene,
|
||||
tls,
|
||||
ss.cache->paint_brush.mix_colors,
|
||||
color_attribute);
|
||||
BKE_pbvh_node_mark_update_color(nodes[i]);
|
||||
});
|
||||
});
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
color_attribute.finish();
|
||||
}
|
||||
|
||||
@@ -894,7 +894,6 @@ void do_smear_brush(const Depsgraph &depsgraph,
|
||||
nodes[i],
|
||||
tls,
|
||||
color_attribute);
|
||||
BKE_pbvh_node_mark_update_color(nodes[i]);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -926,10 +925,10 @@ void do_smear_brush(const Depsgraph &depsgraph,
|
||||
nodes[i],
|
||||
tls,
|
||||
color_attribute);
|
||||
BKE_pbvh_node_mark_update_color(nodes[i]);
|
||||
});
|
||||
});
|
||||
}
|
||||
pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
|
||||
color_attribute.finish();
|
||||
}
|
||||
|
||||
|
||||
@@ -1202,15 +1202,16 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, StepData &step_data)
|
||||
return;
|
||||
}
|
||||
|
||||
MutableSpan<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
|
||||
const Span<bke::pbvh::MeshNode> nodes = pbvh.nodes<bke::pbvh::MeshNode>();
|
||||
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
|
||||
Array<bool> modified_verts(mesh.verts_num, false);
|
||||
restore_color(object, step_data, modified_verts);
|
||||
node_mask.foreach_index([&](const int i) {
|
||||
if (indices_contain_true(modified_verts, nodes[i].all_verts())) {
|
||||
BKE_pbvh_node_mark_update_color(nodes[i]);
|
||||
}
|
||||
});
|
||||
const IndexMask changed_nodes = IndexMask::from_predicate(
|
||||
node_mask, GrainSize(1), memory, [&](const int i) {
|
||||
return indices_contain_true(modified_verts, nodes[i].all_verts());
|
||||
});
|
||||
pbvh.tag_attribute_changed(changed_nodes, mesh.active_color_attribute);
|
||||
break;
|
||||
}
|
||||
case Type::Geometry: {
|
||||
|
||||
Reference in New Issue
Block a user