BLI: refactor IndexMask for better performance and memory usage #104629

Merged
Jacques Lucke merged 254 commits from JacquesLucke/blender:index-mask-refactor into main 2023-05-24 18:11:47 +02:00
2 changed files with 25 additions and 21 deletions
Showing only changes of commit debd1010f8 - Show all commits

View File

@ -63,6 +63,11 @@ struct IndexMaskData {
RawChunkIterator end_it;
};
struct IndexMaskSegment {
int64_t start_index;
OffsetSpan<int64_t, int16_t> indices;
};
class IndexMask {
private:
IndexMaskData data_;
@ -80,7 +85,7 @@ class IndexMask {
IndexMask slice(IndexRange range) const;
template<typename Fn> void foreach_raw_segment(Fn &&fn) const;
template<typename Fn> void foreach_segment(Fn &&fn) const;
template<typename Fn> void foreach_span(Fn &&fn) const;
template<typename Fn> void foreach_index(Fn &&fn) const;
template<typename Fn> void foreach_span_or_range(Fn &&fn) const;
@ -389,7 +394,7 @@ inline int16_t Chunk::segment_size(const int16_t segment_i) const
return this->cumulative_segment_sizes[segment_i + 1] - this->cumulative_segment_sizes[segment_i];
}
template<typename Fn> inline void IndexMask::foreach_raw_segment(Fn &&fn) const
template<typename Fn> inline void IndexMask::foreach_segment(Fn &&fn) const
{
if (data_.indices_num == 0) {
return;
@ -422,7 +427,8 @@ template<typename Fn> inline void IndexMask::foreach_raw_segment(Fn &&fn) const
const int16_t segment_size = stored_segment_size - segment_drop_front - segment_drop_back;
const Span<int16_t> indices_span{indices_in_segment, segment_size};
fn(counter, offset, indices_span);
const IndexMaskSegment segment{counter, {offset, indices_span}};
fn(segment);
counter += segment_size;
segment_drop_front = 0;
@ -435,20 +441,14 @@ template<typename Fn> inline void IndexMask::foreach_raw_segment(Fn &&fn) const
template<typename Fn> inline void IndexMask::foreach_span(Fn &&fn) const
{
this->foreach_raw_segment([&](const int64_t /*mask_index_offset*/,
const int64_t indices_in_segment_offset,
const Span<int16_t> indices_in_segment) {
fn(OffsetSpan<int64_t, int16_t>(indices_in_segment_offset, indices_in_segment));
});
this->foreach_segment([&](const IndexMaskSegment &segment) { fn(segment.indices); });
}
template<typename Fn> inline void IndexMask::foreach_index(Fn &&fn) const
{
this->foreach_raw_segment([&](const int64_t /*mask_index_offset*/,
const int64_t indices_in_segment_offset,
const Span<int16_t> indices_in_segment) {
for (const int16_t index : indices_in_segment) {
fn(index + indices_in_segment_offset);
this->foreach_segment([&](const IndexMaskSegment &segment) {
for (const int64_t index : segment.indices) {
fn(index);
}
});
}
@ -456,16 +456,13 @@ template<typename Fn> inline void IndexMask::foreach_index(Fn &&fn) const
template<typename Fn> inline void IndexMask::foreach_span_or_range(Fn &&fn) const
{
IndexRangeChecker is_index_mask;
this->foreach_raw_segment([&, is_index_mask](const int64_t /*mask_index_offset*/,
const int64_t indices_in_segment_offset,
const Span<int16_t> indices_in_segment) {
if (is_index_mask.check(indices_in_segment)) {
const int64_t start = indices_in_segment.first() + indices_in_segment_offset;
const int64_t size = indices_in_segment.size();
fn(IndexRange(start, size));
this->foreach_segment([&, is_index_mask](const IndexMaskSegment &segment) {
const OffsetSpan<int64_t, int16_t> indices = segment.indices;
if (is_index_mask.check(indices.base_span())) {
fn(IndexRange(indices[0], indices.size()));
}
else {
fn(OffsetSpan<int64_t, int16_t>(indices_in_segment_offset, indices_in_segment));
fn(indices);
}
});
}

View File

@ -2,6 +2,8 @@
#pragma once
#include "BLI_span.hh"
namespace blender {
template<typename T, typename BaseT> class OffsetSpan {
@ -14,6 +16,11 @@ template<typename T, typename BaseT> class OffsetSpan {
{
}
Span<BaseT> base_span() const
{
return data_;
}
int64_t size() const
{
return data_.size();