Skip to content

Commit fc0883d

Browse files
committed
shaders: codegen for per_pixel_adjust shader nodes
1 parent ccc195e commit fc0883d

File tree

7 files changed

+176
-6
lines changed

7 files changed

+176
-6
lines changed

node-graph/gcore-shaders/src/color/color.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::discrete_srgb::{float_to_srgb_u8, srgb_u8_to_float};
33
use bytemuck::{Pod, Zeroable};
44
use core::fmt::Debug;
55
use core::hash::Hash;
6+
use glam::Vec4;
67
use half::f16;
78
#[cfg(target_arch = "spirv")]
89
use num_traits::Euclid;
@@ -1075,6 +1076,21 @@ impl Color {
10751076
..*self
10761077
}
10771078
}
1079+
1080+
#[inline(always)]
1081+
pub const fn from_vec4(vec: Vec4) -> Self {
1082+
Self {
1083+
red: vec.x,
1084+
green: vec.y,
1085+
blue: vec.z,
1086+
alpha: vec.w,
1087+
}
1088+
}
1089+
1090+
#[inline(always)]
1091+
pub fn to_vec4(&self) -> Vec4 {
1092+
Vec4::new(self.red, self.green, self.blue, self.alpha)
1093+
}
10781094
}
10791095

10801096
#[cfg(test)]

node-graph/graster-nodes/src/adjustments.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ fn luminance<T: Adjust<Color>>(
5050
Table<Raster<CPU>>,
5151
GradientStops,
5252
)]
53+
#[gpu_image]
5354
mut input: T,
5455
luminance_calc: LuminanceCalculation,
5556
) -> T {
@@ -74,6 +75,7 @@ fn gamma_correction<T: Adjust<Color>>(
7475
Table<Raster<CPU>>,
7576
GradientStops,
7677
)]
78+
#[gpu_image]
7779
mut input: T,
7880
#[default(2.2)]
7981
#[range((0.01, 10.))]
@@ -94,6 +96,7 @@ fn extract_channel<T: Adjust<Color>>(
9496
Table<Raster<CPU>>,
9597
GradientStops,
9698
)]
99+
#[gpu_image]
97100
mut input: T,
98101
channel: RedGreenBlueAlpha,
99102
) -> T {
@@ -117,6 +120,7 @@ fn make_opaque<T: Adjust<Color>>(
117120
Table<Raster<CPU>>,
118121
GradientStops,
119122
)]
123+
#[gpu_image]
120124
mut input: T,
121125
) -> T {
122126
input.adjust(|color| {
@@ -142,6 +146,7 @@ fn brightness_contrast<T: Adjust<Color>>(
142146
Table<Raster<CPU>>,
143147
GradientStops,
144148
)]
149+
#[gpu_image]
145150
mut input: T,
146151
brightness: SignedPercentage,
147152
contrast: SignedPercentage,
@@ -231,6 +236,7 @@ fn levels<T: Adjust<Color>>(
231236
Table<Raster<CPU>>,
232237
GradientStops,
233238
)]
239+
#[gpu_image]
234240
mut image: T,
235241
#[default(0.)] shadows: Percentage,
236242
#[default(50.)] midtones: Percentage,
@@ -298,6 +304,7 @@ async fn black_and_white<T: Adjust<Color>>(
298304
Table<Raster<CPU>>,
299305
GradientStops,
300306
)]
307+
#[gpu_image]
301308
mut image: T,
302309
#[default(Color::BLACK)] tint: Color,
303310
#[default(40.)]
@@ -370,6 +377,7 @@ async fn hue_saturation<T: Adjust<Color>>(
370377
Table<Raster<CPU>>,
371378
GradientStops,
372379
)]
380+
#[gpu_image]
373381
mut input: T,
374382
hue_shift: Angle,
375383
saturation_shift: SignedPercentage,
@@ -404,6 +412,7 @@ async fn invert<T: Adjust<Color>>(
404412
Table<Raster<CPU>>,
405413
GradientStops,
406414
)]
415+
#[gpu_image]
407416
mut input: T,
408417
) -> T {
409418
input.adjust(|color| {
@@ -426,6 +435,7 @@ async fn threshold<T: Adjust<Color>>(
426435
Table<Raster<CPU>>,
427436
GradientStops,
428437
)]
438+
#[gpu_image]
429439
mut image: T,
430440
#[default(50.)] min_luminance: Percentage,
431441
#[default(100.)] max_luminance: Percentage,
@@ -471,6 +481,7 @@ async fn vibrance<T: Adjust<Color>>(
471481
Table<Raster<CPU>>,
472482
GradientStops,
473483
)]
484+
#[gpu_image]
474485
mut image: T,
475486
vibrance: SignedPercentage,
476487
) -> T {
@@ -636,6 +647,7 @@ async fn channel_mixer<T: Adjust<Color>>(
636647
Table<Raster<CPU>>,
637648
GradientStops,
638649
)]
650+
#[gpu_image]
639651
mut image: T,
640652

