Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
data_layout_policy.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <tuple>
5#include <type_traits>
6#include <utility>
7
8#include "gaia/core/span.h"
9#include "gaia/core/utility.h"
10#include "gaia/mem/mem_alloc.h"
11#include "gaia/mem/mem_sani.h"
12#include "gaia/meta/reflection.h"
13
14namespace gaia {
15 namespace mem {
17 enum class DataLayout : uint8_t {
18 AoS = 0,
19 SoA = 1,
20 SoA8 = 2,
21 SoA16 = 3,
22
23 Count = 4
24 };
25
26#define GAIA_LAYOUT(layout_name) static constexpr auto gaia_Data_Layout = ::gaia::mem::DataLayout::layout_name
27
28 // Helper templates
30 namespace detail {
31 template <typename T>
32 constexpr uint32_t get_alignment() {
33 if constexpr (std::is_empty_v<T>)
34 // Always consider 0 for empty types
35 return 0U;
36 else {
37 // Use at least 4 (32-bit systems) or 8 (64-bit systems) bytes for alignment
38 return (uint32_t)core::get_min(sizeof(uintptr_t), alignof(T));
39 }
40 }
41
48 constexpr size_t get_aligned_byte_offset(uintptr_t address, size_t alig, size_t itemSize, size_t cnt) {
49 const auto padding = mem::padding(address, alig);
50 address += padding + itemSize * cnt;
51 return address;
52 }
53
60 template <typename T, size_t Alignment>
61 constexpr size_t get_aligned_byte_offset(uintptr_t address, size_t cnt) {
62 const auto padding = mem::padding<Alignment>(address);
63 address += padding + sizeof(T) * cnt;
64 return address;
65 }
66 } // namespace detail
68
72 template <DataLayout TDataLayout, typename TItem>
76 template <typename TItem>
77 struct data_layout_properties<DataLayout::AoS, TItem> {
79 constexpr static DataLayout Layout = DataLayout::AoS;
81 constexpr static size_t PackSize = 1;
83 constexpr static size_t Alignment = detail::get_alignment<TItem>();
84 };
87 template <typename TItem>
88 struct data_layout_properties<DataLayout::SoA, TItem> {
90 constexpr static DataLayout Layout = DataLayout::SoA;
92 constexpr static size_t PackSize = 4;
94 constexpr static size_t Alignment = PackSize * 4;
95 };
98 template <typename TItem>
99 struct data_layout_properties<DataLayout::SoA8, TItem> {
101 constexpr static DataLayout Layout = DataLayout::SoA8;
103 constexpr static size_t PackSize = 8;
105 constexpr static size_t Alignment = PackSize * 4;
106 };
109 template <typename TItem>
110 struct data_layout_properties<DataLayout::SoA16, TItem> {
112 constexpr static DataLayout Layout = DataLayout::SoA16;
114 constexpr static size_t PackSize = 16;
116 constexpr static size_t Alignment = PackSize * 4;
117 };
118
122 template <DataLayout TDataLayout, typename TItem>
124
128 template <DataLayout TDataLayout, typename TItem>
133 template <DataLayout TDataLayout, typename TItem>
135
140 template <DataLayout TDataLayout, typename TItem, size_t Ids>
146 template <DataLayout TDataLayout, typename TItem, size_t Ids>
148
161 template <typename ValueType>
164 using TargetCastType = std::add_pointer_t<ValueType>;
165
170
175 GAIA_NODISCARD static constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept {
176 const auto offset = detail::get_aligned_byte_offset<ValueType, Alignment>(addr, cnt);
177 return (uint32_t)(offset - addr);
178 }
179
184 template <typename Allocator>
185 GAIA_NODISCARD static uint8_t* alloc(size_t cnt) noexcept {
186 const auto bytes = get_min_byte_size(0, cnt);
187 auto* pData = (ValueType*)mem::AllocHelper::alloc<uint8_t, Allocator>(bytes);
188 core::call_ctor_raw_n(pData, cnt);
189 return (uint8_t*)pData;
190 }
191
197 template <typename Allocator>
198 static void free(void* pData, size_t cap, size_t cnt) noexcept {
199 if (pData == nullptr)
200 return;
201 core::call_dtor_n((ValueType*)pData, cnt);
202 GAIA_MEM_SANI_DEL_BLOCK(sizeof(ValueType), pData, cap, cnt);
203 return mem::AllocHelper::free<Allocator>(pData);
204 }
205
210 template <typename Allocator>
211 static void free(void* pData, size_t cnt) noexcept {
212 if (pData == nullptr)
213 return;
214 core::call_dtor_n((ValueType*)pData, cnt);
215 return mem::AllocHelper::free<Allocator>(pData);
216 }
217
222 GAIA_NODISCARD constexpr static ValueType get_value(std::span<const ValueType> s, size_t idx) noexcept {
223 return s[idx];
224 }
225
230 GAIA_NODISCARD constexpr static const ValueType& get(std::span<const ValueType> s, size_t idx) noexcept {
231 return s[idx];
232 }
233
238 GAIA_NODISCARD constexpr static ValueType& set(std::span<ValueType> s, size_t idx) noexcept {
239 return s[idx];
240 }
241 };
242
243 template <typename ValueType>
244 struct data_view_policy<DataLayout::AoS, ValueType>: data_view_policy_aos<ValueType> {};
245
248 template <typename ValueType>
252
254 std::span<const uint8_t> m_data;
255
258 data_view_policy_aos_get(std::span<uint8_t> data): m_data({(const uint8_t*)data.data(), data.size()}) {}
261 data_view_policy_aos_get(std::span<const uint8_t> data): m_data({(const uint8_t*)data.data(), data.size()}) {}
265 template <typename C>
266 data_view_policy_aos_get(const C& c): m_data({(const uint8_t*)c.data(), c.size()}) {
267 static_assert(!std::is_same_v<C, data_view_policy_aos_get>);
268 }
269
273 GAIA_NODISCARD const ValueType& operator[](size_t idx) const noexcept {
274 GAIA_ASSERT(idx < m_data.size());
275 return ((const ValueType*)m_data.data())[idx];
276 }
277
280 GAIA_NODISCARD decltype(auto) data() const noexcept {
281 return (const uint8_t*)m_data.data();
282 }
283
286 GAIA_NODISCARD auto size() const noexcept {
287 return m_data.size();
288 }
289 };
290
291 template <typename ValueType>
292 struct data_view_policy_get<DataLayout::AoS, ValueType>: data_view_policy_aos_get<ValueType> {};
293
296 template <typename ValueType>
300
302 std::span<uint8_t> m_data;
303
306 data_view_policy_aos_set(std::span<uint8_t> data): m_data({(uint8_t*)data.data(), data.size()}) {}
309 data_view_policy_aos_set(std::span<const uint8_t> data): m_data({(uint8_t*)data.data(), data.size()}) {}
313 template <typename C>
314 data_view_policy_aos_set(const C& c): m_data({(uint8_t*)c.data(), c.size()}) {
315 static_assert(!std::is_same_v<C, data_view_policy_aos_set>);
316 }
317
321 GAIA_NODISCARD ValueType& operator[](size_t idx) noexcept {
322 GAIA_ASSERT(idx < m_data.size());
323 return ((ValueType*)m_data.data())[idx];
324 }
325
329 GAIA_NODISCARD const ValueType& operator[](size_t idx) const noexcept {
330 GAIA_ASSERT(idx < m_data.size());
331 return ((const ValueType*)m_data.data())[idx];
332 }
333
336 GAIA_NODISCARD auto data() const noexcept {
337 return m_data.data();
338 }
339
342 GAIA_NODISCARD auto size() const noexcept {
343 return m_data.size();
344 }
345 };
346
347 template <typename ValueType>
348 struct data_view_policy_set<DataLayout::AoS, ValueType>: data_view_policy_aos_set<ValueType> {};
349
361 GAIA_NODISCARD static const uint8_t*
362 get(const void* pData, uint32_t alignment, std::span<const uint8_t> fieldSizes, uint32_t fieldIdx, uint32_t row,
363 uint32_t capacity) noexcept {
364 GAIA_ASSERT(pData != nullptr);
365 GAIA_ASSERT(alignment != 0 && fieldIdx < fieldSizes.size() && row < capacity);
366
367 auto address = (uintptr_t)pData;
368 GAIA_FOR(fieldIdx) {
369 address = detail::get_aligned_byte_offset(address, alignment, fieldSizes[i], capacity);
370 }
371 address += mem::padding(address, alignment);
372 return (const uint8_t*)address + ((uintptr_t)fieldSizes[fieldIdx] * row);
373 }
374
383 GAIA_NODISCARD static uint8_t*
384 set(void* pData, uint32_t alignment, std::span<const uint8_t> fieldSizes, uint32_t fieldIdx, uint32_t row,
385 uint32_t capacity) noexcept {
386 return const_cast<uint8_t*>(get(pData, alignment, fieldSizes, fieldIdx, row, capacity));
387 }
388 };
389
401 template <DataLayout TDataLayout, typename ValueType>
403 static_assert(std::is_copy_assignable_v<ValueType>);
404
406 using TTuple = decltype(meta::struct_to_tuple(std::declval<ValueType>()));
408 using TargetCastType = uint8_t*;
409
415 constexpr static size_t TTupleItems = std::tuple_size<TTuple>::value;
416 static_assert(Alignment > 0U, "SoA data can't be zero-aligned");
417
420 template <size_t Item>
421 using value_type = typename std::tuple_element<Item, TTuple>::type;
424 template <size_t Item>
425 using const_value_type = typename std::add_const<value_type<Item>>::type;
426
431 GAIA_NODISCARD constexpr static uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept {
432 const auto offset = get_aligned_byte_offset<TTupleItems>(addr, cnt);
433 return (uint32_t)(offset - addr);
434 }
435
440 template <typename Allocator>
441 GAIA_NODISCARD static uint8_t* alloc(size_t cnt) noexcept {
442 const auto bytes = get_min_byte_size(0, cnt);
443 return mem::AllocHelper::alloc_alig<uint8_t, Allocator>(Alignment, bytes);
444 }
445
451 template <typename Allocator>
452 static void free(void* pData, size_t cap, size_t cnt) noexcept {
453 if (pData == nullptr)
454 return;
455
456 mem_del_block(pData, cap, cnt);
457 return mem::AllocHelper::free_alig<Allocator>(pData);
458 }
459
464 static void mem_add_block(void* pData, size_t cap, size_t count) {
465 meta::each_member(ValueType{}, [&](auto&&... item) {
466 auto address = mem::align<Alignment>((uintptr_t)pData);
467 ((
468 //
469 GAIA_MEM_SANI_ADD_BLOCK(sizeof(item), (void*)address, cap, count),
470 // Skip towards the next element and make sure the address is aligned properly
471 address = mem::align<Alignment>(address + (sizeof(item) * cap))),
472 ...);
473 });
474 }
475
480 static void mem_del_block(void* pData, size_t cap, size_t count) {
481 meta::each_member(ValueType{}, [&](auto&&... item) {
482 auto address = mem::align<Alignment>((uintptr_t)pData);
483 ((
484 //
485 GAIA_MEM_SANI_DEL_BLOCK(sizeof(item), (void*)address, cap, count),
486 // Skip towards the next element and make sure the address is aligned properly
487 address = mem::align<Alignment>(address + (sizeof(item) * cap))),
488 ...);
489 });
490 }
491
497 static void mem_push_block(void* pData, size_t cap, size_t count, size_t n) {
498 meta::each_member(ValueType{}, [&](auto&&... item) {
499 auto address = mem::align<Alignment>((uintptr_t)pData);
500 ((
501 //
502 GAIA_MEM_SANI_PUSH_N(sizeof(item), (void*)address, cap, count, n),
503 // Skip towards the next element and make sure the address is aligned properly
504 address = mem::align<Alignment>(address + (sizeof(item) * cap))),
505 ...);
506 });
507 }
508
514 static void mem_pop_block(void* pData, size_t cap, size_t count, size_t n) {
515 meta::each_member(ValueType{}, [&](auto&&... item) {
516 auto address = mem::align<Alignment>((uintptr_t)pData);
517 ((
518 //
519 GAIA_MEM_SANI_POP_N(sizeof(item), (void*)address, cap, count, n),
520 // Skip towards the next element and make sure the address is aligned properly
521 address = mem::align<Alignment>(address + (sizeof(item) * cap))),
522 ...);
523 });
524 }
525
530 GAIA_NODISCARD constexpr static ValueType get(std::span<const uint8_t> s, size_t idx) noexcept {
531 return get_inter(meta::struct_to_tuple(ValueType{}), s, idx, std::make_index_sequence<TTupleItems>());
532 }
533
539 template <size_t Item>
540 GAIA_NODISCARD constexpr static auto get(std::span<const uint8_t> s, size_t idx = 0) noexcept {
541 const auto offset = get_aligned_byte_offset<Item>((uintptr_t)s.data(), s.size());
542 const auto& ref = get_ref<const value_type<Item>>(reinterpret_cast<const uint8_t*>(offset), idx);
543 return std::span{&ref, s.size() - idx};
544 }
545
547 class accessor {
548 std::span<uint8_t> m_data;
549 size_t m_idx;
550
551 public:
555 constexpr accessor(std::span<uint8_t> data, size_t idx): m_data(data), m_idx(idx) {}
556
559 constexpr void operator=(const ValueType& val) noexcept {
560 set_inter(meta::struct_to_tuple(val), m_data, m_idx, std::make_index_sequence<TTupleItems>());
561 }
562
565 constexpr void operator=(ValueType&& val) noexcept {
566 set_inter(meta::struct_to_tuple(GAIA_MOV(val)), m_data, m_idx, std::make_index_sequence<TTupleItems>());
567 }
568
571 GAIA_NODISCARD constexpr operator ValueType() const noexcept {
572 return get_inter(
573 meta::struct_to_tuple(ValueType{}), {(const uint8_t*)m_data.data(), m_data.size()}, m_idx,
574 std::make_index_sequence<TTupleItems>());
575 }
576 };
577
582 GAIA_NODISCARD constexpr static auto set(std::span<uint8_t> s, size_t idx) noexcept {
583 return accessor(s, idx);
584 }
585
591 template <size_t Item>
592 GAIA_NODISCARD constexpr static auto set(std::span<uint8_t> s, size_t idx = 0) noexcept {
593 const auto offset = get_aligned_byte_offset<Item>((uintptr_t)s.data(), s.size());
594 auto& ref = get_ref<value_type<Item>>((const uint8_t*)offset, idx);
595 return std::span{&ref, s.size() - idx};
596 }
597
598 private:
599 template <size_t... Ids>
600 GAIA_NODISCARD constexpr static size_t
601 get_aligned_byte_offset_seq(uintptr_t address, size_t cnt, std::index_sequence<Ids...> /*no_name*/) {
602 ((address = detail::get_aligned_byte_offset(address, Alignment, sizeof(value_type<Ids>), cnt)), ...);
603 address += mem::padding(address, Alignment);
604 return address;
605 }
606
607 template <uint32_t N>
608 GAIA_NODISCARD constexpr static size_t get_aligned_byte_offset(uintptr_t address, size_t cnt) {
609 return get_aligned_byte_offset_seq(address, cnt, std::make_index_sequence<N>());
610 }
611
612 template <typename TMemberType>
613 GAIA_NODISCARD constexpr static TMemberType& get_ref(const uint8_t* data, size_t idx) noexcept {
614 // Write the value directly to the memory address.
615 // Usage of unaligned_ref is not necessary because the memory is aligned.
616 auto* pCastData = (TMemberType*)data;
617 return pCastData[idx];
618 }
619
620 template <typename Tup, size_t... Ids>
621 GAIA_NODISCARD constexpr static ValueType
622 get_inter(Tup&& t, std::span<const uint8_t> s, size_t idx, std::index_sequence<Ids...> /*no_name*/) noexcept {
623 auto address = mem::align<Alignment>((uintptr_t)s.data());
624 ((
625 // Put the value at the address into our tuple. Data is aligned so we can read directly.
626 std::get<Ids>(t) = get_ref<value_type<Ids>>((const uint8_t*)address, idx),
627 // Skip towards the next element and make sure the address is aligned properly
628 address = mem::align<Alignment>(address + (sizeof(value_type<Ids>) * s.size()))),
629 ...);
630 return meta::tuple_to_struct<ValueType, TTuple>(GAIA_FWD(t));
631 }
632
633 template <typename Tup, size_t... Ids>
634 constexpr static void
635 set_inter(Tup&& t, std::span<uint8_t> s, size_t idx, std::index_sequence<Ids...> /*no_name*/) noexcept {
636 auto address = mem::align<Alignment>((uintptr_t)s.data());
637 ((
638 // Set the tuple value. Data is aligned so we can write directly.
639 get_ref<value_type<Ids>>((uint8_t*)address, idx) = std::get<Ids>(t),
640 // Skip towards the next element and make sure the address is aligned properly
641 address = mem::align<Alignment>(address + (sizeof(value_type<Ids>) * s.size()))),
642 ...);
643 }
644 };
645
646 template <typename ValueType>
647 struct data_view_policy<DataLayout::SoA, ValueType>: //
648 data_view_policy_soa<DataLayout::SoA, ValueType> {};
649 template <typename ValueType>
650 struct data_view_policy<DataLayout::SoA8, ValueType>: //
651 data_view_policy_soa<DataLayout::SoA8, ValueType> {};
652 template <typename ValueType>
653 struct data_view_policy<DataLayout::SoA16, ValueType>: //
654 data_view_policy_soa<DataLayout::SoA16, ValueType> {};
655
659 template <DataLayout TDataLayout, typename ValueType>
661 static_assert(std::is_copy_assignable_v<ValueType>);
662
665
668 template <size_t Item>
671 using const_value_type = typename view_policy::template const_value_type<Item>;
672 };
673
675 std::span<const uint8_t> m_data;
676
679 data_view_policy_soa_get(std::span<uint8_t> data): m_data({(const uint8_t*)data.data(), data.size()}) {}
682 data_view_policy_soa_get(std::span<const uint8_t> data): m_data({(const uint8_t*)data.data(), data.size()}) {}
686 template <typename C>
687 data_view_policy_soa_get(const C& c): m_data({(const uint8_t*)c.data(), c.size()}) {
688 static_assert(!std::is_same_v<C, data_view_policy_soa_get>);
689 }
690
694 GAIA_NODISCARD constexpr decltype(auto) operator[](size_t idx) const noexcept {
695 return view_policy::get(m_data, idx);
696 }
697
701 template <size_t Item>
702 GAIA_NODISCARD constexpr auto get() const noexcept {
703 auto s = view_policy::template get<Item>(m_data);
704 return std::span(s.data(), s.size());
705 }
706
709 GAIA_NODISCARD decltype(auto) data() const noexcept {
710 return (const uint8_t*)m_data.data();
711 }
712
715 GAIA_NODISCARD auto size() const noexcept {
716 return m_data.size();
717 }
718 };
719
720 template <typename ValueType>
721 struct data_view_policy_get<DataLayout::SoA, ValueType>: //
722 data_view_policy_soa_get<DataLayout::SoA, ValueType> {};
723 template <typename ValueType>
724 struct data_view_policy_get<DataLayout::SoA8, ValueType>: //
725 data_view_policy_soa_get<DataLayout::SoA8, ValueType> {};
726 template <typename ValueType>
727 struct data_view_policy_get<DataLayout::SoA16, ValueType>: //
728 data_view_policy_soa_get<DataLayout::SoA16, ValueType> {};
729
733 template <DataLayout TDataLayout, typename ValueType>
735 static_assert(std::is_copy_assignable_v<ValueType>);
736
739
742 template <size_t Item>
745 using value_type = typename view_policy::template value_type<Item>;
747 using const_value_type = typename view_policy::template const_value_type<Item>;
748 };
749
751 std::span<uint8_t> m_data;
752
755 data_view_policy_soa_set(std::span<uint8_t> data): m_data({(uint8_t*)data.data(), data.size()}) {}
758 data_view_policy_soa_set(std::span<const uint8_t> data): m_data({(uint8_t*)data.data(), data.size()}) {}
762 template <typename C>
763 data_view_policy_soa_set(const C& c): m_data({(uint8_t*)c.data(), c.size()}) {
764 static_assert(!std::is_same_v<C, data_view_policy_soa_set>);
765 }
766
768 struct accessor {
770 std::span<uint8_t> m_data;
772 size_t m_idx;
773
776 constexpr void operator=(const ValueType& val) noexcept {
778 }
781 constexpr void operator=(ValueType&& val) noexcept {
782 view_policy::set(m_data, m_idx) = GAIA_FWD(val);
783 }
784 };
785
789 GAIA_NODISCARD constexpr decltype(auto) operator[](size_t idx) const noexcept {
790 return view_policy::get({(const uint8_t*)m_data.data(), m_data.size()}, idx);
791 }
795 GAIA_NODISCARD constexpr auto operator[](size_t idx) noexcept {
796 return accessor{m_data, idx};
797 }
798
802 template <size_t Item>
803 GAIA_NODISCARD constexpr auto get() const noexcept {
804 auto s = view_policy::template get<Item>(m_data);
805 return std::span(s.data(), s.size());
806 }
807
811 template <size_t Item>
812 GAIA_NODISCARD constexpr auto set() noexcept {
813 auto s = view_policy::template set<Item>(m_data);
814 return std::span(s.data(), s.size());
815 }
816
819 GAIA_NODISCARD auto data() const noexcept {
820 return m_data.data();
821 }
822
825 GAIA_NODISCARD auto size() const noexcept {
826 return m_data.size();
827 }
828 };
829
830 template <typename ValueType>
831 struct data_view_policy_set<DataLayout::SoA, ValueType>: //
832 data_view_policy_soa_set<DataLayout::SoA, ValueType> {};
833 template <typename ValueType>
834 struct data_view_policy_set<DataLayout::SoA8, ValueType>: //
835 data_view_policy_soa_set<DataLayout::SoA8, ValueType> {};
836 template <typename ValueType>
837 struct data_view_policy_set<DataLayout::SoA16, ValueType>: //
838 data_view_policy_soa_set<DataLayout::SoA16, ValueType> {};
839
840 //----------------------------------------------------------------------
841 // Helpers
842 //----------------------------------------------------------------------
843
845 namespace detail {
846 template <typename, typename = void>
847 struct auto_view_policy_inter {
848 static constexpr DataLayout data_layout_type = DataLayout::AoS;
849 };
850 template <typename T>
851 struct auto_view_policy_inter<T, std::void_t<decltype(T::gaia_Data_Layout)>> {
852 static constexpr DataLayout data_layout_type = T::gaia_Data_Layout;
853 };
854
855 template <typename, typename = void>
856 struct is_soa_layout: std::false_type {};
857 template <typename T>
858 struct is_soa_layout<T, std::void_t<decltype(T::gaia_Data_Layout)>>:
859 std::bool_constant<!std::is_empty_v<T> && (T::gaia_Data_Layout != DataLayout::AoS)> {};
860 } // namespace detail
862
865 template <typename T>
866 using auto_view_policy = data_view_policy<detail::auto_view_policy_inter<T>::data_layout_type, T>;
869 template <typename T>
870 using auto_view_policy_get = data_view_policy_get<detail::auto_view_policy_inter<T>::data_layout_type, T>;
873 template <typename T>
874 using auto_view_policy_set = data_view_policy_set<detail::auto_view_policy_inter<T>::data_layout_type, T>;
875
878 template <typename T>
879 inline constexpr bool is_soa_layout_v = detail::is_soa_layout<T>::value;
880
881 } // namespace mem
882} // namespace gaia
Proxy used to read or assign one complete SoA value.
Definition data_layout_policy.h:547
constexpr void operator=(const ValueType &val) noexcept
Assigns a copied value to the selected SoA fields.
Definition data_layout_policy.h:559
constexpr accessor(std::span< uint8_t > data, size_t idx)
Creates a value proxy.
Definition data_layout_policy.h:555
constexpr void operator=(ValueType &&val) noexcept
Assigns a moved value to the selected SoA fields.
Definition data_layout_policy.h:565
Compile-time properties of a data layout.
Definition data_layout_policy.h:73
Read-only byte view over AoS values.
Definition data_layout_policy.h:249
std::span< const uint8_t > m_data
Raw data pointed to by the view policy.
Definition data_layout_policy.h:254
data_view_policy_aos_get(std::span< uint8_t > data)
Creates a read-only view over mutable bytes.
Definition data_layout_policy.h:258
GAIA_NODISCARD auto size() const noexcept
Returns the backing span size.
Definition data_layout_policy.h:286
GAIA_NODISCARD const ValueType & operator[](size_t idx) const noexcept
Returns a value by index.
Definition data_layout_policy.h:273
data_view_policy_aos_get(const C &c)
Creates a read-only view over a contiguous container.
Definition data_layout_policy.h:266
data_view_policy_aos_get(std::span< const uint8_t > data)
Creates a read-only view over bytes.
Definition data_layout_policy.h:261
GAIA_NODISCARD decltype(auto) data() const noexcept
Returns the backing byte address.
Definition data_layout_policy.h:280
Mutable byte view over AoS values.
Definition data_layout_policy.h:297
data_view_policy_aos_set(std::span< const uint8_t > data)
Creates a mutable view from a byte span.
Definition data_layout_policy.h:309
GAIA_NODISCARD ValueType & operator[](size_t idx) noexcept
Returns a mutable value by index.
Definition data_layout_policy.h:321
GAIA_NODISCARD auto size() const noexcept
Returns the backing span size.
Definition data_layout_policy.h:342
std::span< uint8_t > m_data
Raw data pointed to by the view policy.
Definition data_layout_policy.h:302
data_view_policy_aos_set(const C &c)
Creates a mutable view over a contiguous container.
Definition data_layout_policy.h:314
GAIA_NODISCARD const ValueType & operator[](size_t idx) const noexcept
Returns a read-only value by index.
Definition data_layout_policy.h:329
GAIA_NODISCARD auto data() const noexcept
Returns the backing byte address.
Definition data_layout_policy.h:336
data_view_policy_aos_set(std::span< uint8_t > data)
Creates a mutable view over bytes.
Definition data_layout_policy.h:306
View policy for accessing and storing data in the AoS way. Good for random access and when accessing ...
Definition data_layout_policy.h:162
static constexpr size_t Alignment
Required byte alignment.
Definition data_layout_policy.h:169
static GAIA_NODISCARD constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept
Calculates the bytes required for a value range.
Definition data_layout_policy.h:175
static GAIA_NODISCARD uint8_t * alloc(size_t cnt) noexcept
Allocates and default-constructs an AoS value range.
Definition data_layout_policy.h:185
static void free(void *pData, size_t cnt) noexcept
Destroys and releases an AoS value range.
Definition data_layout_policy.h:211
GAIA_NODISCARD static constexpr ValueType get_value(std::span< const ValueType > s, size_t idx) noexcept
Copies a value from an AoS span.
Definition data_layout_policy.h:222
std::add_pointer_t< ValueType > TargetCastType
Pointer type used to address stored values.
Definition data_layout_policy.h:164
GAIA_NODISCARD static constexpr ValueType & set(std::span< ValueType > s, size_t idx) noexcept
Returns a mutable value reference from an AoS span.
Definition data_layout_policy.h:238
static void free(void *pData, size_t cap, size_t cnt) noexcept
Destroys and releases an instrumented AoS value range.
Definition data_layout_policy.h:198
static constexpr DataLayout Layout
Physical layout.
Definition data_layout_policy.h:167
GAIA_NODISCARD static constexpr const ValueType & get(std::span< const ValueType > s, size_t idx) noexcept
Returns a read-only value reference from an AoS span.
Definition data_layout_policy.h:230
Indexed read-only view metadata.
Definition data_layout_policy.h:141
Read-only view for a selected layout and item type.
Definition data_layout_policy.h:129
Indexed mutable view metadata.
Definition data_layout_policy.h:147
Mutable view for a selected layout and item type.
Definition data_layout_policy.h:134
Type-erased policy for addressing one field value in SoA storage. The field arrays use the same align...
Definition data_layout_policy.h:352
static GAIA_NODISCARD const uint8_t * get(const void *pData, uint32_t alignment, std::span< const uint8_t > fieldSizes, uint32_t fieldIdx, uint32_t row, uint32_t capacity) noexcept
Returns one read-only field value from type-erased SoA storage.
Definition data_layout_policy.h:362
static GAIA_NODISCARD uint8_t * set(void *pData, uint32_t alignment, std::span< const uint8_t > fieldSizes, uint32_t fieldIdx, uint32_t row, uint32_t capacity) noexcept
Returns one mutable field value from type-erased SoA storage.
Definition data_layout_policy.h:384
Metadata for a selected field.
Definition data_layout_policy.h:669
typename view_policy::template const_value_type< Item > const_value_type
Const-qualified field type.
Definition data_layout_policy.h:671
Read-only byte view over SoA values.
Definition data_layout_policy.h:660
data_view_policy_soa_get(std::span< const uint8_t > data)
Creates a read-only view over bytes.
Definition data_layout_policy.h:682
data_view_policy_soa_get(std::span< uint8_t > data)
Creates a read-only view over mutable bytes.
Definition data_layout_policy.h:679
std::span< const uint8_t > m_data
Raw data pointed to by the view policy.
Definition data_layout_policy.h:675
GAIA_NODISCARD decltype(auto) data() const noexcept
Returns the backing byte address.
Definition data_layout_policy.h:709
GAIA_NODISCARD auto size() const noexcept
Returns the backing span size.
Definition data_layout_policy.h:715
data_view_policy_soa_get(const C &c)
Creates a read-only view over a contiguous container.
Definition data_layout_policy.h:687
GAIA_NODISCARD constexpr auto get() const noexcept
Returns a read-only span over one field.
Definition data_layout_policy.h:702
Proxy used to assign one complete value.
Definition data_layout_policy.h:768
constexpr void operator=(ValueType &&val) noexcept
Assigns a moved value.
Definition data_layout_policy.h:781
constexpr void operator=(const ValueType &val) noexcept
Assigns a copied value.
Definition data_layout_policy.h:776
size_t m_idx
Value index.
Definition data_layout_policy.h:772
std::span< uint8_t > m_data
Backing byte span.
Definition data_layout_policy.h:770
Metadata for a selected field.
Definition data_layout_policy.h:743
typename view_policy::template const_value_type< Item > const_value_type
Const-qualified field type.
Definition data_layout_policy.h:747
typename view_policy::template value_type< Item > value_type
Mutable field type.
Definition data_layout_policy.h:745
Mutable byte view over SoA values.
Definition data_layout_policy.h:734
GAIA_NODISCARD constexpr auto set() noexcept
Returns a mutable span over one field.
Definition data_layout_policy.h:812
data_view_policy_soa_set(std::span< uint8_t > data)
Creates a mutable view over bytes.
Definition data_layout_policy.h:755
data_view_policy_soa_set(const C &c)
Creates a mutable view over a contiguous container.
Definition data_layout_policy.h:763
std::span< uint8_t > m_data
Raw data pointed to by the view policy.
Definition data_layout_policy.h:751
GAIA_NODISCARD constexpr auto operator[](size_t idx) noexcept
Returns a mutable proxy by index.
Definition data_layout_policy.h:795
data_view_policy_soa_set(std::span< const uint8_t > data)
Creates a mutable view from a byte span.
Definition data_layout_policy.h:758
GAIA_NODISCARD auto size() const noexcept
Returns the backing span size.
Definition data_layout_policy.h:825
GAIA_NODISCARD constexpr auto get() const noexcept
Returns a read-only span over one field.
Definition data_layout_policy.h:803
GAIA_NODISCARD auto data() const noexcept
Returns the backing byte address.
Definition data_layout_policy.h:819
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:402
GAIA_NODISCARD static constexpr ValueType get(std::span< const uint8_t > s, size_t idx) noexcept
Reconstructs a value from its SoA fields.
Definition data_layout_policy.h:530
static void mem_pop_block(void *pData, size_t cap, size_t count, size_t n)
Poisons removed SoA values for the memory sanitizer.
Definition data_layout_policy.h:514
static void mem_add_block(void *pData, size_t cap, size_t count)
Registers a newly allocated SoA range with the memory sanitizer.
Definition data_layout_policy.h:464
uint8_t * TargetCastType
Pointer type used to address SoA storage.
Definition data_layout_policy.h:408
static constexpr DataLayout Layout
Physical layout.
Definition data_layout_policy.h:411
static constexpr size_t Alignment
Required byte alignment.
Definition data_layout_policy.h:413
typename std::add_const< value_type< Item > >::type const_value_type
Const-qualified type of a reflected field.
Definition data_layout_policy.h:425
static GAIA_NODISCARD uint8_t * alloc(size_t cnt) noexcept
Allocates an SoA value range.
Definition data_layout_policy.h:441
decltype(meta::struct_to_tuple(std::declval< ValueType >())) TTuple
Tuple representation of the reflected value fields.
Definition data_layout_policy.h:406
GAIA_NODISCARD static constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept
Calculates the bytes required for an SoA value range.
Definition data_layout_policy.h:431
static void mem_del_block(void *pData, size_t cap, size_t count)
Unregisters an SoA range from the memory sanitizer.
Definition data_layout_policy.h:480
GAIA_NODISCARD static constexpr auto set(std::span< uint8_t > s, size_t idx) noexcept
Returns a mutable proxy for one complete value.
Definition data_layout_policy.h:582
static void mem_push_block(void *pData, size_t cap, size_t count, size_t n)
Makes newly appended SoA values addressable by the memory sanitizer.
Definition data_layout_policy.h:497
static void free(void *pData, size_t cap, size_t cnt) noexcept
Releases an instrumented SoA value range.
Definition data_layout_policy.h:452
GAIA_NODISCARD static constexpr auto set(std::span< uint8_t > s, size_t idx=0) noexcept
Returns a mutable span over one SoA field.
Definition data_layout_policy.h:592
static constexpr size_t TTupleItems
Number of reflected fields.
Definition data_layout_policy.h:415
GAIA_NODISCARD static constexpr auto get(std::span< const uint8_t > s, size_t idx=0) noexcept
Returns a read-only span over one SoA field.
Definition data_layout_policy.h:540
typename std::tuple_element< Item, TTuple >::type value_type
Type of a reflected field.
Definition data_layout_policy.h:421
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:123