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