Skip to content

Open Questions

Single source of truth for design decisions. Updated as we resolve questions.

Resolution Key

  • Resolved - Decision made, documented
  • 🔶 Leaning - Direction chosen, may revisit
  • Open - Needs investigation/decision

Core Architecture

QuestionStatusNotes
Type system for slots✅ ResolvedSimpler than maki (opaque types). Generics unnecessary given typed slots.
Unified graph container✅ ResolvedYes. Single Graph type, typed slots (Output<T>/Input<T>), compile-time safety for Rust, runtime TypeId validation for loaded graphs. Value enum at execution.
Portable workflows✅ ResolvedYes. JSON (human-readable) + optional binary. Versioned files, ops declare compatibility. External refs via IDs, optional asset embedding for full portability.
Parameter system✅ ResolvedYes, first-class across all domains
Modularity✅ ResolvedVery modular, bevy philosophy. Plugin crates for optional features.
Bevy integration✅ ResolvedLow priority. Separate adapter crate if needed. Must not affect core design - resin is standalone first.
Evaluation strategy✅ ResolvedEvaluator trait. Lazy default, others as needed. See evaluation-strategy
Time models✅ ResolvedEvalContext for time, explicit baking, numeric rates + explicit conversion, block = audio iteration, hybrid nodes = feedback edges, determinism = best effort + strict mode. See time-models

Expression Language

See expression-language for full design.

QuestionStatusNotes
Backend selection✅ ResolvedCranelift JIT (CPU hot paths), WGSL (GPU), Interpreted (fallback)
Expression AST scope✅ ResolvedMath + conditionals + let bindings. No loops (use graph recurrence)
Per-domain or unified✅ ResolvedUnified Expr, domains bind different variables (position, uv, time, etc.)
Built-in functions✅ ResolvedWGSL built-ins as reference set. Plugin functions decompose or backend traits
Value representation✅ ResolvedEnum (not dyn trait). Vectors/matrices feature-gated. Square matrices only
Matrix operations✅ Resolved* works on matrices (WGSL-style). Type inference dispatches
Crate structure✅ Resolvedcore + macros + parse + wgsl + cranelift. Interpreter in core
Expr -> WGSL codegen✅ ResolvedString generation from AST. Decomposition-first for plugins.
Expr -> Cranelift codegen✅ ResolvedIR generation, external calls for complex functions.
Plugin function API✅ ResolvedCore trait + backend extension traits in backend crates.
Constant folding✅ ResolvedAST -> AST transform (could be in dew or wrapper).

Ops & Serialization

QuestionStatusNotes
Ops as values✅ ResolvedYes, ops are serializable structs. Derive macro for DynOp impl. See ops-as-values
Plugin op registration✅ ResolvedCore defines trait + serialization contract. Plugin loading is host's responsibility. Optional adapters (rhizome-resin-wasm-plugins, etc.) for common cases. See plugin-architecture
Graph evaluation caching✅ ResolvedHash-based caching at node boundaries (salsa-style). Inputs unchanged -> return cached output
External references✅ ResolvedIDs + resolution context (ComfyUI pattern). Optional asset embedding for portability (any size).

Meshes

QuestionStatusNotes
Half-edge vs index-based✅ ResolvedHalf-edge internal, indexed on export. Accept memory cost for topology ops. See mesh-representation
Instancing✅ ResolvedPlugin crate (rhizome-resin-instances), not core. Provides Instances type + scatter ops + merge to Mesh.
SDF integration✅ ResolvedSDF is Field<Vec3, f32>. SDF ops are field combinators. Meshing via explicit operators (MarchingCubes, etc.). Optional Sdf marker trait for type-level guarantees.
Fields for selection✅ ResolvedYes. Field<VertexData, bool> for inline/lazy selection, SelectionSet for materialized/named/manual picks. Same Field vs materialized pattern.

Audio

QuestionStatusNotes
Sample rate✅ ResolvedRuntime from EvalContext. Nodes query ctx.sample_rate. Lazy buffer init (one-time cost per rate). Same graph works at any host rate.
Block size✅ ResolvedHost-controlled, variable. Nodes handle any size. Block size from EvalContext. Feedback edges update per-block.
Modulation depth✅ ResolvedHybrid. Node author decides which params are modulatable via #[modulatable]. Explicit mod inputs, not implicit on everything. Graph resolves per-block (not per-sample), zero cost when unconnected.
Polyphony model✅ ResolvedPer-graph cloning (Pd pattern). Plugin crate (rhizome-resin-poly), not core. Voice allocator clones graph instances, mixes output. Matches instancing pattern.
Control vs audio rate✅ ResolvedNo special types. Control rate = lower numeric rate. Explicit conversion nodes if needed (from mixed rates decision).
State management✅ ResolvedRecurrent graphs: feedback edges carry state, nodes stay pure. Delay granularity per-edge, mixed rates via explicit conversion. See recurrent-graphs

Textures

