mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 07:48:02 +08:00
Graphene CLI + quantization research (#1320)
* Implement skeleton for graphene-cli * Configure gpu surface on non wasm32 targets * Create window with full hd size * Create window using the graphen-cli * Use window size for surface creation * Reuse surface configuration * Reduce window size for native applications to 800x600 * Add compute pipeline test * Poll wgpu execution externally * Remove cache node after texture upload * Add profiling instructions * Add more debug markers * Evaluate extract node before flattening the network * Reenable hue saturation node for compilation * Make hue saturation node work on the gpu + make f32 default for user inputs * Add version of test files without caching * Only dispatch each workgroup not pixel * ICE * Add quantization to gpu code * Fix quantization * Load images at graph runtime * Fix quantization calculation * Feature gate quantization * Use git version of autoquant * Add license to `graphene-cli` * Fix graphene-cli test case * Ignore tests on non unix platforms * Fix flattening test
This commit is contained in:
@@ -99,7 +99,7 @@ impl DocumentNode {
|
||||
document_node_path: self.path.unwrap_or(Vec::new()),
|
||||
}
|
||||
} else {
|
||||
unreachable!("tried to resolve not flattened node on resolved node");
|
||||
unreachable!("tried to resolve not flattened node on resolved node {:?}", self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -654,10 +654,13 @@ impl NodeNetwork {
|
||||
|
||||
/// Recursively dissolve non-primitive document nodes and return a single flattened network of nodes.
|
||||
pub fn flatten_with_fns(&mut self, node: NodeId, map_ids: impl Fn(NodeId, NodeId) -> NodeId + Copy, gen_id: impl Fn() -> NodeId + Copy) {
|
||||
let (id, mut node) = self
|
||||
self.resolve_extract_nodes();
|
||||
let Some((id, mut node)) = self
|
||||
.nodes
|
||||
.remove_entry(&node)
|
||||
.unwrap_or_else(|| panic!("The node which was supposed to be flattened does not exist in the network, id {} network {:#?}", node, self));
|
||||
.remove_entry(&node) else {
|
||||
warn!("The node which was supposed to be flattened does not exist in the network, id {} network {:#?}", node, self);
|
||||
return;
|
||||
};
|
||||
|
||||
if self.disabled.contains(&id) {
|
||||
node.implementation = DocumentNodeImplementation::Unresolved("graphene_core::ops::IdNode".into());
|
||||
@@ -665,11 +668,12 @@ impl NodeNetwork {
|
||||
self.nodes.insert(id, node);
|
||||
return;
|
||||
}
|
||||
log::debug!("Flattening node {:?}", &node.name);
|
||||
|
||||
// replace value inputs with value nodes
|
||||
for input in &mut node.inputs {
|
||||
// Skip inputs that are already value nodes
|
||||
if node.implementation == DocumentNodeImplementation::Unresolved("graphene_core::value::ValueNode".into()) {
|
||||
if node.implementation == DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -690,7 +694,7 @@ impl NodeNetwork {
|
||||
DocumentNode {
|
||||
name: "Value".into(),
|
||||
inputs: vec![NodeInput::Value { tagged_value, exposed }],
|
||||
implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ValueNode".into()),
|
||||
implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into()),
|
||||
path,
|
||||
..Default::default()
|
||||
},
|
||||
@@ -706,6 +710,8 @@ impl NodeNetwork {
|
||||
}
|
||||
|
||||
if let DocumentNodeImplementation::Network(mut inner_network) = node.implementation {
|
||||
// Resolve all extract nodes in the inner network
|
||||
inner_network.resolve_extract_nodes();
|
||||
// Connect all network inputs to either the parent network nodes, or newly created value nodes.
|
||||
inner_network.map_ids(|inner_id| map_ids(id, inner_id));
|
||||
let new_nodes = inner_network.nodes.keys().cloned().collect::<Vec<_>>();
|
||||
@@ -717,8 +723,10 @@ impl NodeNetwork {
|
||||
assert_eq!(
|
||||
node.inputs.len(),
|
||||
inner_network.inputs.len(),
|
||||
"The number of inputs to the node and the inner network must be the same {}",
|
||||
node.name
|
||||
"The number of inputs to the node and the inner network must be the same for {}. The node has {:?} inputs, the network has {:?} inputs.",
|
||||
node.name,
|
||||
node.inputs,
|
||||
inner_network.inputs
|
||||
);
|
||||
// Match the document node input and the inputs of the inner network
|
||||
for (document_input, network_input) in node.inputs.into_iter().zip(inner_network.inputs.iter()) {
|
||||
@@ -829,21 +837,30 @@ impl NodeNetwork {
|
||||
self.nodes.retain(|_, node| !matches!(node.implementation, DocumentNodeImplementation::Extract));
|
||||
|
||||
for (_, node) in &mut extraction_nodes {
|
||||
log::info!("extraction network: {:#?}", &self);
|
||||
if let DocumentNodeImplementation::Extract = node.implementation {
|
||||
assert_eq!(node.inputs.len(), 1);
|
||||
log::debug!("Resolving extract node {:?}", node);
|
||||
let NodeInput::Node { node_id, output_index, .. } = node.inputs.pop().unwrap() else {
|
||||
panic!("Extract node has no input");
|
||||
panic!("Extract node has no input, inputs: {:?}", node.inputs);
|
||||
};
|
||||
assert_eq!(output_index, 0);
|
||||
// TODO: check if we can readd lambda checking
|
||||
let mut input_node = self.nodes.remove(&node_id).unwrap();
|
||||
node.implementation = DocumentNodeImplementation::Unresolved("graphene_core::value::ValueNode".into());
|
||||
node.implementation = DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into());
|
||||
if let Some(input) = input_node.inputs.get_mut(0) {
|
||||
*input = match &input {
|
||||
NodeInput::Node { .. } => NodeInput::Network(generic!(T)),
|
||||
ni => NodeInput::Network(ni.ty()),
|
||||
};
|
||||
}
|
||||
|
||||
for input in input_node.inputs.iter_mut() {
|
||||
match input {
|
||||
NodeInput::Node { .. } | NodeInput::Value { .. } => *input = NodeInput::Network(generic!(T)),
|
||||
_ => (),
|
||||
if let NodeInput::Node { .. } = input {
|
||||
*input = NodeInput::Network(generic!(T))
|
||||
}
|
||||
}
|
||||
log::debug!("Extract node {:?} resolved to {:?}", node, input_node);
|
||||
node.inputs = vec![NodeInput::value(TaggedValue::DocumentNode(input_node), false)];
|
||||
}
|
||||
}
|
||||
@@ -1108,7 +1125,7 @@ mod test {
|
||||
tagged_value: TaggedValue::U32(2),
|
||||
exposed: false,
|
||||
}],
|
||||
implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ValueNode".into()),
|
||||
implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into()),
|
||||
path: Some(vec![1, 4]),
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
@@ -55,6 +55,7 @@ pub enum TaggedValue {
|
||||
ManipulatorGroupIds(Vec<graphene_core::uuid::ManipulatorGroupId>),
|
||||
Font(graphene_core::text::Font),
|
||||
BrushStrokes(Vec<graphene_core::vector::brush_stroke::BrushStroke>),
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
BrushCache(BrushCache),
|
||||
Segments(Vec<graphene_core::raster::ImageFrame<Color>>),
|
||||
DocumentNode(DocumentNode),
|
||||
@@ -193,6 +194,7 @@ impl<'a> TaggedValue {
|
||||
TaggedValue::F64(x) => x.to_string() + "_f64",
|
||||
TaggedValue::Bool(x) => x.to_string(),
|
||||
TaggedValue::BlendMode(blend_mode) => "BlendMode::".to_string() + &blend_mode.to_string(),
|
||||
TaggedValue::Color(color) => "graphene_core::Color::from_rgbaf32_unchecked(0.,0.,0.,1.)".to_string(),
|
||||
_ => panic!("Cannot convert to primitive string"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,12 @@ pub struct Compiler {}
|
||||
|
||||
impl Compiler {
|
||||
pub fn compile(&self, mut network: NodeNetwork, resolve_inputs: bool) -> impl Iterator<Item = ProtoNetwork> {
|
||||
let node_ids = network.nodes.keys().copied().collect::<Vec<_>>();
|
||||
println!("flattening");
|
||||
let node_ids = network.nodes.keys().copied().collect::<Vec<_>>();
|
||||
for id in node_ids {
|
||||
network.flatten(id);
|
||||
}
|
||||
network.remove_redundant_id_nodes();
|
||||
network.resolve_extract_nodes();
|
||||
network.remove_dead_nodes();
|
||||
let proto_networks = network.into_proto_networks();
|
||||
proto_networks.map(move |mut proto_network| {
|
||||
|
||||
@@ -20,10 +20,10 @@ pub type LocalFuture<'n, T> = Pin<Box<dyn core::future::Future<Output = T> + 'n>
|
||||
pub type Any<'n> = Box<dyn DynAny<'n> + 'n>;
|
||||
pub type FutureAny<'n> = DynFuture<'n, Any<'n>>;
|
||||
pub type TypeErasedNode<'n> = dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n;
|
||||
pub type TypeErasedPinnedRef<'n> = Pin<&'n (dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n)>;
|
||||
pub type TypeErasedRef<'n> = &'n (dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n);
|
||||
pub type TypeErasedBox<'n> = Box<dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n>;
|
||||
pub type TypeErasedPinned<'n> = Pin<Box<dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n>>;
|
||||
pub type TypeErasedPinnedRef<'n> = Pin<&'n TypeErasedNode<'n>>;
|
||||
pub type TypeErasedRef<'n> = &'n TypeErasedNode<'n>;
|
||||
pub type TypeErasedBox<'n> = Box<TypeErasedNode<'n>>;
|
||||
pub type TypeErasedPinned<'n> = Pin<Box<TypeErasedNode<'n>>>;
|
||||
|
||||
pub type NodeConstructor = for<'a> fn(Vec<Arc<NodeContainer>>) -> DynFuture<'static, TypeErasedBox<'static>>;
|
||||
|
||||
@@ -181,7 +181,7 @@ impl Hash for ConstructionArgs {
|
||||
impl ConstructionArgs {
|
||||
pub fn new_function_args(&self) -> Vec<String> {
|
||||
match self {
|
||||
ConstructionArgs::Nodes(nodes) => nodes.iter().map(|n| format!("&n{}", n.0)).collect(),
|
||||
ConstructionArgs::Nodes(nodes) => nodes.iter().map(|n| format!("n{:0x}", n.0)).collect(),
|
||||
ConstructionArgs::Value(value) => vec![value.to_primitive_string()],
|
||||
ConstructionArgs::Inline(inline) => vec![inline.expr.clone()],
|
||||
}
|
||||
@@ -248,7 +248,7 @@ impl ProtoNode {
|
||||
|
||||
pub fn value(value: ConstructionArgs, path: Vec<NodeId>) -> Self {
|
||||
Self {
|
||||
identifier: NodeIdentifier::new("graphene_core::value::ValueNode"),
|
||||
identifier: NodeIdentifier::new("graphene_core::value::ClonedNode"),
|
||||
construction_args: value,
|
||||
input: ProtoNodeInput::None,
|
||||
document_node_path: path,
|
||||
|
||||
Reference in New Issue
Block a user