Add include_spv!() macro, donated by Ralith (#26)

This commit is contained in:
Jay Oster 2019-10-27 19:50:15 -07:00 committed by GitHub
parent 994cc9a03c
commit 5795fa7943
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 24 deletions

1
Cargo.lock generated
View file

@ -702,7 +702,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "pixels"
version = "0.0.1"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"pixels-mocks 0.1.0",

View file

@ -11,7 +11,6 @@ categories = ["graphics", "rendering"]
license = "MIT"
[dependencies]
byteorder = "1.3"
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs", rev = "012d08d64de924da93289c2b51fb06b22d7348cf" }
[dev-dependencies]

View file

@ -16,14 +16,15 @@ use std::error::Error as StdError;
use std::fmt;
use std::rc::Rc;
pub use crate::macros::*;
pub use crate::render_pass::{BoxedRenderPass, Device, Queue, RenderPass};
use crate::renderers::Renderer;
pub use wgpu;
use wgpu::{Extent3d, TextureView};
mod macros;
mod render_pass;
pub use render_pass::{BoxedRenderPass, Device, Queue, RenderPass};
mod renderers;
use renderers::Renderer;
type RenderPassFactory = Box<dyn Fn(Device, Queue, &TextureView, &Extent3d) -> BoxedRenderPass>;

42
src/macros.rs Normal file
View file

@ -0,0 +1,42 @@
//! Provides a macro and type for including SPIR-V shaders in const data.
//!
//! In an ideal world, a shader will be compiled at build-time directly into the executable. This
//! is opposed to the typical method of including a shader, which reads a GLSL source code file
//! from the file system at start, compiles it, and sends it to the GPU. That process adds a
//! non-trivial amount of time to startup, and additional error handling code at runtime.
//!
//! This macro moves all of that complexity to build-time. At least for the SPIR-V part of the
//! shader pipeline. (`gfx-hal` backends have their own SPIR-V-to-native compilers at runtime.)
//!
//! Cribbed with permission from Ralith
//! See: https://github.com/MaikKlein/ash/pull/245
/// Include correctly aligned and typed precompiled SPIR-V
///
/// Does not account for endianness mismatches between the SPIR-V file and the target. See
/// [`wgpu::read_spirv`] for a more general solution.
#[macro_export]
macro_rules! include_spv {
($path:expr) => {
&$crate::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 = 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)
}
}
}
#[repr(align(4))]
#[doc(hidden)]
pub struct Align4<T: ?Sized>(pub T);

View file

@ -1,8 +1,8 @@
use byteorder::{ByteOrder, LittleEndian};
use std::fmt;
use std::rc::Rc;
use wgpu::{self, Extent3d, TextureView};
use crate::include_spv;
use crate::render_pass::{BoxedRenderPass, Device, Queue, RenderPass};
/// Renderer implements [`RenderPass`].
@ -24,24 +24,8 @@ impl Renderer {
texture_view: &TextureView,
texture_size: &Extent3d,
) -> BoxedRenderPass {
let vert_spv = include_bytes!("../shaders/vert.spv");
let mut vert = Vec::new();
vert.resize_with(
vert_spv.len() / std::mem::size_of::<u32>(),
Default::default,
);
LittleEndian::read_u32_into(vert_spv, &mut vert);
let frag_spv = include_bytes!("../shaders/frag.spv");
let mut frag = Vec::new();
frag.resize_with(
frag_spv.len() / std::mem::size_of::<u32>(),
Default::default,
);
LittleEndian::read_u32_into(frag_spv, &mut frag);
let vs_module = device.create_shader_module(&vert);
let fs_module = device.create_shader_module(&frag);
let vs_module = device.create_shader_module(include_spv!("../shaders/vert.spv"));
let fs_module = device.create_shader_module(include_spv!("../shaders/frag.spv"));
// Create a texture sampler with nearest neighbor
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {