Skip to content

Commit 181408e

Browse files
Type erased pipelines
1 parent cfd993e commit 181408e

8 files changed

Lines changed: 40 additions & 61 deletions

File tree

node-graph/graph-craft/src/document.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,10 @@ impl NodeNetwork {
896896
let (import_id, _ty) = self.scope_injections.get(key.as_ref()).expect("Tried to import a non existent key from scope");
897897
// TODO use correct output index
898898
nested_node.inputs[nested_input_index] = NodeInput::node(*import_id, 0);
899+
900+
if let Some(input_node) = self.nodes.get_mut(import_id) {
901+
input_node.original_location.dependants[0].push(nested_node_id);
902+
}
899903
}
900904
NodeInput::Reflection(_) => unreachable!("Reflection inputs should have been replaced with value nodes"),
901905
}

node-graph/interpreted-executor/src/node_registry.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
200200
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => ListDyn, Context => graphene_std::ContextFeatures]),
201201
#[cfg(target_family = "wasm")]
202202
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => CanvasHandle, Context => graphene_std::ContextFeatures]),
203-
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => wgpu_executor::WgpuPipelineCache<graphene_std::render_pixel_preview::PixelPreview>, Context => graphene_std::ContextFeatures]),
204-
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => wgpu_executor::WgpuPipelineCache<graphene_std::render_background::BackgroundCompositor>, Context => graphene_std::ContextFeatures]),
203+
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => wgpu_executor::WgpuPipelineCache, Context => graphene_std::ContextFeatures]),
205204
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => &wgpu_executor::WgpuExecutor, Context => graphene_std::ContextFeatures]),
206205
// ==========
207206
// MEMO NODES
@@ -288,8 +287,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
288287
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => graphene_std::transform::ScaleType]),
289288
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::InterpolationDistribution]),
290289
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => RenderIntermediate]),
291-
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => wgpu_executor::WgpuPipelineCache<graphene_std::render_pixel_preview::PixelPreview>]),
292-
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => wgpu_executor::WgpuPipelineCache<graphene_std::render_background::BackgroundCompositor>]),
290+
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => wgpu_executor::WgpuPipelineCache]),
293291
async_node!(graphene_core::memo::MemoizeNode<_, _>, input: Context, fn_params: [Context => &wgpu_executor::WgpuExecutor]),
294292
];
295293
// =============

node-graph/interpreted-executor/src/util.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use graph_craft::ProtoNodeIdentifier;
21
use graph_craft::application_io::PlatformEditorApi;
32
use graph_craft::concrete;
43
use graph_craft::document::value::TaggedValue;
@@ -8,7 +7,6 @@ use graphene_std::Context;
87
use graphene_std::ContextFeatures;
98
use graphene_std::uuid::NodeId;
109
use std::sync::Arc;
11-
use wgpu_executor::WgpuExecutor;
1210

1311
pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<PlatformEditorApi>) -> NodeNetwork {
1412
network.generate_node_paths(&[]);
@@ -109,7 +107,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<PlatformE
109107
};
110108