641653
monochrome: bool,
@@ -764,6 +776,7 @@ async fn selective_color<T: Adjust<Color>>(
764776
Table<Raster<CPU>>,
765777
GradientStops,
766778
)]
779+
#[gpu_image]
767780
mut image: T,
768781

769782
mode: RelativeAbsolute,
@@ -906,6 +919,7 @@ async fn posterize<T: Adjust<Color>>(
906919
Table<Raster<CPU>>,
907920
GradientStops,
908921
)]
922+
#[gpu_image]
909923
mut input: T,
910924
#[default(4)]
911925
#[hard_min(2.)]
@@ -939,6 +953,7 @@ async fn exposure<T: Adjust<Color>>(
939953
Table<Raster<CPU>>,
940954
GradientStops,
941955
)]
956+
#[gpu_image]
942957
mut input: T,
943958
exposure: f64,
944959
offset: f64,

node-graph/graster-nodes/src/blending_nodes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,15 @@ async fn blend<T: Blend<Color> + Send>(
130130
Table<Raster<CPU>>,
131131
GradientStops,
132132
)]
133+
#[gpu_image]
133134
over: T,
134135
#[expose]
135136
#[implementations(
136137
Color,
137138
Table<Raster<CPU>>,
138139
GradientStops,
139140
)]
141+
#[gpu_image]
140142
under: T,
141143
blend_mode: BlendMode,
142144
#[default(100.)] opacity: Percentage,
@@ -152,6 +154,7 @@ fn color_overlay<T: Adjust<Color>>(
152154
Table<Raster<CPU>>,
153155
GradientStops,
154156
)]
157+
#[gpu_image]
155158
mut image: T,
156159
#[default(Color::BLACK)] color: Color,
157160
blend_mode: BlendMode,

node-graph/node-macro/src/codegen.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::parsing::*;
22
use convert_case::{Case, Casing};
33
use proc_macro_crate::FoundCrate;
4-
use proc_macro2::TokenStream as TokenStream2;
4+
use proc_macro2::{TokenStream as TokenStream2, TokenStream};
55
use quote::{ToTokens, format_ident, quote, quote_spanned};
66
use std::sync::atomic::AtomicU64;
77
use syn::punctuated::Punctuated;
@@ -347,6 +347,7 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
347347

348348
let cfg = crate::shader_nodes::modify_cfg(&attributes);
349349
let node_input_accessor = generate_node_input_references(parsed, fn_generics, &field_idents, &graphene_core, &identifier, &cfg);
350+
let shader_entry_point = attributes.shader_node.as_ref().map(|n| n.codegen_shader_entry_point(parsed)).unwrap_or(Ok(TokenStream::new()))?;
350351
Ok(quote! {
351352
/// Underlying implementation for [#struct_name]
352353
#[inline]
@@ -435,6 +436,8 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
435436
NODE_METADATA.lock().unwrap().insert(#identifier(), metadata);
436437
}
437438
}
439+
440+
#shader_entry_point
438441
})
439442
}
440443

@@ -637,6 +640,7 @@ fn generate_register_node_impl(parsed: &ParsedNodeFn, field_names: &[&Ident], st
637640
})
638641
}
639642

