chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
276 / 282
97.9%
Branches:
327 / 358
91.3%
Functions:
17 / 17
100.0%

stage/publish/publisher.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/stage/publish/publisher.h"
3
4 #include <algorithm>
5 #include <optional>
6
7 #include "chrono_batch_render/device/commands.h"
8 #include "chrono_batch_render/device/queue.h"
9 #include "chrono_batch_render/stage/columns/kernels/changes.h"
10 #include "chrono_batch_render/util/error.h"
11 #include "chrono_batch_render/util/log.h"
12 #include "chrono_batch_render/util/profiler.h"
13
14 namespace chrono::batch_render {
15
16 683 void Publisher::Finish() {
17
2/2
✓ Branch 0 taken 12294 times.
✓ Branch 1 taken 683 times.
12977 for (const Scheduled& scheduled : m_scheduled) {
18 12294 scheduled.table->Finish();
19 }
20 683 }
21
22 21841 bool Publisher::Pending() const {
23
4/4
✓ Branch 0 taken 20580 times.
✓ Branch 1 taken 1261 times.
✓ Branch 2 taken 20527 times.
✓ Branch 3 taken 53 times.
21841 return m_structure.GetColumnStore().WriteSequence() != m_writes ||
24
6/6
✓ Branch 0 taken 20580 times.
✓ Branch 1 taken 1261 times.
✓ Branch 2 taken 20527 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 20458 times.
42368 m_structure.Epoch() != m_epoch ||
25 20527 std::ranges::any_of(
26 167689 m_scheduled, [](const Scheduled& scheduled) { return scheduled.table->Pending(); });
27 }
28
29 6526 void Publisher::Add(Table& table) {
30
2/2
✓ Branch 1 taken 5192 times.
✓ Branch 2 taken 6524 times.
11716 for (const TableId output : table.TableOutputs()) {
31
2/2
✓ Branch 1 taken 6785 times.
✓ Branch 2 taken 5191 times.
11976 for (const TableId input : table.TableInputs()) {
32
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 6784 times.
6785 if (input == output) {
33
2/2
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
1 throw Error("Table {} reads its own output", table.Name());
34 }
35 }
36
2/2
✓ Branch 0 taken 23109 times.
✓ Branch 1 taken 5190 times.
28299 for (const Scheduled& earlier : m_scheduled) {
37
2/2
✓ Branch 1 taken 4237 times.
✓ Branch 2 taken 23108 times.
27345 for (const TableId input : earlier.table->TableInputs()) {
38
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 4236 times.
4237 if (input == output) {
39
1/1
✓ Branch 1 taken 1 time.
1 throw Error("Table {} writes a table {} reads, so add {} first", table.Name(),
40
3/3
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✓ Branch 8 taken 1 time.
2 earlier.table->Name(), table.Name());
41 }
42 }
43 }
44 }
45
2/2
✓ Branch 1 taken 2886 times.
✓ Branch 2 taken 6524 times.
9410 for (const ColumnRef column : table.RowInputs()) {
46 2886 m_structure.GetColumnStore().TrackRows(column);
47 }
48
1/1
✓ Branch 1 taken 6524 times.
6524 m_scheduled.push_back({&table});
49 6524 }
50
51 9 Ordinal Publisher::SealedStamp(Ordinal ordinal) const {
52 9 const auto after = std::ranges::upper_bound(m_sealed, ordinal, {}, &Sealed::ordinal);
53
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 2 times.
16 return after == m_sealed.begin() ? 0 : std::prev(after)->stamp;
54 }
55
56 148163 Ordinal Publisher::SealedOrdinal(Ordinal stamp, Ordinal sealing) const {
57 148163 const auto found = std::ranges::lower_bound(m_sealed, stamp, {}, &Sealed::stamp);
58
2/2
✓ Branch 0 taken 5364 times.
✓ Branch 1 taken 142799 times.
148163 return found == m_sealed.end() ? sealing : found->ordinal;
59 }
60
61 10474 ChangeSet Publisher::Build(Ordinal since, Ordinal until, Ordinal sealing,
62 std::span<const ColumnRef> columns, std::span<const ColumnRef> rows,
63 std::vector<Ref<device::Buffer>>* reused) {
64
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10469 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
10474 CHRONO_BATCH_RENDER_ZONE("Publisher/Changes");
65
2/2
✓ Branch 0 taken 5359 times.
✓ Branch 1 taken 5115 times.
10474 ColumnStore& store = m_structure.GetColumnStore();
66 10474 ChangeSet changes;
67
2/2
✓ Branch 0 taken 5359 times.
✓ Branch 1 taken 5115 times.
10474 changes.since = since == 0 ? 0 : SealedOrdinal(since, sealing);
68 10474 changes.until = SealedOrdinal(until, sealing);
69 10474 changes.sinceStamp = since;
70 10474 changes.untilStamp = until;
71 10474 changes.resync = since == 0;
72 10474 {
73
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10469 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 10 taken 10474 times.
10474 CHRONO_BATCH_RENDER_ZONE("Publisher/StructureLog");
74 10474 const std::span<const StructureEntry> log = m_structure.Log();
75 142804 for (auto at = std::ranges::upper_bound(log, since, {}, &StructureEntry::ordinal);
76
3/4
✓ Branch 0 taken 132330 times.
✓ Branch 1 taken 10474 times.
✓ Branch 2 taken 132330 times.
✗ Branch 3 not taken.
142804 at != log.end() && at->ordinal <= until; ++at) {
77 132330 StructureEntry entry = *at;
78 132330 entry.ordinal = SealedOrdinal(entry.ordinal, sealing);
79
2/2
✓ Branch 0 taken 379 times.
✓ Branch 1 taken 131951 times.
132330 if (entry.api != SchemaId::None) {
80
1/1
✓ Branch 1 taken 379 times.
379 changes.apis.push_back(entry);
81 } else {
82
3/3
✓ Branch 0 taken 129266 times.
✓ Branch 1 taken 2685 times.
✓ Branch 3 taken 131951 times.
131951 (entry.added ? changes.added : changes.removed).push_back(entry);
83 }
84 }
85
4/4
✓ Branch 0 taken 2915 times.
✓ Branch 1 taken 7559 times.
✓ Branch 2 taken 804 times.
✓ Branch 3 taken 2111 times.
10474 changes.structure = !changes.added.empty() || !changes.removed.empty();
86 10474 }
87 10474 {
88
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10469 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 10 taken 10474 times.
10474 CHRONO_BATCH_RENDER_ZONE("Publisher/Worlds");
89 10474 const uint32_t worlds = m_structure.GetPrims().WorldCount();
90
2/2
✓ Branch 0 taken 12006 times.
✓ Branch 1 taken 10474 times.
22480 for (uint32_t slot = 0; slot <= worlds; ++slot) {
91
2/2
✓ Branch 0 taken 1532 times.
✓ Branch 1 taken 10474 times.
12006 const uint32_t world = SlotWorld(slot);
92
1/1
✓ Branch 1 taken 12006 times.
12006 const Ordinal stamp = store.WorldStamp(world);
93
3/4
✓ Branch 0 taken 11386 times.
✓ Branch 1 taken 620 times.
✓ Branch 2 taken 11386 times.
✗ Branch 3 not taken.
12006 if (stamp > since && stamp <= until) {
94
1/1
✓ Branch 1 taken 11386 times.
11386 changes.worlds.push_back(world);
95 }
96 }
97 10474 std::ranges::sort(changes.worlds);
98 10474 }
99 10474 {
100
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10469 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 10 taken 10474 times.
10474 CHRONO_BATCH_RENDER_ZONE("Publisher/ArrayRows");
101
2/2
✓ Branch 0 taken 268339 times.
✓ Branch 1 taken 10474 times.
278813 for (const ColumnRef column : columns) {
102
2/2
✓ Branch 0 taken 61316 times.
✓ Branch 1 taken 207023 times.
268339 if (IsArray(column.column->type)) {
103
2/2
✓ Branch 1 taken 61316 times.
✓ Branch 4 taken 61316 times.
61316 changes.arrays.emplace_back(column, store.ArrayRows(column, since, until));
104 }
105 }
106 10474 }
107
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 9910 times.
10474 if (rows.empty()) {
108 return changes;
109 }
110
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 559 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 10 taken 564 times.
564 CHRONO_BATCH_RENDER_ZONE("Publisher/CompactRows");
111
2/2
✓ Branch 0 taken 558 times.
✓ Branch 1 taken 6 times.
564 if (reused != nullptr) {
112
1/1
✓ Branch 1 taken 558 times.
558 reused->resize(rows.size());
113 }
114 564 device::Queue& queue = store.GetDevice().GetQueue();
115 564 std::optional<device::CommandEncoder> encoder;
116
2/2
✓ Branch 0 taken 4071 times.
✓ Branch 1 taken 564 times.
4635 for (size_t i = 0; i < rows.size(); ++i) {
117
1/1
✓ Branch 1 taken 4071 times.
4071 const ColumnRef column = rows[i];
118
1/1
✓ Branch 1 taken 4071 times.
4071 store.TrackRows(column);
119
1/1
✓ Branch 1 taken 4071 times.
4071 const ColumnTable& table = store.Schema(column.schema);
120
2/2
✓ Branch 0 taken 3732 times.
✓ Branch 1 taken 339 times.
4071 const uint32_t count = table.Rows();
121 4071 const uint64_t bytes =
122
2/2
✓ Branch 0 taken 3732 times.
✓ Branch 1 taken 339 times.
4071 (uint64_t(kChangedRowsOffset) + std::max(count, 1u)) * sizeof(uint32_t);
123
2/2
✓ Branch 0 taken 4065 times.
✓ Branch 1 taken 6 times.
4071 Ref<device::Buffer> buffer = reused != nullptr ? (*reused)[i] : nullptr;
124
4/4
✓ Branch 0 taken 1811 times.
✓ Branch 1 taken 2260 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 1791 times.
4071 if (!buffer || buffer->Bytes() < bytes) {
125
4/4
✓ Branch 1 taken 2280 times.
✓ Branch 4 taken 2280 times.
✓ Branch 6 taken 20 times.
✓ Branch 7 taken 2260 times.
2300 buffer = store.GetDevice().CreateBuffer({.bytes = bytes, .label = "changed rows"});
126 2280 if (reused != nullptr) {
127
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 2254 times.
2294 (*reused)[i] = buffer;
128 }
129 }
130
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 3507 times.
4071 if (!encoder) {
131
1/1
✓ Branch 1 taken 564 times.
1128 encoder.emplace(queue.CreateEncoder());
132 }
133
2/2
✓ Branch 1 taken 4071 times.
✓ Branch 4 taken 4071 times.
4071 encoder->Fill(buffer->Slice(0, kChangedRowsOffset * sizeof(uint32_t)));
134
1/1
✓ Branch 1 taken 4071 times.
4071 encoder->Barrier();
135 4071 CompactParams params{};
136
2/2
✓ Branch 1 taken 4071 times.
✓ Branch 4 taken 4071 times.
4071 params.stamps.address = table.Pages(store.StampColumn(column));
137
2/2
✓ Branch 1 taken 4071 times.
✓ Branch 4 taken 4071 times.
4071 params.tablePrims.address = table.Pages(store.PrimsColumn(column.schema));
138
1/1
✓ Branch 1 taken 4071 times.
4071 params.out.address = buffer->Address();
139 4071 params.since = since;
140 4071 params.until = until;
141 4071 params.rows = count;
142
1/1
✓ Branch 1 taken 4071 times.
4071 store.Record(*encoder, "CompactChanged", params, count);
143
1/1
✓ Branch 1 taken 4071 times.
4071 changes.columns.emplace_back(column, buffer, count);
144 4071 }
145
1/2
✓ Branch 0 taken 564 times.
✗ Branch 1 not taken.
564 if (encoder) {
146
2/4
✓ Branch 1 taken 564 times.
✓ Branch 4 taken 564 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
564 queue.Submit(encoder->Finish());
147 }
148
1/2
✓ Branch 0 taken 564 times.
✗ Branch 1 not taken.
564 return changes;
149 15034 }
150
151 1203 bool Publisher::RunTables(Ordinal stamp, Ordinal ordinal, std::span<Table* const> only) {
152 1203 ColumnStore& store = m_structure.GetColumnStore();
153 1203 bool ran = false;
154
2/2
✓ Branch 0 taken 17737 times.
✓ Branch 1 taken 1202 times.
18939 for (Scheduled& scheduled : m_scheduled) {
155 17737 Table& table = *scheduled.table;
156
4/4
✓ Branch 0 taken 648 times.
✓ Branch 1 taken 17089 times.
✓ Branch 3 taken 612 times.
✓ Branch 4 taken 36 times.
17737 if (!only.empty() && std::ranges::find(only, &table) == only.end()) {
157 7272 continue;
158 }
159 17125 const bool written = std::ranges::any_of(table.Inputs(), [&](ColumnRef input) {
160 308976 return store.LastWrite(input) > scheduled.writes;
161 });
162
4/4
✓ Branch 1 taken 16145 times.
✓ Branch 2 taken 980 times.
✓ Branch 3 taken 8067 times.
✓ Branch 4 taken 8078 times.
17125 const bool restructured = table.Structural() && m_structure.Epoch() != scheduled.epoch;
163 17125 const bool tabled = std::ranges::any_of(table.TableInputs(), [&](TableId id) {
164
1/2
✓ Branch 0 taken 13286 times.
✗ Branch 1 not taken.
13286 return m_versions.Version(id) > scheduled.logged;
165 });
166
8/8
✓ Branch 0 taken 12012 times.
✓ Branch 1 taken 5113 times.
✓ Branch 2 taken 7486 times.
✓ Branch 3 taken 4526 times.
✓ Branch 4 taken 6702 times.
✓ Branch 5 taken 784 times.
✓ Branch 7 taken 42 times.
✓ Branch 8 taken 6660 times.
17125 if (scheduled.ran && !written && !restructured && !tabled && !table.Pending()) {
167 6660 continue;
168 }
169
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10460 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
10465 CHRONO_BATCH_RENDER_ZONE("Publisher/Table");
170 20930 ChangeSet changes = Build(scheduled.ran ? scheduled.stamp : 0, stamp, ordinal,
171
5/5
✓ Branch 1 taken 10465 times.
✓ Branch 4 taken 10465 times.
✓ Branch 6 taken 5352 times.
✓ Branch 7 taken 5113 times.
✓ Branch 9 taken 10465 times.
10465 table.Inputs(), table.RowInputs(), &scheduled.changed);
172 10465 {
173
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 10460 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✓ Branch 10 taken 10465 times.
10465 CHRONO_BATCH_RENDER_ZONE("Publisher/Versions");
174
3/3
✓ Branch 1 taken 10465 times.
✓ Branch 3 taken 19721 times.
✓ Branch 4 taken 10465 times.
30186 for (const TableId id : table.TableInputs()) {
175
4/4
✓ Branch 0 taken 19610 times.
✓ Branch 1 taken 111 times.
✓ Branch 2 taken 8760 times.
✓ Branch 3 taken 10961 times.
39331 if (m_versions.Version(id) > scheduled.logged) {
176
1/1
✓ Branch 1 taken 8760 times.
8760 changes.wrote.push_back(id);
177
1/1
✓ Branch 1 taken 8760 times.
8760 m_versions.Collect(id, scheduled.logged, changes.worlds);
178 }
179 }
180 10465 }
181
1/1
✓ Branch 1 taken 10464 times.
10465 const uint64_t writes = store.WriteSequence();
182
1/1
✓ Branch 1 taken 10464 times.
10465 const uint64_t epoch = m_structure.Epoch();
183
1/1
✓ Branch 1 taken 10464 times.
10465 const uint64_t logged = m_versions.Sequence();
184 10465 ++table.m_runs;
185 10465 ++m_tableRuns;
186
1/1
✓ Branch 1 taken 10464 times.
10465 table.Run(changes, m_versions);
187
1/2
✓ Branch 0 taken 10464 times.
✗ Branch 1 not taken.
10464 if (m_header != nullptr) {
188
1/1
✓ Branch 1 taken 10464 times.
10464 m_header->Describe(table);
189 }
190 10464 scheduled.writes = writes;
191 10464 scheduled.epoch = epoch;
192 10464 scheduled.logged = logged;
193 10464 scheduled.stamp = stamp;
194 10464 scheduled.ran = true;
195 10464 ran = true;
196 10466 }
197 1202 return ran;
198 }
199
200 1166 void Publisher::Trim(Ordinal stamp) {
201
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1161 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
1166 CHRONO_BATCH_RENDER_ZONE("Publisher/Trim");
202 1166 ColumnStore& store = m_structure.GetColumnStore();
203 1166 Ordinal seen = stamp;
204 1166 std::vector<std::pair<ColumnRef, Ordinal>> held;
205
2/2
✓ Branch 0 taken 17087 times.
✓ Branch 1 taken 1166 times.
18253 for (const Scheduled& scheduled : m_scheduled) {
206
3/3
✓ Branch 1 taken 17087 times.
✓ Branch 3 taken 16108 times.
✓ Branch 4 taken 979 times.
17087 if (scheduled.table->Structural()) {
207
2/2
✓ Branch 0 taken 521 times.
✓ Branch 1 taken 15587 times.
16629 seen = std::min(seen, scheduled.stamp);
208 }
209
3/3
✓ Branch 1 taken 17087 times.
✓ Branch 3 taken 422860 times.
✓ Branch 4 taken 17087 times.
439947 for (const ColumnRef column : scheduled.table->Inputs()) {
210
2/2
✓ Branch 0 taken 329426 times.
✓ Branch 1 taken 93434 times.
422860 if (!IsArray(column.column->type)) {
211 329426 continue;
212 }
213 93434 const auto found = std::ranges::find_if(
214
2/2
✓ Branch 0 taken 2625727 times.
✓ Branch 1 taken 38178 times.
2663905 held, [&](const auto& entry) { return entry.first.column == column.column; });
215
2/2
✓ Branch 0 taken 55256 times.
✓ Branch 1 taken 38178 times.
93434 if (found == held.end()) {
216
1/1
✓ Branch 1 taken 55256 times.
55256 held.emplace_back(column, scheduled.stamp);
217 } else {
218
2/2
✓ Branch 0 taken 1970 times.
✓ Branch 1 taken 36208 times.
40148 found->second = std::min(found->second, scheduled.stamp);
219 }
220 }
221 }
222
1/1
✓ Branch 1 taken 1166 times.
1166 store.TrimArrayWrites(stamp, held);
223
2/2
✓ Branch 0 taken 1153 times.
✓ Branch 1 taken 13 times.
1166 if (!m_scheduled.empty()) {
224 1153 m_structure.TrimLog(seen);
225 }
226 1166 uint64_t logged = m_versions.Sequence();
227
2/2
✓ Branch 0 taken 17087 times.
✓ Branch 1 taken 1166 times.
18253 for (const Scheduled& scheduled : m_scheduled) {
228
3/3
✓ Branch 1 taken 17087 times.
✓ Branch 3 taken 6599 times.
✓ Branch 4 taken 10488 times.
17087 if (!scheduled.table->TableInputs().empty()) {
229
2/2
✓ Branch 0 taken 1038 times.
✓ Branch 1 taken 5561 times.
7637 logged = std::min(logged, scheduled.logged);
230 }
231 }
232
1/1
✓ Branch 1 taken 1166 times.
1166 m_versions.Trim(logged);
233 1166 }
234
235 16861 device::Operation Publisher::Publish(Ordinal ordinal, Stream producer) {
236
2/2
✓ Branch 0 taken 4323 times.
✓ Branch 1 taken 12538 times.
16861 CheckStoreLock(m_structure.GetColumnStore().Lock(), "Publishing a scene");
237
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 16856 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
16861 CHRONO_BATCH_RENDER_ZONE("Publisher/Publish");
238
4/4
✓ Branch 0 taken 16494 times.
✓ Branch 1 taken 367 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 16492 times.
16861 if (!m_sealed.empty() && ordinal <= m_sealed.back().ordinal) {
239 2 throw Error("Publishing ordinal {}, but {} is already published", ordinal,
240
1/1
✓ Branch 2 taken 2 times.
2 m_sealed.back().ordinal);
241 }
242
1/1
✓ Branch 1 taken 16859 times.
16859 ColumnStore& store = m_structure.GetColumnStore();
243
1/1
✓ Branch 1 taken 16859 times.
16859 device::Queue& queue = store.GetDevice().GetQueue();
244
1/1
✓ Branch 1 taken 16859 times.
16859 queue.Follow(producer);
245
1/1
✓ Branch 1 taken 16859 times.
16859 const Ordinal stamp = store.Stamp();
246 16859 device::Operation done;
247
3/3
✓ Branch 1 taken 16859 times.
✓ Branch 3 taken 1167 times.
✓ Branch 4 taken 15692 times.
16859 if (Pending()) {
248
1/1
✓ Branch 1 taken 1167 times.
1167 queue.BeginBatch();
249 1167 try {
250
1/1
✓ Branch 1 taken 1167 times.
1167 store.Flush();
251
1/1
✓ Branch 1 taken 1166 times.
1167 RunTables(stamp, ordinal);
252
1/1
✓ Branch 1 taken 1166 times.
1166 Trim(stamp);
253
1/1
✓ Branch 1 taken 1166 times.
1166 Seal();
254
1/1
✓ Branch 1 taken 1166 times.
1166 store.DeviceData();
255 1 } catch (...) {
256
1/1
✓ Branch 1 taken 1 time.
1 queue.EndBatch();
257 1 store.SetStamp(stamp + 1);
258 1 throw;
259 1 }
260
1/1
✓ Branch 1 taken 1166 times.
1166 done = queue.EndBatch();
261 }
262
1/1
✓ Branch 1 taken 16858 times.
16858 m_sealed.push_back({ordinal, stamp});
263
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 16857 times.
16858 if (m_sealed.size() > 2 * kSealedHistory) {
264 1 m_sealed.erase(m_sealed.begin(), m_sealed.end() - ptrdiff_t(kSealedHistory));
265 }
266 16858 store.SetStamp(stamp + 1);
267 16858 m_writes = store.WriteSequence();
268 16858 m_epoch = m_structure.Epoch();
269 16858 return done;
270 16861 }
271
272 36 device::Operation Publisher::Refresh(std::span<Table* const> tables) {
273
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 CheckStoreLock(m_structure.GetColumnStore().Lock(), "Refreshing a scene's tables");
274
4/5
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 33 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
36 CHRONO_BATCH_RENDER_ZONE("Publisher/Refresh");
275
1/1
✓ Branch 1 taken 36 times.
36 ColumnStore& store = m_structure.GetColumnStore();
276
1/1
✓ Branch 1 taken 36 times.
36 device::Queue& queue = store.GetDevice().GetQueue();
277
1/1
✓ Branch 1 taken 36 times.
36 const Ordinal stamp = store.Stamp();
278
1/1
✓ Branch 1 taken 36 times.
36 queue.BeginBatch();
279 36 bool ran = false;
280 36 try {
281
1/1
✓ Branch 1 taken 36 times.
36 store.Flush();
282
1/1
✓ Branch 1 taken 36 times.
36 ran = RunTables(stamp, Published() + 1, tables);
283
1/1
✓ Branch 1 taken 36 times.
36 store.DeviceData();
284 ✗ } catch (...) {
285
0/1
✗ Branch 1 not taken.
✗ queue.EndBatch();
286 ✗ store.SetStamp(stamp + 1);
287 ✗ throw;
288 ✗ }
289
1/1
✓ Branch 1 taken 36 times.
36 const device::Operation done = queue.EndBatch();
290
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 3 times.
36 if (ran) {
291 33 store.SetStamp(stamp + 1);
292 }
293 36 return done;
294 36 }
295
296 10 ChangeSet Publisher::Changes(Ordinal since, std::span<const ColumnRef> columns) {
297
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 9 times.
10 if (since > Published()) {
298
1/1
✓ Branch 2 taken 1 time.
1 throw Error("Changes since {}, but only {} is published", since, Published());
299 }
300
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 const Ordinal until = m_sealed.empty() ? 0 : m_sealed.back().stamp;
301 9 return Build(SealedStamp(since), until, Published(), columns, columns);
302 }
303
304 1167 void Publisher::Seal() {
305
4/5
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1162 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
1167 CHRONO_BATCH_RENDER_ZONE("Publisher/Seal");
306
1/1
✓ Branch 1 taken 1167 times.
1167 auto pinned = std::make_shared<PinnedTables>();
307
1/2
✓ Branch 0 taken 1167 times.
✗ Branch 1 not taken.
1167 if (m_header != nullptr) {
308
1/1
✓ Branch 1 taken 1167 times.
1167 const std::span<const std::byte> header = m_header->Seal(
309
1/1
✓ Branch 1 taken 1167 times.
1167 m_structure.GetColumnStore().Data(), m_structure.GetPrims().WorldCount());
310
1/1
✓ Branch 1 taken 1167 times.
1167 pinned->header.assign(header.begin(), header.end());
311 }
312
4/4
✓ Branch 0 taken 801 times.
✓ Branch 1 taken 366 times.
✓ Branch 2 taken 493 times.
✓ Branch 3 taken 308 times.
1167 if (m_pinned && m_pinned->header == pinned->header) {
313
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 493 times.
493 pinned->buffer = m_pinned->buffer;
314
1/2
✓ Branch 0 taken 674 times.
✗ Branch 1 not taken.
674 } else if (!pinned->header.empty()) {
315
2/2
✓ Branch 1 taken 674 times.
✓ Branch 4 taken 674 times.
1348 pinned->buffer = m_structure.GetColumnStore().GetDevice().CreateBuffer(
316
2/3
✓ Branch 1 taken 674 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 674 times.
1348 {.label = "snapshot header"}, std::span<const std::byte>(pinned->header));
317 }
318
1/2
✓ Branch 0 taken 1167 times.
✗ Branch 1 not taken.
1167 if (pinned->buffer) {
319
1/1
✓ Branch 1 taken 1167 times.
1167 pinned->held.emplace_back(pinned->buffer);
320 }
321 1167 pinned->content = m_tableRuns;
322
2/2
✓ Branch 0 taken 17105 times.
✓ Branch 1 taken 1167 times.
18272 for (const Scheduled& scheduled : m_scheduled) {
323
1/1
✓ Branch 1 taken 17105 times.
17105 scheduled.table->Hold(pinned->held);
324
2/2
✓ Branch 1 taken 17105 times.
✓ Branch 4 taken 17105 times.
17105 pinned->versions.emplace_back(scheduled.table->Name(), scheduled.table->Runs());
325 }
326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1167 times.
1167 m_pinned = std::move(pinned);
327 2515 }
328
329 3868 Snapshot Publisher::Acquire(Stream consumer) {
330
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3866 times.
3868 if (m_sealed.empty()) {
331
2/2
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
4 throw Error("Nothing is published yet");
332 }
333
1/1
✓ Branch 1 taken 3866 times.
3866 ColumnStore& store = m_structure.GetColumnStore();
334 3866 Snapshot snapshot;
335 3866 snapshot.ordinal = Published();
336
1/1
✓ Branch 1 taken 3866 times.
3866 store.DeviceData();
337
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3865 times.
3866 if (!m_pinned) {
338
1/1
✓ Branch 1 taken 1 time.
1 Seal();
339 }
340
1/2
✓ Branch 0 taken 3866 times.
✗ Branch 1 not taken.
3866 snapshot.tables = m_pinned->buffer ? m_pinned->buffer->Address() : 0;
341 3866 snapshot.pinned = m_pinned;
342
1/1
✓ Branch 1 taken 3866 times.
3866 snapshot.ready = store.GetDevice().GetQueue().Mark();
343
1/1
✓ Branch 1 taken 3866 times.
3866 snapshot.ready.Wait(consumer);
344 3866 ++m_outstanding;
345 3866 return snapshot;
346 ✗ }
347
348 3867 void Publisher::Release(const Snapshot& snapshot, Stream consumer) {
349
3/4
✓ Branch 0 taken 3866 times.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 3866 times.
3867 if (m_outstanding == 0 || snapshot.ordinal == 0) {
350
2/2
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
2 throw Error("Releasing a snapshot that wasn't acquired");
351 }
352 3866 m_structure.GetColumnStore().GetDevice().GetQueue().Follow(consumer);
353 3866 --m_outstanding;
354 3866 }
355
356 4 uint64_t Snapshot::Version() const {
357
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 return pinned ? PinnedTables::From(*this).content : 0;
358 }
359
360 343 uint64_t Snapshot::Version(std::string_view table) const {
361
1/2
✓ Branch 0 taken 343 times.
✗ Branch 1 not taken.
343 if (!pinned) {
362 return 0;
363 }
364 343 const PinnedTables& held = PinnedTables::From(*this);
365
4/4
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 2966 times.
✓ Branch 2 taken 3308 times.
✓ Branch 3 taken 1 time.
3309 for (const auto& [name, version] : held.versions) {
366
2/2
✓ Branch 0 taken 342 times.
✓ Branch 1 taken 2966 times.
3308 if (name == table) {
367 342 return version;
368 }
369 }
370 1 std::string names;
371
3/3
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 1 time.
19 for (const auto& [name, version] : held.versions) {
372
4/4
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 1 time.
✓ Branch 6 taken 18 times.
54 names += (names.empty() ? "" : ", ") + std::string(name);
373 }
374
1/1
✓ Branch 2 taken 1 time.
1 throw Error("A snapshot has no table \"{}\", only {}", table, names);
375 1 }
376
377 }
378