From b1a5ab17c8518ae3670d0a056273126a4bbb896c Mon Sep 17 00:00:00 2001 From: firestar99 Date: Tue, 26 Aug 2025 14:10:50 +0200 Subject: [PATCH] node-macro: add `CrateIdent` struct containing resolved crate paths --- Cargo.lock | 1 + node-graph/gcore-shaders/Cargo.toml | 1 + node-graph/gcore-shaders/src/lib.rs | 1 + node-graph/gcore-shaders/src/shaders/mod.rs | 5 ++ node-graph/node-macro/src/codegen.rs | 16 ++----- node-graph/node-macro/src/crate_ident.rs | 46 +++++++++++++++++++ node-graph/node-macro/src/lib.rs | 1 + node-graph/node-macro/src/parsing.rs | 20 ++------ node-graph/node-macro/src/shader_nodes/mod.rs | 7 +-- .../src/shader_nodes/per_pixel_adjust.rs | 38 +++++++-------- 10 files changed, 86 insertions(+), 50 deletions(-) create mode 100644 node-graph/gcore-shaders/src/shaders/mod.rs create mode 100644 node-graph/node-macro/src/crate_ident.rs diff --git a/Cargo.lock b/Cargo.lock index 7189e30817..4efc07dfe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2140,6 +2140,7 @@ dependencies = [ "num-traits", "serde", "specta", + "spirv-std", ] [[package]] diff --git a/node-graph/gcore-shaders/Cargo.toml b/node-graph/gcore-shaders/Cargo.toml index 7278b62acc..6e38c66386 100644 --- a/node-graph/gcore-shaders/Cargo.toml +++ b/node-graph/gcore-shaders/Cargo.toml @@ -35,6 +35,7 @@ glam = { workspace = true } half = { workspace = true, default-features = false } num-derive = { workspace = true } num-traits = { workspace = true } +spirv-std = { workspace = true } # Workspace std dependencies serde = { workspace = true, optional = true } diff --git a/node-graph/gcore-shaders/src/lib.rs b/node-graph/gcore-shaders/src/lib.rs index 9b310ea9d7..b6b681e51f 100644 --- a/node-graph/gcore-shaders/src/lib.rs +++ b/node-graph/gcore-shaders/src/lib.rs @@ -5,6 +5,7 @@ pub mod choice_type; pub mod color; pub mod context; pub mod registry; +pub mod shaders; pub use context::Ctx; pub use glam; diff --git a/node-graph/gcore-shaders/src/shaders/mod.rs b/node-graph/gcore-shaders/src/shaders/mod.rs new file mode 100644 index 0000000000..5e05a3b77e --- /dev/null +++ b/node-graph/gcore-shaders/src/shaders/mod.rs @@ -0,0 +1,5 @@ +pub mod __private { + pub use bytemuck; + pub use glam; + pub use spirv_std; +} diff --git a/node-graph/node-macro/src/codegen.rs b/node-graph/node-macro/src/codegen.rs index 98bb5588a9..6b96e10aea 100644 --- a/node-graph/node-macro/src/codegen.rs +++ b/node-graph/node-macro/src/codegen.rs @@ -1,6 +1,5 @@ use crate::parsing::*; use convert_case::{Case, Casing}; -use proc_macro_crate::FoundCrate; use proc_macro2::TokenStream as TokenStream2; use quote::{ToTokens, format_ident, quote, quote_spanned}; use std::sync::atomic::AtomicU64; @@ -10,7 +9,7 @@ use syn::token::Comma; use syn::{Error, Ident, PatIdent, Token, WhereClause, WherePredicate, parse_quote}; static NODE_ID: AtomicU64 = AtomicU64::new(0); -pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result { +pub(crate) fn generate_node_code(crate_ident: &CrateIdent, parsed: &ParsedNodeFn) -> syn::Result { let ParsedNodeFn { vis, attributes, @@ -24,10 +23,10 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result syn::Result quote!(crate), - FoundCrate::Name(name) => { - let ident = Ident::new(name, proc_macro2::Span::call_site()); - quote!( #ident ) - } - }; - let mut future_idents = Vec::new(); let field_types: Vec<_> = fields @@ -295,7 +286,7 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result, + gcore_shaders: syn::Result, + wgpu_executor: syn::Result, +} + +impl CrateIdent { + pub fn gcore(&self) -> syn::Result<&TokenStream> { + self.gcore.as_ref().map_err(Clone::clone) + } + + pub fn gcore_shaders(&self) -> syn::Result<&TokenStream> { + self.gcore_shaders.as_ref().map_err(Clone::clone) + } + + pub fn wgpu_executor(&self) -> syn::Result<&TokenStream> { + self.wgpu_executor.as_ref().map_err(Clone::clone) + } +} + +impl Default for CrateIdent { + fn default() -> Self { + let find_crate = |orig_name| match crate_name(orig_name) { + Ok(FoundCrate::Itself) => Ok(quote!(crate)), + Ok(FoundCrate::Name(name)) => { + let name = format_ident!("{}", name); + Ok(quote!(::#name)) + } + Err(e) => Err(syn::Error::new(Span::call_site(), &format!("Could not find dependency on `{orig_name}`:\n{e}"))), + }; + + let gcore = find_crate("graphene-core"); + let gcore_shaders = find_crate("graphene-core-shaders").or_else(|eshaders| { + gcore + .as_ref() + .map(Clone::clone) + .map_err(|ecore| syn::Error::new(Span::call_site(), &format!("{ecore}\n\nFallback: {eshaders}"))) + }); + let wgpu_executor = find_crate("wgpu-executor"); + Self { gcore, gcore_shaders, wgpu_executor } + } +} diff --git a/node-graph/node-macro/src/lib.rs b/node-graph/node-macro/src/lib.rs index a944c4f73b..3ff09d3753 100644 --- a/node-graph/node-macro/src/lib.rs +++ b/node-graph/node-macro/src/lib.rs @@ -3,6 +3,7 @@ use proc_macro_error2::proc_macro_error; use syn::GenericParam; mod codegen; +mod crate_ident; mod derive_choice_type; mod parsing; mod shader_nodes; diff --git a/node-graph/node-macro/src/parsing.rs b/node-graph/node-macro/src/parsing.rs index 00e3377f63..81f86107de 100644 --- a/node-graph/node-macro/src/parsing.rs +++ b/node-graph/node-macro/src/parsing.rs @@ -12,6 +12,7 @@ use syn::{ }; use crate::codegen::generate_node_code; +use crate::crate_ident::CrateIdent; use crate::shader_nodes::ShaderNodeType; #[derive(Clone, Debug)] @@ -35,7 +36,6 @@ pub(crate) struct ParsedNodeFn { pub(crate) is_async: bool, pub(crate) fields: Vec, pub(crate) body: TokenStream2, - pub(crate) crate_name: proc_macro_crate::FoundCrate, pub(crate) description: String, } @@ -313,12 +313,6 @@ fn parse_node_fn(attr: TokenStream2, item: TokenStream2) -> syn::Result syn::Result(attrs: &'a [Attribute], name: &str) -> Option<&'a Attri // Modify the new_node_fn function to use the code generation pub fn new_node_fn(attr: TokenStream2, item: TokenStream2) -> syn::Result { + let crate_ident = CrateIdent::default(); let mut parsed_node = parse_node_fn(attr, item.clone()).map_err(|e| Error::new(e.span(), format!("Failed to parse node function: {e}")))?; parsed_node.replace_impl_trait_in_input(); crate::validation::validate_node_fn(&parsed_node).map_err(|e| Error::new(e.span(), format!("Validation Error: {e}")))?; - generate_node_code(&parsed_node).map_err(|e| Error::new(e.span(), format!("Failed to generate node code: {e}"))) + generate_node_code(&crate_ident, &parsed_node).map_err(|e| Error::new(e.span(), format!("Failed to generate node code: {e}"))) } impl ParsedNodeFn { @@ -677,7 +671,6 @@ impl ParsedNodeFn { #[cfg(test)] mod tests { use super::*; - use proc_macro_crate::FoundCrate; use proc_macro2::Span; use quote::{quote, quote_spanned}; use syn::parse_quote; @@ -829,7 +822,6 @@ mod tests { unit: None, }], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: String::from("Multi\nLine\n"), }; @@ -911,7 +903,6 @@ mod tests { }, ], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: String::from("Hello\n\t\t\t\tWorld\n"), }; @@ -974,7 +965,6 @@ mod tests { unit: None, }], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: "Test\n".into(), }; @@ -1041,7 +1031,6 @@ mod tests { unit: None, }], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: String::new(), }; @@ -1110,7 +1099,6 @@ mod tests { unit: None, }], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: String::new(), }; @@ -1172,7 +1160,6 @@ mod tests { unit: None, }], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: String::new(), }; @@ -1214,7 +1201,6 @@ mod tests { is_async: false, fields: vec![], body: TokenStream2::new(), - crate_name: FoundCrate::Itself, description: String::new(), }; diff --git a/node-graph/node-macro/src/shader_nodes/mod.rs b/node-graph/node-macro/src/shader_nodes/mod.rs index d82ca8bfa8..7ff3677d61 100644 --- a/node-graph/node-macro/src/shader_nodes/mod.rs +++ b/node-graph/node-macro/src/shader_nodes/mod.rs @@ -1,3 +1,4 @@ +use crate::crate_ident::CrateIdent; use crate::parsing::{NodeFnAttributes, ParsedNodeFn}; use crate::shader_nodes::per_pixel_adjust::PerPixelAdjust; use proc_macro2::{Ident, TokenStream}; @@ -50,11 +51,11 @@ impl Parse for ShaderNodeType { } pub trait ShaderCodegen { - fn codegen(&self, parsed: &ParsedNodeFn) -> syn::Result; + fn codegen(&self, crate_ident: &CrateIdent, parsed: &ParsedNodeFn) -> syn::Result; } impl ShaderCodegen for ShaderNodeType { - fn codegen(&self, parsed: &ParsedNodeFn) -> syn::Result { + fn codegen(&self, crate_ident: &CrateIdent, parsed: &ParsedNodeFn) -> syn::Result { match self { ShaderNodeType::None | ShaderNodeType::ShaderNode => (), _ => { @@ -66,7 +67,7 @@ impl ShaderCodegen for ShaderNodeType { match self { ShaderNodeType::None | ShaderNodeType::ShaderNode => Ok(ShaderTokens::default()), - ShaderNodeType::PerPixelAdjust(x) => x.codegen(parsed), + ShaderNodeType::PerPixelAdjust(x) => x.codegen(crate_ident, parsed), } } } diff --git a/node-graph/node-macro/src/shader_nodes/per_pixel_adjust.rs b/node-graph/node-macro/src/shader_nodes/per_pixel_adjust.rs index f01c364223..1f9e2e37e0 100644 --- a/node-graph/node-macro/src/shader_nodes/per_pixel_adjust.rs +++ b/node-graph/node-macro/src/shader_nodes/per_pixel_adjust.rs @@ -1,7 +1,7 @@ +use crate::crate_ident::CrateIdent; use crate::parsing::{Input, NodeFnAttributes, ParsedField, ParsedFieldType, ParsedNodeFn, RegularParsedField}; use crate::shader_nodes::{SHADER_NODES_FEATURE_GATE, ShaderCodegen, ShaderNodeType, ShaderTokens}; use convert_case::{Case, Casing}; -use proc_macro_crate::FoundCrate; use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, format_ident, quote}; use std::borrow::Cow; @@ -19,7 +19,7 @@ impl Parse for PerPixelAdjust { } impl ShaderCodegen for PerPixelAdjust { - fn codegen(&self, parsed: &ParsedNodeFn) -> syn::Result { + fn codegen(&self, crate_ident: &CrateIdent, parsed: &ParsedNodeFn) -> syn::Result { let fn_name = &parsed.fn_name; let mut params; @@ -74,6 +74,7 @@ impl ShaderCodegen for PerPixelAdjust { let shader_node_mod = format_ident!("{}_shader_node", fn_name); let codegen = PerPixelAdjustCodegen { + crate_ident, parsed, params, has_uniform, @@ -93,6 +94,7 @@ impl ShaderCodegen for PerPixelAdjust { } pub struct PerPixelAdjustCodegen<'a> { + crate_ident: &'a CrateIdent, parsed: &'a ParsedNodeFn, params: Vec>, has_uniform: bool, @@ -107,6 +109,9 @@ pub struct PerPixelAdjustCodegen<'a> { impl PerPixelAdjustCodegen<'_> { fn codegen_shader_entry_point(&self) -> syn::Result { let fn_name = &self.parsed.fn_name; + let gcore_shaders = self.crate_ident.gcore_shaders()?; + let reexport = quote!(#gcore_shaders::shaders::__private); + let uniform_members = self .params .iter() @@ -139,16 +144,16 @@ impl PerPixelAdjustCodegen<'_> { Ok(quote! { pub mod #entry_point_mod { use super::*; - use graphene_core_shaders::color::Color; - use spirv_std::spirv; - use spirv_std::glam::{Vec4, Vec4Swizzles}; - use spirv_std::image::{Image2d, ImageWithMethods}; - use spirv_std::image::sample_with::lod; + use #gcore_shaders::color::Color; + use #reexport::glam::{Vec4, Vec4Swizzles}; + use #reexport::spirv_std::spirv; + use #reexport::spirv_std::image::{Image2d, ImageWithMethods}; + use #reexport::spirv_std::image::sample_with::lod; pub const #entry_point_name: &str = core::concat!(core::module_path!(), "::entry_point"); #[repr(C)] - #[derive(Copy, Clone, bytemuck::NoUninit)] + #[derive(Copy, Clone, #reexport::bytemuck::NoUninit)] pub struct #uniform_struct_ident { #(pub #uniform_members),* } @@ -169,10 +174,8 @@ impl PerPixelAdjustCodegen<'_> { } fn codegen_gpu_node(&self) -> syn::Result { - let gcore = match &self.parsed.crate_name { - FoundCrate::Itself => format_ident!("crate"), - FoundCrate::Name(name) => format_ident!("{name}"), - }; + let gcore = self.crate_ident.gcore()?; + let wgpu_executor = self.crate_ident.wgpu_executor()?; // adapt fields for gpu node let raster_gpu: Type = parse_quote!(#gcore::table::Table<#gcore::raster_types::Raster<#gcore::raster_types::GPU>>); @@ -207,13 +210,13 @@ impl PerPixelAdjustCodegen<'_> { .collect::>>()?; // insert wgpu_executor field - let wgpu_executor = format_ident!("__wgpu_executor"); + let executor = format_ident!("__wgpu_executor"); fields.push(ParsedField { pat_ident: PatIdent { attrs: vec![], by_ref: None, mutability: None, - ident: parse_quote!(#wgpu_executor), + ident: parse_quote!(#executor), subpat: None, }, name: None, @@ -271,7 +274,7 @@ impl PerPixelAdjustCodegen<'_> { let entry_point_name = &self.entry_point_name; let body = quote! { { - #wgpu_executor.shader_runtime.run_per_pixel_adjust(&::wgpu_executor::shader_runtime::per_pixel_adjust_runtime::Shaders { + #executor.shader_runtime.run_per_pixel_adjust(&::wgpu_executor::shader_runtime::per_pixel_adjust_runtime::Shaders { wgsl_shader: crate::WGSL_SHADER, fragment_shader_name: super::#entry_point_name, has_uniform: #has_uniform, @@ -300,11 +303,10 @@ impl PerPixelAdjustCodegen<'_> { is_async: true, fields, body, - crate_name: self.parsed.crate_name.clone(), description: "".to_string(), }; parsed_node_fn.replace_impl_trait_in_input(); - let gpu_node_impl = crate::codegen::generate_node_code(&parsed_node_fn)?; + let gpu_node_impl = crate::codegen::generate_node_code(self.crate_ident, &parsed_node_fn)?; // wrap node in `mod #gpu_node_mod` let shader_node_mod = &self.shader_node_mod; @@ -312,7 +314,7 @@ impl PerPixelAdjustCodegen<'_> { #[cfg(feature = #SHADER_NODES_FEATURE_GATE)] mod #shader_node_mod { use super::*; - use wgpu_executor::WgpuExecutor; + use #wgpu_executor::WgpuExecutor; #gpu_node_impl }