SPIR-V reading helper

This commit is contained in:
Benjamin Saunders 2018-12-07 00:59:06 -08:00
parent bcaa563c5b
commit 4546b26736
2 changed files with 57 additions and 0 deletions

View file

@ -1,6 +1,7 @@
#[macro_use]
extern crate lazy_static;
extern crate shared_library;
pub use device::Device;
pub use entry::{Entry, InstanceError, LoadingError};
pub use instance::Instance;

View file

@ -2,6 +2,7 @@ use std::iter::Iterator;
use std::marker::PhantomData;
use std::mem::size_of;
use std::os::raw::c_void;
use std::{io, slice};
use vk;
/// `Align` handles dynamic alignment. The is useful for dynamic uniform buffers where
@ -80,3 +81,58 @@ impl<'a, T: Copy + 'a> Iterator for AlignIter<'a, T> {
}
}
}
/// Decode SPIR-V from bytes.
///
/// This function handles SPIR-V of arbitrary endianness gracefully, and returns correctly aligned
/// storage.
///
/// # Examples
/// ```no_run
/// // Decode SPIR-V from a file
/// let mut file = std::fs::File::open("/path/to/shader.spv").unwrap();
/// let words = ash::util::read_spv(&mut file).unwrap();
/// ```
/// ```
/// // Decode SPIR-V from memory
/// const SPIRV: &[u8] = &[
/// // ...
/// # 0x03, 0x02, 0x23, 0x07,
/// ];
/// let words = ash::util::read_spv(&mut std::io::Cursor::new(&SPIRV[..])).unwrap();
/// ```
pub fn read_spv<R: io::Read + io::Seek>(x: &mut R) -> io::Result<Vec<u32>> {
let size = x.seek(io::SeekFrom::End(0))?;
if size % 4 != 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"input length not divisible by 4",
));
}
if size > usize::max_value() as u64 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "input too long"));
}
let words = (size / 4) as usize;
let mut result = Vec::<u32>::with_capacity(words);
x.seek(io::SeekFrom::Start(0))?;
unsafe {
x.read_exact(slice::from_raw_parts_mut(
result.as_mut_ptr() as *mut u8,
words * 4,
))?;
result.set_len(words);
}
const MAGIC_NUMBER: u32 = 0x07230203;
if result.len() > 0 && result[0] == MAGIC_NUMBER.swap_bytes() {
for word in &mut result {
*word = word.swap_bytes();
}
}
if result.len() == 0 || result[0] != MAGIC_NUMBER {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"input missing SPIR-V magic number",
));
}
Ok(result)
}