Skip to content

Commit 410940d

Browse files
committed
shaders: codegen for per_pixel_adjust shader nodes
1 parent bb3acbf commit 410940d

File tree

7 files changed

+179
-6
lines changed

7 files changed

+179
-6
lines changed

node-graph/gcore-shaders/src/color/color_types.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(not(feature = "std"))]
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
@@ -52,6 +52,7 @@ fn luminance<T: Adjust<Color>>(
5252
Table<GradientStops>,
5353
GradientStops,
5454
)]
55+
#[gpu_image]
5556
mut input: T,
5657
luminance_calc: LuminanceCalculation,
5758
) -> T {
@@ -77,6 +78,7 @@ fn gamma_correction<T: Adjust<Color>>(
7778
Table<GradientStops>,
7879
GradientStops,
7980
)]
81+
#[gpu_image]
8082
mut input: T,
8183
#[default(2.2)]
8284
#[range((0.01, 10.))]
@@ -98,6 +100,7 @@ fn extract_channel<T: Adjust<Color>>(
98100
Table<GradientStops>,
99101
GradientStops,
100102
)]
103+
#[gpu_image]
101104
mut input: T,
102105
channel: RedGreenBlueAlpha,
103106
) -> T {
@@ -122,6 +125,7 @@ fn make_opaque<T: Adjust<Color>>(
122125
Table<GradientStops>,
123126
GradientStops,
124127
)]
128+
#[gpu_image]
125129
mut input: T,
126130
) -> T {
127131
input.adjust(|color| {
@@ -148,6 +152,7 @@ fn brightness_contrast<T: Adjust<Color>>(
148152
Table<GradientStops>,
149153
GradientStops,
150154
)]
155+
#[gpu_image]
151156
mut input: T,
152157
brightness: SignedPercentageF32,
153158
contrast: SignedPercentageF32,
@@ -238,6 +243,7 @@ fn levels<T: Adjust<Color>>(
238243
Table<GradientStops>,
239244
GradientStops,
240245
)]
246+
#[gpu_image]
241247
mut image: T,
242248
#[default(0.)] shadows: PercentageF32,
243249
#[default(50.)] midtones: PercentageF32,
@@ -306,6 +312,7 @@ fn black_and_white<T: Adjust<Color>>(
306312
Table<GradientStops>,
307313
GradientStops,
308314
)]
315+
#[gpu_image]
309316
mut image: T,
310317
#[default(Color::BLACK)] tint: Color,
311318
#[default(40.)]
@@ -379,6 +386,7 @@ fn hue_saturation<T: Adjust<Color>>(
379386
Table<GradientStops>,
380387
GradientStops,
381388
)]
389+
#[gpu_image]
382390
mut input: T,
383391
hue_shift: AngleF32,
384392
saturation_shift: SignedPercentageF32,
@@ -414,6 +422,7 @@ fn invert<T: Adjust<Color>>(
414422
Table<GradientStops>,
415423
GradientStops,
416424
)]
425+
#[gpu_image]
417426
mut input: T,
418427
) -> T {
419428
input.adjust(|color| {
@@ -437,6 +446,7 @@ fn threshold<T: Adjust<Color>>(
437446
Table<GradientStops>,
438447
GradientStops,
439448
)]
449+
#[gpu_image]
440450
mut image: T,
441451
#[default(50.)] min_luminance: PercentageF32,
442452
#[default(100.)] max_luminance: PercentageF32,
@@ -483,6 +493,7 @@ fn vibrance<T: Adjust<Color>>(
483493
Table<GradientStops>,
484494
GradientStops,
485495
)]
496+
#[gpu_image]
486497
mut image: T,
487498
vibrance: SignedPercentageF32,
488499
) -> T {
@@ -649,6 +660,7 @@ fn channel_mixer<T: Adjust<Color>>(
649660
Table<GradientStops>,
650661
GradientStops,
651662
)]
663+
#[gpu_image]
652664
mut image: T,
653665

654666
monochrome: bool,
@@ -778,6 +790,7 @@ fn selective_color<T: Adjust<Color>>(
778790
Table<GradientStops>,
779791
GradientStops,
780792
)]
793+
#[gpu_image]
781794
mut image: T,
782795

