chrono_batch_render/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
47 / 87
54.0%
Branches:
33 / 88
37.5%
Functions:
6 / 8
75.0%

stage/views/layout.cpp
Line Branch Exec Source
1 // SPDX-License-Identifier: BSD-3-Clause
2 #include "chrono_batch_render/stage/views/layout.h"
3
4 #include <optional>
5 #include <string>
6
7 #include "chrono_batch_render/device/queue.h"
8 #include "chrono_batch_render/util/error.h"
9
10 namespace chrono::batch_render {
11
12 namespace {
13
14 22 bool Contiguous(const DLTensor& tensor) {
15
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 18 times.
22 if (tensor.strides == nullptr) {
16 return true;
17 }
18
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (tensor.ndim == 1) {
19 4 return tensor.strides[0] == 1;
20 }
21
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ return tensor.strides[1] == 1 && tensor.strides[0] == tensor.shape[1];
22 }
23
24 ✗ bool Same(DLDevice a, DLDevice b) {
25
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ return a.device_type == b.device_type && a.device_id == b.device_id;
26 }
27
28 }
29
30 41183 ColumnLayout Layout(ColumnType type) {
31
7/13
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 41109 times.
✓ Branch 7 taken 23 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 16 times.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
41183 switch (type) {
32 ✗ case ColumnType::Bool:
33 ✗ case ColumnType::Uint:
34 ✗ case ColumnType::Enum:
35 ✗ case ColumnType::Token:
36 ✗ case ColumnType::Asset:
37 ✗ case ColumnType::PrimArray:
38 ✗ case ColumnType::TokenArray:
39 ✗ return {{kDLUInt, 32, 1}, 1, device::DType::UInt32};
40 ✗ case ColumnType::Uint64:
41 ✗ return {{kDLUInt, 64, 1}, 1, device::DType::UInt64};
42 2 case ColumnType::Uint2:
43 2 return {{kDLUInt, 32, 1}, 2, device::DType::UInt32};
44 2 case ColumnType::Float2:
45 2 case ColumnType::Float2Array:
46 2 return {{kDLFloat, 32, 1}, 2, device::DType::Float32};
47 28 case ColumnType::Int:
48 28 case ColumnType::IntArray:
49 28 return {{kDLInt, 32, 1}, 1, device::DType::Int32};
50 ✗ case ColumnType::Int64Array:
51 ✗ return {{kDLInt, 64, 1}, 1, device::DType::Int64};
52 41109 case ColumnType::Float:
53 41109 case ColumnType::FloatArray:
54 41109 return {{kDLFloat, 32, 1}, 1, device::DType::Float32};
55 23 case ColumnType::Float3:
56 23 case ColumnType::Float3Array:
57 23 return {{kDLFloat, 32, 1}, 3, device::DType::Float32};
58 ✗ case ColumnType::Float4:
59 ✗ case ColumnType::Float4Array:
60 ✗ return {{kDLFloat, 32, 1}, 4, device::DType::Float32};
61 16 case ColumnType::Double3:
62 16 return {{kDLFloat, 64, 1}, 3, device::DType::Float64};
63 3 case ColumnType::Quatd:
64 3 return {{kDLFloat, 64, 1}, 4, device::DType::Float64};
65 ✗ case ColumnType::WorldTransform:
66 ✗ return {{kDLFloat, 32, 1}, 15, device::DType::Float32};
67 }
68
0/1
✗ Branch 2 not taken.
✗ throw Error("No layout for column type {}", int(type));
69 }
70
71 14 void WaitOnHost(device::Device& device, Stream producer) {
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!producer.IsCompute()) {
73 return;
74 }
75 ✗ device::Queue& queue = device.GetQueue();
76 ✗ queue.Follow(producer);
77 ✗ queue.Mark().Wait();
78 }
79
80 ✗ void CheckReadable(device::Device& device, DLDevice tensor) {
81
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ if (device.ReadsDirectly(tensor)) {
82 ✗ return;
83 }
84 ✗ const std::optional<DLDevice> shared = device.SharedDevice();
85
0/4
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ if (!shared || !Same(*shared, tensor)) {
86 ✗ throw UnsupportedError("{} can't read a tensor on device type {} (device {})",
87
0/1
✗ Branch 2 not taken.
✗ device.Adapter().alias, int(tensor.device_type), tensor.device_id);
88 }
89 }
90
91 21 uint32_t TensorRows(const DLTensor& tensor, const ColumnLayout& layout, std::string_view field) {
92
4/6
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
21 if (tensor.ndim < 1 || tensor.ndim > 2 || (tensor.ndim == 2 && tensor.dtype.lanes != 1)) {
93 ✗ throw Error("{} is written from [n] or [n, lanes] tensors, not {} dimensions", field,
94
0/1
✗ Branch 2 not taken.
✗ tensor.ndim);
95 }
96
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 5 times.
21 const uint32_t lanes = tensor.ndim == 1 ? tensor.dtype.lanes : uint32_t(tensor.shape[1]);
97
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (tensor.dtype.code != layout.dtype.code || tensor.dtype.bits != layout.dtype.bits ||
98
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 20 times.
21 lanes != layout.lanes) {
99 1 throw Error("{} is {} lanes of {}-bit values; the tensor's are {} lanes of {}-bit", field,
100
1/1
✓ Branch 2 taken 1 time.
1 layout.lanes, layout.dtype.bits, lanes, tensor.dtype.bits);
101 }
102
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!Contiguous(tensor)) {
103
0/1
✗ Branch 2 not taken.
✗ throw UnsupportedError("{} is written from contiguous tensors only", field);
104 }
105 20 return uint32_t(tensor.shape[0]);
106 }
107
108 2 uint32_t TensorItems(const DLTensor& tensor, const ColumnLayout& layout, uint32_t prims,
109 std::string_view field) {
110
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 const int32_t dimensions = layout.lanes > 1 ? 3 : 2;
111
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 const int32_t first = prims == 1 && tensor.ndim == dimensions - 1 ? 0 : 1;
112
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 if (tensor.ndim != dimensions - 1 + first || tensor.dtype.lanes != 1 ||
113
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 (first == 1 && tensor.shape[0] != prims) ||
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 (layout.lanes > 1 && tensor.shape[first + 1] != layout.lanes)) {
115 ✗ throw Error("{} of {} prims is held in a [{}, items{}] tensor", field, prims, prims,
116
0/9
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ layout.lanes > 1 ? ", " + std::to_string(layout.lanes) : "");
117 }
118
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tensor.dtype.code != layout.dtype.code || tensor.dtype.bits != layout.dtype.bits) {
119 ✗ throw Error("{} holds {}-bit values; the tensor's are {}-bit", field, layout.dtype.bits,
120
0/1
✗ Branch 2 not taken.
✗ tensor.dtype.bits);
121 }
122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!Contiguous(tensor)) {
123
0/1
✗ Branch 2 not taken.
✗ throw UnsupportedError("{} is held in contiguous tensors only", field);
124 }
125
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (tensor.shape[first] <= 0) {
126
0/1
✗ Branch 2 not taken.
✗ throw Error("{} is held in a tensor of at least one item per prim", field);
127 }
128 2 return uint32_t(tensor.shape[first]);
129 }
130
131 15 const std::byte* TensorBytes(const DLTensor& tensor) {
132 15 return static_cast<const std::byte*>(tensor.data) + tensor.byte_offset;
133 }
134
135 }
136