Incremental compilation and stable node IDs (#977)

* Generate stable node ids

* checkpoint

* Implement borrow tree

* Add eval function on borrow tree

* Refactor Node trait to fix lifetime issues

* Compiler infinite loop

* Impl compose pair

* Transition to double lifetime on trait

* Change node trait to use a generic arg for the input

* Start adapting node_macro

* Migrate more nodes to new macro

* Fix raster tests

* Port vector nodes

* Make Node trait object safe

* Fix FlatMapResultNode

* Translate most of gstd

* Fix DowncastBothNode

* Refactor node trait once again to allow for HRTB for type erased nodes

* Start working on type erased nodes

* Try getting DowncastBothNode to work

* Introduce Upcasting node + work on BorrowTree

* Make enough 'static to get the code to compile

* Transition DynamicExecutor to use borrow tree

* Make Compose Node use HRTB's

* Fix MapResultNode

* Disable blur test

* Add workaround for Composing type erased nodes

* Convert more nodes in the node_registry

* Convert more of the node_registry

* Add update tree fn and hook up to frontend

* Fix blur node

* Implement CacheNode

* Make frontend use graph compiler

* Fix document_node_types type declaration for most nodes

* Remove unused imports

* Move comment down

* Reuse nodes via borrow tree

* Deprecate trait based value in favor of TaggedValue

* Remove unsafe code in buffer creation

* Fix blur node

* Fix stable node id generation

* Fix types for Image adjustment document nodes

* Fix Imaginate Node

* Remove unused imports

* Remove log

* Fix off by one error

* Remove macro generated imaginate node entry

* Create parameterized add node

* Fix test case

* Remove link from layer_panel.rs

* Fix formatting
This commit is contained in:
Dennis Kobert
2023-02-07 20:06:24 +01:00
committed by Keavon Chambers
parent 77e69f4e5b
commit 620540d7cd
36 changed files with 1548 additions and 1869 deletions

View File

@@ -2,8 +2,11 @@ pub use dyn_any::StaticType;
use dyn_any::{DynAny, Upcast};
use dyn_clone::DynClone;
pub use glam::DVec2;
use graphene_core::Node;
use std::hash::Hash;
pub use std::sync::Arc;
use crate::executor::Any;
pub use crate::imaginate_input::{ImaginateMaskStartingFill, ImaginateSamplingMethod, ImaginateStatus};
/// A type that is known, allowing serialization (serde::Deserialize is not object safe)
@@ -29,9 +32,83 @@ pub enum TaggedValue {
LayerPath(Option<Vec<u64>>),
}
impl TaggedValue {
#[allow(clippy::derive_hash_xor_eq)]
impl Hash for TaggedValue {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
match self {
Self::None => 0.hash(state),
Self::String(s) => {
1.hash(state);
s.hash(state)
}
Self::U32(u) => {
2.hash(state);
u.hash(state)
}
Self::F32(f) => {
3.hash(state);
f.to_bits().hash(state)
}
Self::F64(f) => {
4.hash(state);
f.to_bits().hash(state)
}
Self::Bool(b) => {
5.hash(state);
b.hash(state)
}
Self::DVec2(v) => {
6.hash(state);
v.to_array().iter().for_each(|x| x.to_bits().hash(state))
}
Self::OptionalDVec2(None) => 7.hash(state),
Self::OptionalDVec2(Some(v)) => {
8.hash(state);
Self::DVec2(*v).hash(state)
}
Self::Image(i) => {
9.hash(state);
i.hash(state)
}
Self::RcImage(i) => {
10.hash(state);
i.hash(state)
}
Self::Color(c) => {
11.hash(state);
c.hash(state)
}
Self::Subpath(s) => {
12.hash(state);
s.hash(state)
}
Self::RcSubpath(s) => {
13.hash(state);
s.hash(state)
}
Self::ImaginateSamplingMethod(m) => {
14.hash(state);
m.hash(state)
}
Self::ImaginateMaskStartingFill(f) => {
15.hash(state);
f.hash(state)
}
Self::ImaginateStatus(s) => {
16.hash(state);
s.hash(state)
}
Self::LayerPath(p) => {
17.hash(state);
p.hash(state)
}
}
}
}
impl<'a> TaggedValue {
/// Converts to a Box<dyn DynAny> - this isn't very neat but I'm not sure of a better approach
pub fn to_value(self) -> Value {
pub fn to_any(self) -> Any<'a> {
match self {
TaggedValue::None => Box::new(()),
TaggedValue::String(x) => Box::new(x),
@@ -54,19 +131,35 @@ impl TaggedValue {
}
}
pub type Value = Box<dyn ValueTrait>;
pub struct UpcastNode {
value: TaggedValue,
}
impl<'input> Node<'input, Box<dyn DynAny<'input> + 'input>> for UpcastNode {
type Output = Box<dyn DynAny<'input> + 'input>;
pub trait ValueTrait: DynAny<'static> + Upcast<dyn DynAny<'static>> + std::fmt::Debug + DynClone {}
fn eval<'s: 'input>(&'s self, _: Box<dyn DynAny<'input> + 'input>) -> Self::Output {
self.value.clone().to_any()
}
}
impl UpcastNode {
pub fn new(value: TaggedValue) -> Self {
Self { value }
}
}
pub trait IntoValue: Sized + ValueTrait + 'static {
fn into_any(self) -> Value {
pub type Value<'a> = Box<dyn for<'i> ValueTrait<'i> + 'a>;
pub trait ValueTrait<'a>: DynAny<'a> + Upcast<dyn DynAny<'a> + 'a> + std::fmt::Debug + DynClone + Sync + Send + 'a {}
pub trait IntoValue<'a>: Sized + for<'i> ValueTrait<'i> + 'a {
fn into_any(self) -> Value<'a> {
Box::new(self)
}
}
impl<T: 'static + StaticType + Upcast<dyn DynAny<'static>> + std::fmt::Debug + PartialEq + Clone> ValueTrait for T {}
impl<'a, T: 'a + StaticType + Upcast<dyn DynAny<'a> + 'a> + std::fmt::Debug + PartialEq + Clone + Sync + Send + 'a> ValueTrait<'a> for T {}
impl<T: 'static + ValueTrait> IntoValue for T {}
impl<'a, T: for<'i> ValueTrait<'i> + 'a> IntoValue<'a> for T {}
#[repr(C)]
pub(crate) struct Vtable {
@@ -81,7 +174,7 @@ pub(crate) struct TraitObject {
pub(crate) vtable: &'static Vtable,
}
impl PartialEq for Box<dyn ValueTrait> {
impl<'a> PartialEq for Box<dyn for<'i> ValueTrait<'i> + 'a> {
#[cfg_attr(miri, ignore)]
fn eq(&self, other: &Self) -> bool {
if self.type_id() != other.type_id() {
@@ -96,7 +189,16 @@ impl PartialEq for Box<dyn ValueTrait> {
}
}
impl Clone for Value {
impl<'a> Hash for Value<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) };
let size = self_trait_object.vtable.size;
let self_mem = unsafe { std::slice::from_raw_parts(self_trait_object.self_ptr, size) };
self_mem.hash(state);
}
}
impl<'a> Clone for Value<'a> {
fn clone(&self) -> Self {
let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) };
let size = self_trait_object.vtable.size;
@@ -116,6 +218,7 @@ mod test {
use super::*;
#[test]
#[cfg_attr(miri, ignore)]
fn test_any_src() {
assert!(2_u32.into_any() == 2_u32.into_any());
assert!(2_u32.into_any() != 3_u32.into_any());