vecmem 1.24.0
Loading...
Searching...
No Matches
buffer.ipp
1/* VecMem project, part of the ACTS project (R&D line)
2 *
3 * (c) 2023-2026 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/containers/details/aligned_multiple_placement.hpp"
11#include "vecmem/edm/details/buffer_traits.hpp"
12#include "vecmem/edm/details/schema_traits.hpp"
13#include "vecmem/edm/details/view_traits.hpp"
14
15// System include(s).
16#include <stdexcept>
17#include <tuple>
18#include <type_traits>
19
20namespace vecmem {
21namespace edm {
22
23template <typename... VARTYPES>
24VECMEM_HOST buffer<schema<VARTYPES...>>::buffer(size_type capacity,
25 memory_resource& mr,
27 : view_type(capacity) {
28
29 // Make sure that this constructor is not used for a container that has
30 // jagged vectors in it.
31 static_assert(
32 std::disjunction_v<type::details::is_jagged_vector<VARTYPES>...> ==
33 false,
34 "Use the other buffer constructor with jagged vector variables!");
35
36 // Perform the appropriate setup.
37 switch (type) {
39 setup_fixed(std::vector<std::size_t>(capacity), mr, nullptr,
40 std::index_sequence_for<VARTYPES...>{});
41 break;
43 setup_resizable(std::vector<std::size_t>(capacity), mr, nullptr,
44 std::index_sequence_for<VARTYPES...>{});
45 break;
46 default:
47 throw std::invalid_argument("Unknown buffer type");
48 }
49}
50
51template <typename... VARTYPES>
52template <
53 typename SIZE_TYPE, typename SIZE_ALLOC,
54 std::enable_if_t<
55 std::is_integral_v<SIZE_TYPE> && std::is_unsigned_v<SIZE_TYPE>, bool>>
56VECMEM_HOST buffer<schema<VARTYPES...>>::buffer(
57 const std::vector<SIZE_TYPE, SIZE_ALLOC>& capacities,
58 memory_resource& main_mr, memory_resource* host_mr,
61
62 // Make sure that this constructor is only used for a container that has
63 // jagged vectors in it.
64 static_assert(
65 std::disjunction_v<type::details::is_jagged_vector<VARTYPES>...>,
66 "Use the other buffer constructor without jagged vector variables!");
67
68 // Perform the appropriate setup.
69 switch (type) {
71 setup_fixed(capacities, main_mr, host_mr,
72 std::index_sequence_for<VARTYPES...>{});
73 break;
75 setup_resizable(capacities, main_mr, host_mr,
76 std::index_sequence_for<VARTYPES...>{});
77 break;
78 default:
79 throw std::invalid_argument("Unknown buffer type");
80 }
81}
82
83template <typename... VARTYPES>
84VECMEM_HOST memory_resource* buffer<schema<VARTYPES...>>::resource() const {
85
86 return m_memory.get_deleter().resource();
87}
88
89template <typename... VARTYPES>
90VECMEM_HOST memory_resource* buffer<schema<VARTYPES...>>::host_resource()
91 const {
92
93 return m_host_memory.get_deleter().resource();
94}
95
96template <typename... VARTYPES>
97template <typename SIZE_TYPE, typename SIZE_ALLOC, std::size_t... INDICES>
98VECMEM_HOST void buffer<schema<VARTYPES...>>::setup_fixed(
99 const std::vector<SIZE_TYPE, SIZE_ALLOC>& capacities, memory_resource& mr,
100 memory_resource* host_mr, std::index_sequence<INDICES...>) {
101
102 // Sanity check.
103 static_assert(sizeof...(VARTYPES) == sizeof...(INDICES),
104 "Invalid number of indices");
105
106 // Tuple of pointers to the allocated "layout objects" and "payloads".
107 std::tuple<typename details::view_type<VARTYPES>::layout_ptr...>
109 std::tuple<typename details::view_type<VARTYPES>::layout_ptr...>
111 std::tuple<typename details::view_type<VARTYPES>::payload_ptr...>
113
114 // Allocate memory for fixed sized variables.
115 std::tie(m_memory, std::get<INDICES>(layout_ptrs)...,
116 std::get<INDICES>(payload_ptrs)...) =
122
123 // Set the base class's memory views.
124 view_type::m_layout = details::find_layout_view<VARTYPES...>(
127 view_type::m_payload = details::find_payload_view<VARTYPES...>(
129 {details::buffer_alloc<VARTYPES>::payload_size(capacities)...});
130
131 // If requested, allocate host memory for the layouts.
132 if (host_mr != nullptr) {
133
134 // Allocate memory for just the layout in host memory.
135 std::tie(m_host_memory, std::get<INDICES>(host_layout_ptrs)...) =
137 typename details::view_type<VARTYPES>::layout_type...>(
138 *host_mr,
139 details::buffer_alloc<VARTYPES>::layout_size(capacities)...);
140
141 // Set the base class's memory view.
142 view_type::m_host_layout = details::find_layout_view<VARTYPES...>(
143 host_layout_ptrs,
144 {details::buffer_alloc<VARTYPES>::layout_size(capacities)...});
145 } else {
146 // The layout is apparently host accessible.
147 view_type::m_host_layout = view_type::m_layout;
148 }
149
150 // Initialize the views from all the raw pointers.
151 view_type::m_views =
152 details::make_buffer_views<SIZE_TYPE, SIZE_ALLOC, VARTYPES...>(
153 capacities, layout_ptrs, host_layout_ptrs, payload_ptrs,
154 std::index_sequence_for<VARTYPES...>{});
155}
156
157template <typename... VARTYPES>
158template <typename SIZE_TYPE, typename SIZE_ALLOC, std::size_t... INDICES>
159VECMEM_HOST void buffer<schema<VARTYPES...>>::setup_resizable(
160 const std::vector<SIZE_TYPE, SIZE_ALLOC>& capacities, memory_resource& mr,
161 memory_resource* host_mr, std::index_sequence<INDICES...>) {
162
163 // Sanity check(s).
164 static_assert(sizeof...(VARTYPES) == sizeof...(INDICES),
165 "Invalid number of indices");
166 static_assert(
167 std::disjunction_v<type::details::is_vector<VARTYPES>...>,
168 "Trying to create a resizable container without any vector variables!");
169
170 // Does the container have jagged vectors in it?
171 constexpr bool has_jagged_vectors =
172 std::disjunction_v<type::details::is_jagged_vector<VARTYPES>...>;
173
174 // Pointers to the allocated "size variables".
175 std::tuple<typename details::view_type<VARTYPES>::size_ptr...> sizes_ptrs;
176
177 // Tuple of pointers to the allocated "layout objects" and "payloads".
178 std::tuple<typename details::view_type<VARTYPES>::layout_ptr...>
179 layout_ptrs;
180 std::tuple<typename details::view_type<VARTYPES>::layout_ptr...>
181 host_layout_ptrs;
182 std::tuple<typename details::view_type<VARTYPES>::payload_ptr...>
183 payload_ptrs;
184
185 // Allocate memory for fixed sized variables. A little differently for
186 // containers that have some jagged vectors, versus ones that only have
187 // 1D vectors.
188 if constexpr (has_jagged_vectors) {
189 // Perform the allocation.
190 std::tie(m_memory, std::get<INDICES>(sizes_ptrs)...,
191 std::get<INDICES>(layout_ptrs)...,
192 std::get<INDICES>(payload_ptrs)...) =
194 typename details::view_type<VARTYPES>::size_type...,
195 typename details::view_type<VARTYPES>::layout_type...,
196 typename details::view_type<VARTYPES>::payload_type...>(
197 mr, details::buffer_alloc<VARTYPES>::layout_size(capacities)...,
198 details::buffer_alloc<VARTYPES>::layout_size(capacities)...,
199 details::buffer_alloc<VARTYPES>::payload_size(capacities)...);
200 // Point the base class at the size array.
201 view_type::m_size = {
202 static_cast<typename view_type::memory_view_type::size_type>(
203 (details::buffer_alloc<VARTYPES>::layout_size(capacities) +
204 ...) *
205 sizeof(typename view_type::size_type)),
206 reinterpret_cast<typename view_type::memory_view_type::pointer>(
207 details::find_first_pointer(
208 sizes_ptrs, std::index_sequence_for<VARTYPES...>{}))};
209 } else {
210 // Perform the allocation.
211 typename view_type::size_pointer size = nullptr;
212 std::tie(m_memory, size, std::get<INDICES>(layout_ptrs)...,
213 std::get<INDICES>(payload_ptrs)...) =
215 typename view_type::size_type,
216 typename details::view_type<VARTYPES>::layout_type...,
217 typename details::view_type<VARTYPES>::payload_type...>(
218 mr, 1u,
219 details::buffer_alloc<VARTYPES>::layout_size(capacities)...,
220 details::buffer_alloc<VARTYPES>::payload_size(capacities)...);
221 // Point the base class at the size variable.
222 view_type::m_size = {
223 static_cast<typename view_type::memory_view_type::size_type>(
224 sizeof(typename view_type::size_type)),
225 reinterpret_cast<typename view_type::memory_view_type::pointer>(
226 size)};
227 // Set all size pointers to point at the one allocated number.
228 ((std::get<INDICES>(sizes_ptrs) = size), ...);
229 }
230
231 // Set the base class's memory views.
232 view_type::m_layout = details::find_layout_view<VARTYPES...>(
233 layout_ptrs,
234 {details::buffer_alloc<VARTYPES>::layout_size(capacities)...});
235 view_type::m_payload = details::find_payload_view<VARTYPES...>(
236 payload_ptrs,
237 {details::buffer_alloc<VARTYPES>::payload_size(capacities)...});
238
239 // If requested, allocate host memory for the layouts.
240 if (host_mr != nullptr) {
241
242 // Allocate memory for just the layout in host memory.
243 std::tie(m_host_memory, std::get<INDICES>(host_layout_ptrs)...) =
245 typename details::view_type<VARTYPES>::layout_type...>(
246 *host_mr,
247 details::buffer_alloc<VARTYPES>::layout_size(capacities)...);
248
249 // Set the base class's memory view.
250 view_type::m_host_layout = details::find_layout_view<VARTYPES...>(
251 host_layout_ptrs,
252 {details::buffer_alloc<VARTYPES>::layout_size(capacities)...});
253 } else {
254 // The layout is apparently host accessible.
255 view_type::m_host_layout = view_type::m_layout;
256 }
257
258 // Initialize the views from all the raw pointers.
259 view_type::m_views =
260 details::make_buffer_views<SIZE_TYPE, SIZE_ALLOC, VARTYPES...>(
261 capacities, sizes_ptrs, layout_ptrs, host_layout_ptrs, payload_ptrs,
262 std::index_sequence_for<VARTYPES...>{});
263}
264
265} // namespace edm
266
267template <typename... VARTYPES>
270
271 return buffer;
272}
273
274template <typename... VARTYPES>
275VECMEM_HOST edm::view<edm::details::add_const_t<edm::schema<VARTYPES...>>>
277
278 return buffer;
279}
280
281} // namespace vecmem
An allocator class that wraps a memory resource.
Definition allocator.hpp:37
typename view_type::size_type size_type
Size type used for the container.
Definition buffer.hpp:180
Technical base type for buffer<schema<VARTYPES...>>
Definition buffer.hpp:28
buffer_type
"Overall type" for a buffer object
Definition buffer_type.hpp:13
@ fixed_size
The buffer has a fixed number of elements.
@ resizable
The buffer is resizable/expandable.
std::tuple< vecmem::unique_alloc_ptr< char[]>, std::add_pointer_t< Ts >... > aligned_multiple_placement(vecmem::memory_resource &r, Ps &&... ps)
Allocation of aligned arrays of given types.
Definition aligned_multiple_placement.ipp:137
Main namespace for the vecmem classes/functions.
Definition atomic_ref.hpp:16
VECMEM_HOST data::vector_view< T > get_data(array< T, N > &a)
Helper function creating a vecmem::data::vector_view object.
Definition array.ipp:217
Definition buffer_traits.hpp:31
Definition view_traits.hpp:33
Meta type describing the "schema" of an SoA container.
Definition schema.hpp:46