Skip to content

Commit

Permalink
Helper macro for including precompiled SPIR-V
Browse files Browse the repository at this point in the history
Should help suppress the temptation to court UB via naive
include_bytes. Implementation placed in the root because macros are
always imported via the root and it'd be weird for the returned type
to not be beside it.
  • Loading branch information
Ralith committed Oct 28, 2019
1 parent e67df26 commit ba79eea
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 11 deletions.
27 changes: 27 additions & 0 deletions ash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,36 @@ impl<'r, T> RawPtr<T> for Option<&'r T> {
}
}

/// Include correctly aligned and typed precompiled SPIR-V
///
/// Does not account for endianness mismatches between the SPIR-V file and the target. See
/// `util::read_spv` for a more general solution.
#[macro_export]
macro_rules! include_spv {
($path:expr) => {
&$crate::util::Align4(*include_bytes!($path)) as &$crate::Spirv
};
}

/// Type returned by `include_spv`, convertible to `&[u32]`
///
/// The definition of this type is unstable.
pub type Spirv = util::Align4<[u8]>;

impl std::ops::Deref for Spirv {
type Target = [u32];
fn deref(&self) -> &[u32] {
#[allow(clippy::cast_ptr_alignment)]
unsafe {
std::slice::from_raw_parts(self.0.as_ptr() as *const u32, self.0.len() / 4)
}
}
}

#[cfg(test)]
mod tests {
use super::vk;

#[test]
fn test_ptr_chains() {
let mut variable_pointers = vk::PhysicalDeviceVariablePointerFeatures::builder();
Expand Down
4 changes: 4 additions & 0 deletions ash/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,7 @@ pub fn read_spv<R: io::Read + io::Seek>(x: &mut R) -> io::Result<Vec<u32>> {
}
Ok(result)
}

#[repr(align(4))]
#[doc(hidden)]
pub struct Align4<T: ?Sized>(pub T);
16 changes: 5 additions & 11 deletions examples/src/bin/triangle.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use ash::util::*;
use ash::vk;
use ash::{include_spv, vk, Spirv};
use examples::*;
use std::default::Default;
use std::ffi::CString;
use std::io::Cursor;
use std::mem;
use std::mem::align_of;

Expand Down Expand Up @@ -198,17 +197,12 @@ fn main() {
base.device
.bind_buffer_memory(vertex_input_buffer, vertex_input_buffer_memory, 0)
.unwrap();
let mut vertex_spv_file =
Cursor::new(&include_bytes!("../../shader/triangle/vert.spv")[..]);
let mut frag_spv_file = Cursor::new(&include_bytes!("../../shader/triangle/frag.spv")[..]);

let vertex_code =
read_spv(&mut vertex_spv_file).expect("Failed to read vertex shader spv file");
let vertex_shader_info = vk::ShaderModuleCreateInfo::builder().code(&vertex_code);
const VERTEX_CODE: &Spirv = include_spv!("../../shader/triangle/vert.spv");
let vertex_shader_info = vk::ShaderModuleCreateInfo::builder().code(VERTEX_CODE);

let frag_code =
read_spv(&mut frag_spv_file).expect("Failed to read fragment shader spv file");
let frag_shader_info = vk::ShaderModuleCreateInfo::builder().code(&frag_code);
const FRAG_CODE: &Spirv = include_spv!("../../shader/triangle/frag.spv");
let frag_shader_info = vk::ShaderModuleCreateInfo::builder().code(FRAG_CODE);

let vertex_shader_module = base
.device
Expand Down

0 comments on commit ba79eea

Please sign in to comment.