Loading...
Searching...
No Matches
BufferDecode.hpp
1#pragma once
2#include <algorithm>
3#include <bit>
4#include <cmath>
5#include <cstddef>
6#include <cstdint>
7#include <cstring>
8#include <span>
9
16{
17enum class ElementType : int
18{
19 Float,
20 Half,
21 Int,
22 UInt,
24 UNorm8,
25 UInt8
26};
27
28struct Layout
29{
30 ElementType type{ElementType::Float};
32 int components{1};
35 int64_t stride{};
37 int64_t offset{};
38
39 bool operator==(const Layout&) const noexcept = default;
40};
41
42constexpr int componentBytes(ElementType t) noexcept
43{
44 switch(t)
45 {
46 case ElementType::Half:
47 return 2;
49 case ElementType::UInt8:
50 return 1;
51 default:
52 return 4;
53 }
54}
55
56constexpr int components(const Layout& l) noexcept
57{
58 return std::clamp(l.components, 1, 4);
59}
60
62constexpr int64_t elementBytes(const Layout& l) noexcept
63{
64 return int64_t(componentBytes(l.type)) * components(l);
65}
66
67constexpr int64_t strideOf(const Layout& l) noexcept
68{
69 return l.stride > 0 ? l.stride : elementBytes(l);
70}
71
73constexpr int64_t elementCount(const Layout& l, int64_t bytes) noexcept
74{
75 const int64_t room = bytes - std::max<int64_t>(l.offset, 0);
76 const int64_t e = elementBytes(l);
77 if(room < e)
78 return 0;
79 return (room - e) / strideOf(l) + 1;
80}
81
83inline constexpr int64_t max_readback_bytes = int64_t(16) << 20;
84
86inline constexpr int64_t max_view_elements = int64_t(1) << 20;
87
90{
92 int64_t first{};
94 int64_t step{1};
96 int64_t count{};
98 int64_t window{};
100 bool capped{};
101
102 bool operator==(const Sampling&) const noexcept = default;
103};
104
111 int64_t available, int64_t first, int64_t max_elements, int64_t element_bytes,
112 int64_t cap_bytes, bool overview) noexcept
113{
114 Sampling s;
115 s.first = std::clamp<int64_t>(first, 0, std::max<int64_t>(available, 0));
116 s.window = std::max<int64_t>(available, 0) - s.first;
117 if(s.window <= 0)
118 return s;
119 const int64_t fit = std::max<int64_t>(1, cap_bytes / std::max<int64_t>(element_bytes, 1));
120 const int64_t asked = std::max<int64_t>(1, max_elements);
121 const int64_t limit = std::min(asked, fit);
122 s.capped = fit < asked && s.window > fit;
123 if(overview && s.window > limit)
124 {
125 s.step = (s.window + limit - 1) / limit;
126 s.count = (s.window + s.step - 1) / s.step;
127 }
128 else
129 s.count = std::min(s.window, limit);
130 return s;
131}
132
138constexpr int64_t contiguousFit(
139 int64_t stride, int64_t element_bytes, int64_t misalign, int64_t cap_bytes) noexcept
140{
141 const int64_t room = cap_bytes - element_bytes - misalign - 3;
142 if(room < 0)
143 return 0;
144 return room / std::max<int64_t>(stride, 1) + 1;
145}
146
148constexpr bool integral(ElementType t) noexcept
149{
150 return t == ElementType::Int || t == ElementType::UInt || t == ElementType::UInt8;
151}
152
154inline float halfToFloat(uint16_t h) noexcept
155{
156 const uint32_t sign = uint32_t(h & 0x8000u) << 16;
157 const uint32_t exponent = (h >> 10) & 0x1fu;
158 const uint32_t mantissa = h & 0x3ffu;
159 if(exponent == 0)
160 {
161 const float f = std::ldexp(float(mantissa), -24);
162 return sign ? -f : f;
163 }
164 if(exponent == 31)
165 return std::bit_cast<float>(sign | 0x7f800000u | (mantissa << 13));
166 return std::bit_cast<float>(sign | ((exponent + 112u) << 23) | (mantissa << 13));
167}
168
170inline float readComponent(ElementType t, const unsigned char* p) noexcept
171{
172 switch(t)
173 {
174 case ElementType::Float: {
175 float v;
176 std::memcpy(&v, p, 4);
177 return v;
178 }
179 case ElementType::Half: {
180 uint16_t v;
181 std::memcpy(&v, p, 2);
182 return halfToFloat(v);
183 }
184 case ElementType::Int: {
185 int32_t v;
186 std::memcpy(&v, p, 4);
187 return float(v);
188 }
189 case ElementType::UInt: {
190 uint32_t v;
191 std::memcpy(&v, p, 4);
192 return float(v);
193 }
195 return *p / 255.f;
196 case ElementType::UInt8:
197 return float(*p);
198 }
199 return 0.f;
200}
201
207inline int64_t
208decode(const Layout& l, std::span<const unsigned char> bytes, std::span<float> out) noexcept
209{
210 const int n = components(l);
211 const int cb = componentBytes(l.type);
212 const int64_t stride = strideOf(l);
213 const int64_t count = std::min(
214 elementCount(l, int64_t(bytes.size())), int64_t(out.size()) / n);
215 const unsigned char* src = bytes.data() + std::max<int64_t>(l.offset, 0);
216 float* dst = out.data();
217 for(int64_t i = 0; i < count; i++, src += stride)
218 for(int c = 0; c < n; c++)
219 *dst++ = readComponent(l.type, src + c * cb);
220 return count;
221}
222}
Definition BufferDecode.hpp:16
constexpr Sampling sampleElements(int64_t available, int64_t first, int64_t max_elements, int64_t element_bytes, int64_t cap_bytes, bool overview) noexcept
Definition BufferDecode.hpp:110
int64_t decode(const Layout &l, std::span< const unsigned char > bytes, std::span< float > out) noexcept
Definition BufferDecode.hpp:208
constexpr int64_t elementBytes(const Layout &l) noexcept
Bytes one element covers.
Definition BufferDecode.hpp:62
constexpr int64_t max_view_elements
Elements a view reads at most.
Definition BufferDecode.hpp:86
ElementType
Definition BufferDecode.hpp:18
@ UNorm8
0 to 255 read as 0 to 1
float halfToFloat(uint16_t h) noexcept
IEEE 754 binary16 to binary32, subnormals, infinities and NaN included.
Definition BufferDecode.hpp:154
constexpr int64_t max_readback_bytes
Bytes one readback holds at most, whatever the layout and the controls.
Definition BufferDecode.hpp:83
constexpr bool integral(ElementType t) noexcept
Whether the values are integers, to print them as such.
Definition BufferDecode.hpp:148
constexpr int64_t elementCount(const Layout &l, int64_t bytes) noexcept
Whole elements in bytes bytes, the first at the layout's offset.
Definition BufferDecode.hpp:73
float readComponent(ElementType t, const unsigned char *p) noexcept
One component at p, which needs no alignment.
Definition BufferDecode.hpp:170
constexpr int64_t contiguousFit(int64_t stride, int64_t element_bytes, int64_t misalign, int64_t cap_bytes) noexcept
Definition BufferDecode.hpp:138
Definition BufferDecode.hpp:29
int64_t stride
Definition BufferDecode.hpp:35
int64_t offset
Bytes before the first element.
Definition BufferDecode.hpp:37
int components
1 to 4
Definition BufferDecode.hpp:32
Which elements of a buffer a view reads.
Definition BufferDecode.hpp:90
int64_t window
Elements from the first to the end of the buffer.
Definition BufferDecode.hpp:98
int64_t step
Elements from one read to the next: 1 reads them all.
Definition BufferDecode.hpp:94
int64_t count
Elements read.
Definition BufferDecode.hpp:96
bool capped
Whether the bytes a readback holds kept count below what was asked.
Definition BufferDecode.hpp:100
int64_t first
Index of the first element read.
Definition BufferDecode.hpp:92