-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathmod.rs
More file actions
78 lines (69 loc) · 2.59 KB
/
mod.rs
File metadata and controls
78 lines (69 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use crate::parsing::{NodeFnAttributes, ParsedNodeFn};
use crate::shader_nodes::per_pixel_adjust::PerPixelAdjust;
use proc_macro2::{Ident, TokenStream};
use quote::quote;
use strum::VariantNames;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{Error, Token};
pub mod per_pixel_adjust;
pub const STD_FEATURE_GATE: &str = "std";
pub const SHADER_NODES_FEATURE_GATE: &str = "shader-nodes";
pub fn modify_cfg(attributes: &NodeFnAttributes) -> TokenStream {
let feature_gate = match &attributes.shader_node {
// shader node cfg is done on the mod
Some(ShaderNodeType::ShaderNode) => quote!(),
Some(_) => quote!(feature = #STD_FEATURE_GATE),
None => quote!(),
};
let cfgs: Punctuated<_, Token![,]> = match &attributes.cfg {
None => [&feature_gate].into_iter().collect(),
Some(cfg) => [cfg, &feature_gate].into_iter().collect(),
};
quote!(#[cfg(all(#cfgs))])
}
#[derive(Debug, Clone, VariantNames)]
pub(crate) enum ShaderNodeType {
/// Marker for this node being in a gpu node crate, but not having a gpu implementation. This is distinct from not
/// declaring `shader_node` at all, as it will wrap the CPU node with a `#[cfg(feature = "std")]` feature gate.
None,
/// Marker for this node being a generated gpu node implementation, that should not emit anything to prevent
/// recursively generating more gpu nodes. But it still counts as a gpu node and will get the
/// `#[cfg(feature = "std")]` feature gate around it's impl.
ShaderNode,
PerPixelAdjust(PerPixelAdjust),
}
impl Parse for ShaderNodeType {
fn parse(input: ParseStream) -> syn::Result<Self> {
let ident: Ident = input.parse()?;
Ok(match ident.to_string().as_str() {
"None" => ShaderNodeType::None,
"PerPixelAdjust" => ShaderNodeType::PerPixelAdjust(PerPixelAdjust::parse(input)?),
_ => return Err(Error::new_spanned(&ident, format!("attr 'shader_node' must be one of {:?}", Self::VARIANTS))),
})
}
}
pub trait ShaderCodegen {
fn codegen(&self, parsed: &ParsedNodeFn) -> syn::Result<ShaderTokens>;
}
impl ShaderCodegen for ShaderNodeType {
fn codegen(&self, parsed: &ParsedNodeFn) -> syn::Result<ShaderTokens> {
match self {
ShaderNodeType::None | ShaderNodeType::ShaderNode => (),
_ => {
if parsed.is_async {
return Err(Error::new_spanned(&parsed.fn_name, "Shader nodes must not be async"));
}
}
}
match self {
ShaderNodeType::None | ShaderNodeType::ShaderNode => Ok(ShaderTokens::default()),
ShaderNodeType::PerPixelAdjust(x) => x.codegen(parsed),
}
}
}
#[derive(Clone, Default)]
pub struct ShaderTokens {
pub shader_entry_point: TokenStream,
pub gpu_node: TokenStream,
}