diff --git a/ash/src/lib.rs b/ash/src/lib.rs index a3addf6..d984711 100644 --- a/ash/src/lib.rs +++ b/ash/src/lib.rs @@ -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; diff --git a/ash/src/util.rs b/ash/src/util.rs index 8abd572..178da36 100644 --- a/ash/src/util.rs +++ b/ash/src/util.rs @@ -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(x: &mut R) -> io::Result> { + 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::::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) +}