vecmem 1.18.0
Loading...
Searching...
No Matches
buffer_traits.hpp
1/* VecMem project, part of the ACTS project (R&D line)
2 *
3 * (c) 2023-2025 CERN for the benefit of the ACTS project
4 *
5 * Mozilla Public License Version 2.0
6 */
7#pragma once
8
9// Local include(s).
10#include "vecmem/edm/details/schema_traits.hpp"
11#include "vecmem/edm/details/view_traits.hpp"
12#include "vecmem/edm/schema.hpp"
13#include "vecmem/edm/view.hpp"
14#include "vecmem/memory/unique_ptr.hpp"
15#include "vecmem/utils/tuple.hpp"
16#include "vecmem/utils/types.hpp"
17
18// System include(s).
19#include <array>
20#include <numeric>
21#include <tuple>
22#include <type_traits>
23#include <vector>
24
25namespace vecmem::edm::details {
26
29
30template <typename TYPE>
32
33template <typename TYPE>
34struct buffer_alloc<type::scalar<TYPE>> {
36 template <typename SIZE_TYPE = std::size_t,
37 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
38 VECMEM_HOST static std::size_t payload_size(
39 const std::vector<SIZE_TYPE, SIZE_ALLOC>&) {
40 return 1u;
41 }
43 template <typename SIZE_TYPE = std::size_t,
44 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
45 VECMEM_HOST static std::size_t layout_size(
46 const std::vector<SIZE_TYPE, SIZE_ALLOC>&) {
47 return 0u;
48 }
50 template <typename SIZE_TYPE = std::size_t,
51 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
52 VECMEM_HOST static typename view_type<type::scalar<TYPE>>::type make_view(
53 const std::vector<SIZE_TYPE, SIZE_ALLOC>&, unsigned int*,
54 typename view_type<type::scalar<TYPE>>::layout_ptr,
55 typename view_type<type::scalar<TYPE>>::layout_ptr,
56 typename view_type<type::scalar<TYPE>>::payload_ptr ptr) {
57 return ptr;
58 }
59}; // struct buffer_alloc
60
61template <typename TYPE>
62struct buffer_alloc<type::vector<TYPE>> {
64 template <typename SIZE_TYPE = std::size_t,
65 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
66 VECMEM_HOST static std::size_t payload_size(
67 const std::vector<SIZE_TYPE, SIZE_ALLOC>& sizes) {
68 return sizes.size();
69 }
71 template <typename SIZE_TYPE = std::size_t,
72 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
73 VECMEM_HOST static std::size_t layout_size(
74 const std::vector<SIZE_TYPE, SIZE_ALLOC>&) {
75 return 0u;
76 }
78 template <typename SIZE_TYPE = std::size_t,
79 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
80 VECMEM_HOST static typename view_type<type::vector<TYPE>>::type make_view(
81 const std::vector<SIZE_TYPE, SIZE_ALLOC>& capacity, unsigned int* size,
82 typename view_type<type::vector<TYPE>>::layout_ptr,
83 typename view_type<type::vector<TYPE>>::layout_ptr,
84 typename view_type<type::vector<TYPE>>::payload_ptr ptr) {
85 return {static_cast<
86 typename view_type<type::vector<TYPE>>::type::size_type>(
87 capacity.size()),
88 size, ptr};
89 }
90}; // struct buffer_alloc
91
92template <typename TYPE>
93struct buffer_alloc<type::jagged_vector<TYPE>> {
95 template <typename SIZE_TYPE = std::size_t,
96 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
97 VECMEM_HOST static std::size_t payload_size(
98 const std::vector<SIZE_TYPE, SIZE_ALLOC>& sizes) {
99 return std::accumulate(sizes.begin(), sizes.end(),
100 static_cast<std::size_t>(0));
101 }
103 template <typename SIZE_TYPE = std::size_t,
104 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
105 VECMEM_HOST static std::size_t layout_size(
106 const std::vector<SIZE_TYPE, SIZE_ALLOC>& sizes) {
107 return sizes.size();
108 }
110 template <typename SIZE_TYPE = std::size_t,
111 typename SIZE_ALLOC = std::allocator<SIZE_TYPE>>
112 VECMEM_HOST static typename view_type<type::jagged_vector<TYPE>>::type
114 const std::vector<SIZE_TYPE, SIZE_ALLOC>& capacities,
115 unsigned int* sizes,
116 typename view_type<type::jagged_vector<TYPE>>::layout_ptr layout,
117 typename view_type<type::jagged_vector<TYPE>>::layout_ptr host_layout,
118 typename view_type<type::jagged_vector<TYPE>>::payload_ptr ptr) {
119
120 // Set up the "layout objects" for use by the view.
122 (host_layout != nullptr ? host_layout : layout);
123 std::ptrdiff_t ptrdiff = 0;
124 for (std::size_t i = 0; i < capacities.size(); ++i) {
125 new (used_layout + i)
126 typename view_type<type::jagged_vector<TYPE>>::layout_type(
127 static_cast<typename view_type<
128 type::jagged_vector<TYPE>>::layout_type::size_type>(
129 capacities[i]),
130 (sizes != nullptr ? &(sizes[i]) : nullptr), ptr + ptrdiff);
131 ptrdiff += capacities[i];
132 }
133
134 // Create the jagged vector view.
135 return {static_cast<
136 typename view_type<type::vector<TYPE>>::type::size_type>(
137 capacities.size()),
138 layout, host_layout};
139 }
140}; // struct buffer_alloc
141
143
145template <typename SIZE_TYPE, typename SIZE_ALLOC, typename... TYPES,
146 std::size_t... INDICES>
147VECMEM_HOST auto make_buffer_views(
148 const std::vector<SIZE_TYPE, SIZE_ALLOC>& sizes,
149 const std::tuple<typename view_type<TYPES>::layout_ptr...>& layouts,
150 const std::tuple<typename view_type<TYPES>::layout_ptr...>& host_layouts,
151 const std::tuple<typename view_type<TYPES>::payload_ptr...>& payloads,
152 std::index_sequence<INDICES...>) {
153
154 return vecmem::make_tuple(buffer_alloc<TYPES>::make_view(
155 sizes, nullptr, std::get<INDICES>(layouts),
156 std::get<INDICES>(host_layouts), std::get<INDICES>(payloads))...);
157}
158
160template <typename SIZE_TYPE, typename SIZE_ALLOC, typename... TYPES,
161 std::size_t... INDICES>
162VECMEM_HOST auto make_buffer_views(
163 const std::vector<SIZE_TYPE, SIZE_ALLOC>& capacities,
164 const std::tuple<typename view_type<TYPES>::size_ptr...>& sizes,
165 const std::tuple<typename view_type<TYPES>::layout_ptr...>& layouts,
166 const std::tuple<typename view_type<TYPES>::layout_ptr...>& host_layouts,
167 const std::tuple<typename view_type<TYPES>::payload_ptr...>& payloads,
168 const std::index_sequence<INDICES...>) {
169
170 // Helper variable(s).
171 constexpr auto is_jagged_vector =
172 std::make_tuple(type::details::is_jagged_vector<TYPES>::value...);
173 constexpr bool has_jagged_vector =
174 std::disjunction_v<type::details::is_jagged_vector<TYPES>...>;
175
176 // The logic here is that if there are any jagged vectors in the schema,
177 // then only the jagged vectors are resizable, the "normal vectors" are not.
178 // But the received "sizes" variable would be hard to set up like that
179 // outside of this function, so the logic has to sit here.
180 return vecmem::make_tuple(buffer_alloc<TYPES>::make_view(
182 ((has_jagged_vector && (!std::get<INDICES>(is_jagged_vector)))
183 ? nullptr
184 : std::get<INDICES>(sizes)),
185 std::get<INDICES>(layouts), std::get<INDICES>(host_layouts),
186 std::get<INDICES>(payloads))...);
187}
188
190template <typename... TYPES, std::size_t INDEX, std::size_t... INDICES>
191VECMEM_HOST constexpr void* find_first_pointer(
192 const std::tuple<TYPES...>& pointers,
193 std::index_sequence<INDEX, INDICES...>) {
194
195 auto ptr = std::get<INDEX>(pointers);
196 if (ptr != nullptr) {
197 return ptr;
198 } else {
199 if constexpr (sizeof...(INDICES) > 0) {
200 return find_first_pointer<TYPES...>(
201 pointers, std::index_sequence<INDICES...>());
202 } else {
203 return nullptr;
204 }
205 }
206}
207
209template <typename... TYPES, std::size_t INDEX, std::size_t... INDICES>
210VECMEM_HOST constexpr void* find_last_pointer(
211 const std::tuple<TYPES...>& pointers,
212 const std::array<std::size_t, sizeof...(TYPES)>& sizes,
213 std::index_sequence<INDEX, INDICES...>) {
214
215 auto ptr = std::get<sizeof...(TYPES) - 1 - INDEX>(pointers);
216 if (ptr != nullptr) {
217 return ptr + std::get<sizeof...(TYPES) - 1 - INDEX>(sizes);
218 } else {
219 if constexpr (sizeof...(INDICES) > 0) {
220 return find_last_pointer<TYPES...>(
221 pointers, sizes, std::index_sequence<INDICES...>());
222 } else {
223 return nullptr;
224 }
225 }
226}
227
229template <typename... TYPES>
230VECMEM_HOST constexpr typename view<schema<TYPES...>>::memory_view_type
231find_layout_view(
232 const std::tuple<typename view_type<TYPES>::layout_ptr...>& layouts,
233 const std::array<std::size_t, sizeof...(TYPES)>& sizes) {
234
235 // The result type.
236 using result_type = typename view<schema<TYPES...>>::memory_view_type;
237
238 // Find the first non-zero pointer.
239 auto ptr = static_cast<typename result_type::pointer>(
240 find_first_pointer(layouts, std::index_sequence_for<TYPES...>()));
241 // Find the last non-zero pointer.
242 auto end_ptr = static_cast<typename result_type::pointer>(
243 find_last_pointer(layouts, sizes, std::index_sequence_for<TYPES...>()));
244
245 // Construct the result.
246 return {static_cast<typename result_type::size_type>(end_ptr - ptr), ptr};
247}
248
250template <typename... TYPES>
251VECMEM_HOST constexpr typename view<schema<TYPES...>>::memory_view_type
252find_payload_view(
253 const std::tuple<typename view_type<TYPES>::payload_ptr...>& payloads,
254 const std::array<std::size_t, sizeof...(TYPES)>& sizes) {
255
256 // The result type.
257 using result_type = typename view<schema<TYPES...>>::memory_view_type;
258
259 // Find the first non-zero pointer.
260 auto ptr = static_cast<typename result_type::pointer>(
261 find_first_pointer(payloads, std::index_sequence_for<TYPES...>()));
262 // Find the last non-zero pointer.
263 auto end_ptr = static_cast<typename result_type::pointer>(find_last_pointer(
264 payloads, sizes, std::index_sequence_for<TYPES...>()));
265
266 // Construct the result.
267 return {static_cast<typename result_type::size_type>(end_ptr - ptr), ptr};
268}
269
270} // namespace vecmem::edm::details
An allocator class that wraps a memory resource.
Definition allocator.hpp:37
VECMEM_HOST_AND_DEVICE constexpr const auto & get(const tuple< Ts... > &t) noexcept
Get a constant element out of a tuple.
Definition tuple.ipp:58
VECMEM_HOST_AND_DEVICE constexpr tuple< std::decay_t< Ts >... > make_tuple(Ts &&... args)
Make a tuple with automatic type deduction.
Definition tuple.ipp:87
std::vector< T, vecmem::polymorphic_allocator< T > > vector
Alias type for vectors with our polymorphic allocator.
Definition vector.hpp:35
static VECMEM_HOST view_type< type::jagged_vector< TYPE > >::type make_view(const std::vector< SIZE_TYPE, SIZE_ALLOC > &capacities, unsigned int *sizes, typename view_type< type::jagged_vector< TYPE > >::layout_ptr layout, typename view_type< type::jagged_vector< TYPE > >::layout_ptr host_layout, typename view_type< type::jagged_vector< TYPE > >::payload_ptr ptr)
Construct a view for a jagged vector variable.
Definition buffer_traits.hpp:113
static VECMEM_HOST std::size_t layout_size(const std::vector< SIZE_TYPE, SIZE_ALLOC > &sizes)
The number of "layout meta-objects" to allocate for the payload.
Definition buffer_traits.hpp:105
static VECMEM_HOST std::size_t payload_size(const std::vector< SIZE_TYPE, SIZE_ALLOC > &sizes)
The number of TYPE elements to allocate for the payload.
Definition buffer_traits.hpp:97
static VECMEM_HOST view_type< type::scalar< TYPE > >::type make_view(const std::vector< SIZE_TYPE, SIZE_ALLOC > &, unsigned int *, typename view_type< type::scalar< TYPE > >::layout_ptr, typename view_type< type::scalar< TYPE > >::layout_ptr, typename view_type< type::scalar< TYPE > >::payload_ptr ptr)
Construct a view for a scalar variable.
Definition buffer_traits.hpp:52
static VECMEM_HOST std::size_t payload_size(const std::vector< SIZE_TYPE, SIZE_ALLOC > &)
The number of TYPE elements to allocate for the payload.
Definition buffer_traits.hpp:38
static VECMEM_HOST std::size_t layout_size(const std::vector< SIZE_TYPE, SIZE_ALLOC > &)
The number of "layout meta-objects" to allocate for the payload.
Definition buffer_traits.hpp:45
static VECMEM_HOST std::size_t layout_size(const std::vector< SIZE_TYPE, SIZE_ALLOC > &)
The number of "layout meta-objects" to allocate for the payload.
Definition buffer_traits.hpp:73
static VECMEM_HOST std::size_t payload_size(const std::vector< SIZE_TYPE, SIZE_ALLOC > &sizes)
The number of TYPE elements to allocate for the payload.
Definition buffer_traits.hpp:66
static VECMEM_HOST view_type< type::vector< TYPE > >::type make_view(const std::vector< SIZE_TYPE, SIZE_ALLOC > &capacity, unsigned int *size, typename view_type< type::vector< TYPE > >::layout_ptr, typename view_type< type::vector< TYPE > >::layout_ptr, typename view_type< type::vector< TYPE > >::payload_ptr ptr)
Construct a view for a vector variable.
Definition buffer_traits.hpp:80
Definition buffer_traits.hpp:31
Definition view_traits.hpp:33
2D jagged vector variable
Definition schema.hpp:33
Scalar variable, one for a whole container.
Definition schema.hpp:19
1D vector variable
Definition schema.hpp:26