783796
mode: RelativeAbsolute,
@@ -921,6 +934,7 @@ fn posterize<T: Adjust<Color>>(
921934
Table<GradientStops>,
922935
GradientStops,
923936
)]
937+
#[gpu_image]
924938
mut input: T,
925939
#[default(4)]
926940
#[hard_min(2.)]
@@ -955,6 +969,7 @@ fn exposure<T: Adjust<Color>>(
955969
Table<GradientStops>,
956970
GradientStops,
957971
)]
972+
#[gpu_image]
958973
mut input: T,
959974
exposure: f32,
960975
offset: f32,

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ fn blend<T: Blend<Color> + Send>(
141141
Table<GradientStops>,
142142
GradientStops,
143143
)]
144+
#[gpu_image]
144145
over: T,
145146
#[expose]
146147
#[implementations(
@@ -149,6 +150,7 @@ fn blend<T: Blend<Color> + Send>(
149150
Table<GradientStops>,
150151
GradientStops,
151152
)]
153+
#[gpu_image]
152154
under: T,
153155
blend_mode: BlendMode,
154156
#[default(100.)] opacity: PercentageF32,
@@ -165,6 +167,7 @@ fn color_overlay<T: Adjust<Color>>(
165167
Table<GradientStops>,
166168
GradientStops,
167169
)]
170+
#[gpu_image]
168171
mut image: T,
169172
#[default(Color::BLACK)] color: Color,
170173
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;
@@ -295,6 +295,7 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
295295

296296
let cfg = crate::shader_nodes::modify_cfg(attributes);
297297
let node_input_accessor = generate_node_input_references(parsed, fn_generics, &field_idents, &graphene_core, &identifier, &cfg);
298+
let shader_entry_point = attributes.shader_node.as_ref().map(|n| n.codegen_shader_entry_point(parsed)).unwrap_or(Ok(TokenStream::new()))?;
298299
Ok(quote! {
299300
/// Underlying implementation for [#struct_name]
300301
#[inline]
@@ -384,6 +385,8 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
384385
NODE_METADATA.lock().unwrap().insert(#identifier(), metadata);
385386
}
386387
}
388+
389+
#shader_entry_point
387390
})
388391
}
389392

@@ -586,6 +589,7 @@ fn generate_register_node_impl(parsed: &ParsedNodeFn, field_names: &[&Ident], st
586589
})
587590
}
588591

592+
use crate::shader_nodes::CodegenShaderEntryPoint;
589593
use syn::visit_mut::VisitMut;
590594
use syn::{GenericArgument, Lifetime, Type};
591595

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ pub enum ParsedFieldType {
120120
Node(NodeParsedField),
121121
}
122122

123+
/// a param of any kind, either a concrete type or a generic type with a set of possible types specified via
124+
/// `#[implementation(type)]`
123125
#[derive(Clone, Debug)]
124126
pub struct RegularParsedField {
125127
pub ty: Type,
@@ -131,8 +133,10 @@ pub struct RegularParsedField {
131133
pub number_hard_max: Option<LitFloat>,
132134
pub number_mode_range: Option<ExprTuple>,
133135
pub implementations: Punctuated<Type, Comma>,
136+
pub gpu_image: bool,
134137
}
135138

139+
/// a param of `impl Node` with `#[implementation(in -> out)]`
136140
#[derive(Clone, Debug)]
137141
pub struct NodeParsedField {
138142
pub input_type: Type,
@@ -529,6 +533,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
529533
.map_err(|e| Error::new_spanned(attr, format!("Invalid `step` for argument '{ident}': {e}\nUSAGE EXAMPLE: #[step(2.)]")))
530534
})
531535
.transpose()?;
536+
let gpu_image = extract_attribute(attrs, "gpu_image").is_some();
532537

533538
let (is_node, node_input_type, node_output_type) = parse_node_type(&ty);
534539
let description = attrs
@@ -590,6 +595,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
590595
ty,
591596
value_source,
592597
implementations,
598+
gpu_image,
593599
}),
594600
name,
595601
description,
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)