mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 22:34:43 +00:00
add support for shader macro predefines (#1257)
This commit is contained in:
parent
761fb4e633
commit
1b9233d0e7
@ -11,6 +11,7 @@
|
||||
- Update Winit to 0.20.0
|
||||
- Update dependencies: lazy_static, half, syn, quote & proc-macro2
|
||||
- Swapchain can now be recreated with dimensions of corresponding surface using `recreate()`.
|
||||
- Add support for GLSL macro defines to the `shader!` macro.
|
||||
|
||||
# Version 0.14.0 (2019-08-17)
|
||||
|
||||
|
@ -110,7 +110,7 @@ fn include_callback(requested_source_path_raw: &str, directive_type: IncludeType
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compile(path: Option<String>, base_path: &impl AsRef<Path>, code: &str, ty: ShaderKind, include_directories: &[impl AsRef<Path>]) -> Result<CompilationArtifact, String> {
|
||||
pub fn compile(path: Option<String>, base_path: &impl AsRef<Path>, code: &str, ty: ShaderKind, include_directories: &[impl AsRef<Path>], macro_defines: &[(impl AsRef<str>, impl AsRef<str>)]) -> Result<CompilationArtifact, String> {
|
||||
let mut compiler = Compiler::new().ok_or("failed to create GLSL compiler")?;
|
||||
let mut compile_options = CompileOptions::new()
|
||||
.ok_or("failed to initialize compile option")?;
|
||||
@ -128,6 +128,10 @@ pub fn compile(path: Option<String>, base_path: &impl AsRef<Path>, code: &str, t
|
||||
recursion_depth, include_directories, path.is_some(), base_path)
|
||||
});
|
||||
|
||||
for (macro_name, macro_value) in macro_defines.iter() {
|
||||
compile_options.add_macro_definition(macro_name.as_ref(), Some(macro_value.as_ref()));
|
||||
}
|
||||
|
||||
let content = compiler
|
||||
.compile_into_spirv(&code, ty, root_source_path, "main", Some(&compile_options))
|
||||
.map_err(|e| e.to_string())?;
|
||||
@ -437,6 +441,7 @@ mod tests {
|
||||
// 12th byte. Since we can't generate code for these types, we should
|
||||
// create an error instead of generating incorrect code.
|
||||
let includes: [PathBuf;0] = [];
|
||||
let defines: [(String, String);0] = [];
|
||||
let comp = compile(None, &Path::new(""), "
|
||||
#version 450
|
||||
struct MyStruct {
|
||||
@ -446,7 +451,7 @@ mod tests {
|
||||
MyStruct s;
|
||||
};
|
||||
void main() {}
|
||||
", ShaderKind::Vertex, &includes).unwrap();
|
||||
", ShaderKind::Vertex, &includes, &defines).unwrap();
|
||||
let doc = parse::parse_spirv(comp.as_binary()).unwrap();
|
||||
let res = std::panic::catch_unwind(|| structs::write_structs(&doc));
|
||||
assert!(res.is_err());
|
||||
@ -454,6 +459,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_trivial_alignment() {
|
||||
let includes: [PathBuf;0] = [];
|
||||
let defines: [(String, String);0] = [];
|
||||
let comp = compile(None, &Path::new(""), "
|
||||
#version 450
|
||||
struct MyStruct {
|
||||
@ -463,7 +469,7 @@ mod tests {
|
||||
MyStruct s;
|
||||
};
|
||||
void main() {}
|
||||
", ShaderKind::Vertex, &includes).unwrap();
|
||||
", ShaderKind::Vertex, &includes, &defines).unwrap();
|
||||
let doc = parse::parse_spirv(comp.as_binary()).unwrap();
|
||||
structs::write_structs(&doc);
|
||||
}
|
||||
@ -472,6 +478,7 @@ mod tests {
|
||||
// This is a workaround suggested in the case of test_bad_alignment,
|
||||
// so we should make sure it works.
|
||||
let includes: [PathBuf;0] = [];
|
||||
let defines: [(String, String);0] = [];
|
||||
let comp = compile(None, &Path::new(""), "
|
||||
#version 450
|
||||
struct Vec3Wrap {
|
||||
@ -484,7 +491,7 @@ mod tests {
|
||||
MyStruct s;
|
||||
};
|
||||
void main() {}
|
||||
", ShaderKind::Vertex, &includes).unwrap();
|
||||
", ShaderKind::Vertex, &includes, &defines).unwrap();
|
||||
let doc = parse::parse_spirv(comp.as_binary()).unwrap();
|
||||
structs::write_structs(&doc);
|
||||
}
|
||||
@ -493,26 +500,29 @@ mod tests {
|
||||
fn test_include_resolution() {
|
||||
let root_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let empty_includes: [PathBuf;0] = [];
|
||||
let defines: [(String, String);0] = [];
|
||||
let _compile_relative = compile(Some(String::from("tests/include_test.glsl")), &root_path, "
|
||||
#version 450
|
||||
#include \"include_dir_a/target_a.glsl\"
|
||||
#include \"include_dir_b/target_b.glsl\"
|
||||
void main() {}
|
||||
", ShaderKind::Vertex, &empty_includes).expect("Cannot resolve include files");
|
||||
", ShaderKind::Vertex, &empty_includes, &defines).expect("Cannot resolve include files");
|
||||
|
||||
let _compile_include_paths = compile(Some(String::from("tests/include_test.glsl")), &root_path, "
|
||||
#version 450
|
||||
#include <target_a.glsl>
|
||||
#include <target_b.glsl>
|
||||
void main() {}
|
||||
", ShaderKind::Vertex,&[root_path.join("tests/include_dir_a"), root_path.join("tests/include_dir_b")]).expect("Cannot resolve include files");
|
||||
", ShaderKind::Vertex,&[root_path.join("tests/include_dir_a"), root_path.join("tests/include_dir_b")],
|
||||
&defines).expect("Cannot resolve include files");
|
||||
|
||||
let _compile_include_paths_with_relative = compile(Some(String::from("tests/include_test.glsl")), &root_path, "
|
||||
#version 450
|
||||
#include <target_a.glsl>
|
||||
#include <../include_dir_b/target_b.glsl>
|
||||
void main() {}
|
||||
", ShaderKind::Vertex,&[root_path.join("tests/include_dir_a")]).expect("Cannot resolve include files");
|
||||
", ShaderKind::Vertex,&[root_path.join("tests/include_dir_a")],
|
||||
&defines).expect("Cannot resolve include files");
|
||||
|
||||
let absolute_path = root_path.join("tests/include_dir_a/target_a.glsl");
|
||||
let absolute_path_str = absolute_path.to_str().expect("Cannot run tests in a folder with non unicode characters");
|
||||
@ -520,12 +530,31 @@ mod tests {
|
||||
#version 450
|
||||
#include \"{}\"
|
||||
void main() {{}}
|
||||
", absolute_path_str), ShaderKind::Vertex, &empty_includes).expect("Cannot resolve include files");
|
||||
", absolute_path_str), ShaderKind::Vertex, &empty_includes, &defines).expect("Cannot resolve include files");
|
||||
|
||||
let _compile_recursive = compile(Some(String::from("tests/include_test.glsl")), &root_path, "
|
||||
#version 450
|
||||
#include <target_c.glsl>
|
||||
void main() {}
|
||||
", ShaderKind::Vertex,&[root_path.join("tests/include_dir_b"), root_path.join("tests/include_dir_c")]).expect("Cannot resolve include files");
|
||||
", ShaderKind::Vertex,&[root_path.join("tests/include_dir_b"), root_path.join("tests/include_dir_c")],
|
||||
&defines).expect("Cannot resolve include files");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_macros() {
|
||||
let empty_includes: [PathBuf;0] = [];
|
||||
let defines= vec![("NAME1", ""), ("NAME2", "58")];
|
||||
let no_defines: [(String, String);0] = [];
|
||||
let need_defines = "
|
||||
#version 450
|
||||
#if defined(NAME1) && NAME2 > 29
|
||||
void main() {}
|
||||
#endif
|
||||
";
|
||||
let compile_no_defines = compile(None, &Path::new(""), need_defines, ShaderKind::Vertex, &empty_includes, &no_defines);
|
||||
assert!(compile_no_defines.is_err());
|
||||
|
||||
let compile_defines = compile(None, &Path::new(""), need_defines, ShaderKind::Vertex, &empty_includes, &defines);
|
||||
compile_defines.expect("Setting shader macros did not work");
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,11 @@
|
||||
//! to specify one or more standard include directories. Relative paths are relative to the
|
||||
//! directory, which contains the source file the `#include "..."` directive is declared in.
|
||||
//!
|
||||
//! ## `define: [("NAME", "VALUE"), ...]
|
||||
//!
|
||||
//! Adds the given macro definitions to the pre-processor. This is equivalent to passing `-DNAME=VALUE`
|
||||
//! on the command line.
|
||||
//!
|
||||
//! ## `dump: true`
|
||||
//!
|
||||
//! The crate fails to compile but prints the generated rust code to stdout.
|
||||
@ -185,6 +190,7 @@ struct MacroInput {
|
||||
shader_kind: ShaderKind,
|
||||
source_kind: SourceKind,
|
||||
include_directories: Vec<String>,
|
||||
macro_defines: Vec<(String, String)>,
|
||||
dump: bool,
|
||||
}
|
||||
|
||||
@ -194,6 +200,7 @@ impl Parse for MacroInput {
|
||||
let mut shader_kind = None;
|
||||
let mut source_kind = None;
|
||||
let mut include_directories = Vec::new();
|
||||
let mut macro_defines = Vec::new();
|
||||
|
||||
while !input.is_empty() {
|
||||
let name: Ident = input.parse()?;
|
||||
@ -233,6 +240,24 @@ impl Parse for MacroInput {
|
||||
let path: LitStr = input.parse()?;
|
||||
source_kind = Some(SourceKind::Path(path.value()));
|
||||
}
|
||||
"define" => {
|
||||
let array_input;
|
||||
bracketed!(array_input in input);
|
||||
|
||||
while !array_input.is_empty() {
|
||||
let tuple_input;
|
||||
parenthesized!(tuple_input in array_input);
|
||||
|
||||
let name: LitStr = tuple_input.parse()?;
|
||||
tuple_input.parse::<Token![,]>()?;
|
||||
let value: LitStr = tuple_input.parse()?;
|
||||
macro_defines.push((name.value(), value.value()));
|
||||
|
||||
if !array_input.is_empty() {
|
||||
array_input.parse::<Token![,]>()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
"include" => {
|
||||
let in_brackets;
|
||||
bracketed!(in_brackets in input);
|
||||
@ -274,7 +299,7 @@ impl Parse for MacroInput {
|
||||
|
||||
let dump = dump.unwrap_or(false);
|
||||
|
||||
Ok(MacroInput { shader_kind, source_kind, include_directories, dump })
|
||||
Ok(MacroInput { shader_kind, source_kind, include_directories, dump, macro_defines })
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,6 +337,6 @@ pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
full_include_path
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let content = codegen::compile(path, &root_path, &source_code, input.shader_kind, &include_paths).unwrap();
|
||||
let content = codegen::compile(path, &root_path, &source_code, input.shader_kind, &include_paths, &input.macro_defines).unwrap();
|
||||
codegen::reflect("Shader", content.as_binary(), input.dump).unwrap().into()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user