Skip to content

RUNE-301: RuneValue Proposed

Updated2026-08-23

Summary

RuneValue is a 4-byte NaN-boxed uint32_t that stores either a static IEEE-754 float, an ordinary animation slot index, or a derived token produced by expression and sampled-path outputs. It is the fundamental numeric transport type for animatable parameters in the rendering engine.

Motivation

Animation as a first-class citizen requires every numeric parameter to potentially be animated without bloating command payloads. RuneValue preserves float-sized storage and blittable ABI layout while still carrying snapshot-local indirections for animated and derived values.

Design

Bit Layout

text
static float:      [S EEEEEEEE MMMMMMMMMMMMMMMMMMMMMMM]
animated slot:     [0 11111111 1IIIIIIIIIIIIIIIIIIIIIII]
derived token:     [1 11111111 1TTTTTTTTTTTTTTTTTTTTTT]
  • 0x7FC00000 is the canonical static NaN tag.
  • Ordinary animated values store (index + 1) in the low 21 bits.
  • Derived values set the sign bit and store a non-zero token in the low 22 bits. Native resolves that token to an animation slot with rune_value_derived_slot().

Detection

c
bool rune_value_is_animated(RuneValue v) {
    if ((v & 0x7FC00000u) != 0x7FC00000u) return false;
    const uint32_t mask = (v & 0x80000000u) != 0 ? 0x003FFFFFu : 0x001FFFFFu;
    return (v & mask) != 0;
}

Derived values intentionally participate in rune_value_is_animated() because replay resolves them through snapshot-local animation storage.

Encoding Rules

  • static values are stored by bit-casting the original float
  • user-provided NaN values are canonicalized to 0x7FC00000
  • ordinary slot payload 0 is reserved for canonical static NaN
  • derived token 0 is invalid

Resolve

The render thread resolves RuneValues in two phases:

  1. evaluate ordinary animation descriptors into snapshot->resolved[]
  2. execute the ordered DATA_EXPRESSION bytecode so derived outputs fill their assigned slots

Replay then performs one lightweight branch and array lookup:

c
float resolve_value(RuneValue v, const float* resolved) {
    if (rune_value_is_animated(v)) return resolved[rune_value_anim_index(v)];
    return rune_value_to_float(v);
}

Memory Model

  • RuneValue is copied by value and embedded inline in commands, data records, and metadata descriptors
  • ordinary animated values reference entries in the owning snapshot's anims[] array
  • derived values are downstream-only outputs owned by the recording node's expression/sample program
  • no float round-trip occurs before render-thread resolve, avoiding accidental payload canonicalization

Error Handling

  • invalid or stale derived tokens are rejected during recording and liveness validation
  • out-of-bounds slot resolution asserts in debug builds; release builds return 0.0f
  • user NaN input remains a static canonical NaN, not a forged animated payload

API Surface

c
typedef uint32_t RuneValue;
csharp
[StructLayout(LayoutKind.Explicit, Size = 4)]
public readonly struct RuneValue {
    [FieldOffset(0)] private readonly uint _bits;
}

Performance

  • static resolve: one predictable branch plus 4-byte reinterpret
  • animated resolve: branch, slot decode, then snapshot-array lookup
  • derived resolve reuses the same storage path after expression execution instead of introducing a second transport type

Alternatives Considered

ApproachRejected because
Separate float + tag/flag fieldsincreases command size and marshal overhead
Distinct expression-output transport typecomplicates every command/data encoding path
double for everythingdoubles storage without a documented need

Dependencies

  • RUNE-300 (ABI — blittable type, P/Invoke marshaling)

Test Strategy

  1. verify static float round-trip preserves bits except canonical NaN normalization
  2. verify ordinary animation slot encoding/decoding and invalid payload handling
  3. verify derived tokens resolve through rune_value_derived_slot() into snapshot-local slots
  4. verify C# helpers mirror native IsAnimated and AnimIndex behavior
  5. verify render-thread resolve executes ordinary slots before expression-derived outputs

Rune Project brings Rune Story authoring together with the Rune Engine rendering foundation.