chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
273 / 316
86.4%
Branches:
210 / 289
72.7%
Functions:
21 / 23
91.3%

scene/tables/semantics.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/scene/tables/semantics.h"
3
4 #include <algorithm>
5 #include <cstring>
6
7 #include "chrono_batch_render/device/queue.h"
8 #include "chrono_batch_render/scene/records/render_tables.h"
9 #include "chrono_batch_render/scene/schema/columns.h"
10 #include "chrono_batch_render/stage/publish/change_set.h"
11 #include "chrono_batch_render/util/error.h"
12 #include "chrono_batch_render/util/profiler.h"
13 #include "chrono_batch_render/util/span.h"
14
15 namespace chrono::batch_render {
16
17 namespace {
18
19 77779 uint64_t Mix(uint64_t x) {
20 77779 x ^= x >> 30;
21 77779 x *= 0xbf58476d1ce4e5b9ull;
22 77779 x ^= x >> 27;
23 77779 x *= 0x94d049bb133111ebull;
24 77779 return x ^ (x >> 31);
25 }
26
27 }
28
29 7159 StableId HashPath(std::string_view path) {
30 7159 uint64_t a = 0xcbf29ce484222325ull;
31 7159 uint64_t b = 0x6a09e667f3bcc909ull;
32
2/2
✓ Branch 0 taken 63461 times.
✓ Branch 1 taken 7159 times.
70620 for (const char c : path) {
33 63461 a = (a ^ uint8_t(c)) * 0x100000001b3ull;
34 63461 b = Mix(b ^ uint8_t(c));
35 }
36 7159 a = Mix(a ^ path.size());
37 7159 b = Mix(b + a);
38 7159 StableId id{{uint32_t(a), uint32_t(a >> 32), uint32_t(b), uint32_t(b >> 32)}};
39
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 7159 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
7159 if (id.words[0] == 0 && id.words[1] == 0 && id.words[2] == 0) {
40 ✗ id.words[0] = 1;
41 }
42 7159 return id;
43 }
44
45 3 std::vector<std::byte> PackIdMap(std::span<const std::pair<StableId, std::string>> entries) {
46 3 constexpr size_t kRecordBytes = 6 * sizeof(uint32_t);
47 3 size_t textBytes = 0;
48
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 for (const auto& [id, text] : entries) {
49 9 textBytes += text.size();
50 }
51 3 const size_t first = entries.size() * kRecordBytes;
52 3 std::vector<std::byte> bytes(first + textBytes + sizeof(uint32_t));
53 3 size_t offset = first;
54
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 for (size_t i = 0; i < entries.size(); ++i) {
55 9 const auto& [id, text] = entries[i];
56 9 const uint32_t record[6] = {id.words[0], id.words[1], id.words[2],
57 9 id.words[3], uint32_t(text.size()), uint32_t(offset)};
58 9 std::memcpy(bytes.data() + i * kRecordBytes, record, kRecordBytes);
59 9 std::memcpy(bytes.data() + offset, text.data(), text.size());
60 9 offset += text.size();
61 }
62 3 const uint32_t count = uint32_t(entries.size());
63 3 std::memcpy(bytes.data() + offset, &count, sizeof(count));
64 3 return bytes;
65 }
66
67 476 void SemanticTable::Describe(RenderTables& tables) const {
68 476 tables.semantics = Data();
69 476 }
70
71 2358 std::span<const ColumnRef> SemanticTable::Inputs() const {
72 2358 static constexpr ColumnRef kInputs[] = {kSemanticsLabelsAPISemanticsLabels};
73 2358 return kInputs;
74 }
75
76 8631 bool SemanticTable::Pending() const {
77 8631 return m_wanted != m_taxonomies;
78 }
79
80 13 void SemanticTable::Require(std::span<const Token> taxonomies) {
81 13 m_wanted.assign(taxonomies.begin(), taxonomies.end());
82 13 }
83
84 21 uint32_t SemanticTable::TaxonomyIndex(Token taxonomy) const {
85 21 const auto found = std::ranges::find(m_taxonomies, taxonomy);
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (found == m_taxonomies.end()) {
87
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("Semantics has no taxonomy {}", m_structure.GetTokens().Text(taxonomy));
88 }
89 21 return uint32_t(found - m_taxonomies.begin());
90 }
91
92 13 uint32_t SemanticTable::SemanticId(Token taxonomy, uint32_t prim) const {
93 13 return m_semanticIds[size_t(TaxonomyIndex(taxonomy)) * m_stride + prim];
94 }
95
96 5 uint32_t SemanticTable::LabeledPrim(Token taxonomy, uint32_t prim) const {
97 5 return m_semanticPrims[size_t(TaxonomyIndex(taxonomy)) * m_stride + prim];
98 }
99
100 76 const SemanticTable::Labels* SemanticTable::FindLabels(uint32_t prim, Token taxonomy,
101 std::map<uint64_t, Labels>& reads) const {
102 76 const uint32_t row =
103 76 m_structure.GetPrims().InstanceRow(prim, SchemaId::SemanticsLabelsAPI, taxonomy.id);
104
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 52 times.
76 if (row == kNoRow) {
105 return nullptr;
106 }
107 24 ColumnStore& store = m_structure.GetColumnStore();
108 24 const ArrayRef array = store.Array(kSemanticsLabelsAPISemanticsLabels, row);
109
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (array.address == 0) {
110 return nullptr;
111 }
112 24 auto [found, added] = reads.try_emplace(array.address);
113
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 7 times.
24 if (added) {
114
1/1
✓ Branch 3 taken 17 times.
17 found->second = Items<uint32_t>(store.Arrays(ColumnType::TokenArray).Read(array));
115 }
116 24 return &found->second;
117 }
118
119 7236 void SemanticTable::TrackRows(uint32_t prim) {
120
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7233 times.
7236 if (const auto rows = m_labelRows.find(prim); rows != m_labelRows.end()) {
121
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 for (const uint32_t row : rows->second) {
122 3 m_byLabelRow.erase(row);
123 }
124 3 m_labelRows.erase(rows);
125 }
126 7236 const Prims& prims = m_structure.GetPrims();
127
2/2
✓ Branch 1 taken 7148 times.
✓ Branch 2 taken 88 times.
7236 if (!prims.Alive(prim)) {
128 return;
129 }
130
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 7148 times.
7165 for (const ApiInstance& entry : prims.Instances(prim, SchemaId::SemanticsLabelsAPI)) {
131 17 m_byLabelRow[entry.row] = prim;
132 17 m_labelRows[prim].push_back(entry.row);
133 }
134 }
135
136 7096 void SemanticTable::Resolve(uint32_t prim, std::map<uint64_t, Labels>& reads) {
137 7096 const Prims& prims = m_structure.GetPrims();
138
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 7096 times.
7147 for (uint32_t taxonomy = 0; taxonomy < m_taxonomies.size(); ++taxonomy) {
139 51 uint32_t at = prim;
140 51 std::span<const uint32_t> tokens;
141
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 27 times.
103 while (at != kNoPrim) {
142
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 52 times.
76 if (const Labels* labels = FindLabels(at, m_taxonomies[taxonomy], reads)) {
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 tokens = *labels;
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (!tokens.empty()) {
145 break;
146 }
147 }
148 52 at = prims.Record(at).parent;
149 }
150 51 uint32_t id = 1;
151
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 27 times.
51 if (at != kNoPrim) {
152 24 std::map<Labels, uint32_t>& sets = m_sets[taxonomy];
153
1/1
✓ Branch 2 taken 24 times.
48 id = sets.try_emplace(Labels(tokens.begin(), tokens.end()), uint32_t(sets.size() + 2))
154 24 .first->second;
155 }
156 51 m_semanticIds[size_t(taxonomy) * m_stride + prim] = id;
157 51 m_semanticPrims[size_t(taxonomy) * m_stride + prim] = at;
158 }
159 7096 ++m_stats.resolved;
160 7096 }
161
162 476 void SemanticTable::Grow(uint32_t prims) {
163
2/2
✓ Branch 0 taken 191 times.
✓ Branch 1 taken 285 times.
476 if (prims <= m_stride) {
164 191 return;
165 }
166 285 const uint32_t stride = std::max({prims, m_stride * 2, 64u});
167 285 const size_t taxonomies = m_taxonomies.size();
168
1/1
✓ Branch 2 taken 285 times.
285 std::vector<uint32_t> ids(taxonomies * stride, 0);
169
1/1
✓ Branch 1 taken 285 times.
285 std::vector<uint32_t> owners(taxonomies * stride, kNoPrim);
170
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 285 times.
298 for (size_t taxonomy = 0; taxonomy < taxonomies; ++taxonomy) {
171 26 std::copy_n(m_semanticIds.begin() + ptrdiff_t(taxonomy * m_stride), m_stride,
172 13 ids.begin() + ptrdiff_t(taxonomy * stride));
173 13 std::copy_n(m_semanticPrims.begin() + ptrdiff_t(taxonomy * m_stride), m_stride,
174 13 owners.begin() + ptrdiff_t(taxonomy * stride));
175 }
176 285 m_semanticIds = std::move(ids);
177 285 m_semanticPrims = std::move(owners);
178
1/1
✓ Branch 1 taken 285 times.
285 m_stableIds.resize(stride, StableId{});
179 285 m_stride = stride;
180 285 m_stats.reallocated = true;
181 285 }
182
183 465 void SemanticTable::Upload(std::span<const uint32_t> prims) {
184
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 285 times.
465 device::Device& device = m_structure.GetColumnStore().GetDevice();
185
2/2
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 285 times.
465 device::Queue& queue = device.GetQueue();
186
4/6
✓ Branch 0 taken 180 times.
✓ Branch 1 taken 285 times.
✓ Branch 2 taken 180 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 180 times.
465 if (m_stats.reallocated || !m_stableBuffer || prims.size() > 256) {
187
3/3
✓ Branch 1 taken 285 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 282 times.
288 m_stableBuffer = device.CreateBuffer({.label = "stable ids"}, m_stableIds);
188
1/1
✓ Branch 1 taken 285 times.
570 m_idBuffer = device.CreateBuffer(
189
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 12 times.
285 {.bytes = std::max<uint64_t>(m_semanticIds.size() * sizeof(uint32_t), 4),
190 285 .label = "semantic ids"},
191
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 282 times.
285 std::span<const uint32_t>(m_semanticIds));
192
1/1
✓ Branch 1 taken 285 times.
570 m_primBuffer = device.CreateBuffer(
193
2/2
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 12 times.
285 {.bytes = std::max<uint64_t>(m_semanticPrims.size() * sizeof(uint32_t), 4),
194 285 .label = "semantic prims"},
195
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 282 times.
285 std::span<const uint32_t>(m_semanticPrims));
196 } else {
197
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 180 times.
482 for (const uint32_t prim : prims) {
198 302 queue.Write(m_stableBuffer->Slice(prim * sizeof(StableId), sizeof(StableId)),
199 302 &m_stableIds[prim]);
200
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 302 times.
311 for (size_t taxonomy = 0; taxonomy < m_taxonomies.size(); ++taxonomy) {
201 9 const size_t at = taxonomy * m_stride + prim;
202 9 queue.Write(m_idBuffer->Slice(at * sizeof(uint32_t), sizeof(uint32_t)),
203 9 &m_semanticIds[at]);
204 9 queue.Write(m_primBuffer->Slice(at * sizeof(uint32_t), sizeof(uint32_t)),
205 9 &m_semanticPrims[at]);
206 }
207 }
208 }
209 465 m_data.stableIds.address = m_stableBuffer->Address();
210 465 m_data.semanticIds.address = m_idBuffer->Address();
211 465 m_data.semanticPrims.address = m_primBuffer->Address();
212 465 m_data.stride = m_stride;
213 465 m_data.taxonomyCount = uint32_t(m_taxonomies.size());
214 1866 }
215
216 476 void SemanticTable::Run(const ChangeSet& changes, TableVersions&) {
217
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 471 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
476 CHRONO_BATCH_RENDER_ZONE("Semantics/Run");
218 476 m_stats = {};
219 476 {
220
1/1
✓ Branch 1 taken 476 times.
476 const std::lock_guard lock(m_mapMutex);
221 476 m_maps.clear();
222 476 }
223
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 282 times.
476 const Prims& prims = m_structure.GetPrims();
224
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 282 times.
476 const Paths& paths = m_structure.GetPaths();
225
5/6
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 282 times.
✓ Branch 2 taken 194 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 193 times.
476 const bool full = !m_built || changes.resync || m_wanted != m_taxonomies;
226
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 193 times.
476 std::map<uint64_t, Labels> reads;
227 476 std::vector<uint32_t> changed;
228
229
2/2
✓ Branch 0 taken 283 times.
✓ Branch 1 taken 193 times.
476 if (full) {
230
1/1
✓ Branch 1 taken 283 times.
283 m_taxonomies = m_wanted;
231
1/1
✓ Branch 1 taken 283 times.
283 m_sets.assign(m_taxonomies.size(), {});
232 283 m_stride = 0;
233 283 m_semanticIds.clear();
234 283 m_semanticPrims.clear();
235 283 m_stableIds.clear();
236 283 m_byLabelRow.clear();
237 283 m_labelRows.clear();
238
1/1
✓ Branch 1 taken 283 times.
283 Grow(prims.Size());
239
2/2
✓ Branch 0 taken 1872 times.
✓ Branch 1 taken 283 times.
2155 for (uint32_t prim = 0; prim < prims.Size(); ++prim) {
240
2/3
✓ Branch 1 taken 1872 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1872 times.
1872 if (!prims.Alive(prim)) {
241 ✗ continue;
242 }
243
1/1
✓ Branch 1 taken 1872 times.
1872 m_stableIds[prim] = HashPath(paths.Path(prim));
244
1/1
✓ Branch 1 taken 1872 times.
1872 TrackRows(prim);
245
1/1
✓ Branch 1 taken 1872 times.
1872 Resolve(prim, reads);
246
1/1
✓ Branch 1 taken 1872 times.
1872 changed.push_back(prim);
247 }
248 283 m_stats.reallocated = true;
249 } else {
250
1/1
✓ Branch 1 taken 193 times.
193 Grow(prims.Size());
251
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 193 times.
335 for (const StructureEntry& entry : changes.removed) {
252
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 142 times.
142 if (entry.prim >= m_stride) {
253 ✗ continue;
254 }
255 142 m_stableIds[entry.prim] = {};
256
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 142 times.
144 for (size_t taxonomy = 0; taxonomy < m_taxonomies.size(); ++taxonomy) {
257 2 m_semanticIds[taxonomy * m_stride + entry.prim] = 0;
258 2 m_semanticPrims[taxonomy * m_stride + entry.prim] = kNoPrim;
259 }
260
1/1
✓ Branch 1 taken 142 times.
142 TrackRows(entry.prim);
261
1/1
✓ Branch 1 taken 142 times.
142 changed.push_back(entry.prim);
262 }
263 193 std::set<uint32_t> resolve;
264
2/2
✓ Branch 0 taken 5248 times.
✓ Branch 1 taken 193 times.
5441 for (const StructureEntry& entry : changes.added) {
265
6/6
✓ Branch 1 taken 5248 times.
✓ Branch 3 taken 5232 times.
✓ Branch 4 taken 16 times.
✓ Branch 6 taken 5232 times.
✓ Branch 8 taken 10 times.
✓ Branch 9 taken 5222 times.
5248 if (!prims.Alive(entry.prim) || prims.Generation(entry.prim) != entry.generation) {
266 26 continue;
267 }
268
1/1
✓ Branch 1 taken 5222 times.
5222 m_stableIds[entry.prim] = HashPath(paths.Path(entry.prim));
269
1/1
✓ Branch 1 taken 5222 times.
5222 TrackRows(entry.prim);
270
1/1
✓ Branch 1 taken 5222 times.
5222 resolve.insert(entry.prim);
271 }
272
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 193 times.
205 for (const StructureEntry& entry : changes.apis) {
273
1/5
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
12 if (entry.api != SchemaId::SemanticsLabelsAPI || !prims.Alive(entry.prim) ||
274
0/3
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ prims.Generation(entry.prim) != entry.generation) {
275 12 continue;
276 }
277
0/1
✗ Branch 1 not taken.
✗ TrackRows(entry.prim);
278
0/3
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ for (const uint32_t at : paths.Subtree(entry.prim)) {
279
0/1
✗ Branch 1 not taken.
✗ resolve.insert(at);
280 ✗ }
281 }
282
3/3
✓ Branch 1 taken 193 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 193 times.
199 for (const uint32_t row : changes.ArrayRows(kSemanticsLabelsAPISemanticsLabels)) {
283 6 const auto prim = m_byLabelRow.find(row);
284
4/5
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
9 if (prim == m_byLabelRow.end() || !prims.Alive(prim->second)) {
285 3 continue;
286 }
287
3/3
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 3 times.
8 for (const uint32_t at : paths.Subtree(prim->second)) {
288
1/1
✓ Branch 1 taken 5 times.
5 resolve.insert(at);
289 3 }
290 }
291
2/2
✓ Branch 0 taken 5224 times.
✓ Branch 1 taken 193 times.
5417 for (const uint32_t prim : resolve) {
292
1/1
✓ Branch 1 taken 5224 times.
5224 Resolve(prim, reads);
293
1/1
✓ Branch 1 taken 5224 times.
5224 changed.push_back(prim);
294 }
295 193 }
296
3/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 465 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
476 if (!changed.empty() || !m_built) {
297
1/1
✓ Branch 1 taken 465 times.
465 Upload(changed);
298 }
299 476 m_built = true;
300 476 }
301
302 4 std::vector<std::vector<std::string>> SemanticTable::SetTexts(uint32_t taxonomy) const {
303 4 const Tokens& tokens = m_structure.GetTokens();
304 4 std::vector<std::vector<std::string>> texts(m_sets[taxonomy].size());
305
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 for (const auto& [labels, id] : m_sets[taxonomy]) {
306
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for (const uint32_t label : labels) {
307
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 texts[id - 2].emplace_back(tokens.Text(Token{label}));
308 }
309 }
310 4 return texts;
311 ✗ }
312
313 3 IdEntries SemanticTable::SemanticIdEntries(Token taxonomy) const {
314
1/1
✓ Branch 3 taken 3 times.
3 const std::string name(m_structure.GetTokens().Text(taxonomy));
315 3 IdEntries entries = {
316
1/1
✓ Branch 1 taken 3 times.
3 {StableId{{0, 0, 0, 0}}, "BACKGROUND", "", {{name, {"BACKGROUND"}}}},
317 {StableId{{1, 0, 0, 0}}, "UNLABELLED", "", {{name, {"UNLABELLED"}}}},
318
5/7
✓ Branch 1 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 6 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
27 };
319
2/2
✓ Branch 1 taken 3 times.
✓ Branch 4 taken 3 times.
3 const std::vector<std::vector<std::string>> texts = SetTexts(TaxonomyIndex(taxonomy));
320
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 for (uint32_t i = 0; i < texts.size(); ++i) {
321
1/1
✓ Branch 1 taken 5 times.
5 std::string text = name + ": ";
322
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 for (size_t j = 0; j < texts[i].size(); ++j) {
323
2/3
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5 times.
15 text += (j > 0 ? "," : "") + texts[i][j];
324 }
325
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
25 entries.push_back({StableId{{i + 2, 0, 0, 0}}, text + ";", "", {{name, texts[i]}}});
326 5 }
327 6 return entries;
328 36 }
329
330 ✗ std::set<uint32_t> SemanticTable::LabeledPrims(Token taxonomy) const {
331 ✗ const Prims& prims = m_structure.GetPrims();
332 ✗ const size_t first = size_t(TaxonomyIndex(taxonomy)) * m_stride;
333 ✗ std::set<uint32_t> labeled;
334
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ for (uint32_t prim = 0; prim < std::min(prims.Size(), m_stride); ++prim) {
335
0/1
✗ Branch 1 not taken.
✗ const uint32_t at = m_semanticPrims[first + prim];
336
0/5
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ if (prims.Alive(prim) && at != kNoPrim) {
337
0/1
✗ Branch 1 not taken.
✗ labeled.insert(at);
338 }
339 }
340 ✗ return labeled;
341 ✗ }
342
343 ✗ IdEntries SemanticTable::PrimEntries(Token taxonomy, bool stable) const {
344
0/1
✗ Branch 3 not taken.
✗ const std::string name(m_structure.GetTokens().Text(taxonomy));
345
0/1
✗ Branch 1 not taken.
✗ const uint32_t index = TaxonomyIndex(taxonomy);
346 ✗ IdEntries entries = {
347
0/1
✗ Branch 1 not taken.
✗ {StableId{{0, 0, 0, 0}}, "BACKGROUND", "", {{name, {"BACKGROUND"}}}},
348
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ {stable ? StableId{{0, 0, 0, 1}} : StableId{{1, 0, 0, 0}},
349 "UNLABELLED",
350 "",
351 {{name, {"UNLABELLED"}}}},
352
0/7
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ };
353
0/1
✗ Branch 1 not taken.
✗ const std::vector<std::vector<std::string>> texts = SetTexts(index);
354
0/3
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ for (const uint32_t prim : LabeledPrims(taxonomy)) {
355
0/1
✗ Branch 1 not taken.
✗ const uint32_t id = m_semanticIds[size_t(index) * m_stride + prim];
356
0/1
✗ Branch 1 not taken.
✗ std::string path = m_structure.GetPaths().Path(prim);
357
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ entries.push_back({stable ? m_stableIds[prim] : StableId{{prim + 2, 0, 0, 0}},
358 path,
359 path,
360
0/1
✗ Branch 1 not taken.
✗ {{name, texts[id - 2]}}});
361 ✗ }
362 ✗ return entries;
363 ✗ }
364
365 4 IdEntries SemanticTable::Entries(RenderVarSource source, Token taxonomy) const {
366
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
4 switch (source) {
367 3 case RenderVarSource::SemanticSegmentation:
368 3 case RenderVarSource::SemanticIdMap:
369 3 return SemanticIdEntries(taxonomy);
370 ✗ case RenderVarSource::NonStableInstanceSegmentation:
371 ✗ return PrimEntries(taxonomy, false);
372 ✗ case RenderVarSource::SemanticInstanceSegmentation:
373 ✗ return PrimEntries(taxonomy, true);
374 1 default:
375 1 return StableIdEntries();
376 }
377 }
378
379 5 SemanticMap SemanticTable::Map(RenderVarSource source, Token taxonomy) {
380 5 const std::lock_guard lock(m_mapMutex);
381 5 const auto key = std::pair(source, taxonomy.id);
382
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 4 times.
5 if (const auto found = m_maps.find(key); found != m_maps.end()) {
383
1/1
✓ Branch 1 taken 1 time.
1 return found->second;
384 }
385
5/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 4 times.
4 CHRONO_BATCH_RENDER_ZONE("Semantics/Map");
386
1/1
✓ Branch 1 taken 4 times.
4 IdMap map;
387 4 std::vector<std::pair<StableId, std::string>> texts;
388
3/3
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 4 times.
16 for (const IdEntry& entry : Entries(source, taxonomy)) {
389 12 const StableId& id = entry.id;
390
1/1
✓ Branch 1 taken 12 times.
12 IdLabel& label = map[{id.words[0], id.words[1], id.words[2], id.words[3]}];
391
1/1
✓ Branch 1 taken 12 times.
12 label.path = entry.path;
392
1/1
✓ Branch 1 taken 12 times.
12 label.labels.insert(entry.labels.begin(), entry.labels.end());
393
1/1
✓ Branch 1 taken 12 times.
12 texts.emplace_back(id, entry.text);
394 4 }
395
2/2
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
4 SemanticMap built{std::make_shared<const IdMap>(std::move(map))};
396
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (source == RenderVarSource::SemanticIdMap || source == RenderVarSource::StableIdMap) {
397
1/1
✓ Branch 1 taken 2 times.
2 const std::vector<std::byte> bytes = PackIdMap(texts);
398 2 built.packed =
399
5/6
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
6 device::Tensor(m_structure.GetColumnStore().GetDevice().CreateBuffer(
400
1/1
✓ Branch 1 taken 2 times.
2 {.label = "semantic id map"}, std::span<const std::byte>(bytes)),
401
1/1
✓ Branch 1 taken 2 times.
4 0, device::DType::UInt8, {int64_t(bytes.size())});
402 2 }
403
2/2
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
4 return m_maps.emplace(key, std::move(built)).first->second;
404 13 }
405
406 1 IdEntries SemanticTable::StableIdEntries() const {
407 1 const Prims& prims = m_structure.GetPrims();
408 1 std::vector<std::vector<std::vector<std::string>>> texts;
409
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for (uint32_t taxonomy = 0; taxonomy < m_taxonomies.size(); ++taxonomy) {
410
1/1
✓ Branch 1 taken 1 time.
2 texts.push_back(SetTexts(taxonomy));
411 }
412 1 IdEntries entries;
413
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for (uint32_t prim = 0; prim < prims.Size(); ++prim) {
414
3/5
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
2 if (!prims.Alive(prim) ||
415
2/4
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1 (!IsA(prims.Record(prim).schema, SchemaId::Gprim) && !m_labelRows.contains(prim))) {
416 ✗ continue;
417 }
418
1/1
✓ Branch 1 taken 1 time.
1 IdEntry& entry = entries.emplace_back();
419
1/1
✓ Branch 1 taken 1 time.
1 entry.id = m_stableIds[prim];
420
2/2
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
2 entry.path = entry.text = m_structure.GetPaths().Path(prim);
421
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 for (uint32_t taxonomy = 0; prim < m_stride && taxonomy < m_taxonomies.size(); ++taxonomy) {
422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 const uint32_t id = m_semanticIds[size_t(taxonomy) * m_stride + prim];
423
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (id >= 2) {
424
0/1
✗ Branch 1 not taken.
✗ entry.labels.emplace_back(m_structure.GetTokens().Text(m_taxonomies[taxonomy]),
425
0/1
✗ Branch 1 not taken.
✗ texts[taxonomy][id - 2]);
426 }
427 }
428 }
429 1 return entries;
430 1 }
431
432 }
433