chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
246 / 285
86.3%
Branches:
260 / 357
72.8%
Functions:
15 / 15
100.0%

scene/tables/sensor_pipelines.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/scene/tables/sensor_pipelines.h"
3
4 #include <algorithm>
5 #include <cstring>
6
7 #include "chrono_batch_render/device/queue.h"
8 #include "chrono_batch_render/scene/schema/columns.h"
9 #include "chrono_batch_render/sensor_pipeline/node.h"
10 #include "chrono_batch_render/stage/publish/change_set.h"
11 #include "chrono_batch_render/stage/views/attribute.h"
12 #include "chrono_batch_render/stage/views/view.h"
13 #include "chrono_batch_render/util/error.h"
14 #include "chrono_batch_render/util/log.h"
15 #include "chrono_batch_render/util/profiler.h"
16 #include "chrono_batch_render/util/span.h"
17
18 namespace chrono::batch_render {
19
20 namespace {
21
22 enum class AnyEnum : uint32_t {};
23
24 275 std::vector<ColumnRef> SensorPipelineInputs() {
25 275 std::vector<ColumnRef> inputs;
26
3/3
✓ Branch 1 taken 31347 times.
✓ Branch 3 taken 31072 times.
✓ Branch 4 taken 275 times.
31347 for (uint32_t id = 0; id < SchemaCount(); ++id) {
27 31072 const auto schema = SchemaId(id);
28
2/2
✓ Branch 0 taken 22258 times.
✓ Branch 1 taken 8264 times.
30522 if (schema != SchemaId::Connectable && schema != SchemaId::Shader &&
29
3/3
✓ Branch 0 taken 30522 times.
✓ Branch 1 taken 550 times.
✓ Branch 3 taken 30522 times.
31072 !IsA(schema, SchemaId::SensorNode) && schema != SchemaId::SensorPipeline &&
30
2/2
✓ Branch 0 taken 21708 times.
✓ Branch 1 taken 550 times.
22258 schema != SchemaId::RenderVar) {
31 21708 continue;
32 }
33
1/1
✓ Branch 1 taken 9364 times.
9364 const Span<const ColumnInfo> columns = Columns(schema);
34
2/2
✓ Branch 0 taken 15424 times.
✓ Branch 1 taken 9364 times.
24788 for (uint32_t index = 0; index < columns.size(); ++index) {
35
1/1
✓ Branch 1 taken 15424 times.
15424 inputs.push_back({schema, &columns[index], index});
36 }
37 }
38 275 return inputs;
39 ✗ }
40
41 13 bool SameInstance(const SensorPipelineInstance& a, const SensorPipelineInstance& b) {
42
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
13 return a.definition == b.definition && a.words == b.words && a.error == b.error &&
43
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 a.resolved.key == b.resolved.key;
44 }
45
46 }
47
48 353 SensorPipelineTable::SensorPipelineTable(Structure& structure)
49
4/6
✓ Branch 2 taken 353 times.
✓ Branch 5 taken 353 times.
✓ Branch 8 taken 353 times.
✓ Branch 13 taken 353 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
706 : m_structure(structure), m_library(1), m_registry(sensor_pipeline::SensorPipelineNodes()) {}
50
51 2824 std::span<const ColumnRef> SensorPipelineTable::Inputs() const {
52
2/2
✓ Branch 1 taken 275 times.
✓ Branch 2 taken 2549 times.
2824 if (m_inputSchemas != SchemaCount()) {
53 275 m_inputs = SensorPipelineInputs();
54 275 m_inputSchemas = SchemaCount();
55 }
56 2824 return m_inputs;
57 }
58
59 8746 std::shared_ptr<const sensor_pipeline::NodeRegistry> SensorPipelineTable::Registry() const {
60 8746 const std::lock_guard lock(m_mutex);
61
1/2
✓ Branch 0 taken 8746 times.
✗ Branch 1 not taken.
17492 return m_registry;
62 8746 }
63
64 197 std::shared_ptr<const SensorPipelineInstance> SensorPipelineTable::Find(uint32_t prim) const {
65 197 const std::lock_guard lock(m_mutex);
66 197 const auto found = m_instances.find(prim);
67
3/4
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 165 times.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
362 return found == m_instances.end() ? nullptr : found->second;
68 197 }
69
70 24 std::shared_ptr<const sensor_pipeline::SensorPipelineSet> SensorPipelineTable::Definitions() const {
71 24 return m_library.Snapshot();
72 }
73
74 232 std::vector<sensor_pipeline::ConnectionDesc> SensorPipelineTable::Connections(uint32_t prim) const {
75 232 std::vector<sensor_pipeline::ConnectionDesc> connections;
76
2/2
✓ Branch 0 taken 194 times.
✓ Branch 1 taken 232 times.
426 for (const ConnectionCache::Connection& connection : m_connections.Get(prim)) {
77
1/1
✓ Branch 1 taken 194 times.
388 connections.push_back({.input = std::string(connection.input),
78 194 .source = connection.source,
79 .sourcePath = connection.source != kNoPrim
80
1/1
✓ Branch 1 taken 194 times.
194 ? m_structure.GetPaths().Path(connection.source)
81 : std::string("nothing"),
82
1/1
✓ Branch 1 taken 194 times.
194 .output = std::string(connection.output)});
83 }
84 232 return connections;
85 388 }
86
87 187 sensor_pipeline::NodeDesc SensorPipelineTable::GatherNode(uint32_t prim) const {
88 187 const Prims& prims = m_structure.GetPrims();
89 187 const SchemaId schema = prims.Record(prim).schema;
90 187 const uint64_t apis = prims.Record(prim).apis;
91
2/2
✓ Branch 2 taken 187 times.
✓ Branch 6 taken 187 times.
187 const View view(m_structure, schema, std::vector<uint32_t>{prim});
92
1/1
✓ Branch 1 taken 187 times.
187 const Tokens& tokens = m_structure.GetTokens();
93
2/2
✓ Branch 1 taken 187 times.
✓ Branch 4 taken 187 times.
187 sensor_pipeline::NodeDesc node{.prim = prim, .path = m_structure.GetPaths().Path(prim)};
94
6/7
✓ Branch 1 taken 187 times.
✓ Branch 4 taken 187 times.
✓ Branch 7 taken 187 times.
✓ Branch 10 taken 187 times.
✓ Branch 15 taken 187 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 187 times.
374 node.id = std::string(tokens.Text(view.Get<Token>(kShaderId).Get().front()));
95
1/1
✓ Branch 1 taken 187 times.
187 node.inputs = Connections(prim);
96
1/1
✓ Branch 1 taken 187 times.
187 const sensor_pipeline::NodeRegistry& registry = *m_registry;
97
1/1
✓ Branch 1 taken 187 times.
187 const uint32_t def = registry.Find(node.id);
98
1/2
✓ Branch 0 taken 187 times.
✗ Branch 1 not taken.
187 if (def == sensor_pipeline::kNoDef) {
99 return node;
100 }
101
2/2
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 187 times.
303 for (const sensor_pipeline::UniformDef& uniform : registry[def].uniforms) {
102
1/1
✓ Branch 1 taken 116 times.
116 const ColumnRef column = FindColumn(schema, apis, uniform.name);
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 116 times.
116 if (!column) {
104 ✗ continue;
105 }
106
2/4
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
116 std::string value;
107
2/4
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
116 switch (column.column->type) {
108 101 case ColumnType::Enum: {
109
3/4
✓ Branch 1 taken 101 times.
✓ Branch 4 taken 101 times.
✓ Branch 7 taken 101 times.
✗ Branch 8 not taken.
101 const uint32_t index = uint32_t(view.Get<AnyEnum>(column).Get().front());
110
2/3
✓ Branch 0 taken 101 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 101 times.
101 value = index < column.column->tokens.size() ? std::string(column.column->tokens[index])
111
0/1
✗ Branch 1 not taken.
101 : uniform.fallback;
112 101 break;
113 }
114 ✗ case ColumnType::Token:
115
0/6
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ value = std::string(tokens.Text(view.Get<Token>(column).Get().front()));
116 ✗ break;
117 15 case ColumnType::Bool:
118
4/6
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 15 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 15 times.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
30 value = view.Get<bool>(column).Get().front() ? "true" : "false";
119 15 break;
120 ✗ default:
121 ✗ throw Error("{}'s {} is a uniform, so it must be a token or a bool", node.path,
122
0/1
✗ Branch 2 not taken.
✗ uniform.name);
123 }
124
1/1
✓ Branch 1 taken 116 times.
116 node.uniforms.emplace_back(uniform.name, std::move(value));
125 116 }
126 187 const std::vector<sensor_pipeline::ParameterDef>& parameters = registry[def].parameters;
127
2/2
✓ Branch 1 taken 104 times.
✓ Branch 2 taken 187 times.
291 for (uint32_t index = 0; index < parameters.size(); ++index) {
128
1/1
✓ Branch 1 taken 104 times.
104 const sensor_pipeline::ParameterDef& parameter = parameters[index];
129
1/1
✓ Branch 1 taken 104 times.
104 const ColumnRef column = FindColumn(schema, apis, parameter.name);
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
104 if (!column) {
131 104 continue;
132 }
133 104 const ColumnType type = column.column->type;
134 104 const bool copied = parameter.type == sensor_pipeline::ParameterType::Int
135
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 97 times.
104 ? type == ColumnType::Int
136 : parameter.type == sensor_pipeline::ParameterType::Bool
137
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 94 times.
97 ? type == ColumnType::Bool
138 94 : (type == ColumnType::Float || type == ColumnType::Float2 ||
139
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 type == ColumnType::Float3 || type == ColumnType::Float4) &&
140
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 ElementBytes(type) == parameter.words * sizeof(uint32_t);
141
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (copied) {
142
2/2
✓ Branch 1 taken 104 times.
✓ Branch 4 taken 104 times.
208 m_gathered[prim].push_back(
143
1/1
✓ Branch 1 taken 104 times.
104 {index, column, m_structure.GetPrims().Row(prim, column.schema)});
144 104 continue;
145 }
146 ✗ std::vector<float> values;
147
0/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ switch (type) {
148 ✗ case ColumnType::Float:
149
0/5
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ values = {view.Get<float>(column).Get().front()};
150 ✗ break;
151 ✗ case ColumnType::Int:
152
0/5
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ values = {float(view.Get<int32_t>(column).Get().front())};
153 ✗ break;
154 ✗ case ColumnType::Bool:
155
0/7
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ values = {view.Get<bool>(column).Get().front() ? 1.0f : 0.0f};
156 ✗ break;
157 ✗ case ColumnType::Float2: {
158
0/4
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ const Float2 value = view.Get<Float2>(column).Get().front();
159
0/1
✗ Branch 1 not taken.
✗ values = {value.x, value.y};
160 ✗ break;
161 }
162 ✗ case ColumnType::Float3: {
163
0/4
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ const Float3 value = view.Get<Float3>(column).Get().front();
164
0/1
✗ Branch 1 not taken.
✗ values = {value.x, value.y, value.z};
165 ✗ break;
166 }
167 ✗ case ColumnType::Float4: {
168
0/4
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ const Float4 value = view.Get<Float4>(column).Get().front();
169
0/1
✗ Branch 1 not taken.
✗ values = {value.x, value.y, value.z, value.w};
170 ✗ break;
171 }
172 ✗ default:
173
0/1
✗ Branch 2 not taken.
✗ throw Error("{}'s {} is a value, so it must be numeric", node.path, parameter.name);
174 }
175
0/1
✗ Branch 1 not taken.
✗ node.values.emplace_back(parameter.name, std::move(values));
176 ✗ }
177 return node;
178 187 }
179
180 478 std::vector<SensorPipelineTable::Tap> SensorPipelineTable::GatherTaps() const {
181 478 const Prims& prims = m_structure.GetPrims();
182 478 const Tokens& tokens = m_structure.GetTokens();
183 478 std::vector<Tap> taps;
184
2/2
✓ Branch 0 taken 11431 times.
✓ Branch 1 taken 478 times.
11909 for (uint32_t prim = 0; prim < prims.Size(); ++prim) {
185
6/6
✓ Branch 1 taken 11431 times.
✓ Branch 3 taken 10620 times.
✓ Branch 4 taken 811 times.
✓ Branch 6 taken 10620 times.
✓ Branch 8 taken 10166 times.
✓ Branch 9 taken 454 times.
11431 if (!prims.Alive(prim) || prims.Record(prim).schema != SchemaId::RenderVar) {
186 11426 continue;
187 }
188
3/3
✓ Branch 1 taken 454 times.
✓ Branch 4 taken 454 times.
✓ Branch 8 taken 454 times.
454 const View view(m_structure, SchemaId::RenderVar, std::vector<uint32_t>{prim});
189
6/7
✓ Branch 1 taken 454 times.
✓ Branch 4 taken 454 times.
✓ Branch 7 taken 454 times.
✓ Branch 10 taken 454 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 449 times.
✓ Branch 13 taken 5 times.
908 if (tokens.Text(view.Get<Token>(kRenderVarSourceName).Get().front()) != kTapSource) {
190 449 continue;
191 }
192
2/4
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
5 const std::vector<uint32_t> targets = view.GetArray<uint32_t>(kRenderVarTap).Get(0);
193
3/5
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 if (targets.empty() || !prims.Alive(targets.front())) {
194 ✗ continue;
195 }
196 10 taps.push_back(
197
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 {m_structure.GetPaths().Path(prim), targets.front(),
198
4/5
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 7 taken 5 times.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
15 std::string(tokens.Text(view.Get<Token>(kRenderVarTapOutput).Get().front()))});
199 459 }
200 478 return taps;
201 15 }
202
203 45 sensor_pipeline::SensorPipelineDesc SensorPipelineTable::Gather(uint32_t pipeline,
204 std::span<const Tap> taps) const {
205 45 const Prims& prims = m_structure.GetPrims();
206 45 sensor_pipeline::SensorPipelineDesc desc{.prim = pipeline,
207 45 .path = m_structure.GetPaths().Path(pipeline)};
208
1/1
✓ Branch 1 taken 45 times.
45 desc.outputs = Connections(pipeline);
209
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 45 times.
53 for (const Tap& tap : taps) {
210
1/1
✓ Branch 1 taken 8 times.
8 const std::string node = m_structure.GetPaths().Path(tap.node);
211
6/9
✓ Branch 1 taken 8 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
21 if (!node.starts_with(desc.path + "/") ||
212
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 !IsA(prims.Record(tap.node).schema, SchemaId::SensorNode)) {
213 3 continue;
214 }
215
1/1
✓ Branch 1 taken 5 times.
5 std::string output = tap.output;
216
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 if (output.empty()) {
217
1/1
✓ Branch 1 taken 4 times.
4 const sensor_pipeline::NodeDesc described = GatherNode(tap.node);
218
1/1
✓ Branch 1 taken 4 times.
4 const uint32_t def = m_registry->Find(described.id);
219
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 if (def == sensor_pipeline::kNoDef || (*m_registry)[def].outputs.size() != 1) {
220 ✗ throw Error("{} taps {}, so its tapOutput must name one of the node's outputs",
221
0/1
✗ Branch 2 not taken.
✗ tap.name, node);
222 }
223
1/1
✓ Branch 2 taken 4 times.
4 output = (*m_registry)[def].outputs.front().name;
224 4 }
225 5 desc.outputs.push_back(
226 10 {.input = tap.name, .source = tap.node, .sourcePath = node, .output = output});
227 8 }
228 45 std::vector<uint32_t> pending;
229 45 std::vector<uint32_t> seen;
230
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 45 times.
104 for (const sensor_pipeline::ConnectionDesc& output : desc.outputs) {
231
1/1
✓ Branch 1 taken 59 times.
59 pending.push_back(output.source);
232 }
233
2/2
✓ Branch 0 taken 196 times.
✓ Branch 1 taken 45 times.
241 while (!pending.empty()) {
234 196 const uint32_t prim = pending.back();
235 196 pending.pop_back();
236
4/6
✓ Branch 0 taken 196 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 183 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 183 times.
✗ Branch 6 not taken.
379 if (prim == kNoPrim || std::ranges::find(seen, prim) != seen.end() ||
237
2/2
✓ Branch 1 taken 183 times.
✓ Branch 4 taken 183 times.
183 !IsA(prims.Record(prim).schema, SchemaId::SensorNode)) {
238 13 continue;
239 }
240
1/1
✓ Branch 1 taken 183 times.
183 seen.push_back(prim);
241
1/1
✓ Branch 1 taken 183 times.
183 sensor_pipeline::NodeDesc node = GatherNode(prim);
242
2/2
✓ Branch 0 taken 137 times.
✓ Branch 1 taken 183 times.
320 for (const sensor_pipeline::ConnectionDesc& input : node.inputs) {
243
1/1
✓ Branch 1 taken 137 times.
137 pending.push_back(input.source);
244 }
245
1/1
✓ Branch 1 taken 183 times.
183 desc.nodes.push_back(std::move(node));
246 183 }
247 45 std::ranges::sort(desc.nodes, {}, &sensor_pipeline::NodeDesc::prim);
248 45 return desc;
249 50 }
250
251 485 void SensorPipelineTable::Run(const ChangeSet& changes, TableVersions&) {
252
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 480 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
485 CHRONO_BATCH_RENDER_ZONE("Pipelines/Run");
253
1/1
✓ Branch 1 taken 485 times.
485 ColumnStore& store = m_structure.GetColumnStore();
254 485 std::shared_ptr<const sensor_pipeline::NodeRegistry> nodes =
255
1/1
✓ Branch 1 taken 485 times.
485 sensor_pipeline::SensorPipelineNodes();
256
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 480 times.
485 const bool reloaded = nodes != m_registry;
257
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 480 times.
485 if (reloaded) {
258
1/1
✓ Branch 1 taken 5 times.
5 const std::lock_guard lock(m_mutex);
259 5 m_registry = std::move(nodes);
260 5 }
261 485 std::vector<const ColumnInfo*> written;
262
3/3
✓ Branch 1 taken 485 times.
✓ Branch 3 taken 27207 times.
✓ Branch 4 taken 485 times.
27692 for (const ColumnRef input : Inputs()) {
263
3/3
✓ Branch 1 taken 27207 times.
✓ Branch 3 taken 1210 times.
✓ Branch 4 taken 25997 times.
27207 if (store.LastWrite(input) > m_seen) {
264
1/1
✓ Branch 1 taken 1210 times.
1210 written.push_back(input.column);
265 }
266 }
267
2/2
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 5 times.
485 m_seen = store.WriteSequence();
268 485 const bool restructured =
269
8/8
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 209 times.
✓ Branch 3 taken 271 times.
✓ Branch 4 taken 32 times.
✓ Branch 5 taken 177 times.
✓ Branch 6 taken 21 times.
✓ Branch 7 taken 11 times.
485 reloaded || changes.resync || changes.structure || !changes.apis.empty();
270
3/3
✓ Branch 1 taken 21 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 7 times.
21 if (!restructured && std::ranges::all_of(written, [&](const ColumnInfo* column) {
271 23 return m_pack.Reads(column);
272 })) {
273
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (!written.empty()) {
274
1/1
✓ Branch 1 taken 7 times.
7 Pack(false);
275 }
276 7 return;
277 }
278
1/1
✓ Branch 1 taken 478 times.
478 const Prims& prims = m_structure.GetPrims();
279
1/1
✓ Branch 1 taken 478 times.
478 const sensor_pipeline::NodeRegistry& registry = *m_registry;
280
1/1
✓ Branch 1 taken 478 times.
478 std::map<uint32_t, std::shared_ptr<const SensorPipelineInstance>> resolved;
281
1/1
✓ Branch 1 taken 478 times.
478 m_connections.Update(changes);
282
1/1
✓ Branch 1 taken 478 times.
478 const std::vector<Tap> taps = GatherTaps();
283 478 m_gathered.clear();
284
1/1
✓ Branch 1 taken 478 times.
478 m_pack.Clear();
285 478 uint32_t words = 0;
286 478 bool changed = false;
287
2/2
✓ Branch 0 taken 11431 times.
✓ Branch 1 taken 478 times.
11909 for (uint32_t prim = 0; prim < prims.Size(); ++prim) {
288
7/7
✓ Branch 1 taken 11431 times.
✓ Branch 3 taken 10620 times.
✓ Branch 4 taken 811 times.
✓ Branch 6 taken 10620 times.
✓ Branch 9 taken 10620 times.
✓ Branch 11 taken 45 times.
✓ Branch 12 taken 10575 times.
11431 if (!prims.Alive(prim) || !IsA(prims.Record(prim).schema, SchemaId::SensorPipeline)) {
289 11386 continue;
290 }
291
1/1
✓ Branch 1 taken 45 times.
45 auto instance = std::make_shared<SensorPipelineInstance>();
292
1/1
✓ Branch 1 taken 45 times.
45 instance->prim = prim;
293
1/3
✓ Branch 1 taken 45 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
45 instance->path = m_structure.GetPaths().Path(prim);
294 45 try {
295
1/1
✓ Branch 1 taken 45 times.
45 instance->resolved =
296
2/2
✓ Branch 1 taken 45 times.
✓ Branch 4 taken 44 times.
45 sensor_pipeline::ResolveSensorPipeline(Gather(prim, taps), registry);
297
2/2
✓ Branch 1 taken 44 times.
✓ Branch 4 taken 44 times.
44 instance->definition = m_library.Intern(instance->resolved.key, [&](uint32_t id) {
298 38 return sensor_pipeline::BuildDefinition(id, instance->resolved, registry);
299 });
300
1/1
✓ Branch 1 taken 44 times.
44 const auto definitions = m_library.Snapshot();
301 44 const sensor_pipeline::SensorPipelineDefinition& definition =
302
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 *definitions->Find(instance->definition);
303
1/3
✓ Branch 1 taken 44 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
44 instance->words = sensor_pipeline::PackWords(definition, instance->resolved, registry);
304 44 instance->firstWord = words;
305 44 words += uint32_t(instance->words.size());
306
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 44 times.
221 for (uint32_t node = 0; node < instance->resolved.nodes.size(); ++node) {
307 177 const sensor_pipeline::ResolvedNode& each = instance->resolved.nodes[node];
308 177 const auto found = m_gathered.find(each.prim);
309
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 76 times.
177 if (found == m_gathered.end()) {
310 101 continue;
311 }
312 76 const std::vector<sensor_pipeline::ParameterDef>& parameters =
313 76 registry[each.def].parameters;
314
2/2
✓ Branch 0 taken 101 times.
✓ Branch 1 taken 76 times.
177 for (const Gathered& gathered : found->second) {
315 101 uint32_t offset = definition.parameterOffsets[node];
316
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 101 times.
135 for (uint32_t index = 0; index < gathered.parameter; ++index) {
317 34 offset += parameters[index].words;
318 }
319
1/1
✓ Branch 1 taken 101 times.
101 m_pack.Copy(gathered.column, gathered.row, instance->firstWord + offset);
320 }
321 }
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
45 } catch (const Error& error) {
323
1/1
✓ Branch 2 taken 1 time.
1 instance->error = error.what();
324
1/1
✓ Branch 1 taken 1 time.
1 Log(LogLevel::Warning, "{}", instance->error);
325 1 }
326
1/1
✓ Branch 1 taken 45 times.
45 const std::shared_ptr<const SensorPipelineInstance> previous = Find(prim);
327
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 4 times.
45 changed |= !previous || !SameInstance(*previous, *instance);
328
1/1
✓ Branch 1 taken 45 times.
45 resolved.emplace(prim, std::move(instance));
329 45 }
330 478 {
331
1/1
✓ Branch 1 taken 478 times.
478 const std::lock_guard lock(m_mutex);
332 478 changed |= resolved.size() != m_instances.size();
333 478 m_instances = std::move(resolved);
334
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 443 times.
478 if (changed) {
335 35 ++m_version;
336 }
337 478 }
338
3/3
✓ Branch 0 taken 445 times.
✓ Branch 1 taken 33 times.
✓ Branch 3 taken 478 times.
923 m_words.Reserve(m_structure.GetColumnStore().GetDevice(), std::max(words, 1u));
339
1/1
✓ Branch 1 taken 478 times.
478 m_pack.Build(store, false);
340
1/1
✓ Branch 1 taken 478 times.
478 Pack(true);
341 965 }
342
343 485 void SensorPipelineTable::Pack(bool rewrite) {
344
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 480 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
485 CHRONO_BATCH_RENDER_ZONE("Pipelines/Pack");
345
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 7 times.
485 device::Device& device = m_structure.GetColumnStore().GetDevice();
346
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 7 times.
485 device::Queue& queue = device.GetQueue();
347
2/2
✓ Branch 0 taken 478 times.
✓ Branch 1 taken 7 times.
485 if (rewrite) {
348
4/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 478 times.
523 for (const auto& [prim, instance] : m_instances) {
349
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 3 times.
45 if (!instance->words.empty()) {
350
2/2
✓ Branch 1 taken 42 times.
✓ Branch 4 taken 42 times.
42 queue.Write(
351
1/1
✓ Branch 1 taken 42 times.
42 m_words.Buffer()->Slice(uint64_t(instance->firstWord) * sizeof(uint32_t),
352
1/1
✓ Branch 1 taken 42 times.
42 instance->words.size() * sizeof(uint32_t)),
353
1/1
✓ Branch 1 taken 42 times.
42 instance->words.data());
354 }
355 }
356 }
357
2/3
✓ Branch 0 taken 485 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 485 times.
970 m_pack.Pack(m_structure.GetColumnStore(), m_words.Address());
358 485 }
359
360 6 std::vector<uint32_t> SensorPipelineTable::ReadWords(const SensorPipelineInstance& instance) const {
361
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if (instance.words.empty() || !m_words.Buffer()) {
362 ✗ return instance.words;
363 }
364 6 device::Queue& queue = m_structure.GetColumnStore().GetDevice().GetQueue();
365 6 const device::Download download = queue.ReadAsync(m_words.Buffer()->Slice(
366 6 uint64_t(instance.firstWord) * sizeof(uint32_t), instance.words.size() * sizeof(uint32_t)));
367
1/1
✓ Branch 1 taken 6 times.
6 download.Wait();
368
1/1
✓ Branch 1 taken 6 times.
6 std::vector<uint32_t> words(instance.words.size());
369
1/1
✓ Branch 1 taken 6 times.
6 std::memcpy(words.data(), download.Bytes().data(), words.size() * sizeof(uint32_t));
370 6 return words;
371 6 }
372
373 }
374