chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
212 / 233
91.0%
Branches:
243 / 338
71.9%
Functions:
18 / 18
100.0%

stage/views/poses.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/stage/views/poses.h"
3
4 #include <utility>
5
6 #include "chrono_batch_render/device/device.h"
7 #include "chrono_batch_render/device/queue.h"
8 #include "chrono_batch_render/scene/schema/columns.h"
9 #include "chrono_batch_render/stage/columns/column_store.h"
10 #include "chrono_batch_render/stage/columns/kernels/cells.h"
11 #include "chrono_batch_render/stage/views/layout.h"
12 #include "chrono_batch_render/stage/views/staged.h"
13 #include "chrono_batch_render/stage/views/view_state.h"
14 #include "chrono_batch_render/stage/views/world_poses.h"
15 #include "chrono_batch_render/util/profiler.h"
16
17 namespace chrono::batch_render {
18
19 namespace {
20
21 83233 uint32_t SourceRows(const DLTensor& tensor, int64_t width, const char* what) {
22
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 83233 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
83233 const bool lanes = tensor.ndim == 1 && tensor.dtype.lanes == width;
23 166466 const bool wide =
24
3/6
✓ Branch 0 taken 83233 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83233 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 83233 times.
83233 tensor.ndim >= 2 && tensor.shape[tensor.ndim - 1] == width && tensor.dtype.lanes == 1;
25
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83233 times.
83233 if (!wide && !lanes) {
26
0/1
✗ Branch 2 not taken.
✗ throw Error("{} are written from [..., {}] tensors", what, width);
27 }
28
2/4
✓ Branch 0 taken 83233 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 83233 times.
83233 if (tensor.dtype.code != kDLFloat || (tensor.dtype.bits != 32 && tensor.dtype.bits != 64)) {
29 ✗ throw Error("{} are float32 or float64, not {}-bit code {}", what, tensor.dtype.bits,
30
0/1
✗ Branch 2 not taken.
✗ tensor.dtype.code);
31 }
32
2/2
✓ Branch 0 taken 1138 times.
✓ Branch 1 taken 82095 times.
83233 if (tensor.strides != nullptr) {
33 1138 int64_t expected = 1;
34
2/2
✓ Branch 0 taken 2276 times.
✓ Branch 1 taken 1138 times.
3414 for (int dim = tensor.ndim - 1; dim >= 0; --dim) {
35
2/4
✓ Branch 0 taken 2276 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2276 times.
2276 if (tensor.shape[dim] != 1 && tensor.strides[dim] != expected) {
36
0/1
✗ Branch 2 not taken.
✗ throw UnsupportedError("{} are written from contiguous tensors only", what);
37 }
38 2276 expected *= tensor.shape[dim];
39 }
40 }
41 uint64_t rows = 1;
42
3/4
✓ Branch 0 taken 166466 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83233 times.
✓ Branch 3 taken 83233 times.
332932 for (int dim = 0; dim < tensor.ndim - (lanes ? 0 : 1); ++dim) {
43 83233 rows *= uint64_t(tensor.shape[dim]);
44 }
45 83233 return uint32_t(rows);
46 }
47
48 137025 void CheckOwn(device::Device& device, const device::Tensor& tensor, const char* what) {
49
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 137025 times.
137025 if (&tensor.GetDevice() != &device) {
50 ✗ throw Error("{} are on {}, not the scene's {}; Device::Copy or Device::Import moves them",
51
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ what, tensor.GetDevice().Adapter().alias, device.Adapter().alias);
52 }
53 137025 const Span<const int64_t> shape = tensor.Shape();
54 137025 const Span<const int64_t> strides = tensor.Strides();
55 137025 int64_t packed = 1;
56
2/2
✓ Branch 0 taken 274047 times.
✓ Branch 1 taken 137025 times.
411072 for (size_t axis = shape.size(); axis-- > 0;) {
57
4/6
✓ Branch 0 taken 274047 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 138553 times.
✓ Branch 3 taken 135494 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 138553 times.
274047 if (!strides.empty() && shape[axis] > 1 && strides[axis] != packed) {
58
0/1
✗ Branch 2 not taken.
✗ throw UnsupportedError("{} are written from contiguous tensors only", what);
59 }
60 274047 packed *= shape[axis];
61 }
62 137025 }
63
64 137023 uint32_t TensorRows(device::Device& device, const device::Tensor& tensor, int64_t width,
65 const char* what) {
66 137023 const Span<const int64_t> shape = tensor.Shape();
67
3/4
✓ Branch 0 taken 137023 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 137022 times.
137023 if (shape.size() < 2 || shape.back() != width) {
68
1/1
✓ Branch 2 taken 1 time.
1 throw Error("{} are written from [..., {}] tensors", what, width);
69 }
70
3/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 137008 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
137022 if (tensor.Type() != device::DType::Float32 && tensor.Type() != device::DType::Float64) {
71
0/1
✗ Branch 2 not taken.
✗ throw Error("{} are float32 or float64", what);
72 }
73 137022 CheckOwn(device, tensor, what);
74 uint64_t rows = 1;
75
2/2
✓ Branch 0 taken 137022 times.
✓ Branch 1 taken 137022 times.
274044 for (size_t dim = 0; dim + 1 < shape.size(); ++dim) {
76 137022 rows *= uint64_t(shape[dim]);
77 }
78 137022 return uint32_t(rows);
79 }
80
81 }
82
83 35466 Poses::Poses(std::shared_ptr<ViewState> view)
84
3/6
✓ Branch 0 taken 35466 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 35466 times.
✓ Branch 6 taken 35466 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
141864 : m_translate(view, kXformableTranslate), m_orient(std::move(view), kXformableOrient) {}
85
86 2217 device::Operation Poses::Write(const DLTensor& source, Stream producer, QuaternionOrder order,
87 const DLTensor* rows, const DLTensor* mask) {
88 2217 SourceRows(source, kPoseWords, "Poses");
89 2217 device::Device& device = m_translate.GetColumnStore().GetDevice();
90
2/2
✓ Branch 1 taken 2208 times.
✓ Branch 2 taken 9 times.
2217 const StoreLock* store = m_translate.GetColumnStore().Lock();
91 2217 std::optional<StoreLock::Guard> lock =
92
2/2
✓ Branch 0 taken 2208 times.
✓ Branch 1 taken 9 times.
2217 store ? store->TryLock() : std::optional<StoreLock::Guard>(std::in_place);
93
2/2
✓ Branch 0 taken 1071 times.
✓ Branch 1 taken 1146 times.
2217 if (!lock) {
94 1071 std::optional<StagedTensor> values;
95 1071 std::optional<StagedTensor> stagedRows;
96 1071 std::optional<StagedTensor> stagedMask;
97
4/6
✓ Branch 1 taken 1071 times.
✓ Branch 4 taken 1071 times.
✓ Branch 6 taken 1071 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1071 times.
✗ Branch 9 not taken.
3213 if (store->CanDefer() && StageOptional(device, &source, producer, values) &&
98
3/5
✓ Branch 0 taken 1071 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1071 times.
✓ Branch 5 taken 1071 times.
✗ Branch 6 not taken.
3213 StageOptional(device, rows, producer, stagedRows) &&
99
1/1
✓ Branch 1 taken 1071 times.
1071 StageOptional(device, mask, producer, stagedMask)) {
100
2/2
✓ Branch 5 taken 1071 times.
✓ Branch 8 taken 1071 times.
2142 store->Defer([poses = *this, values = std::move(*values), order,
101 stagedRows = std::move(stagedRows),
102 stagedMask = std::move(stagedMask)]() mutable {
103 1071 DLTensor rowView;
104 1071 DLTensor maskView;
105 1071 const DLTensor written = values.View();
106 1071 poses.Write(written, values.Producer(), order, ViewOptional(stagedRows, rowView),
107 1071 ViewOptional(stagedMask, maskView));
108 1071 });
109 1071 return {};
110 }
111
0/1
✗ Branch 1 not taken.
✗ lock = store->Lock();
112 1071 }
113
3/3
✓ Branch 1 taken 1146 times.
✓ Branch 4 taken 1146 times.
✓ Branch 7 taken 1145 times.
1147 return Write(device.Import(source, producer, "pose staging"), producer, order,
114
8/9
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1145 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1145 times.
✓ Branch 12 taken 1 time.
✓ Branch 13 taken 1144 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 time.
2294 rows ? device.Import(*rows, producer, "pose rows") : device::Tensor(),
115
8/9
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1144 times.
✓ Branch 3 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 1144 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 1143 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 1 time.
2296 mask ? device.Import(*mask, producer, "pose mask") : device::Tensor());
116 2216 }
117
118 40508 device::Operation Poses::Write(const DLTensor& translation, const DLTensor& rotation,
119 Stream producer, QuaternionOrder order, const DLTensor* rows,
120 const DLTensor* mask) {
121
1/2
✓ Branch 2 taken 40508 times.
✗ Branch 3 not taken.
40508 if (SourceRows(translation, 3, "Translations") != SourceRows(rotation, 4, "Rotations") ||
122
1/2
✓ Branch 0 taken 40508 times.
✗ Branch 1 not taken.
40508 translation.dtype.bits != rotation.dtype.bits) {
123
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("Translations and rotations need as many rows and the same precision");
124 }
125 40508 device::Device& device = m_translate.GetColumnStore().GetDevice();
126
2/2
✓ Branch 1 taken 40507 times.
✓ Branch 2 taken 1 time.
40508 const StoreLock* store = m_translate.GetColumnStore().Lock();
127 40508 std::optional<StoreLock::Guard> lock =
128
2/2
✓ Branch 0 taken 40507 times.
✓ Branch 1 taken 1 time.
40508 store ? store->TryLock() : std::optional<StoreLock::Guard>(std::in_place);
129
2/2
✓ Branch 0 taken 6565 times.
✓ Branch 1 taken 33943 times.
40508 if (!lock) {
130 6565 std::optional<StagedTensor> translations;
131 6565 std::optional<StagedTensor> rotations;
132 6565 std::optional<StagedTensor> stagedRows;
133 6565 std::optional<StagedTensor> stagedMask;
134
4/6
✓ Branch 1 taken 6565 times.
✓ Branch 4 taken 6543 times.
✓ Branch 6 taken 6543 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 6543 times.
✗ Branch 9 not taken.
19651 if (store->CanDefer() && StageOptional(device, &translation, producer, translations) &&
135
2/3
✓ Branch 1 taken 6543 times.
✓ Branch 3 taken 6543 times.
✗ Branch 4 not taken.
13086 StageOptional(device, &rotation, producer, rotations) &&
136
4/5
✓ Branch 0 taken 6543 times.
✓ Branch 1 taken 22 times.
✓ Branch 3 taken 6543 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6543 times.
19651 StageOptional(device, rows, producer, stagedRows) &&
137
1/1
✓ Branch 1 taken 6543 times.
6543 StageOptional(device, mask, producer, stagedMask)) {
138
2/2
✓ Branch 6 taken 6543 times.
✓ Branch 9 taken 6543 times.
13086 store->Defer([poses = *this, translations = std::move(*translations),
139 6543 rotations = std::move(*rotations), order,
140 stagedRows = std::move(stagedRows),
141 stagedMask = std::move(stagedMask)]() mutable {
142 6543 DLTensor rowView;
143 6543 DLTensor maskView;
144 6543 const DLTensor moved = translations.View();
145 6543 const DLTensor turned = rotations.View();
146 6543 poses.Write(moved, turned, translations.Producer(), order,
147 6543 ViewOptional(stagedRows, rowView), ViewOptional(stagedMask, maskView));
148 6543 });
149 6543 return {};
150 }
151
1/1
✓ Branch 1 taken 22 times.
22 lock = store->Lock();
152 6565 }
153
3/3
✓ Branch 1 taken 33965 times.
✓ Branch 4 taken 33965 times.
✓ Branch 7 taken 33965 times.
33965 return Write(device.Import(translation, producer, "translation staging"),
154
2/2
✓ Branch 1 taken 33965 times.
✓ Branch 4 taken 33965 times.
67930 device.Import(rotation, producer, "rotation staging"), producer, order,
155
7/9
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 33964 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 33964 times.
✓ Branch 12 taken 1 time.
✓ Branch 13 taken 33964 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
67931 rows ? device.Import(*rows, producer, "pose rows") : device::Tensor(),
156
3/9
✗ Branch 0 not taken.
✓ Branch 1 taken 33965 times.
✗ Branch 3 not taken.
✗ Branch 6 not taken.
✓ Branch 9 taken 33965 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 33965 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
67930 mask ? device.Import(*mask, producer, "pose mask") : device::Tensor());
157 40508 }
158
159 1147 device::Operation Poses::Write(const device::Tensor& source, Stream producer, QuaternionOrder order,
160 const device::Tensor& rows, const device::Tensor& mask) {
161 1147 return Dispatch(source, nullptr, producer, order, rows, mask);
162 }
163
164 33966 device::Operation Poses::Write(const device::Tensor& translation, const device::Tensor& rotation,
165 Stream producer, QuaternionOrder order, const device::Tensor& rows,
166 const device::Tensor& mask) {
167 33966 device::Device& device = m_translate.GetColumnStore().GetDevice();
168 33966 if (TensorRows(device, translation, 3, "Translations") !=
169
1/2
✓ Branch 1 taken 33965 times.
✗ Branch 2 not taken.
33965 TensorRows(device, rotation, 4, "Rotations") ||
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33965 times.
33965 translation.Type() != rotation.Type()) {
171
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("Translations and rotations need as many rows and the same precision");
172 }
173 33965 return Dispatch(translation, &rotation, producer, order, rows, mask);
174 }
175
176 35126 void Poses::CheckSources(const device::Tensor& values, const device::Tensor* rotations,
177 const device::Tensor& rows) const {
178
2/2
✓ Branch 1 taken 1160 times.
✓ Branch 2 taken 33966 times.
35126 device::Device& device = m_translate.GetColumnStore().GetDevice();
179
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 33966 times.
35126 const uint32_t width = rotations ? 3 : kPoseWords;
180 35126 const uint32_t sourceRows = TensorRows(device, values, width, "Poses");
181
3/4
✓ Branch 0 taken 33966 times.
✓ Branch 1 taken 1160 times.
✓ Branch 3 taken 33966 times.
✗ Branch 4 not taken.
35126 if (rotations && (TensorRows(device, *rotations, 4, "Rotations") != sourceRows ||
182
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33966 times.
33966 rotations->Type() != values.Type())) {
183
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("Translations and rotations need as many rows and the same precision");
184 }
185
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35123 times.
35126 if (!rows.Empty()) {
186
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 const bool indices = rows.Shape().size() == 1 && (rows.Type() == device::DType::Int32 ||
187
0/2
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ rows.Type() == device::DType::UInt32);
188
1/2
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (!indices || uint32_t(rows.Shape()[0]) != Size()) {
189 ✗ throw Error("Pose rows are a contiguous [{}] int32 or uint32 tensor, a source row per "
190 "prim",
191
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Size());
192 }
193 3 CheckOwn(device, rows, "Pose rows");
194
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 35122 times.
35123 } else if (sourceRows != Size()) {
195
2/2
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
1 throw Error("A tensor of {} poses for {} prims", sourceRows, Size());
196 }
197 35125 }
198
199 35119 device::Operation Poses::Dispatch(const device::Tensor& values, const device::Tensor* rotations,
200 Stream producer, QuaternionOrder order,
201 const device::Tensor& rows, const device::Tensor& mask) {
202
2/2
✓ Branch 1 taken 35108 times.
✓ Branch 2 taken 11 times.
35119 const auto lock = LockStore(m_translate.GetColumnStore().Lock());
203
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 35116 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 10 taken 35119 times.
35119 CHRONO_BATCH_RENDER_ZONE("Scene/Write");
204
2/3
✓ Branch 1 taken 35119 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35119 times.
35119 if (Size() == 0) {
205 ✗ return {};
206 }
207
1/1
✓ Branch 1 taken 35119 times.
35119 ColumnStore& store = m_translate.GetColumnStore();
208
1/1
✓ Branch 1 taken 35118 times.
35119 device::Device& device = store.GetDevice();
209
1/1
✓ Branch 1 taken 35118 times.
35119 CheckSources(values, rotations, rows);
210
1/1
✓ Branch 1 taken 35118 times.
35118 const UntypedAttribute::Mask selected = m_translate.Upload(mask);
211
1/1
✓ Branch 1 taken 35118 times.
35118 const bool doubles = values.Type() == device::DType::Float64;
212
1/1
✓ Branch 1 taken 35118 times.
35118 store.Flush();
213
1/1
✓ Branch 1 taken 35118 times.
35118 device.GetQueue().Follow(producer);
214 35118 PoseParams params{};
215
1/1
✓ Branch 1 taken 35118 times.
35118 params.translateStamps = store.Stamps(kXformableTranslate);
216
1/1
✓ Branch 1 taken 35118 times.
35118 params.orientStamps = store.Stamps(kXformableOrient);
217
2/2
✓ Branch 1 taken 35118 times.
✓ Branch 4 taken 35118 times.
35118 params.translate.address = store.Schema(SchemaId::Xformable).Pages(kXformableTranslate.index);
218
2/2
✓ Branch 1 taken 35118 times.
✓ Branch 4 taken 35118 times.
35118 params.orient.address = store.Schema(SchemaId::Xformable).Pages(kXformableOrient.index);
219
1/1
✓ Branch 1 taken 35118 times.
35118 const RowSource rowSource = m_translate.m_view->Source(SchemaId::Xformable);
220 35118 params.rows.address = rowSource.rows;
221 35118 params.firstRow = rowSource.firstRow;
222
1/1
✓ Branch 1 taken 35118 times.
35118 params.values.address = values.Address();
223
3/3
✓ Branch 0 taken 33965 times.
✓ Branch 1 taken 1153 times.
✓ Branch 3 taken 33965 times.
35118 params.rotations.address = rotations ? rotations->Address() : 0;
224
3/3
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 35116 times.
✓ Branch 3 taken 2 times.
35118 params.sources.address = rows.Empty() ? 0 : rows.Address();
225 35118 params.mask.address = selected.address;
226
1/1
✓ Branch 1 taken 35118 times.
35118 params.count = Size();
227
2/2
✓ Branch 0 taken 35109 times.
✓ Branch 1 taken 9 times.
35118 params.doubles = doubles ? 1 : 0;
228 35118 params.order = uint32_t(order);
229
1/1
✓ Branch 1 taken 35118 times.
35118 store.Touch(kXformableTranslate);
230
1/1
✓ Branch 1 taken 35118 times.
35118 store.Touch(kXformableOrient);
231
1/1
✓ Branch 1 taken 35118 times.
35118 m_translate.StampWorlds();
232
1/1
✓ Branch 1 taken 35118 times.
35118 const device::Operation written = store.Dispatch("WritePoses", params, params.count);
233
2/2
✓ Branch 1 taken 35118 times.
✓ Branch 4 taken 35118 times.
35118 store.Reassert(kXformableTranslate, m_translate.Rows().rows);
234
2/4
✓ Branch 1 taken 35118 times.
✓ Branch 4 taken 35118 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
35118 store.Reassert(kXformableOrient, m_translate.Rows().rows);
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35118 times.
35118 return written;
236 35120 }
237
238 115 device::Tensor Poses::Read(device::DType type, Stream consumer, QuaternionOrder order) const {
239
2/2
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 7 times.
115 const auto lock = LockStore(m_translate.GetColumnStore().Lock());
240
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 112 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 10 taken 115 times.
115 CHRONO_BATCH_RENDER_ZONE("Scene/Read");
241
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 if (type != device::DType::Float32 && type != device::DType::Float64) {
242
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("Poses are gathered as float32 or float64");
243 }
244
1/1
✓ Branch 1 taken 115 times.
115 ColumnStore& store = m_translate.GetColumnStore();
245
1/1
✓ Branch 1 taken 115 times.
115 device::Device& device = store.GetDevice();
246 115 const bool doubles = type == device::DType::Float64;
247
1/1
✓ Branch 1 taken 115 times.
115 store.Flush();
248
1/1
✓ Branch 1 taken 115 times.
115 const Ref<device::Buffer> values = device.CreateBuffer(
249
3/4
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 115 times.
228 {.bytes = std::max<uint64_t>(uint64_t(Size()) * kPoseWords * (doubles ? 8 : 4), 4),
250 .usage = device::BufferUsage::Interop,
251
1/1
✓ Branch 1 taken 115 times.
115 .label = "gathered poses"});
252 115 PoseParams params{};
253
1/1
✓ Branch 1 taken 115 times.
115 params.translate.address = store.Schema(SchemaId::Xformable).Pages(kXformableTranslate.index);
254
2/2
✓ Branch 1 taken 115 times.
✓ Branch 4 taken 115 times.
115 params.orient.address = store.Schema(SchemaId::Xformable).Pages(kXformableOrient.index);
255
1/1
✓ Branch 1 taken 115 times.
115 const RowSource rowSource = m_translate.m_view->Source(SchemaId::Xformable);
256 115 params.rows.address = rowSource.rows;
257 115 params.firstRow = rowSource.firstRow;
258
1/1
✓ Branch 1 taken 115 times.
115 params.values.address = values->Address();
259
1/1
✓ Branch 1 taken 115 times.
115 params.count = Size();
260
2/2
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 2 times.
115 params.doubles = doubles ? 1 : 0;
261 115 params.order = uint32_t(order);
262
2/2
✓ Branch 1 taken 115 times.
✓ Branch 4 taken 115 times.
115 store.Dispatch("ReadPoses", params, params.count).Wait(consumer);
263
4/7
✓ Branch 1 taken 115 times.
✓ Branch 4 taken 115 times.
✓ Branch 7 taken 115 times.
✓ Branch 11 taken 115 times.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
460 return device::Tensor(values, 0, type, {int64_t(Size()), int64_t(kPoseWords)});
264 460 }
265
266 class Batch {
267 public:
268 238 explicit Batch(device::Queue& queue) : m_queue(&queue) {
269
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 230 times.
231 m_queue->BeginBatch();
270 238 }
271
272 Batch(const Batch&) = delete;
273 Batch& operator=(const Batch&) = delete;
274
275 238 ~Batch() {
276
2/2
✓ Branch 0 taken 231 times.
✓ Branch 1 taken 7 times.
238 if (m_queue != nullptr) {
277 231 m_queue->EndBatch();
278 }
279 238 }
280
281 7 device::Operation End() {
282 7 return std::exchange(m_queue, nullptr)->EndBatch();
283 }
284
285 private:
286 device::Queue* m_queue = nullptr;
287 };
288
289 238 static WorldPoseSource& WorldPoses(const ViewState& view) {
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 WorldPoseSource* source = view.GetStructure().GetWorldPoses();
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 238 times.
238 if (source == nullptr) {
292
0/1
✗ Branch 2 not taken.
✗ throw UnsupportedError("World poses need a scene, which composes the hierarchy");
293 }
294 238 return *source;
295 }
296
297 7 device::Operation Poses::WriteWorld(const device::Tensor& values, const device::Tensor* rotations,
298 Stream producer, QuaternionOrder order,
299 const device::Tensor& rows, const device::Tensor& mask) {
300
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const auto lock = LockStore(m_translate.GetColumnStore().Lock());
301
5/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 7 times.
7 CHRONO_BATCH_RENDER_ZONE("Scene/WriteWorld");
302
1/1
✓ Branch 1 taken 7 times.
7 CheckSources(values, rotations, rows);
303
2/3
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
7 if (Size() == 0) {
304 ✗ return {};
305 }
306
2/2
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
7 device::Queue& queue = m_translate.GetColumnStore().GetDevice().GetQueue();
307
1/1
✓ Branch 1 taken 7 times.
7 queue.Follow(producer);
308
1/1
✓ Branch 1 taken 7 times.
7 Batch batch(queue);
309
1/1
✓ Branch 1 taken 7 times.
7 const device::Tensor local = WorldPoses(*m_translate.m_view)
310
1/1
✓ Branch 1 taken 7 times.
7 .Localize(*m_translate.m_view, values, rotations, order, rows);
311
2/2
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
7 Dispatch(local, nullptr, Stream::None(), QuaternionOrder::Xyzw, {}, mask);
312
1/1
✓ Branch 1 taken 7 times.
7 return batch.End();
313 7 }
314
315 230 device::Tensor Poses::ReadWorld(device::DType type, Stream consumer, QuaternionOrder order) const {
316
1/2
✓ Branch 1 taken 230 times.
✗ Branch 2 not taken.
230 const auto lock = LockStore(m_translate.GetColumnStore().Lock());
317
5/6
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 227 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 10 taken 230 times.
230 CHRONO_BATCH_RENDER_ZONE("Scene/ReadWorld");
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 230 times.
230 if (type != device::DType::Float32 && type != device::DType::Float64) {
319
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("World poses are gathered as float32 or float64");
320 }
321
2/2
✓ Branch 1 taken 230 times.
✓ Branch 4 taken 230 times.
230 const Batch batch(m_translate.GetColumnStore().GetDevice().GetQueue());
322
2/2
✓ Branch 1 taken 230 times.
✓ Branch 4 taken 230 times.
460 return WorldPoses(*m_translate.m_view).Read(*m_translate.m_view, type, consumer, order);
323 230 }
324
325 1 device::Tensor Poses::ReadWorldScales(device::DType type, Stream consumer) const {
326
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 const auto lock = LockStore(m_translate.GetColumnStore().Lock());
327
4/6
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 time.
✓ Branch 10 taken 1 time.
1 CHRONO_BATCH_RENDER_ZONE("Scene/ReadWorldScales");
328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if (type != device::DType::Float32 && type != device::DType::Float64) {
329
0/2
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ throw Error("World scales are gathered as float32 or float64");
330 }
331
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 const Batch batch(m_translate.GetColumnStore().GetDevice().GetQueue());
332
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
2 return WorldPoses(*m_translate.m_view).ReadScales(*m_translate.m_view, type, consumer);
333 1 }
334
335 }
336