Skip to content

Commit

Permalink
Add root_path_env property to shaders macro (vulkano-rs#2180)
Browse files Browse the repository at this point in the history
* shaders: minor fix that some Vecs were always allocated with capacity of 0

* shaders: add root_path_env property to allow loading shaders generated by a build script

* shaders: Apply root_path_env suggestions from code review

Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>

* shaders: added root_path_env docs about env vars specified by a build script

---------

Co-authored-by: Firestar99 <4696087-firestar99@users.noreply.gitlab.com>
Co-authored-by: marc0246 <40955683+marc0246@users.noreply.github.com>
  • Loading branch information
3 people authored and hakolao committed Feb 20, 2024
1 parent c8903aa commit 38bbcc3
Showing 1 changed file with 53 additions and 5 deletions.
58 changes: 53 additions & 5 deletions vulkano-shaders/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,20 @@
//! in conjunction with the `src` or `path` field. This allows using shaders compiled through a
//! separate build system.
//!
//! ## `root_path_env: "..."`
//!
//! Instead of searching relative to your `Cargo.toml`, search relative to some other folder
//! specified by this env variable. The intended use case is using `OUT_DIR` to be able to load
//! shaders generated by your build script. Defaults to `CARGO_MANIFEST_DIR` corresponding to the
//! folder of your `Cargo.toml`.
//!
//! See [`cargo-env-vars`] for a full set of env variables set by cargo. It is also possible to
//! specify env variables from within the build script using the following:
//! ```rust
//! # let shader_out_dir = "";
//! println!("cargo:rustc-env=SHADER_OUT_DIR={shader_out_dir}");
//! ```
//!
//! ## `shaders: { first: { src: "...", ty: "..." }, ... }`
//!
//! With these options the user can compile several shaders in a single macro invocation. Each
Expand Down Expand Up @@ -200,6 +214,7 @@
//! | `shaderc-build-from-source` | Build the `shaderc` library from source when compiling. |
//! | `shaderc-debug` | Compile shaders with debug information included. |
//!
//! [`cargo-env-vars`]: https://doc.rust-lang.org/cargo/reference/environment-variables.html
//! [cargo-expand]: https://github.com/dtolnay/cargo-expand
//! [`ShaderModule::from_words_with_data`]: vulkano::shader::ShaderModule::from_words_with_data
//! [`SpecializationConstants`]: vulkano::shader::SpecializationConstants
Expand Down Expand Up @@ -247,12 +262,34 @@ pub fn shader(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
}

fn shader_inner(mut input: MacroInput) -> Result<TokenStream> {
let root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());
let (root, relative_path_error_msg) = match input.root_path_env.as_ref() {
None => (
env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()),
"to your Cargo.toml".to_owned(),
),
Some(root_path_env) => {
let root = match env::var(root_path_env.value()) {
Ok(e) => e,
Err(e) => {
bail!(
root_path_env,
"failed to fetch environment variable: {e}; typical parameters are \
`OUT_DIR` to gather results from your build script, or left default to \
search relative to your Cargo.toml",
)
}
};
let env = root_path_env.value();
let error = format!("to the path `{root}` specified by the env variable `{env:?}`");
(root, error)
}
};

let root_path = Path::new(&root);
let shaders = mem::take(&mut input.shaders); // yoink

let mut shaders_code = Vec::with_capacity(input.shaders.len());
let mut types_code = Vec::with_capacity(input.shaders.len());
let mut shaders_code = Vec::with_capacity(shaders.len());
let mut types_code = Vec::with_capacity(shaders.len());
let mut type_registry = TypeRegistry::default();

for (name, (shader_kind, source_kind)) in shaders {
Expand All @@ -273,7 +310,7 @@ fn shader_inner(mut input: MacroInput) -> Result<TokenStream> {
bail!(
path,
"file `{full_path:?}` was not found, note that the path must be relative \
to your Cargo.toml",
{relative_path_error_msg}",
);
}

Expand Down Expand Up @@ -302,7 +339,7 @@ fn shader_inner(mut input: MacroInput) -> Result<TokenStream> {
bail!(
path,
"file `{full_path:?}` was not found, note that the path must be relative \
to your Cargo.toml",
{relative_path_error_msg}",
);
}

Expand Down Expand Up @@ -350,6 +387,7 @@ enum SourceKind {
}

struct MacroInput {
root_path_env: Option<LitStr>,
include_directories: Vec<PathBuf>,
macro_defines: Vec<(String, String)>,
shared_constants: bool,
Expand All @@ -365,6 +403,7 @@ impl MacroInput {
#[cfg(test)]
fn empty() -> Self {
MacroInput {
root_path_env: None,
include_directories: Vec::new(),
macro_defines: Vec::new(),
shared_constants: false,
Expand All @@ -382,6 +421,7 @@ impl Parse for MacroInput {
fn parse(input: ParseStream<'_>) -> Result<Self> {
let root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into());

let mut root_path_env = None;
let mut include_directories = Vec::new();
let mut macro_defines = Vec::new();
let mut shared_constants = None;
Expand Down Expand Up @@ -583,6 +623,13 @@ impl Parse for MacroInput {
}
}
}
"root_path_env" => {
let lit = input.parse::<LitStr>()?;
if root_path_env.is_some() {
bail!(lit, "field `root_path_env` is already defined");
}
root_path_env = Some(lit);
}
"include" => {
let in_brackets;
bracketed!(in_brackets in input);
Expand Down Expand Up @@ -709,6 +756,7 @@ impl Parse for MacroInput {
}

Ok(MacroInput {
root_path_env,
include_directories,
macro_defines,
shared_constants: shared_constants.unwrap_or(false),
Expand Down

0 comments on commit 38bbcc3

Please sign in to comment.