Implement Infrastructure to reuse previous frames for brush drawing

Implement Infrastructuro to reuse the previous evaluation of the
node graph to blend the new stroke with instead of drawing the
entire trace from scratch.
This does not transition to a blending based approach because that still
caused regressions but allows the brush node to work with input data
natively.

Test Plan:
- Use the brush tool in the editor and check for regressions
- Evaluate the performance

Reviewers: Keavon

Pull Request: https://github.com/GraphiteEditor/Graphite/pull/1190
This commit is contained in:
Dennis Kobert
2023-05-03 13:14:41 +02:00
committed by Keavon Chambers
parent ebf67eaa82
commit 3adcc3031a
19 changed files with 282 additions and 172 deletions
+38 -10
View File
@@ -9,15 +9,45 @@ pub struct DynAnyNode<I, O, Node> {
_i: PhantomData<I>,
_o: PhantomData<O>,
}
#[node_macro::node_fn(DynAnyNode<_I, _O>)]
fn any_node<_I: StaticType, _O: StaticType, N>(input: Any<'input>, node: &'any_input N) -> Any<'input>
impl<'input, _I: 'input + StaticType, _O: 'input + StaticType, N: 'input, S0: 'input> Node<'input, Any<'input>> for DynAnyNode<_I, _O, S0>
where
N: for<'any_input> Node<'any_input, _I, Output = _O>,
S0: for<'any_input> Node<'any_input, (), Output = &'any_input N>,
{
let node_name = core::any::type_name::<N>();
let input: Box<_I> = dyn_any::downcast(input).unwrap_or_else(|e| panic!("DynAnyNode Input, {e} in:\n{node_name}"));
Box::new(node.eval(*input))
type Output = Any<'input>;
#[inline]
fn eval(&'input self, input: Any<'input>) -> Self::Output {
let node = self.node.eval(());
{
let node_name = core::any::type_name::<N>();
let input: Box<_I> = dyn_any::downcast(input).unwrap_or_else(|e| panic!("DynAnyNode Input, {0} in:\n{1}", e, node_name));
Box::new(node.eval(*input))
}
}
fn reset(self: std::pin::Pin<&mut Self>) {
let wrapped_node = unsafe { self.map_unchecked_mut(|e| &mut e.node) };
Node::reset(wrapped_node);
}
fn serialize(&self) -> Option<std::sync::Arc<dyn core::any::Any>> {
self.node.eval(()).serialize()
}
}
impl<'input, _I: StaticType, _O: StaticType, N, S0: 'input> DynAnyNode<_I, _O, S0>
where
S0: for<'any_input> Node<'any_input, (), Output = &'any_input N>,
{
pub const fn new(node: S0) -> Self {
Self {
node,
_i: core::marker::PhantomData,
_o: core::marker::PhantomData,
}
}
}
pub struct DynAnyRefNode<I, O, Node> {
node: Node,
_i: PhantomData<(I, O)>,
@@ -28,11 +58,9 @@ where
{
type Output = Any<'input>;
fn eval(&'input self, input: Any<'input>) -> Self::Output {
{
let node_name = core::any::type_name::<N>();
let input: Box<_I> = dyn_any::downcast(input).unwrap_or_else(|e| panic!("DynAnyRefNode Input, {e} in:\n{node_name}"));
Box::new(self.node.eval(*input))
}
let node_name = core::any::type_name::<N>();
let input: Box<_I> = dyn_any::downcast(input).unwrap_or_else(|e| panic!("DynAnyRefNode Input, {e} in:\n{node_name}"));
Box::new(self.node.eval(*input))
}
fn reset(self: std::pin::Pin<&mut Self>) {
let wrapped_node = unsafe { self.map_unchecked_mut(|e| &mut e.node) };