1use crate::vk;
2use std::iter::Iterator;
3use std::marker::PhantomData;
4use std::mem::size_of;
5use std::os::raw::c_void;
6use std::{io, slice};
7
8#[derive(Debug, Clone)]
16pub struct Align<T> {
17 ptr: *mut c_void,
18 elem_size: vk::DeviceSize,
19 size: vk::DeviceSize,
20 _m: PhantomData<T>,
21}
22
23#[derive(Debug)]
24pub struct AlignIter<'a, T: 'a> {
25 align: &'a mut Align<T>,
26 current: vk::DeviceSize,
27}
28
29impl<T: Copy> Align<T> {
30 pub fn copy_from_slice(&mut self, slice: &[T]) {
31 use std::slice::from_raw_parts_mut;
32 if self.elem_size == size_of::<T>() as u64 {
33 unsafe {
34 let mapped_slice = from_raw_parts_mut(self.ptr as *mut T, slice.len());
35 mapped_slice.copy_from_slice(slice);
36 }
37 } else {
38 for (i, val) in self.iter_mut().enumerate().take(slice.len()) {
39 *val = slice[i];
40 }
41 }
42 }
43}
44
45fn calc_padding(adr: vk::DeviceSize, align: vk::DeviceSize) -> vk::DeviceSize {
46 (align - adr % align) % align
47}
48
49impl<T> Align<T> {
50 pub unsafe fn new(ptr: *mut c_void, alignment: vk::DeviceSize, size: vk::DeviceSize) -> Self {
51 let padding = calc_padding(size_of::<T>() as vk::DeviceSize, alignment);
52 let elem_size = size_of::<T>() as vk::DeviceSize + padding;
53 assert!(calc_padding(size, alignment) == 0, "size must be aligned");
54 Self {
55 ptr,
56 elem_size,
57 size,
58 _m: PhantomData,
59 }
60 }
61
62 pub fn iter_mut(&mut self) -> AlignIter<T> {
63 AlignIter {
64 current: 0,
65 align: self,
66 }
67 }
68}
69
70impl<'a, T: Copy + 'a> Iterator for AlignIter<'a, T> {
71 type Item = &'a mut T;
72 fn next(&mut self) -> Option<Self::Item> {
73 if self.current == self.align.size {
74 return None;
75 }
76 unsafe {
77 let ptr = (self.align.ptr as *mut u8).offset(self.current as isize) as *mut T;
79 self.current += self.align.elem_size;
80 Some(&mut *ptr)
81 }
82 }
83}
84
85pub fn read_spv<R: io::Read + io::Seek>(x: &mut R) -> io::Result<Vec<u32>> {
105 let size = x.seek(io::SeekFrom::End(0))?;
106 if size % 4 != 0 {
107 return Err(io::Error::new(
108 io::ErrorKind::InvalidData,
109 "input length not divisible by 4",
110 ));
111 }
112 if size > usize::max_value() as u64 {
113 return Err(io::Error::new(io::ErrorKind::InvalidData, "input too long"));
114 }
115 let words = (size / 4) as usize;
116 let mut result = vec![0u32; words];
120 x.seek(io::SeekFrom::Start(0))?;
121 x.read_exact(unsafe { slice::from_raw_parts_mut(result.as_mut_ptr() as *mut u8, words * 4) })?;
122 const MAGIC_NUMBER: u32 = 0x0723_0203;
123 if !result.is_empty() && result[0] == MAGIC_NUMBER.swap_bytes() {
124 for word in &mut result {
125 *word = word.swap_bytes();
126 }
127 }
128 if result.is_empty() || result[0] != MAGIC_NUMBER {
129 return Err(io::Error::new(
130 io::ErrorKind::InvalidData,
131 "input missing SPIR-V magic number",
132 ));
133 }
134 Ok(result)
135}