643+
use crate::shader_nodes::CodegenShaderEntryPoint;
640644
use syn::visit_mut::VisitMut;
641645
use syn::{GenericArgument, Lifetime, Type};
642646

node-graph/node-macro/src/parsing.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ impl Parse for ParsedWidgetOverride {
104104

105105
#[derive(Debug)]
106106
pub(crate) enum ParsedField {
107+
/// a param of any kind, either a concrete type or a generic type with a set of possible types specified via
108+
/// `#[implementation(type)]`
107109
Regular {
108110
pat_ident: PatIdent,
109111
name: Option<LitStr>,
@@ -121,7 +123,9 @@ pub(crate) enum ParsedField {
121123
number_step: Option<LitFloat>,
122124
implementations: Punctuated<Type, Comma>,
123125
unit: Option<LitStr>,
126+
gpu_image: bool,
124127
},
128+
/// a param of `impl Node` with `#[implementation(in -> out)]`
125129
Node {
126130
pat_ident: PatIdent,
127131
name: Option<LitStr>,
@@ -533,6 +537,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
533537
.map_err(|e| Error::new_spanned(attr, format!("Invalid `step` for argument '{}': {}\nUSAGE EXAMPLE: #[step(2.)]", ident, e)))
534538
})
535539
.transpose()?;
540+
let gpu_image = extract_attribute(attrs, "gpu_image").is_some();
536541

537542
let (is_node, node_input_type, node_output_type) = parse_node_type(&ty);
538543
let description = attrs
@@ -597,6 +602,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
597602
value_source,
598603
implementations,
599604
unit,
605+
gpu_image,
600606
})
601607
}
602608
}
Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
use crate::parsing::NodeFnAttributes;
1+
use crate::parsing::{NodeFnAttributes, ParsedNodeFn};
2+
use crate::shader_nodes::per_pixel_adjust::PerPixelAdjust;
23
use proc_macro2::{Ident, TokenStream};
34
use quote::quote;
4-
use strum::{EnumString, VariantNames};
5+
use strum::VariantNames;
56
use syn::Error;
67
use syn::parse::{Parse, ParseStream};
78

9+
pub mod per_pixel_adjust;
10+
811
pub const STD_FEATURE_GATE: &str = "std";
912

1013
pub fn modify_cfg(attributes: &NodeFnAttributes) -> TokenStream {
@@ -16,17 +19,33 @@ pub fn modify_cfg(attributes: &NodeFnAttributes) -> TokenStream {
1619
}
1720
}
1821

19-
#[derive(Debug, EnumString, VariantNames)]
22+
#[derive(Debug, VariantNames)]
2023
pub(crate) enum ShaderNodeType {
21-
PerPixelAdjust,
24+
PerPixelAdjust(PerPixelAdjust),
2225
}
2326

2427
impl Parse for ShaderNodeType {
2528
fn parse(input: ParseStream) -> syn::Result<Self> {
2629
let ident: Ident = input.parse()?;
2730
Ok(match ident.to_string().as_str() {
28-
"PerPixelAdjust" => ShaderNodeType::PerPixelAdjust,
31+
"PerPixelAdjust" => ShaderNodeType::PerPixelAdjust(PerPixelAdjust::parse(input)?),
2932
_ => return Err(Error::new_spanned(&ident, format!("attr 'shader_node' must be one of {:?}", Self::VARIANTS))),
3033
})
3134
}
3235
}
36+
37+
pub trait CodegenShaderEntryPoint {
38+
fn codegen_shader_entry_point(&self, parsed: &ParsedNodeFn) -> syn::Result<TokenStream>;
39+
}
40+
41+
impl CodegenShaderEntryPoint for ShaderNodeType {
42+
fn codegen_shader_entry_point(&self, parsed: &ParsedNodeFn) -> syn::Result<TokenStream> {
43+
if parsed.is_async {
44+
return Err(Error::new_spanned(&parsed.fn_name, "Shader nodes must not be async"));
45+
}
46+
47+
match self {
48+
ShaderNodeType::PerPixelAdjust(x) => x.codegen_shader_entry_point(parsed),
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)