Remove type from NodeInput::Network

This commit is contained in:
hypercube 2024-10-26 20:18:31 +01:00 committed by Keavon Chambers
parent 9eeefaad90
commit 45fd24650a
14 changed files with 53 additions and 54 deletions

View file

@ -3421,10 +3421,7 @@ impl NodeNetworkInterface {
pub fn create_wire(&mut self, output_connector: &OutputConnector, input_connector: &InputConnector, network_path: &[NodeId]) {
let input = match output_connector {
OutputConnector::Node { node_id, output_index } => NodeInput::node(*node_id, *output_index),
OutputConnector::Import(import_index) => NodeInput::Network {
import_type: graph_craft::generic!(T),
import_index: *import_index,
},
OutputConnector::Import(import_index) => NodeInput::Network { import_index: *import_index },
};
self.set_input(input_connector, input, network_path);

View file

@ -229,7 +229,7 @@ impl NodeRuntime {
// We assume only one output
assert_eq!(scoped_network.exports.len(), 1, "Graph with multiple outputs not yet handled");
let c = Compiler {};
let proto_network = match c.compile_single(scoped_network) {
let proto_network = match c.compile_single(scoped_network, &[concrete!(RenderConfig)]) {
Ok(network) => network,
Err(e) => return Err(e),
};

View file

@ -30,6 +30,7 @@
// Number presentation
export let displayDecimalPlaces = 2;
export let unit = "";
$: console.info("new unit", unit);
export let unitIsHiddenWhenEditing = true;
// Mode behavior

View file

@ -13,7 +13,8 @@ fn main() {
let network = add_network();
let compiler = graph_craft::graphene_compiler::Compiler {};
let proto_network = compiler.compile_single(network).unwrap();
let input_types = vec![concrete!(Color), concrete!(Color), concrete!(u32)];
let proto_network = compiler.compile_single(network, &input_types).unwrap();
let io = ShaderIO {
inputs: vec![
@ -25,7 +26,7 @@ fn main() {
output: ShaderInput::OutputBuffer((), concrete!(Color)),
};
let compile_request = CompileRequest::new(vec![proto_network], vec![concrete!(Color), concrete!(Color), concrete!(u32)], vec![concrete!(Color)], io);
let compile_request = CompileRequest::new(vec![proto_network], input_types, vec![concrete!(Color)], io);
let response = client
.post("http://localhost:3000/compile/spirv")
.timeout(Duration::from_secs(30))

View file

@ -1,12 +1,14 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use graph_craft::util::DEMO_ART;
fn compile_to_proto(c: &mut Criterion) {
use graph_craft::util::{compile, load_from_name};
use graph_craft::util::{compile_with_render_config, load_from_name};
let mut c = c.benchmark_group("Compile Network cold");
for name in DEMO_ART {
let network = load_from_name(name);
c.bench_function(name, |b| b.iter_batched(|| network.clone(), |network| compile(black_box(network)), criterion::BatchSize::SmallInput));
c.bench_function(name, |b| {
b.iter_batched(|| network.clone(), |network| compile_with_render_config(black_box(network)), criterion::BatchSize::SmallInput)
});
}
}

View file

@ -5,7 +5,7 @@ use iai_callgrind::{black_box, library_benchmark, library_benchmark_group, main}
#[library_benchmark]
#[benches::with_setup(args = ["isometric-fountain", "painted-dreams", "procedural-string-lights", "red-dress", "valley-of-spires"], setup = load_from_name)]
pub fn compile_to_proto(_input: NodeNetwork) {
black_box(compile(_input));
black_box(compile_with_render_config(_input));
}
library_benchmark_group!(name = compile_group; benchmarks = compile_to_proto);

View file

@ -286,7 +286,7 @@ impl DocumentNode {
}
}
fn resolve_proto_node(mut self) -> ProtoNode {
fn resolve_proto_node(mut self, global_import_types: &[Type]) -> ProtoNode {
assert!(!self.inputs.is_empty() || self.manual_composition.is_some(), "Resolving document node {self:#?} with no inputs");
let DocumentNodeImplementation::ProtoNode(fqn) = self.implementation else {
unreachable!("tried to resolve not flattened node on resolved node {self:?}");
@ -311,7 +311,10 @@ impl DocumentNode {
let node = if lambda { ProtoNodeInput::NodeLambda(node_id) } else { ProtoNodeInput::Node(node_id) };
(node, ConstructionArgs::Nodes(vec![]))
}
NodeInput::Network { import_type, .. } => (ProtoNodeInput::ManualComposition(import_type), ConstructionArgs::Nodes(vec![])),
NodeInput::Network { import_index } => {
let ty = global_import_types.get(import_index).expect("import index in global_import_types").clone();
(ProtoNodeInput::ManualComposition(ty), ConstructionArgs::Nodes(vec![]))
}
NodeInput::Inline(inline) => (ProtoNodeInput::None, ConstructionArgs::Inline(inline)),
NodeInput::Scope(_) => unreachable!("Scope input was not resolved"),
NodeInput::Reflection(_) => unreachable!("Reflection input was not resolved"),
@ -355,9 +358,8 @@ pub enum NodeInput {
/// A hardcoded value that can't change after the graph is compiled. Gets converted into a value node during graph compilation.
Value { tagged_value: MemoHash<TaggedValue>, exposed: bool },
// TODO: Remove import_type and get type from parent node input
/// Input that is provided by the parent network to this document node, instead of from a hardcoded value or another node within the same network.
Network { import_type: Type, import_index: usize },
Network { import_index: usize },
/// Input that is extracted from the parent scopes the node resides in. The string argument is the key.
Scope(Cow<'static, str>),
@ -403,8 +405,8 @@ impl NodeInput {
Self::Value { tagged_value, exposed }
}
pub const fn network(import_type: Type, import_index: usize) -> Self {
Self::Network { import_type, import_index }
pub fn network(_import_type: Type, import_index: usize) -> Self {
Self::Network { import_index }
}
pub fn scope(key: impl Into<Cow<'static, str>>) -> Self {
@ -447,7 +449,7 @@ impl NodeInput {
match self {
NodeInput::Node { .. } => unreachable!("ty() called on NodeInput::Node"),
NodeInput::Value { tagged_value, .. } => tagged_value.ty(),
NodeInput::Network { import_type, .. } => import_type.clone(),
NodeInput::Network { .. } => unreachable!("ty() called on NodeInput::Network"),
NodeInput::Inline(_) => panic!("ty() called on NodeInput::Inline"),
NodeInput::Scope(_) => unreachable!("ty() called on NodeInput::Scope"),
NodeInput::Reflection(_) => concrete!(Metadata),
@ -1312,8 +1314,8 @@ impl NodeNetwork {
}
/// Creates a proto network for evaluating each output of this network.
pub fn into_proto_networks(self) -> impl Iterator<Item = ProtoNetwork> {
let nodes: Vec<_> = self.nodes.into_iter().map(|(id, node)| (id, node.resolve_proto_node())).collect();
pub fn into_proto_networks(self, global_import_types: &[Type]) -> impl Iterator<Item = ProtoNetwork> {
let nodes: Vec<_> = self.nodes.into_iter().map(|(id, node)| (id, node.resolve_proto_node(global_import_types))).collect();
// Create a network to evaluate each output
if self.exports.len() == 1 {
@ -1507,7 +1509,7 @@ mod test {
..Default::default()
};
let proto_node = document_node.resolve_proto_node();
let proto_node = document_node.resolve_proto_node(&[concrete!(u32)]);
let reference = ProtoNode {
identifier: "graphene_core::structural::ConsNode".into(),
input: ProtoNodeInput::ManualComposition(concrete!(u32)),
@ -1577,7 +1579,7 @@ mod test {
.collect(),
};
let network = flat_network();
let mut resolved_network = network.into_proto_networks().collect::<Vec<_>>();
let mut resolved_network = network.into_proto_networks(&[concrete!(u32)]).collect::<Vec<_>>();
resolved_network[0].nodes.sort_unstable_by_key(|(id, _)| *id);
println!("{:#?}", resolved_network[0]);

View file

@ -6,7 +6,7 @@ use crate::proto::{LocalFuture, ProtoNetwork};
pub struct Compiler {}
impl Compiler {
pub fn compile(&self, mut network: NodeNetwork) -> impl Iterator<Item = Result<ProtoNetwork, String>> {
pub fn compile(&self, mut network: NodeNetwork, global_import_types: &[crate::Type]) -> impl Iterator<Item = Result<ProtoNetwork, String>> {
let node_ids = network.nodes.keys().copied().collect::<Vec<_>>();
network.populate_dependants();
for id in node_ids {
@ -15,7 +15,7 @@ impl Compiler {
network.resolve_scope_inputs();
network.remove_redundant_id_nodes();
// network.remove_dead_nodes(0);
let proto_networks = network.into_proto_networks();
let proto_networks = network.into_proto_networks(global_import_types);
proto_networks.map(move |mut proto_network| {
proto_network.resolve_inputs()?;
@ -23,9 +23,9 @@ impl Compiler {
Ok(proto_network)
})
}
pub fn compile_single(&self, network: NodeNetwork) -> Result<ProtoNetwork, String> {
pub fn compile_single(&self, network: NodeNetwork, global_import_types: &[crate::Type]) -> Result<ProtoNetwork, String> {
assert_eq!(network.exports.len(), 1, "Graph with multiple outputs not yet handled");
let Some(proto_network) = self.compile(network).next() else {
let Some(proto_network) = self.compile(network, global_import_types).next() else {
return Err("Failed to convert graph into proto graph".to_string());
};
proto_network

View file

@ -7,9 +7,9 @@ pub fn load_network(document_string: &str) -> NodeNetwork {
serde_json::from_value::<NodeNetwork>(document["network_interface"]["network"].clone()).expect("Failed to parse document")
}
pub fn compile(network: NodeNetwork) -> ProtoNetwork {
pub fn compile_with_render_config(network: NodeNetwork) -> ProtoNetwork {
let compiler = Compiler {};
compiler.compile_single(network).unwrap()
compiler.compile_single(network, &[concrete!(graphene_core::application_io::RenderConfig)]).unwrap()
}
pub fn load_from_name(name: &str) -> NodeNetwork {

View file

@ -1,7 +1,7 @@
use graph_craft::document::*;
use graph_craft::graphene_compiler::{Compiler, Executor};
use graph_craft::util::load_network;
use graph_craft::wasm_application_io::EditorPreferences;
use graph_craft::{concrete, document::*};
use graphene_core::application_io::{ApplicationIo, NodeGraphUpdateSender};
use graphene_core::text::FontCache;
use graphene_std::wasm_application_io::{WasmApplicationIo, WasmEditorApi};
@ -105,7 +105,7 @@ fn create_executor(document_string: String, editor_api: Arc<WasmEditorApi>) -> R
let wrapped_network = wrap_network_in_scope(network.clone(), editor_api);
let compiler = Compiler {};
let protograph = compiler.compile_single(wrapped_network)?;
let protograph = compiler.compile_single(wrapped_network, &[concrete!(graphene_core::application_io::RenderConfig)])?;
let executor = block_on(DynamicExecutor::new(protograph)).unwrap();
Ok(executor)
}

View file

@ -18,23 +18,17 @@ use crate::wasm_application_io::WasmApplicationIo;
// TODO: Move to graph-craft
#[node_macro::node(category("Debug: GPU"))]
async fn compile_gpu<'a: 'n>(_: (), node: &'a DocumentNode, typing_context: TypingContext, io: ShaderIO) -> Result<compilation_client::Shader, String> {
async fn compile_gpu<'a: 'n>(_: (), node: &'a DocumentNode, typing_context: TypingContext, input_types: Vec<Type>, io: ShaderIO) -> Result<compilation_client::Shader, String> {
let mut typing_context = typing_context;
let compiler = graph_craft::graphene_compiler::Compiler {};
let DocumentNodeImplementation::Network(ref network) = node.implementation else { panic!() };
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone()).collect();
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone(), &input_types).collect();
let proto_networks = proto_networks?;
for network in proto_networks.iter() {
typing_context.update(network).expect("Failed to type check network");
}
// TODO: do a proper union
let input_types = proto_networks[0]
.inputs
.iter()
.map(|id| typing_context.type_of(*id).unwrap())
.map(|node_io| node_io.return_value.clone())
.collect();
let output_types = proto_networks.iter().map(|network| typing_context.type_of(network.output).unwrap().return_value.clone()).collect();
Ok(compilation_client::compile(proto_networks, input_types, output_types, io).await.unwrap())
@ -187,11 +181,12 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node
..Default::default()
};
log::debug!("compiling network");
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone()).collect();
let global_input_types = vec![concrete!(u32), concrete!(Color)];
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone(), &global_input_types).collect();
log::debug!("compiling shader");
let shader = compilation_client::compile(
proto_networks?,
vec![concrete!(u32), concrete!(Color)],
global_input_types,
vec![concrete!(Color)],
ShaderIO {
inputs: vec![
@ -317,7 +312,15 @@ async fn blend_gpu_image(_: (), foreground: ImageFrame<Color>, background: Image
..Default::default()
};
log::debug!("compiling network");
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone()).collect();
let global_input_types = vec![
concrete!(u32),
concrete!(Color),
concrete!(Color),
concrete!(u32),
concrete_with_name!(Mat2, "Mat2"),
concrete_with_name!(Vec2, "Vec2"),
];
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone(), &global_input_types).collect();
let Ok(proto_networks_result) = proto_networks else {
log::error!("Error compiling network in 'blend_gpu_image()");
return ImageFrame::empty();
@ -327,14 +330,7 @@ async fn blend_gpu_image(_: (), foreground: ImageFrame<Color>, background: Image
let shader = compilation_client::compile(
proto_networks,
vec![
concrete!(u32),
concrete!(Color),
concrete!(Color),
concrete!(u32),
concrete_with_name!(Mat2, "Mat2"),
concrete_with_name!(Vec2, "Vec2"),
],
global_input_types,
vec![concrete!(Color)],
ShaderIO {
inputs: vec![

View file

@ -2,13 +2,13 @@ use criterion::{measurement::Measurement, BenchmarkGroup};
use futures::executor::block_on;
use graph_craft::{
proto::ProtoNetwork,
util::{compile, load_from_name, DEMO_ART},
util::{compile_with_render_config, load_from_name, DEMO_ART},
};
use interpreted_executor::dynamic_executor::DynamicExecutor;
pub fn setup_network(name: &str) -> (DynamicExecutor, ProtoNetwork) {
let network = load_from_name(name);
let proto_network = compile(network);
let proto_network = compile_with_render_config(network);
let executor = block_on(DynamicExecutor::new(proto_network.clone())).unwrap();
(executor, proto_network)
}

View file

@ -2,14 +2,14 @@ use criterion::{black_box, criterion_group, criterion_main, measurement::Measure
use graph_craft::{
graphene_compiler::Executor,
proto::ProtoNetwork,
util::{compile, load_from_name, DEMO_ART},
util::{compile_with_render_config, load_from_name, DEMO_ART},
};
use graphene_std::transform::Footprint;
use interpreted_executor::dynamic_executor::DynamicExecutor;
fn update_executor<M: Measurement>(name: &str, c: &mut BenchmarkGroup<M>) {
let network = load_from_name(name);
let proto_network = compile(network);
let proto_network = compile_with_render_config(network);
let empty = ProtoNetwork::default();
let executor = futures::executor::block_on(DynamicExecutor::new(empty)).unwrap();
@ -32,7 +32,7 @@ fn update_executor_demo(c: &mut Criterion) {
fn run_once<M: Measurement>(name: &str, c: &mut BenchmarkGroup<M>) {
let network = load_from_name(name);
let proto_network = compile(network);
let proto_network = compile_with_render_config(network);
let executor = futures::executor::block_on(DynamicExecutor::new(proto_network)).unwrap();
let footprint = Footprint::default();

View file

@ -44,7 +44,7 @@ mod tests {
use graph_craft::graphene_compiler::Compiler;
let compiler = Compiler {};
let protograph = compiler.compile_single(network).expect("Graph should be generated");
let protograph = compiler.compile_single(network, &[concrete!(u32)]).expect("Graph should be generated");
let _exec = block_on(DynamicExecutor::new(protograph)).map(|_e| panic!("The network should not type check ")).unwrap_err();
}