Skip to content

Commit cce943e

Browse files
committed
Implement context modification node insertion
1 parent cccd47a commit cce943e

3 files changed

Lines changed: 64 additions & 9 deletions

File tree

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use graphene_core::uuid::NodeId;
1515
use graphene_core::vector::Vector;
1616
use graphene_core::vector::style::Fill;
1717
use graphene_core::vector::style::GradientStops;
18-
use graphene_core::{Artboard, Color, Graphic, MemoHash, Node, Type};
18+
use graphene_core::{Artboard, Color, ContextFeatures, Graphic, MemoHash, Node, Type};
1919
use graphene_svg_renderer::RenderMetadata;
2020
use std::fmt::Display;
2121
use std::hash::Hash;
@@ -212,6 +212,7 @@ tagged_value! {
212212
BrushStrokes(Vec<BrushStroke>),
213213
BrushCache(BrushCache),
214214
DocumentNode(DocumentNode),
215+
ContextFeatures(ContextFeatures),
215216
Curve(graphene_raster_nodes::curve::Curve),
216217
Footprint(graphene_core::transform::Footprint),
217218
VectorModification(Box<graphene_core::vector::VectorModification>),

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl Compiler {
1717
let proto_networks = network.into_proto_networks();
1818

1919
proto_networks.map(move |mut proto_network| {
20-
proto_network.resolve_inputs()?;
20+
proto_network.insert_context_nullification_nodes()?;
2121
proto_network.generate_stable_node_ids();
2222
Ok(proto_network)
2323
})

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

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::document::value::TaggedValue;
12
use crate::document::{InlineRust, value};
23
use crate::document::{NodeId, OriginalLocation};
34
pub use graphene_core::registry::*;
@@ -296,15 +297,68 @@ impl ProtoNetwork {
296297
/// Inserts context nullification nodes to optimize caching
297298
/// This analysis is performed after topological sorting to ensure proper dependency tracking
298299
pub fn insert_context_nullification_nodes(&mut self) -> Result<(), String> {
299-
// TODO: Implement full context flow analysis with:
300-
// 1. DFS traversal to track context feature requirements
301-
// 2. Branch convergence analysis
302-
// 3. Post-injection nullification
303-
// 4. Insert ContextModificationNode instances where beneficial
300+
// Perform topological sort once
301+
self.reorder_ids()?;
302+
304303
let mut out_nodes = Vec::with_capacity(10);
305304
self.find_context_dependencies(self.output, &mut out_nodes);
306305
out_nodes.sort_by_key(|&(id, _)| id);
307306

307+
// TODO: use outwards edges tracked in original node location instead
308+
// Collect outward edges once
309+
let outwards_edges = self.collect_outwards_edges();
310+
311+
for (node_id, context_deps) in out_nodes {
312+
let memo_node_id = NodeId(self.nodes.len() as u64);
313+
let (_, node) = &self.nodes[node_id.0 as usize];
314+
let path = node.original_location.path.clone();
315+
316+
self.nodes.push((
317+
memo_node_id,
318+
ProtoNode {
319+
construction_args: ConstructionArgs::Nodes(vec![node_id]),
320+
call_argument: concrete!(Context),
321+
identifier: graphene_core::memo::memo::IDENTIFIER,
322+
original_location: OriginalLocation {
323+
path: path.clone(),
324+
..Default::default()
325+
},
326+
..Default::default()
327+
},
328+
));
329+
330+
let nullification_value_node_id = NodeId(self.nodes.len() as u64);
331+
332+
self.nodes.push((
333+
nullification_value_node_id,
334+
ProtoNode {
335+
construction_args: ConstructionArgs::Value(MemoHash::new(TaggedValue::ContextFeatures(context_deps))),
336+
call_argument: concrete!(Context),
337+
identifier: ProtoNodeIdentifier::new("graphene_core::value::ClonedNode"),
338+
original_location: OriginalLocation {
339+
path: path.clone(),
340+
..Default::default()
341+
},
342+
..Default::default()
343+
},
344+
));
345+
let nullification_node_id = NodeId(self.nodes.len() as u64);
346+
self.nodes.push((
347+
nullification_node_id,
348+
ProtoNode {
349+
construction_args: ConstructionArgs::Nodes(vec![memo_node_id, nullification_node_id]),
350+
call_argument: concrete!(Context),
351+
identifier: graphene_core::context_modification::context_modification::IDENTIFIER,
352+
original_location: OriginalLocation {
353+
path: path.clone(),
354+
..Default::default()
355+
},
356+
..Default::default()
357+
},
358+
));
359+
self.replace_node_id(&outwards_edges, node_id, nullification_node_id);
360+
}
361+
308362
Ok(())
309363
}
310364

@@ -321,7 +375,7 @@ impl ProtoNetwork {
321375
};
322376

323377
// Compute the dependencies for each branch and combine all of them
324-
for &(node, _) in inputs {
378+
for &node in inputs {
325379
let branch = self.find_context_dependencies(node, out_nodes);
326380
branch_dependencies.push(branch);
327381
combined_deps |= branch;
@@ -338,7 +392,7 @@ impl ProtoNetwork {
338392
let we_introduce_new_deps = !combined_deps.contains(new_deps);
339393

340394
// For diverging branches, we can add a cache node for all branches which don't reqire all dependencies
341-
for (&(node, _), deps) in inputs.iter().zip(branch_dependencies.into_iter()) {
395+
for (&node, deps) in inputs.iter().zip(branch_dependencies.into_iter()) {
342396
if we_introduce_new_deps || deps != combined_deps {
343397
out_nodes.push((node, deps));
344398
}

0 commit comments

Comments
 (0)