Sculpt: Use bit vector for bounds dirty tags

Reduce the amount of memory used for the tags by 8x
and improve the performance of changed nodes IndexMask
creation.

Part of #118145.
This commit is contained in:
Hans Goudey
2024-09-13 15:45:05 -04:00
parent 34f9b7e36c
commit 5b03fee0d2
2 changed files with 8 additions and 7 deletions

View File

@@ -15,6 +15,7 @@
#include "BLI_array.hh"
#include "BLI_bit_group_vector.hh"
#include "BLI_bit_vector.hh"
#include "BLI_bounds_types.hh"
#include "BLI_compiler_compat.h"
#include "BLI_function_ref.hh"
@@ -196,7 +197,7 @@ class Tree {
* \note Values are only meaningful for leaf nodes.
* \note The vector's size may not match the size of the nodes array.
*/
Vector<bool> bounds_dirty_;
BitVector<> bounds_dirty_;
float planes_[6][4];
int num_planes_;
@@ -221,6 +222,7 @@ class Tree {
/**
* Mark data based on positions for specific BVH nodes dirty. In particular: bounds, normals,
* and GPU data buffers. That data is recomputed later on in functions like #update_bounds.
* \warning Must not be called from multiple threads in parallel.
*/
void tag_positions_changed(const IndexMask &node_mask);
};

View File

@@ -551,8 +551,7 @@ void Tree::tag_positions_changed(const IndexMask &node_mask)
this->bounds_dirty_.resize(std::max(this->bounds_dirty_.size(), node_mask.min_array_size()),
false);
/* TODO: Use `to_bools` with first clear disabled. */
node_mask.foreach_index_optimized<int>(GrainSize(2048),
[&](const int i) { this->bounds_dirty_[i] = true; });
node_mask.foreach_index_optimized<int>([&](const int i) { this->bounds_dirty_[i].set(); });
return std::visit(
[&](auto &nodes) {
node_mask.foreach_index([&](const int i) {
@@ -1088,7 +1087,7 @@ struct BoundsMergeInfo {
template<typename NodeT>
static BoundsMergeInfo merge_child_bounds(MutableSpan<NodeT> nodes,
const Span<bool> dirty,
const BitSpan dirty,
const int node_index)
{
NodeT &node = nodes[node_index];
@@ -1120,7 +1119,7 @@ void flush_bounds_to_parents(Tree &pbvh)
void update_bounds_mesh(const Span<float3> vert_positions, Tree &pbvh)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bools(pbvh.bounds_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.bounds_dirty_, memory);
if (nodes_to_update.is_empty()) {
return;
}
@@ -1133,7 +1132,7 @@ void update_bounds_mesh(const Span<float3> vert_positions, Tree &pbvh)
void update_bounds_grids(const CCGKey &key, const Span<float3> positions, Tree &pbvh)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bools(pbvh.bounds_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.bounds_dirty_, memory);
if (nodes_to_update.is_empty()) {
return;
}
@@ -1147,7 +1146,7 @@ void update_bounds_grids(const CCGKey &key, const Span<float3> positions, Tree &
void update_bounds_bmesh(const BMesh & /*bm*/, Tree &pbvh)
{
IndexMaskMemory memory;
const IndexMask nodes_to_update = IndexMask::from_bools(pbvh.bounds_dirty_, memory);
const IndexMask nodes_to_update = IndexMask::from_bits(pbvh.bounds_dirty_, memory);
if (nodes_to_update.is_empty()) {
return;
}