mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Install record layouts from the pass via set_layout
This commit is contained in:
@@ -278,6 +278,9 @@ pub trait Node<Input> {
|
||||
crate::record::empty_layout()
|
||||
}
|
||||
|
||||
/// Installs this node's resolved record layout; a no-op unless it produces records.
|
||||
fn set_layout(&mut self, _layout: crate::record::RecordLayout) {}
|
||||
|
||||
fn eval_batch<'a>(&'a self, input: &'a Input, range: Range<u64>, scratch: Option<&'a mut [MaybeUninit<Self::Output>]>) -> BatchStatus<'a, Self::Output>
|
||||
where
|
||||
Input: InjectIndex + Copy,
|
||||
|
||||
@@ -243,6 +243,14 @@ pub fn empty_layout() -> &'static Layout {
|
||||
}
|
||||
|
||||
/// Declarative record-io metadata for a node type, emitted by the macro into
|
||||
/// A record node's output layout with the frame size and carrier copy plan derived from it.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct RecordLayout {
|
||||
pub layout: Layout,
|
||||
pub frame_bytes: usize,
|
||||
pub plan: Vec<(usize, usize, usize)>,
|
||||
}
|
||||
|
||||
/// its registry entry so the compiler can fold each wire's layout without
|
||||
/// running the node's constructor. [`fold`](LayoutMeta::fold) reproduces the
|
||||
/// layout the constructor derives at wiring today; the compiler layout pass
|
||||
@@ -287,8 +295,7 @@ pub enum ElementSpec {
|
||||
}
|
||||
|
||||
impl LayoutMeta {
|
||||
/// The meta of an elementwise carrier flip that retypes input 0's element,
|
||||
/// preserving its depth and attributes: what an `Into`/`Convert` coercion derives.
|
||||
/// Keeps input 0's layout but replaces its element.
|
||||
pub fn retype(element: ElementWrite) -> Self {
|
||||
Self {
|
||||
sources: vec![0],
|
||||
@@ -318,6 +325,23 @@ impl LayoutMeta {
|
||||
};
|
||||
base.with_writes(depth, element, &self.writes)
|
||||
}
|
||||
|
||||
/// [`fold`](LayoutMeta::fold) with the frame size and carrier copy plan derived from it.
|
||||
pub fn resolve(&self, inputs: &[Option<&Layout>]) -> RecordLayout {
|
||||
let layout = self.fold(inputs);
|
||||
let frame_bytes = layout.frame_bytes();
|
||||
let plan = match self.sources.first() {
|
||||
// A reducer collapses its carrier's levels, so it writes a fresh record rather than copying fields down.
|
||||
Some(&source) if self.level_delta >= 0 => {
|
||||
let from = inputs[source as usize].expect("layout resolve source input has no layout");
|
||||
let carry_element = matches!(self.element, ElementSpec::Carried);
|
||||
let removes: Vec<(&str, u8)> = self.removes.clone();
|
||||
copy_plan(from, &layout, carry_element, &removes)
|
||||
}
|
||||
_ => Vec::new(),
|
||||
};
|
||||
RecordLayout { layout, frame_bytes, plan }
|
||||
}
|
||||
}
|
||||
|
||||
/// A view of one record: a pointer whose layout is proven at wiring.
|
||||
|
||||
@@ -113,7 +113,6 @@ pub fn cache_key<C: CacheHash + ?Sized>(ctx: &C) -> u64 {
|
||||
pub enum ConstructionError {
|
||||
Arity { expected: usize, got: usize },
|
||||
Type { expected: Box<Type>, found: Box<Type> },
|
||||
MissingLayout,
|
||||
}
|
||||
|
||||
pub struct SharedEdge<N: ?Sized> {
|
||||
@@ -193,7 +192,8 @@ pub struct EdgeHandle {
|
||||
node: Box<DynEdge>,
|
||||
share: fn(&DynEdge) -> Box<DynEdge>,
|
||||
serialize: fn(&DynEdge) -> Option<std::sync::Arc<dyn std::any::Any + Send + Sync>>,
|
||||
layout: fn(&DynEdge) -> Option<&crate::record::Layout>,
|
||||
layout: fn(&DynEdge) -> &crate::record::Layout,
|
||||
set_layout: fn(&mut DynEdge, crate::record::RecordLayout),
|
||||
ty: Type,
|
||||
}
|
||||
|
||||
@@ -228,7 +228,12 @@ impl EdgeHandle {
|
||||
node: Box::new(SharedEdge::new(node)),
|
||||
share: |edge| Box::new(edge.downcast_ref::<SharedEdge<N>>().expect("share hook matches the stored edge type").share()),
|
||||
serialize: |edge| Node::<ContextImpl>::serialize(edge.downcast_ref::<SharedEdge<N>>().expect("serialize hook matches the stored edge type")),
|
||||
layout: |edge| Some(Node::<ContextImpl>::layout(edge.downcast_ref::<SharedEdge<N>>().expect("layout hook matches the stored edge type"))),
|
||||
layout: |edge| Node::<ContextImpl>::layout(edge.downcast_ref::<SharedEdge<N>>().expect("layout hook matches the stored edge type")),
|
||||
set_layout: |edge, layout| {
|
||||
let shared = edge.downcast_mut::<SharedEdge<N>>().expect("set_layout hook matches the stored edge type");
|
||||
let node = std::sync::Arc::get_mut(&mut shared.own).expect("layout is installed before the node is shared");
|
||||
Node::<ContextImpl>::set_layout(node, layout);
|
||||
},
|
||||
ty,
|
||||
}
|
||||
}
|
||||
@@ -243,6 +248,7 @@ impl EdgeHandle {
|
||||
share: self.share,
|
||||
serialize: self.serialize,
|
||||
layout: self.layout,
|
||||
set_layout: self.set_layout,
|
||||
ty: self.ty.clone(),
|
||||
}
|
||||
}
|
||||
@@ -251,10 +257,14 @@ impl EdgeHandle {
|
||||
(self.serialize)(&*self.node)
|
||||
}
|
||||
|
||||
pub fn layout(&self) -> Option<&crate::record::Layout> {
|
||||
pub fn layout(&self) -> &crate::record::Layout {
|
||||
(self.layout)(&*self.node)
|
||||
}
|
||||
|
||||
pub fn set_layout(&mut self, layout: crate::record::RecordLayout) {
|
||||
(self.set_layout)(&mut *self.node, layout);
|
||||
}
|
||||
|
||||
pub fn downcast<T: 'static>(self) -> Result<SharedEdge<ErasedNode<T>>, ConstructionError> {
|
||||
self.downcast_erased(edge_type::<T>())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user