chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
72 / 82
87.8%
Branches:
54 / 98
55.1%
Functions:
4 / 4
100.0%

stage/structure/packing.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/stage/structure/packing.h"
3
4 #include <algorithm>
5 #include <cstring>
6 #include <numeric>
7
8 #include "chrono_batch_render/util/error.h"
9
10 namespace chrono::batch_render {
11
12 namespace {
13
14 54 void CheckPrimvar(const Primvar& primvar) {
15
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (primvar.name.empty()) {
16
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("a primvar needs a name");
17 }
18
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (primvar.elementSize == 0) {
19
0/1
✗ Branch 2 not taken.
✗ throw Error("primvar {} has an elementSize of 0", primvar.name);
20 }
21
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 const uint32_t stride = PrimvarComponents(primvar.type) * primvar.elementSize;
22
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (primvar.words.size() % stride != 0) {
23
0/1
✗ Branch 1 not taken.
✗ throw Error("primvar {} has {} words, not a multiple of its {} per value", primvar.name,
24
0/1
✗ Branch 2 not taken.
✗ primvar.words.size(), stride);
25 }
26
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 54 times.
70 for (const int32_t index : primvar.indices) {
27
2/4
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (index < 0 || uint32_t(index) >= primvar.ValueCount()) {
28
0/1
✗ Branch 1 not taken.
✗ throw Error("primvar {} indexes value {} of {}", primvar.name, index,
29
0/1
✗ Branch 2 not taken.
✗ primvar.ValueCount());
30 }
31 }
32 54 }
33
34 }
35
36 1030 std::vector<int32_t> PackPrimvars(Tokens& tokens, std::span<const Primvar> primvars) {
37
2/2
✓ Branch 0 taken 978 times.
✓ Branch 1 taken 52 times.
1030 if (primvars.empty()) {
38 978 return {};
39 }
40
41 52 std::vector<uint32_t> names(primvars.size());
42
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 52 times.
106 for (size_t i = 0; i < primvars.size(); ++i) {
43
1/1
✓ Branch 1 taken 54 times.
54 CheckPrimvar(primvars[i]);
44
1/1
✓ Branch 1 taken 54 times.
54 names[i] = tokens.Intern(primvars[i].name).id;
45 }
46
1/1
✓ Branch 1 taken 52 times.
52 std::vector<uint32_t> order(primvars.size());
47 52 std::iota(order.begin(), order.end(), 0u);
48 52 std::sort(order.begin(), order.end(),
49
3/24
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 1 time.
✓ Branch 23 taken 1 time.
3 [&](uint32_t a, uint32_t b) { return names[a] < names[b]; });
50
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 52 times.
54 for (size_t i = 1; i < order.size(); ++i) {
51
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (names[order[i]] == names[order[i - 1]]) {
52
0/1
✗ Branch 2 not taken.
✗ throw Error("primvar {} is given twice", primvars[order[i]].name);
53 }
54 }
55
56
1/1
✓ Branch 1 taken 52 times.
52 std::vector<int32_t> table(1 + primvars.size() * kPrimvarEntryWords);
57 52 table[0] = int32_t(primvars.size());
58
2/2
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 52 times.
106 for (size_t slot = 0; slot < order.size(); ++slot) {
59
1/1
✓ Branch 1 taken 54 times.
54 const Primvar& primvar = primvars[order[slot]];
60 54 PrimvarEntry entry{};
61 54 entry.name = names[order[slot]];
62 54 entry.type = uint32_t(primvar.type);
63 54 entry.interpolation = uint32_t(primvar.interpolation);
64 54 entry.elementSize = primvar.elementSize;
65
1/1
✓ Branch 1 taken 54 times.
54 entry.values = uint32_t(table.size());
66
1/1
✓ Branch 1 taken 54 times.
54 entry.valueCount = primvar.ValueCount();
67
1/1
✓ Branch 1 taken 54 times.
54 table.insert(table.end(), primvar.words.begin(), primvar.words.end());
68
1/1
✓ Branch 1 taken 54 times.
54 entry.indices = uint32_t(table.size());
69 54 entry.indexCount = uint32_t(primvar.indices.size());
70
1/1
✓ Branch 1 taken 54 times.
54 table.insert(table.end(), primvar.indices.begin(), primvar.indices.end());
71 54 std::memcpy(table.data() + 1 + slot * kPrimvarEntryWords, &entry, sizeof(entry));
72 }
73 52 return table;
74 52 }
75
76 48 std::vector<Primvar> UnpackPrimvars(const Tokens& tokens, std::span<const int32_t> table) {
77
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 44 times.
48 if (table.empty()) {
78 4 return {};
79 }
80
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 const uint32_t count = uint32_t(table[0]);
81
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (table.size() < 1 + size_t(count) * kPrimvarEntryWords) {
82
0/1
✗ Branch 2 not taken.
✗ throw Error("a primvar table of {} words can't hold {} entries", table.size(), count);
83 }
84 44 std::vector<Primvar> primvars;
85
1/1
✓ Branch 1 taken 44 times.
44 primvars.reserve(count);
86
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 44 times.
94 for (uint32_t slot = 0; slot < count; ++slot) {
87 50 PrimvarEntry entry;
88
1/1
✓ Branch 1 taken 50 times.
50 std::memcpy(&entry, table.data() + 1 + slot * kPrimvarEntryWords, sizeof(entry));
89
1/1
✓ Branch 1 taken 50 times.
50 Primvar primvar;
90
2/2
✓ Branch 1 taken 50 times.
✓ Branch 4 taken 50 times.
50 primvar.name = std::string(tokens.Text(Token{entry.name}));
91 50 primvar.type = PrimvarType(entry.type);
92 50 primvar.interpolation = Interpolation(entry.interpolation);
93 50 primvar.elementSize = entry.elementSize;
94 50 const uint32_t words =
95
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 entry.valueCount * PrimvarComponents(primvar.type) * entry.elementSize;
96
2/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 50 times.
50 if (size_t(entry.values) + words > table.size() ||
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 size_t(entry.indices) + entry.indexCount > table.size()) {
98
0/1
✗ Branch 2 not taken.
✗ throw Error("primvar {} runs past the end of its table", primvar.name);
99 }
100
1/1
✓ Branch 1 taken 50 times.
50 const auto values = table.subspan(entry.values, words);
101
1/1
✓ Branch 1 taken 50 times.
50 primvar.words.assign(values.begin(), values.end());
102
1/1
✓ Branch 1 taken 50 times.
50 const auto indices = table.subspan(entry.indices, entry.indexCount);
103
1/1
✓ Branch 1 taken 50 times.
50 primvar.indices.assign(indices.begin(), indices.end());
104
1/1
✓ Branch 1 taken 50 times.
50 primvars.push_back(std::move(primvar));
105 50 }
106 44 return primvars;
107 44 }
108
109 2187 std::vector<uint32_t> InternTokens(Tokens& tokens, std::span<const std::string> texts) {
110 2187 std::vector<uint32_t> ids;
111
1/1
✓ Branch 1 taken 2187 times.
2187 ids.reserve(texts.size());
112
2/2
✓ Branch 0 taken 635 times.
✓ Branch 1 taken 2187 times.
2822 for (const std::string& text : texts) {
113
1/1
✓ Branch 1 taken 635 times.
1270 ids.push_back(tokens.Intern(text).id);
114 }
115 2187 return ids;
116 ✗ }
117
118 }
119