1 use super::common::GearId; |
1 use super::common::GearId; |
2 use std::{ |
2 use std::{ |
3 any::TypeId, |
3 any::TypeId, |
4 fmt::{Debug, Error, Formatter}, |
4 fmt::{Debug, Error, Formatter}, |
5 marker::PhantomData, |
5 marker::PhantomData, |
6 mem::{size_of, MaybeUninit}, |
6 mem::{align_of, size_of, MaybeUninit}, |
7 num::NonZeroU16, |
7 num::NonZeroU16, |
8 ptr::{copy_nonoverlapping, null_mut, NonNull}, |
8 ptr::{copy_nonoverlapping, null_mut, NonNull}, |
9 slice, |
9 slice, |
10 }; |
10 }; |
11 |
11 |
115 write!(f, "}}\n") |
115 write!(f, "}}\n") |
116 } |
116 } |
117 } |
117 } |
118 |
118 |
119 impl DataBlock { |
119 impl DataBlock { |
120 fn new(mask: u64, element_sizes: &[u16]) -> Self { |
120 fn new(mask: u64, element_sizes: &[u16], element_alignments: &[u8]) -> Self { |
|
121 let total_padding: usize = element_alignments.iter().map(|x| *x as usize).sum(); |
121 let total_size: u16 = element_sizes |
122 let total_size: u16 = element_sizes |
122 .iter() |
123 .iter() |
123 .enumerate() |
124 .enumerate() |
124 .filter(|(i, _)| mask & (1 << *i as u64) != 0) |
125 .filter(|(i, _)| mask & (1 << *i as u64) != 0) |
125 .map(|(_, size)| *size) |
126 .map(|(_, size)| *size) |
126 .sum(); |
127 .sum(); |
127 let max_elements = (BLOCK_SIZE / (total_size as usize + size_of::<GearId>())) as u16; |
128 let max_elements = |
128 |
129 ((BLOCK_SIZE - total_padding) / (total_size as usize + size_of::<GearId>())) as u16; |
|
130 |
|
131 //ensure the block memory is aligned to GearId |
|
132 let tmp_data: Box<[GearId; BLOCK_SIZE / size_of::<GearId>()]> = |
|
133 Box::new(unsafe { MaybeUninit::uninit().assume_init() }); |
129 let mut data: Box<[u8; BLOCK_SIZE]> = |
134 let mut data: Box<[u8; BLOCK_SIZE]> = |
130 Box::new(unsafe { MaybeUninit::uninit().assume_init() }); |
135 unsafe { Box::from_raw(Box::into_raw(tmp_data) as *mut [u8; BLOCK_SIZE]) }; |
|
136 |
131 let mut blocks = [None; 64]; |
137 let mut blocks = [None; 64]; |
132 let mut offset = size_of::<GearId>() * max_elements as usize; |
138 let mut address = unsafe { |
|
139 data.as_mut_ptr() |
|
140 .add(size_of::<GearId>() * max_elements as usize) |
|
141 }; |
133 |
142 |
134 for i in 0..element_sizes.len() { |
143 for i in 0..element_sizes.len() { |
135 if mask & (1 << i as u64) != 0 { |
144 if mask & (1 << i as u64) != 0 { |
136 blocks[i] = Some(NonNull::new(data[offset..].as_mut_ptr()).unwrap()); |
145 unsafe { |
137 offset += element_sizes[i] as usize * max_elements as usize; |
146 address = address.add(address.align_offset(element_alignments[i] as usize)); |
138 } |
147 blocks[i] = Some(NonNull::new_unchecked(address)); |
139 } |
148 address = address.add(element_sizes[i] as usize * max_elements as usize) |
|
149 }; |
|
150 } |
|
151 } |
|
152 |
140 Self { |
153 Self { |
141 elements_count: 0, |
154 elements_count: 0, |
142 max_elements, |
155 max_elements, |
143 data, |
156 data, |
144 component_blocks: blocks, |
157 component_blocks: blocks, |
214 types: Vec<TypeId>, |
227 types: Vec<TypeId>, |
215 tags: Vec<TypeId>, |
228 tags: Vec<TypeId>, |
216 blocks: Vec<DataBlock>, |
229 blocks: Vec<DataBlock>, |
217 block_masks: Vec<BlockMask>, |
230 block_masks: Vec<BlockMask>, |
218 element_sizes: Box<[u16; 64]>, |
231 element_sizes: Box<[u16; 64]>, |
|
232 element_alignments: Box<[u8; 64]>, |
219 lookup: Box<[LookupEntry]>, |
233 lookup: Box<[LookupEntry]>, |
220 } |
234 } |
221 |
235 |
222 impl GearDataManager { |
236 impl GearDataManager { |
223 pub fn new() -> Self { |
237 pub fn new() -> Self { |
225 types: Vec::with_capacity(64), |
239 types: Vec::with_capacity(64), |
226 tags: Vec::with_capacity(64), |
240 tags: Vec::with_capacity(64), |
227 blocks: vec![], |
241 blocks: vec![], |
228 block_masks: vec![], |
242 block_masks: vec![], |
229 element_sizes: Box::new([0; 64]), |
243 element_sizes: Box::new([0; 64]), |
|
244 element_alignments: Box::new([0; 64]), |
230 lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(), |
245 lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(), |
231 } |
246 } |
232 } |
247 } |
233 |
248 |
234 #[inline] |
249 #[inline] |
386 index as u16 |
401 index as u16 |
387 } else { |
402 } else { |
388 self.blocks.push(DataBlock::new( |
403 self.blocks.push(DataBlock::new( |
389 mask.type_mask, |
404 mask.type_mask, |
390 &self.element_sizes[0..self.types.len()], |
405 &self.element_sizes[0..self.types.len()], |
|
406 &self.element_alignments[0..self.types.len()], |
391 )); |
407 )); |
392 self.block_masks.push(mask); |
408 self.block_masks.push(mask); |
393 (self.blocks.len() - 1) as u16 |
409 (self.blocks.len() - 1) as u16 |
394 } |
410 } |
395 } |
411 } |