glsl_to_spirv_macros_impl/
lib.rs1extern crate glsl_to_spirv;
2extern crate proc_macro;
3extern crate syn;
4#[macro_use]
5extern crate quote;
6
7use proc_macro::TokenStream;
8use std::fs::File;
9use std::io::Read;
10use std::path::Path;
11
12#[proc_macro_derive(GLSLEmbedImpl, attributes(src, path, ty))]
33pub fn macro_impl(input: TokenStream) -> TokenStream {
34 let source = input.to_string();
35 let ast = syn::parse_macro_input(&source).ok().expect("Invalid shader macro arguments - you must specify a single string literal.");
36 let mut source_string = None;
37 let mut path_string = None;
38 let mut ty_string = None;
39 for attr in &ast.attrs {
40 match attr.value {
41 syn::MetaItem::NameValue(ref ident, syn::Lit::Str(ref value, _)) => {
42 if ident == "src" {
43 source_string = Some(value.clone());
44 } else if ident == "path" {
45 path_string = Some(value.clone());
46 } else if ident == "ty" {
47 ty_string = Some(value.clone());
48 } else {
49 panic!("Invalid shader macro arguments - you must specify a single string literal.")
50 }
51 }
52 syn::MetaItem::List(ref ident, _) if ident == "allow" => {}
53 _ => panic!("Invalid shader macro arguments - you must specify a single string literal.")
54 }
55 };
56 let source_string = if let Some(source_string) = source_string {
57 source_string
58 } else {
59 let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or(".".into());
60 let path = path_string.unwrap();
61 let full_path = Path::new(&root).join(&path);
62 let mut s = String::new();
63 File::open(full_path)
64 .and_then(|mut file| file.read_to_string(&mut s))
65 .expect(&format!("Error reading shader source file: {:?}", path));
66 s
67 };
68 let ty = match &*ty_string.unwrap() {
69 "vs" => glsl_to_spirv::ShaderType::Vertex,
70 "fs" => glsl_to_spirv::ShaderType::Fragment,
71 "gs" => glsl_to_spirv::ShaderType::Geometry,
72 "tcs" => glsl_to_spirv::ShaderType::TessellationControl,
73 "tes" => glsl_to_spirv::ShaderType::TessellationEvaluation,
74 "cs" => glsl_to_spirv::ShaderType::Compute,
75 _ => panic!()
76 };
77 let mut spirv_file: File = match glsl_to_spirv::compile(&source_string, ty) {
78 Ok(compiled) => compiled,
79 Err(message) => panic!("{}\nfailed to compile shader", message),
80 };
81 let mut spirv_data = Vec::new();
82 spirv_file.read_to_end(&mut spirv_data).unwrap();
83 let count = spirv_data.len();
84 let expanded = quote! {
85 static DATA: [u8; #count] = #spirv_data;
86 };
87
88 expanded.parse().unwrap()
89}