Convert the node catalog to rank-polymorphic kernels, materialize stored values as ranked wires, and display wire rank in the graph

Co-authored-by:    Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
Keavon Chambers
2026-07-20 21:27:13 -07:00
committed by Dennis Kobert
parent 83cfd0225a
commit 04d6c0d5cf
55 changed files with 1781 additions and 995 deletions

View File

@@ -1,5 +1,4 @@
use core_types::gpoll::GPoll;
use core_types::list::List;
use core_types::transform::Footprint;
use core_types::{CacheHash, Color, Context, Ctx, DeriveCtx, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime};
use glam::{DAffine2, DVec2};
@@ -74,15 +73,13 @@ fn quantize_real_time<T>(
Context -> DAffine2,
Context -> Footprint,
Context -> DVec2,
Context -> List<Vector>,
Context -> List<Graphic>,
Context -> List<Raster<CPU>>,
Context -> List<Raster<GPU>>,
Context -> List<Color>,
Context -> List<Artboard>,
Context -> List<Gradient>,
Context -> List<String>,
Context -> List<f64>,
Context -> Vector,
Context -> Graphic,
Context -> Raster<CPU>,
Context -> Raster<GPU>,
Context -> Color,
Context -> Gradient,
Context -> Artboard,
Context -> (),
)]
value: impl Node<Context<'_>, Output = T>,
@@ -114,15 +111,13 @@ fn quantize_animation_time<T>(
Context -> DAffine2,
Context -> Footprint,
Context -> DVec2,
Context -> List<Vector>,
Context -> List<Graphic>,
Context -> List<Raster<CPU>>,
Context -> List<Raster<GPU>>,
Context -> List<Color>,
Context -> List<Artboard>,
Context -> List<Gradient>,
Context -> List<String>,
Context -> List<f64>,
Context -> Vector,
Context -> Graphic,
Context -> Raster<CPU>,
Context -> Raster<GPU>,
Context -> Color,
Context -> Gradient,
Context -> Artboard,
Context -> (),
)]
value: impl Node<Context<'_>, Output = T>,

View File

