EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_PODVector.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Robert Marskar <robert.marskar@sintef.no>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
27#ifndef EBGEOMETRY_PODVECTOR_HPP
28#define EBGEOMETRY_PODVECTOR_HPP
29
30// Std includes
31#include <cstddef>
32#include <cstdint>
33#include <cstring>
34#include <type_traits>
35
36// Our includes
37#include "EBGeometry_GPU.hpp"
38#include "EBGeometry_Macros.hpp"
39#include "EBGeometry_Pool.hpp"
40
41namespace EBGeometry {
42
50template <class T>
51struct PODSpan
52{
54 T* m_ptr = nullptr;
55
57 uint32_t m_size = 0;
58
64 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
65 T&
66 operator[](uint32_t a_i) const noexcept
67 {
69
70 return m_ptr[a_i];
71 }
72
77 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
78 T*
79 begin() const noexcept
80 {
81 return m_ptr;
82 }
83
88 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
89 T*
90 end() const noexcept
91 {
92 return m_ptr + m_size;
93 }
94
99 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
100 uint32_t
101 size() const noexcept
102 {
103 return m_size;
104 }
105};
106
107static_assert(std::is_trivially_copyable_v<PODSpan<float>>, "PODSpan<float> must be trivially copyable");
108static_assert(std::is_trivially_copyable_v<PODSpan<double>>, "PODSpan<double> must be trivially copyable");
109
117template <class T>
119{
120 static_assert(std::is_trivially_copyable_v<T>, "PODVector<T>: T must be trivially copyable (device-visible storage)");
121 static_assert(alignof(T) <= PoolBaseAlign,
122 "PODVector<T>: T's alignment exceeds the Pool's base alignment, so no reservation can align it");
123
125 uint64_t m_offset = 0;
126
128 uint32_t m_size = 0;
129
131 uint32_t m_capacity = 0;
132
141 void
142 reserveFrom(Pool& a_pool, uint32_t a_capacity)
143 {
144 m_offset = a_pool.reserve(a_capacity, sizeof(T), alignof(T));
145 m_size = 0;
146 m_capacity = a_capacity;
147 }
148
154 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
155 T*
156 data(void* a_base) const noexcept
157 {
158 return reinterpret_cast<T*>(static_cast<unsigned char*>(a_base) + m_offset);
159 }
160
166 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
167 const T*
168 data(const void* a_base) const noexcept
169 {
170 return reinterpret_cast<const T*>(static_cast<const unsigned char*>(a_base) + m_offset);
171 }
172
179 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
180 T&
181 at(void* a_base, uint32_t a_i) const noexcept
182 {
184
185 return this->data(a_base)[a_i];
186 }
187
194 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
195 const T&
196 at(const void* a_base, uint32_t a_i) const noexcept
197 {
199
200 return this->data(a_base)[a_i];
201 }
202
207 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
208 uint32_t
209 size() const noexcept
210 {
211 return m_size;
212 }
213
223 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
224 uint64_t
225 endByte() const noexcept
226 {
227 return m_offset + static_cast<uint64_t>(m_capacity) * sizeof(T);
228 }
229
234 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
235 bool
236 empty() const noexcept
237 {
238 return m_size == 0;
239 }
240
249 void
250 push_back(void* a_base, const T& a_value)
251 {
252 EBGEOMETRY_EXPECT(m_size < m_capacity); // the no-realloc invariant
253
254 this->data(a_base)[m_size++] = a_value;
255 }
256
267 void
268 assign(void* a_base, const T* a_src, uint32_t a_count)
269 {
271 "PODVector::assign: the element count must not exceed the reserved capacity (%u > %u)",
272 unsigned(a_count),
273 unsigned(m_capacity));
274
275 // Guard the zero-element case: an empty build reserves nothing, so both this->data(a_base) and
276 // a_src are null, and memcpy's parameters are declared nonnull -- UBSan's nonnull check flags
277 // memcpy(nullptr, nullptr, 0) even though it copies nothing.
278 if (a_count > 0) {
279 std::memcpy(this->data(a_base), a_src, static_cast<size_t>(a_count) * sizeof(T));
280 }
281
282 m_size = a_count;
283 }
284
291 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
293 bind(void* a_base) const noexcept
294 {
295 return PODSpan<T>{this->data(a_base), m_size};
296 }
297
304 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
306 bind(const void* a_base) const noexcept
307 {
308 return PODSpan<const T>{this->data(a_base), m_size};
309 }
310};
311
312static_assert(sizeof(PODVector<float>) == 16, "PODVector layout must be 8 (offset) + 4 (size) + 4 (capacity)");
313static_assert(sizeof(PODVector<double>) == 16, "PODVector layout must be 8 (offset) + 4 (size) + 4 (capacity)");
314static_assert(std::is_trivially_copyable_v<PODVector<float>>, "PODVector<float> must be trivially copyable");
315static_assert(std::is_trivially_copyable_v<PODVector<double>>, "PODVector<double> must be trivially copyable");
316
317} // namespace EBGeometry
318
319#endif // EBGEOMETRY_PODVECTOR_HPP
GPU portability layer: host/device decoration macros and backend detection.
#define EBGEOMETRY_HOST_DEVICE
Mark a function as callable from both host and device code (no-op on host compilers).
Definition EBGeometry_GPU.hpp:80
#define EBGEOMETRY_HOST
Mark a function as callable from host code only (no-op on host compilers).
Definition EBGeometry_GPU.hpp:83
Utility macros for EBGeometry.
#define EBGEOMETRY_REQUIRE(cond,...)
Always-on check of user input and one-time host setup.
Definition EBGeometry_Macros.hpp:84
#define EBGEOMETRY_EXPECT(cond)
Runtime precondition assertion for EBGeometry.
Definition EBGeometry_Macros.hpp:155
Growable bump arena for the GPU memory foundation.
Growable bump arena over a MemoryResource.
Definition EBGeometry_Pool.hpp:183
uint64_t reserve(size_t a_count, size_t a_elemSize, size_t a_alignment)
Bump-reserve a_count * a_elemSize bytes aligned to a_alignment.
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
constexpr size_t PoolBaseAlign
Block-base alignment for every Pool, in bytes.
Definition EBGeometry_MemoryResource.hpp:52
Raw pointer + size view into a Pool block, for hot inner loops.
Definition EBGeometry_PODVector.hpp:52
T * begin() const noexcept
Iterator to the first element.
Definition EBGeometry_PODVector.hpp:79
T * m_ptr
Raw pointer to element 0 inside the pool's block, as resolved when the span was bound.
Definition EBGeometry_PODVector.hpp:54
uint32_t size() const noexcept
Number of elements.
Definition EBGeometry_PODVector.hpp:101
uint32_t m_size
Number of elements.
Definition EBGeometry_PODVector.hpp:57
T * end() const noexcept
Iterator past the last element.
Definition EBGeometry_PODVector.hpp:90
T & operator[](uint32_t a_i) const noexcept
Element access.
Definition EBGeometry_PODVector.hpp:66
Placement-independent descriptor of a POD array inside a Pool.
Definition EBGeometry_PODVector.hpp:119
void assign(void *a_base, const T *a_src, uint32_t a_count)
Bulk-fill the array from a contiguous host source.
Definition EBGeometry_PODVector.hpp:268
void reserveFrom(Pool &a_pool, uint32_t a_capacity)
Reserve a_capacity slots from a_pool, aligned to alignof(T).
Definition EBGeometry_PODVector.hpp:142
uint64_t endByte() const noexcept
One past the last byte this array occupies, measured from the pool base.
Definition EBGeometry_PODVector.hpp:225
T & at(void *a_base, uint32_t a_i) const noexcept
Mutable element access against a_base.
Definition EBGeometry_PODVector.hpp:181
uint64_t m_offset
Byte offset of element 0 from Pool::base.
Definition EBGeometry_PODVector.hpp:125
PODSpan< const T > bind(const void *a_base) const noexcept
Bind a const raw-pointer view for a hot loop.
Definition EBGeometry_PODVector.hpp:306
PODSpan< T > bind(void *a_base) const noexcept
Bind a mutable raw-pointer view for a hot loop.
Definition EBGeometry_PODVector.hpp:293
uint32_t m_capacity
Reserved element slots (fixed after reserveFrom; never reallocates).
Definition EBGeometry_PODVector.hpp:131
T * data(void *a_base) const noexcept
Mutable pointer to element 0 against a_base.
Definition EBGeometry_PODVector.hpp:156
const T & at(const void *a_base, uint32_t a_i) const noexcept
Const element access against a_base.
Definition EBGeometry_PODVector.hpp:196
bool empty() const noexcept
Whether the array is empty.
Definition EBGeometry_PODVector.hpp:236
uint32_t size() const noexcept
Number of constructed elements.
Definition EBGeometry_PODVector.hpp:209
void push_back(void *a_base, const T &a_value)
Append one element into the pre-reserved capacity.
Definition EBGeometry_PODVector.hpp:250
uint32_t m_size
Number of constructed elements.
Definition EBGeometry_PODVector.hpp:128
const T * data(const void *a_base) const noexcept
Const pointer to element 0 against a_base.
Definition EBGeometry_PODVector.hpp:168