diff --git a/Cargo.toml b/Cargo.toml index 5ce770ad..064edac3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "vk-sys", "vulkano", "vulkano-shaders", + "vulkano-shader-derive", "vulkano-win" ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 56731cf9..8a424d8d 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -6,6 +6,7 @@ build = "build.rs" [dependencies] vulkano = { path = "../vulkano" } +vulkano-shader-derive = { path = "../vulkano-shader-derive" } vulkano-win = { path = "../vulkano-win" } cgmath = "0.12.0" image = "0.6.1" diff --git a/examples/build.rs b/examples/build.rs index 37d1adfd..9218c5be 100644 --- a/examples/build.rs +++ b/examples/build.rs @@ -3,8 +3,6 @@ extern crate vulkano_shaders; fn main() { // building the shaders used in the examples vulkano_shaders::build_glsl_shaders([ - ("src/bin/triangle_vs.glsl", vulkano_shaders::ShaderType::Vertex), - ("src/bin/triangle_fs.glsl", vulkano_shaders::ShaderType::Fragment), ("src/bin/teapot_vs.glsl", vulkano_shaders::ShaderType::Vertex), ("src/bin/teapot_fs.glsl", vulkano_shaders::ShaderType::Fragment), ("src/bin/image_vs.glsl", vulkano_shaders::ShaderType::Vertex), diff --git a/examples/src/bin/triangle.rs b/examples/src/bin/triangle.rs index 5752fde8..5701c06c 100644 --- a/examples/src/bin/triangle.rs +++ b/examples/src/bin/triangle.rs @@ -28,6 +28,8 @@ extern crate winit; // winit, and winit doesn't know about vulkano, so import a crate that will provide a link between // the two. extern crate vulkano_win; +#[macro_use] +extern crate vulkano_shader_derive; use vulkano_win::VkSurfaceBuild; @@ -213,9 +215,40 @@ fn main() { // can now use to load the shader. // // Because of some restrictions with the `include!` macro, we need to use a module. - mod vs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/triangle_vs.glsl")} } + mod vs { + #[derive(VulkanoShader)] + #[ty = "vertex"] + #[src = " +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_450pack : enable + +layout(location = 0) in vec2 position; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); +}"] + struct Dummy; + } let vs = vs::Shader::load(&device).expect("failed to create shader module"); - mod fs { include!{concat!(env!("OUT_DIR"), "/shaders/src/bin/triangle_fs.glsl")} } + + mod fs { + #[derive(VulkanoShader)] + #[ty = "fragment"] + #[src = " +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_450pack : enable + +layout(location = 0) out vec4 f_color; + +void main() { + f_color = vec4(1.0, 0.0, 0.0, 1.0); +}"] + struct Dummy; + } let fs = fs::Shader::load(&device).expect("failed to create shader module"); // At this point, OpenGL initialization would be finished. However in Vulkan it is not. OpenGL diff --git a/examples/src/bin/triangle_fs.glsl b/examples/src/bin/triangle_fs.glsl deleted file mode 100644 index 280c28d2..00000000 --- a/examples/src/bin/triangle_fs.glsl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -#version 450 - -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_shading_language_450pack : enable - -layout(location = 0) out vec4 f_color; - -void main() { - f_color = vec4(1.0, 0.0, 0.0, 1.0); -} diff --git a/examples/src/bin/triangle_vs.glsl b/examples/src/bin/triangle_vs.glsl deleted file mode 100644 index bf691a42..00000000 --- a/examples/src/bin/triangle_vs.glsl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -#version 450 - -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_shading_language_450pack : enable - -layout(location = 0) in vec2 position; - -void main() { - gl_Position = vec4(position, 0.0, 1.0); -} diff --git a/vulkano-shader-derive/Cargo.toml b/vulkano-shader-derive/Cargo.toml new file mode 100644 index 00000000..18aadb18 --- /dev/null +++ b/vulkano-shader-derive/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "vulkano-shader-derive" +version = "0.1.0" +authors = ["Pierre Krieger "] + +[lib] +name = "vulkano_shader_derive" +proc-macro = true + +[dependencies] +glsl-to-spirv = { version = "0.1.2", path = "../glsl-to-spirv" } +syn = { version = "0.10", features = ["aster", "visit"] } +vulkano-shaders = { version = "0.3", path = "../vulkano-shaders" } diff --git a/vulkano-shader-derive/src/lib.rs b/vulkano-shader-derive/src/lib.rs new file mode 100644 index 00000000..00924f6f --- /dev/null +++ b/vulkano-shader-derive/src/lib.rs @@ -0,0 +1,46 @@ +extern crate glsl_to_spirv; +extern crate proc_macro; +extern crate syn; +extern crate vulkano_shaders; + +use proc_macro::TokenStream; + +#[proc_macro_derive(VulkanoShader, attributes(src, ty))] +pub fn derive(input: TokenStream) -> TokenStream { + let syn_item = syn::parse_macro_input(&input.to_string()).unwrap(); + + let src = syn_item.attrs.iter().filter_map(|attr| { + match attr.value { + syn::MetaItem::NameValue(ref i, syn::Lit::Str(ref val, _)) if i == "src" => { + Some(val.clone()) + }, + _ => None + } + }).next().expect("Can't find `src` attribute ; put #[src = \"...\"] for example."); + + let ty_str = syn_item.attrs.iter().filter_map(|attr| { + match attr.value { + syn::MetaItem::NameValue(ref i, syn::Lit::Str(ref val, _)) if i == "ty" => { + Some(val.clone()) + }, + _ => None + } + }).next().expect("Can't find `ty` attribute ; put #[ty = \"vertex\"] for example."); + + let ty = match &ty_str[..] { + "vertex" => glsl_to_spirv::ShaderType::Vertex, + "fragment" => glsl_to_spirv::ShaderType::Fragment, + "geometry" => glsl_to_spirv::ShaderType::Geometry, + "tess_ctrl" => glsl_to_spirv::ShaderType::TessellationControl, + "tess_eval" => glsl_to_spirv::ShaderType::TessellationEvaluation, + "compute" => glsl_to_spirv::ShaderType::Compute, + _ => panic!("Unexpected shader type ; valid values: vertex, fragment, geometry, tess_ctrl, tess_eval, compute") + }; + + let spirv_data = match glsl_to_spirv::compile(&src, ty) { + Ok(compiled) => compiled, + Err(message) => panic!("{}\nfailed to compile shader", message), + }; + + vulkano_shaders::reflect("Shader", spirv_data).unwrap().parse().unwrap() +}