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 | 22 | if (tensor.strides == nullptr) { | |
| 16 | return true; | ||
| 17 | } | ||
| 18 | 4 | if (tensor.ndim == 1) { | |
| 19 | 4 | return tensor.strides[0] == 1; | |
| 20 | } | ||
| 21 | ✗ | return tensor.strides[1] == 1 && tensor.strides[0] == tensor.shape[1]; | |
| 22 | } | ||
| 23 | |||
| 24 | ✗ | bool Same(DLDevice a, DLDevice b) { | |
| 25 | ✗ | return a.device_type == b.device_type && a.device_id == b.device_id; | |
| 26 | } | ||
| 27 | |||
| 28 | } | ||
| 29 | |||
| 30 | 41183 | ColumnLayout Layout(ColumnType type) { | |
| 31 | 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 | ✗ | throw Error("No layout for column type {}", int(type)); | |
| 69 | } | ||
| 70 | |||
| 71 | 14 | void WaitOnHost(device::Device& device, Stream producer) { | |
| 72 | 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 | ✗ | if (device.ReadsDirectly(tensor)) { | |
| 82 | ✗ | return; | |
| 83 | } | ||
| 84 | ✗ | const std::optional<DLDevice> shared = device.SharedDevice(); | |
| 85 | ✗ | if (!shared || !Same(*shared, tensor)) { | |
| 86 | ✗ | throw UnsupportedError("{} can't read a tensor on device type {} (device {})", | |
| 87 | ✗ | 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 | 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 | ✗ | tensor.ndim); | |
| 95 | } | ||
| 96 | 21 | const uint32_t lanes = tensor.ndim == 1 ? tensor.dtype.lanes : uint32_t(tensor.shape[1]); | |
| 97 | 21 | if (tensor.dtype.code != layout.dtype.code || tensor.dtype.bits != layout.dtype.bits || | |
| 98 | 21 | lanes != layout.lanes) { | |
| 99 | 1 | throw Error("{} is {} lanes of {}-bit values; the tensor's are {} lanes of {}-bit", field, | |
| 100 | 1 | layout.lanes, layout.dtype.bits, lanes, tensor.dtype.bits); | |
| 101 | } | ||
| 102 | 20 | if (!Contiguous(tensor)) { | |
| 103 | ✗ | 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 | 2 | const int32_t dimensions = layout.lanes > 1 ? 3 : 2; | |
| 111 | 2 | const int32_t first = prims == 1 && tensor.ndim == dimensions - 1 ? 0 : 1; | |
| 112 | 2 | if (tensor.ndim != dimensions - 1 + first || tensor.dtype.lanes != 1 || | |
| 113 | 2 | (first == 1 && tensor.shape[0] != prims) || | |
| 114 | 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 | ✗ | layout.lanes > 1 ? ", " + std::to_string(layout.lanes) : ""); | |
| 117 | } | ||
| 118 | 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 | ✗ | tensor.dtype.bits); | |
| 121 | } | ||
| 122 | 2 | if (!Contiguous(tensor)) { | |
| 123 | ✗ | throw UnsupportedError("{} is held in contiguous tensors only", field); | |
| 124 | } | ||
| 125 | 2 | if (tensor.shape[first] <= 0) { | |
| 126 | ✗ | 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 |