1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! Global convenience API for the component registry.
//!
//! Provides a set of free functions that delegate to a single, process-wide
//! [`ComponentRegistry`] instance, making it straightforward to register
//! components, query IDs, and allocate storage without managing registry
//! lifetimes manually.
//!
//! # Intended use
//! This module is designed for **single-world applications** where one shared
//! component namespace is sufficient.
//!
//! **Multi-world applications** that need isolated registries should construct
//! and own a [`ComponentRegistry`] directly, and pass it by reference to
//! archetype-creation paths (e.g. `Archetype::new`) rather than relying on
//! these global convenience functions.
//!
//! # Lifecycle
//! 1. **Registration** - call [`register_component`] (or [`register_gpu_component`]
//! with the `gpu` feature) for every component type before simulation begins.
//! 2. **Freeze** - call [`freeze_components`] once all components are registered.
//! After this point the registry is immutable: component IDs and storage
//! factories are stable and safe to use for archetype construction.
//! 3. **Query / allocate** - use [`component_id_of`], [`component_description_by_component_id`],
//! and [`make_empty_component`] freely throughout the rest of the program.
//!
//! # GPU support
//! When the `gpu` feature is enabled, [`register_gpu_component`] marks a
//! component as GPU-safe via the [`GPUPod`] contract, allowing it to be
//! mirrored into GPU storage buffers.
//!
//! # Thread safety
//! The global registry is protected by an [`RwLock`]. Concurrent reads are
//! supported; writes (registration, freezing) require exclusive access. All
//! functions return [`RegistryError::PoisonedLock`] if the lock has been
//! poisoned by a panicking writer.
use TypeId;
use size_of;
use ;
use crate;
use crateComponentID;
use ComponentRegistry;
// ---------------------------------------------------------------------------
// Global convenience API (delegates to a shared global registry)
// ---------------------------------------------------------------------------
/// Global registry backing the convenience free functions.
static GLOBAL_REGISTRY: = new;
/// Returns the global component registry.
///
/// For single-world use cases where an instance-owned registry is not needed.
/// Multi-world applications should construct and hold their own
/// [`ComponentRegistry`] instances and pass them explicitly to archetype
/// creation paths instead of using this global.
/// Registers component type `T` in the global registry and returns its `ComponentID`.
///
/// ## Purpose
/// Convenience wrapper around the global `ComponentRegistry`.
///
/// For multi-world applications, prefer calling [`ComponentRegistry::register`]
/// directly on the registry instance that will be passed to `Archetype::new`.
///
/// ## Errors
/// Returns an error if:
/// - the registry is frozen,
/// - `COMPONENT_CAP` is exceeded,
/// - the component is zero-sized,
/// - the registry lock is poisoned.
/// Marker trait for component types that are safe to transfer to and from the GPU.
///
/// ## Purpose
/// `GPUPod` marks a component as **plain-old-data (POD)** suitable for:
/// * direct byte-wise copying into GPU buffers,
/// * use inside GPU storage or uniform buffers,
/// * round-tripping between CPU and GPU without transformation.
///
/// ## Safety
/// This trait is **unsafe** because incorrect implementations can cause
/// undefined behaviour on the GPU or silent data corruption.
///
/// Implementors **must guarantee**:
/// * The type has **no padding with uninitialized bytes**.
/// * The memory layout is stable and identical on CPU and GPU.
/// * The type contains **no pointers, references, or heap allocations**.
/// * The type is trivially copyable (`Copy`) and has no drop glue.
/// * The alignment is compatible with GPU storage buffer rules.
///
/// ## Example
/// ```
/// # #[cfg(feature = "gpu")]
/// # {
/// use syren::GPUPod;
///
/// #[repr(C)]
/// #[derive(Copy, Clone)]
/// struct Position {
/// x: f32,
/// y: f32,
/// }
///
/// unsafe impl GPUPod for Position {}
/// # }
/// ```
pub unsafe
/// Registers a component type as GPU-safe and eligible for GPU execution.
///
/// ## Purpose
/// This function is a GPU-aware extension of `register_component` that
/// explicitly marks the component as safe to:
/// * mirror into GPU buffers,
/// * be bound as a storage buffer in compute shaders,
///
/// Internally, this delegates to [`ComponentRegistry::register_gpu`], which
/// sets the `gpu_usage` flag on the component's [`crate::ComponentDesc`].
///
/// ## Requirements
/// * The component type must implement [`GPUPod`].
/// * The component must already satisfy all normal ECS component constraints
/// (non-zero-sized, `'static`, `Send`, `Sync`).
///
/// ## Safety model
/// This function is safe to call, but relies on the **unsafe contract**
/// of [`GPUPod`] being upheld by the caller.
///
/// ## Freezing behaviour
/// This function must be called **before** `freeze_components`.
/// Calling it after the registry is frozen will return an error.
///
/// ## Returns
/// The assigned [`ComponentID`] for the registered component.
///
/// ## Errors
/// Returns an error if:
/// * the component registry is frozen,
/// * the registry lock is poisoned,
/// * the component violates ECS registration constraints.
/// Freezes the global component registry.
///
/// ## Purpose
/// Prevents any further component registration, making component IDs and storage
/// factories stable for archetype construction.
///
/// ## Errors
/// Returns `RegistryError::PoisonedLock` if the registry lock is poisoned.
/// Returns the registered `ComponentID` for type `T`.
///
/// ## Errors
/// Returns `RegistryError::NotRegistered` if `T` is not registered.
/// Returns `RegistryError::PoisonedLock` if the registry lock is poisoned.