111109
// wrap the inner network in a scope
112-
let mut nodes = vec![
110+
let nodes = vec![
113111
inner_network,
114112
render_node,
115113
DocumentNode {
@@ -118,16 +116,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<PlatformE
118116
..Default::default()
119117
},
120118
];
121-
let mut scope_injections = vec![("editor-api".to_string(), (NodeId(2), concrete!(&PlatformEditorApi)))];
122-
123-
if cfg!(feature = "gpu") {
124-
nodes.push(DocumentNode {
125-
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<&WgpuExecutor>")),
126-
inputs: vec![NodeInput::node(NodeId(2), 0)],
127-
..Default::default()
128-
});
129-
scope_injections.push(("wgpu-executor".to_string(), (NodeId(3), concrete!(&WgpuExecutor))));
130-
}
119+
let scope_injections = vec![("editor-api".to_string(), (NodeId(2), concrete!(&PlatformEditorApi)))];
131120

132121
NodeNetwork {
133122
exports: vec![NodeInput::node(NodeId(1), 0)],

node-graph/libraries/wgpu-executor/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ impl WgpuExecutor {
9797
Ok(texture)
9898
}
9999

100-
pub fn pipeline_init<P: WgpuPipeline>(&self, pipeline: &WgpuPipelineCache<P>) {
101-
pipeline.init(self);
100+
pub fn pipeline_init<P: WgpuPipeline>(&self, pipeline: &WgpuPipelineCache) {
101+
pipeline.init::<P>(self);
102102
}
103103

104104
pub async fn request_texture(&self, size: UVec2) -> Arc<wgpu::Texture> {
Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use dyn_any::StaticType;
2+
use std::any::Any;
23
use std::future::Future;
34
use std::pin::Pin;
45
use std::sync::{Arc, OnceLock};
@@ -7,7 +8,7 @@ use crate::WgpuExecutor;
78

89
pub type PipelineFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
910

10-
pub trait Pipeline: std::any::Any + Send + Sync + Sized {
11+
pub trait Pipeline: Any + Send + Sync + Sized {
1112
type Args<'a>;
1213
type Out: Send;
1314

@@ -16,7 +17,7 @@ pub trait Pipeline: std::any::Any + Send + Sync + Sized {
1617
fn run<'a>(&'a self, executor: &'a WgpuExecutor, args: &'a Self::Args<'_>) -> PipelineFuture<'a, Self::Out>;
1718
}
1819

19-
pub trait AsyncPipeline: std::any::Any + Send + Sync + Sized {
20+
pub trait AsyncPipeline: Any + Send + Sync + Sized {
2021
type Args<'a>;
2122
type Out: Send;
2223

@@ -38,47 +39,34 @@ impl<P: AsyncPipeline> Pipeline for P {
3839
}
3940
}
4041

41-
pub struct PipelineCache<P: Pipeline> {
42-
pipeline: Arc<OnceLock<P>>,
42+
#[derive(Default, Clone)]
43+
pub struct PipelineCache {
44+
pipeline: Arc<OnceLock<Box<dyn Any + Send + Sync>>>,
4345
executor: Arc<OnceLock<WgpuExecutor>>,
4446
}
4547

46-
impl<P: Pipeline> PipelineCache<P> {
47-
pub(super) fn init(&self, executor: &WgpuExecutor) {
48+
impl PipelineCache {
49+
pub(super) fn init<P: Pipeline>(&self, executor: &WgpuExecutor) {
4850
self.executor.get_or_init(|| executor.clone());
51+
self.pipeline.get_or_init(|| Box::new(P::create(executor)));
4952
}
5053

51-
pub async fn run(&self, args: &P::Args<'_>) -> P::Out {
52-
let executor = self.executor.get().expect("PipelineCache not initialized with an executor");
53-
let pipeline = self.pipeline.get_or_init(|| P::create(executor));
54+
pub async fn run<P: Pipeline>(&self, args: &P::Args<'_>) -> P::Out {
55+
let executor = self.executor.get().expect("PipelineCache not initialized");
56+
let entry = self.pipeline.get().expect("PipelineCache not initialized");
57+
let pipeline = (&**entry)
58+
.downcast_ref::<P>()
59+
.unwrap_or_else(|| panic!("PipelineCache type mismatch: run::<{}>() but init used a different pipeline type", std::any::type_name::<P>(),));
5460
pipeline.run(executor, args).await
5561
}
5662
}
5763

58-
impl<P: Pipeline> Default for PipelineCache<P> {
59-
fn default() -> Self {
60-
Self {
61-
pipeline: Arc::new(OnceLock::new()),
62-
executor: Arc::new(OnceLock::new()),
63-
}
64-
}
65-
}
66-
67-
impl<P: Pipeline> Clone for PipelineCache<P> {
68-
fn clone(&self) -> Self {
69-
Self {
70-
pipeline: self.pipeline.clone(),
71-
executor: self.executor.clone(),
72-
}
73-
}
74-
}
75-
76-
impl<P: Pipeline> std::fmt::Debug for PipelineCache<P> {
64+
impl std::fmt::Debug for PipelineCache {
7765
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78-
f.debug_struct("PipelineCache").field("type", &std::any::type_name::<P>()).finish()
66+
f.debug_struct("PipelineCache").field("initialized", &self.pipeline.get().is_some()).finish()
7967
}
8068
}
8169

82-
unsafe impl<P: Pipeline> StaticType for PipelineCache<P> {
83-
type Static = PipelineCache<P>;
70+
unsafe impl StaticType for PipelineCache {
71+
type Static = PipelineCache;
8472
}

node-graph/node-macro/src/shader_nodes/per_pixel_adjust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ impl PerPixelAdjustCodegen<'_> {
233233
ty: ParsedFieldType::Regular(RegularParsedField {
234234
ty: parse_quote!(&'a WgpuExecutor),
235235
exposed: true,
236-
value_source: ParsedValueSource::Scope(parse_quote!("wgpu-executor")),
236+
value_source: ParsedValueSource::Scope(parse_quote!("graphene_std::platform_application_io::WgpuExecutorNode")),
237237
number_soft_min: None,
238238
number_soft_max: None,
239239
number_hard_min: None,

node-graph/nodes/gstd/src/render_background.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use wgpu_executor::{AsyncWgpuPipeline, WgpuExecutor, WgpuPipelineCache};
1414
#[node_macro::node(category(""))]
1515
async fn render_background<'a: 'n>(
1616
ctx: impl Ctx + ExtractFootprint + ExtractVarArgs,
17-
#[scope(background_compositor_pipeline::IDENTIFIER)] pipeline: WgpuPipelineCache<BackgroundCompositor>,
17+
#[scope(background_compositor_pipeline::IDENTIFIER)] pipeline: WgpuPipelineCache,
1818
data: RenderOutput,
1919
) -> RenderOutput {
2020
let footprint = ctx.footprint();
@@ -36,7 +36,7 @@ async fn render_background<'a: 'n>(
3636
RenderOutputType::Texture(foreground_texture) => {
3737
let doc_to_screen = (glam::DAffine2::from_scale(glam::DVec2::splat(render_params.scale)) * render_params.footprint.transform).as_affine2();
3838
let blended = pipeline
39-
.run(&BackgroundCompositorArgs {
39+
.run::<BackgroundCompositor>(&BackgroundCompositorArgs {
4040
foreground: foreground_texture.as_ref(),
4141
backgrounds: &metadata.backgrounds,
4242
document_to_screen: doc_to_screen,
@@ -121,9 +121,9 @@ async fn render_background<'a: 'n>(
121121
async fn background_compositor_pipeline<'a: 'n>(
122122
_ctx: impl Ctx,
123123
#[scope(crate::platform_application_io::wgpu_executor::IDENTIFIER)] executor: &'a WgpuExecutor,
124-
#[data] pipeline: WgpuPipelineCache<BackgroundCompositor>,
125-
) -> WgpuPipelineCache<BackgroundCompositor> {
126-
executor.pipeline_init(pipeline);
124+
#[data] pipeline: WgpuPipelineCache,
125+
) -> WgpuPipelineCache {
126+
executor.pipeline_init::<BackgroundCompositor>(pipeline);
127127
pipeline.clone()
128128
}
129129

node-graph/nodes/gstd/src/render_pixel_preview.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use wgpu_executor::{AsyncWgpuPipeline, WgpuExecutor, WgpuPipelineCache};
1010
#[node_macro::node(category(""))]
1111
pub async fn render_pixel_preview<'a: 'n>(
1212
ctx: impl Ctx + ExtractAll + CloneVarArgs + Sync,
13-
#[scope(pixel_preview_pipeline::IDENTIFIER)] pipeline: WgpuPipelineCache<PixelPreview>,
13+
#[scope(pixel_preview_pipeline::IDENTIFIER)] pipeline: WgpuPipelineCache,
1414
data: impl Node<Context<'static>, Output = RenderOutput> + Send + Sync,
1515
) -> RenderOutput {
1616
let Some(render_params) = ctx.vararg(0).ok().and_then(|v| v.downcast_ref::<RenderParams>()).cloned() else {
@@ -58,7 +58,7 @@ pub async fn render_pixel_preview<'a: 'n>(
5858
let transform = DAffine2::from_translation(-upstream_min) * footprint.transform.inverse() * DAffine2::from_scale(logical_resolution);
5959

6060
let resampled = pipeline
61-
.run(&ResamplerArgs {
61+
.run::<PixelPreview>(&ResamplerArgs {
6262
source: source_texture.as_ref(),
6363
transform: &transform,
6464
size: physical_resolution,
@@ -78,9 +78,9 @@ pub async fn render_pixel_preview<'a: 'n>(
7878
async fn pixel_preview_pipeline<'a: 'n>(
7979
_ctx: impl Ctx,
8080
#[scope(crate::platform_application_io::wgpu_executor::IDENTIFIER)] executor: &'a WgpuExecutor,
81-
#[data] pipeline: WgpuPipelineCache<PixelPreview>,
82-
) -> WgpuPipelineCache<PixelPreview> {
83-
executor.pipeline_init(pipeline);
81+
#[data] pipeline: WgpuPipelineCache,
82+
) -> WgpuPipelineCache {
83+
executor.pipeline_init::<PixelPreview>(pipeline);
8484
pipeline.clone()
8585
}
8686

0 commit comments

Comments
 (0)