Blender V5.0
offset_indices.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_array_utils.hh"
10#include "BLI_offset_indices.hh"
11#include "BLI_task.hh"
12
14
16 const int start_offset)
17{
18 int offset = start_offset;
19 int64_t offset_i64 = start_offset;
20
21 for (const int i : counts_to_offsets.index_range().drop_back(1)) {
22 const int count = counts_to_offsets[i];
23 BLI_assert(count >= 0);
24 counts_to_offsets[i] = offset;
25 offset += count;
26#ifndef NDEBUG
27 offset_i64 += count;
28#endif
29 }
30 counts_to_offsets.last() = offset;
31
32 BLI_assert_msg(offset == offset_i64, "Integer overflow occurred");
33 UNUSED_VARS_NDEBUG(offset_i64);
34
35 return OffsetIndices<int>(counts_to_offsets);
36}
37
38std::optional<OffsetIndices<int>> accumulate_counts_to_offsets_with_overflow_check(
39 MutableSpan<int> counts_to_offsets, int start_offset)
40{
41 /* This variant was measured to be about ~8% slower than the version without overflow check.
42 * Since this function is often a serial bottleneck, we use a separate code path for when an
43 * overflow check is requested. */
44 int64_t offset = start_offset;
45 for (const int i : counts_to_offsets.index_range().drop_back(1)) {
46 const int count = counts_to_offsets[i];
47 BLI_assert(count >= 0);
48 counts_to_offsets[i] = offset;
49 offset += count;
50 }
51 counts_to_offsets.last() = offset;
52 const bool has_overflow = offset >= std::numeric_limits<int>::max();
53 if (has_overflow) {
54 return std::nullopt;
55 }
56 return OffsetIndices<int>(counts_to_offsets);
57}
58
59void fill_constant_group_size(const int size, const int start_offset, MutableSpan<int> offsets)
60{
62 threading::parallel_for(offsets.index_range(), 1024, [&](const IndexRange range) {
63 for (const int64_t i : range) {
64 offsets[i] = size * i + start_offset;
65 }
66 });
67 });
68}
69
71 const IndexMask &mask,
72 MutableSpan<int> sizes)
73{
74 mask.foreach_index_optimized<int64_t>(GrainSize(4096),
75 [&](const int64_t i) { sizes[i] = offsets[i].size(); });
76}
77
79 const IndexMask &mask,
80 MutableSpan<int> sizes)
81{
82 mask.foreach_index_optimized<int64_t>(GrainSize(4096), [&](const int64_t i, const int64_t pos) {
83 sizes[pos] = offsets[i].size();
84 });
85}
86
88 const Span<int> indices,
89 MutableSpan<int> sizes)
90{
92 sizes.size_in_bytes() + offsets.data().size_in_bytes() + indices.size_in_bytes(), [&]() {
93 threading::parallel_for(indices.index_range(), 4096, [&](const IndexRange range) {
94 for (const int i : range) {
95 sizes[i] = offsets[indices[i]].size();
96 }
97 });
98 });
99}
100
102{
103 int count = 0;
104 for (const int i : indices) {
105 count += offsets[i].size();
106 }
107 return count;
108}
109
111{
112 int count = 0;
113 mask.foreach_segment_optimized([&](const auto segment) {
114 if constexpr (std::is_same_v<std::decay_t<decltype(segment)>, IndexRange>) {
115 count += offsets[segment].size();
116 }
117 else {
118 for (const int64_t i : segment) {
119 count += offsets[i].size();
120 }
121 }
122 });
123 return count;
124}
125
127 const IndexMask &selection,
128 const int start_offset,
129 MutableSpan<int> dst_offsets)
130{
131 if (selection.is_empty()) {
132 return {};
133 }
134 int offset = start_offset;
135 selection.foreach_index_optimized<int>([&](const int i, const int pos) {
136 dst_offsets[pos] = offset;
137 offset += src_offsets[i].size();
138 });
139 dst_offsets.last() = offset;
140 return OffsetIndices<int>(dst_offsets);
141}
142
144{
145 threading::parallel_for(offsets.index_range(), 1024, [&](const IndexRange range) {
146 for (const int64_t i : range) {
147 r_map.slice(offsets[i]).fill(i);
148 }
149 });
150}
151
153{
154 BLI_assert(std::all_of(offsets.begin(), offsets.end(), [](int value) { return value == 0; }));
157}
158
159} // namespace blender::offset_indices
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define UNUSED_VARS_NDEBUG(...)
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:501
constexpr T * end() const
Definition BLI_span.hh:548
constexpr T * begin() const
Definition BLI_span.hh:544
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr T & last(const int64_t n=0) const
Definition BLI_span.hh:689
void foreach_index_optimized(Fn &&fn) const
static ushort indices[]
uint pos
int count
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void count_indices(Span< int > indices, MutableSpan< int > counts)
void copy_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
void build_reverse_map(OffsetIndices< int > offsets, MutableSpan< int > r_map)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
std::optional< OffsetIndices< int > > accumulate_counts_to_offsets_with_overflow_check(MutableSpan< int > counts_to_offsets, int start_offset=0)
void gather_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask, MutableSpan< int > sizes)
void fill_constant_group_size(int size, int start_offset, MutableSpan< int > offsets)
void build_reverse_offsets(Span< int > indices, MutableSpan< int > offsets)
int sum_group_sizes(OffsetIndices< int > offsets, const IndexMask &mask)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
void memory_bandwidth_bound_task(const int64_t approximate_bytes_touched, const Function &function)
Definition BLI_task.hh:265
i
Definition text_draw.cc:230