Memoize hashing (#1876)

* Implement memoization wrapper for hashing

* Fix pattern matching errors

* Revert proper point modification hash calculiton

* Remove unused hashing code

* Code review and bug fixes

* Improve pattern matching

* Fix tests

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-08-01 13:42:15 +02:00
committed by GitHub
parent 44ffb635e9
commit a6af5d4831
19 changed files with 224 additions and 466 deletions

View File

@@ -3,7 +3,7 @@ use crate::proto::{ConstructionArgs, ProtoNetwork, ProtoNode, ProtoNodeInput};
use dyn_any::{DynAny, StaticType};
pub use graphene_core::uuid::generate_uuid;
use graphene_core::{Cow, ProtoNodeIdentifier, Type};
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
use glam::IVec2;
use std::collections::hash_map::DefaultHasher;
@@ -442,7 +442,7 @@ pub enum NodeInput {
Node { node_id: NodeId, output_index: usize, lambda: bool },
/// A hardcoded value that can't change after the graph is compiled. Gets converted into a value node during graph compilation.
Value { tagged_value: TaggedValue, exposed: bool },
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.
@@ -478,7 +478,8 @@ impl NodeInput {
Self::Node { node_id, output_index, lambda: true }
}
pub const fn value(tagged_value: TaggedValue, exposed: bool) -> Self {
pub fn value(tagged_value: TaggedValue, exposed: bool) -> Self {
let tagged_value = tagged_value.into();
Self::Value { tagged_value, exposed }
}
@@ -527,6 +528,13 @@ impl NodeInput {
None
}
}
pub fn as_non_exposed_value(&self) -> Option<&TaggedValue> {
if let NodeInput::Value { tagged_value, exposed: false } = self {
Some(tagged_value)
} else {
None
}
}
pub fn as_node(&self) -> Option<NodeId> {
if let NodeInput::Node { node_id, .. } = self {
@@ -1610,7 +1618,7 @@ mod test {
assert_eq!(extraction_network.nodes.len(), 1);
let inputs = extraction_network.nodes.get(&NodeId(1)).unwrap().inputs.clone();
assert_eq!(inputs.len(), 1);
assert!(matches!(&inputs[0], &NodeInput::Value{ tagged_value: TaggedValue::DocumentNode(ref network), ..} if network == &id_node));
assert!(matches!(&inputs[0].as_value(), &Some(TaggedValue::DocumentNode(ref network), ..) if network == &id_node));
}
#[test]
@@ -1621,13 +1629,7 @@ mod test {
NodeId(1),
DocumentNode {
name: "Inc".into(),
inputs: vec![
NodeInput::network(concrete!(u32), 0),
NodeInput::Value {
tagged_value: TaggedValue::U32(2),
exposed: false,
},
],
inputs: vec![NodeInput::network(concrete!(u32), 0), NodeInput::value(TaggedValue::U32(2), false)],
implementation: DocumentNodeImplementation::Network(add_network()),
..Default::default()
},
@@ -1712,7 +1714,7 @@ mod test {
ProtoNode {
identifier: "graphene_core::value::ClonedNode".into(),
input: ProtoNodeInput::None,
construction_args: ConstructionArgs::Value(TaggedValue::U32(2)),
construction_args: ConstructionArgs::Value(TaggedValue::U32(2).into()),
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(4)]),
inputs_source: HashMap::new(),
@@ -1759,10 +1761,7 @@ mod test {
NodeId(14),
DocumentNode {
name: "Value".into(),
inputs: vec![NodeInput::Value {
tagged_value: TaggedValue::U32(2),
exposed: false,
}],
inputs: vec![NodeInput::value(TaggedValue::U32(2), false)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()),
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(4)]),

View File

@@ -5,7 +5,7 @@ use crate::wasm_application_io::WasmEditorApi;
use graphene_core::raster::brush_cache::BrushCache;
use graphene_core::raster::{BlendMode, LuminanceCalculation};
use graphene_core::{Color, Node, Type};
use graphene_core::{Color, MemoHash, Node, Type};
use dyn_any::DynAny;
pub use dyn_any::StaticType;
@@ -207,17 +207,17 @@ impl Display for TaggedValue {
}
pub struct UpcastNode {
value: TaggedValue,
value: MemoHash<TaggedValue>,
}
impl<'input> Node<'input, DAny<'input>> for UpcastNode {
type Output = FutureAny<'input>;
fn eval(&'input self, _: DAny<'input>) -> Self::Output {
Box::pin(async move { self.value.clone().to_any() })
Box::pin(async move { self.value.clone().into_inner().to_any() })
}
}
impl UpcastNode {
pub fn new(value: TaggedValue) -> Self {
pub fn new(value: MemoHash<TaggedValue>) -> Self {
Self { value }
}
}

View File

@@ -160,7 +160,7 @@ impl core::fmt::Display for ProtoNetwork {
/// Defines the arguments used to construct the boxed node struct. This is used to call the constructor function in the `node_registry.rs` file - which is hidden behind a wall of macros.
pub enum ConstructionArgs {
/// A value of a type that is known, allowing serialization (serde::Deserialize is not object safe)
Value(value::TaggedValue),
Value(MemoHash<value::TaggedValue>),
// TODO: use a struct for clearer naming.
/// A list of nodes used as inputs to the constructor function in `node_registry.rs`.
/// The bool indicates whether to treat the node as lambda node.
@@ -230,7 +230,7 @@ impl Default for ProtoNode {
fn default() -> Self {
Self {
identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode"),
construction_args: ConstructionArgs::Value(value::TaggedValue::U32(0)),
construction_args: ConstructionArgs::Value(value::TaggedValue::U32(0).into()),
input: ProtoNodeInput::None,
original_location: OriginalLocation::default(),
skip_deduplication: false,
@@ -940,12 +940,12 @@ mod test {
assert_eq!(
ids,
vec![
NodeId(5686040524603683634),
NodeId(13787140740513543798),
NodeId(1280393769237740322),
NodeId(3100442468152897091),
NodeId(14834729712909816752),
NodeId(8678825113056010444)
NodeId(12083027370457564588),
NodeId(10127202135369428481),
NodeId(3781642984881236270),
NodeId(9447822059040146367),
NodeId(15916837829094140504),
NodeId(1758919868423328454)
]
);
}
@@ -996,7 +996,7 @@ mod test {
ProtoNode {
identifier: "value".into(),
input: ProtoNodeInput::None,
construction_args: ConstructionArgs::Value(value::TaggedValue::U32(2)),
construction_args: ConstructionArgs::Value(value::TaggedValue::U32(2).into()),
..Default::default()
},
),