Compare commits

...

2 Commits

Author SHA1 Message Date
Matthew Gordon 395e641250 Create proc macro for loading single WGSL file
Now to add features.
2024-12-07 12:08:28 -04:00
Matthew Gordon b9f236c5bc Add *~ to .gitignore 2024-12-07 12:07:33 -04:00
4 changed files with 91 additions and 0 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information # MSVC Windows builds of rustc generate these, which store debugging information
*.pdb *.pdb
*~

11
Cargo.toml Normal file
View File

@ -0,0 +1,11 @@
[package]
name = "wgsl-shader-assembler"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
quote = "1.0"
syn = "2.0.90"

2
rust-toolchain.toml Normal file
View File

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

77
src/lib.rs Normal file
View File

@ -0,0 +1,77 @@
#![feature(proc_macro_span)]
use {
proc_macro::TokenStream,
quote::quote,
std::{fs, path::PathBuf},
syn::{parse, LitStr},
};
fn emit_create_shader_module(file_contents: &str) -> TokenStream {
quote! {
wgpu::ShaderModuleDescriptor {
label: None,
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(#file_contents)),
}
}
.into()
}
struct WgslModuleMacroInput {
source_dir: PathBuf,
filename: String,
}
enum Error {
Message(String),
SynError(syn::Error),
}
impl Error {
fn from_message(message: impl Into<String>) -> Self {
Self::Message(message.into())
}
}
impl From<syn::Error> for Error {
fn from(value: syn::Error) -> Self {
Self::SynError(value)
}
}
fn parse_input(token_stream: TokenStream) -> Result<WgslModuleMacroInput, Error> {
let token = token_stream
.clone()
.into_iter()
.next()
.ok_or(Error::from_message("Expected single string literal."))?;
let source_dir = token.span().source_file().path().parent().unwrap().into();
let literal: LitStr = parse(token_stream)?;
let filename = literal.value();
Ok(WgslModuleMacroInput {
source_dir,
filename,
})
}
fn wgsl_module_inner(input_token_stream: TokenStream) -> Result<TokenStream, Error> {
let input = parse_input(input_token_stream)?;
let full_filename = input.source_dir.join(&input.filename);
let contents = fs::read_to_string(&full_filename).map_err(|err| {
Error::from_message(format!(
"Could not open \"{}\": {}",
&full_filename.as_os_str().to_string_lossy(),
err.to_string()
))
})?;
Ok(emit_create_shader_module(&contents))
}
#[proc_macro]
pub fn wgsl_module(input: TokenStream) -> TokenStream {
wgsl_module_inner(input).unwrap_or_else(|err| match err {
Error::Message(message) => quote! { compile_error!(#message) },
Error::SynError(syn_err) => syn_err.into_compile_error(),
}.into())
}