@@ -7,46 +7,6 @@ use graphic_types::vector_types::Gradient;
use graphic_types::{Graphic, Vector};
use raster_types::{CPU, Raster};
#[node_macro::node(category("Context"), path(graphene_core::vector))]
fn read_graphic(ctx: impl Ctx + ExtractVarArgs) -> List<Graphic<'static>> {
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
let var_arg = var_arg as &dyn std::any::Any;
var_arg.downcast_ref().cloned().unwrap_or_default()
}
#[node_macro::node(category("Context"), path(graphene_core::vector))]
fn read_vector(ctx: impl Ctx + ExtractVarArgs) -> List<Vector> {
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
let var_arg = var_arg as &dyn std::any::Any;
var_arg.downcast_ref().cloned().unwrap_or_default()
}
#[node_macro::node(category("Context"), path(graphene_core::vector))]
fn read_raster(ctx: impl Ctx + ExtractVarArgs) -> List<Raster<CPU>> {
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
let var_arg = var_arg as &dyn std::any::Any;
var_arg.downcast_ref().cloned().unwrap_or_default()
}
#[node_macro::node(category("Context"), path(graphene_core::vector))]
fn read_color(ctx: impl Ctx + ExtractVarArgs) -> List<Color> {
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
let var_arg = var_arg as &dyn std::any::Any;
var_arg.downcast_ref().cloned().unwrap_or_default()
}
#[node_macro::node(category("Context"), path(graphene_core::vector))]
fn read_gradient(ctx: impl Ctx + ExtractVarArgs) -> List<Gradient> {
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
let var_arg = var_arg as &dyn std::any::Any;
var_arg.downcast_ref().cloned().unwrap_or_default()
}
/// The mapped row riding as vararg 0, in the production single-item shape.
fn vararg_list<T: 'static>(ctx: &impl ExtractVarArgs) -> Option<&List<T>> {
let arg = ctx.vararg(0).ok()?;
@@ -69,54 +29,30 @@ fn vararg_element<T: Clone + 'static>(ctx: &(impl ExtractVarArgs + ExtractIndex)
.ok_or_else(|| GraphError::new("vararg row addressed past its items").into())
}
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
#[node_macro::node(category("Test"), extent_raw(read_graphic_row_extent))]
pub fn read_graphic_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<Graphic<'static>>, Interrupt> {
vararg_element(ctx)
// The vararg readers: the mapped row's items as the lanes of a level, elements
// only, one node per element type since a reader names its type.
macro_rules! vararg_readers {
($($node:ident / $extent:ident / $node_type:ident: $element:ty;)*) => {
$(
#[node_macro::node(category("Context"), path(graphene_core::vector), extent_raw($extent))]
pub fn $node(ctx: impl Ctx + ExtractVarArgs + ExtractIndex, _primary: ()) -> Result<IList<$element>, Interrupt> {
vararg_element(ctx)
}
fn $extent<C: Ctx + ExtractVarArgs, N>(_: &$node_type<N>, ctx: &C, level: u8) -> GPoll<Extent> {
vararg_lanes::<$element>(ctx, level)
}
)*
};
}
fn read_graphic_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadGraphicRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
vararg_lanes::<Graphic>(ctx, level)
}
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
#[node_macro::node(category("Test"), extent_raw(read_vector_row_extent))]
pub fn read_vector_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<Vector>, Interrupt> {
vararg_element(ctx)
}
fn read_vector_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadVectorRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
vararg_lanes::<Vector>(ctx, level)
}
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
#[node_macro::node(category("Test"), extent_raw(read_raster_row_extent))]
pub fn read_raster_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<Raster<CPU>>, Interrupt> {
vararg_element(ctx)
}
fn read_raster_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadRasterRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
vararg_lanes::<Raster<CPU>>(ctx, level)
}
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
#[node_macro::node(category("Test"), extent_raw(read_color_row_extent))]
pub fn read_color_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<Color>, Interrupt> {
vararg_element(ctx)
}
fn read_color_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadColorRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
vararg_lanes::<Color>(ctx, level)
}
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
#[node_macro::node(category("Test"), extent_raw(read_gradient_row_extent))]
pub fn read_gradient_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<Gradient>, Interrupt> {
vararg_element(ctx)
}
fn read_gradient_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadGradientRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
vararg_lanes::<Gradient>(ctx, level)
vararg_readers! {
read_graphic / read_graphic_extent / ReadGraphicNode: Graphic<'static>;
read_vector / read_vector_extent / ReadVectorNode: Vector;
read_raster / read_raster_extent / ReadRasterNode: Raster<CPU>;
read_color / read_color_extent / ReadColorNode: Color;
read_gradient / read_gradient_extent / ReadGradientNode: Gradient;
read_string / read_string_extent / ReadStringNode: String;
}
#[node_macro::node(category("Context"), path(core_types::vector))]

View File

@@ -9,6 +9,7 @@ fn passthrough<T: Send>(_: impl Ctx, content: T) -> T {
content
}
/// Shifts a whole wire value onto a connector's type through the std `Into` trait, serving the whole-`List` erasure onto `ListDyn` under the input adapter identifier.
#[node_macro::node(category(""), skip_impl)]
fn into<T: Send + Into<O>, O: Send>(_: impl Ctx, value: T, #[data] _out_ty: PhantomData<O>) -> O {
value.into()

View File

@@ -1944,7 +1944,12 @@ mod tests {
let scope = scope_fixture(&generations, &arena);
let ctx = ContextImpl::root(&scope);
let node = install(crate::context::ReadColorRowNode::new(), crate::context::read_color_row_layout_meta(), &[]);
let unit = Layout::default().with_writes(0, core_types::record::element_write::<()>(), &[]);
let node = install(
crate::context::ReadColorNode::new(ValueSource::new(()), &unit),
crate::context::read_color_layout_meta(),
&[Some(&unit)],
);
let out = Node::<ContextImpl>::layout(&node).clone();
assert_eq!(out.depth, 1);
// No row pushed: an empty level, matching the legacy empty-list return.