QuestionStatusNotes
GPU vs CPU✅ ResolvedAbstract over both via burn/CubeCL. See prior-art
Tiling✅ ResolvedExplicit operators. Tiling isn't fundamental to most generators. MakeSeamless, Tile, etc.
Resolution/materialization✅ ResolvedSeparate Field (lazy) / Image (materialized). Resolution explicit at render(). No propagation. See texture-materialization
3D textures✅ ResolvedSame nodes, Vec3 input. Vec4 for looping animation (time as 4th dim). Memory/preview are host concerns.
Texture vs field✅ ResolvedUnified via generic Field<I, O> trait. Same concept, different input types. Time handling -> see Time models.

Vector 2D

QuestionStatusNotes
Curve types✅ ResolvedAll via traits. See curve-types
Precision f32/f64✅ ResolvedSupport both via generic T: Float
Winding rule✅ ResolvedBoth, default non-zero. See winding-rules
Vector networks✅ ResolvedNetwork internally, both APIs as equals. See vector-networks
Text✅ ResolvedInclude outline extraction, exclude layout (harfbuzz territory).
Path ↔ rigging✅ ResolvedRigging (bones+skinning) unified 2D/3D. Morphing is separate Morph<G> trait. Paths can drive rig params (spline IK, curve deformers).

Rigging

QuestionStatusNotes
Unified 2D/3D rig✅ ResolvedYes. Generic Rig<G: HasPositions> trait. Same bones/skinning concepts, just different dimensionality. Live2D validates 2D case.
Deformer stacking✅ ResolvedGraph internal, Stack API. See deformer-stacking
Animation blending✅ ResolvedSeparate crate (rhizome-resin-anim), bevy-style modularity.
Procedural rigging✅ ResolvedPlugin crate (rhizome-resin-autorig). Core provides rig primitives, auto-generation is domain-specific.
Real-time vs offline✅ ResolvedSame API, user manages budget. Solver params (iterations, tolerance) for quality/speed tradeoff. Bone count is authoring choice.

Summary by Status

✅ Resolved (50)

Core Architecture:

  • Type system for slots (simpler than maki, typed slots)
  • Unified graph container (typed slots, Value enum execution)
  • Portable workflows (JSON + binary, versioned, asset embedding)
  • Parameter system (first-class across all domains)
  • Modularity (very modular, plugin crates for optional features)
  • Bevy integration (low priority, standalone first)
  • Evaluation strategy (Evaluator trait, lazy default)
  • Time models (EvalContext, explicit baking, numeric rates, feedback = state)

Expression Language:

  • Backend selection (Cranelift/WGSL/Interpreted)
  • AST scope (math + conditionals + let, no loops)
  • Built-in functions (WGSL as reference, plugin extensions)
  • Value enum (not dyn trait, vectors/matrices feature-gated)
  • Matrix ops (* works on matrices, type inference dispatches)
  • Crate structure (core + macros + parse + wgsl + cranelift)
  • Unified vs per-domain (unified, domains bind different vars)
  • WGSL codegen (string generation, decomposition-first)
  • Cranelift codegen (IR generation, external calls)
  • Plugin function API (core trait + backend extension traits)
  • Constant folding (AST transform in dew or wrapper)

Ops & Serialization:

  • Ops as values (derive macro for DynOp impl)
  • Plugin op registration (core = contract, host = loading)
  • Graph caching (hash-based at node boundaries)
  • External references (IDs + context, asset embedding)

Meshes:

  • Half-edge vs index-based (half-edge internal, indexed export)
  • Instancing (plugin crate)
  • SDF integration (Field<Vec3, f32>, meshing via explicit ops)
  • Fields for selection (Field for lazy, SelectionSet for materialized)

Audio:

  • Sample rate (runtime from EvalContext, lazy buffer init)
  • Block size (host-controlled, variable)
  • Modulation depth (hybrid, per-block resolution)
  • Polyphony (per-graph cloning, plugin crate)
  • Control vs audio rate (no special types, explicit conversion)
  • State management (recurrent graphs, feedback edges)

Textures:

  • GPU vs CPU (burn/CubeCL abstraction)
  • Tiling (explicit operators)
  • Resolution/materialization (Field/Image split, explicit resolution)
  • 3D textures (same nodes, Vec3/Vec4 input)
  • Texture vs field (Field<I,O> trait)

Vector 2D:

  • Curve types (trait-based)
  • Precision f32/f64 (generic T: Float)
  • Winding rule (both, default non-zero)
  • Vector networks (network internal, both APIs)
  • Text (outline extraction, no layout)
  • Path ↔ rigging (paths can drive rigs)

Rigging:

  • Unified 2D/3D rig (generic Rig<G: HasPositions>)
  • Deformer stacking (graph internal, stack API)
  • Animation blending (separate crate)
  • Procedural rigging (plugin crate)
  • Real-time vs offline (same API, solver params)

🔶 Leaning (0)

All promoted to resolved!

❓ Open (0)

All questions resolved!