Skip to content

Architecture and runtime

Rune Engine separates authoring, publication, and rendering into explicit objects so the same runtime can drive windows, offscreen tests, preview, and export without hidden globals.

Mental model

text
Managed caller or Story
  -> mutate RuneNode authoring state
  -> node.Commit()
  -> immutable Snapshot tree
  -> context.Submit(snapshot)
  -> engine render loop or RenderFrame(time)
  -> full-target replay on the current surface

Responsibilities and boundaries

  • RuneEngine owns the render thread, device mode, frame clock, and deferred cleanup queue.
  • Surface owns one output target's size plus window or offscreen backend state.
  • RuneContext pairs one submitted snapshot root with one surface and keeps render-side bookkeeping such as the last rendered root and one-shot force-render flag.
  • RuneNode owns mutable UI-thread authoring state. Nodes belong to an engine, not to a context.
  • Snapshot is the immutable handoff unit. The same snapshot tree can be captured, retained, and submitted explicitly.

That split is deliberate: authoring chooses what to publish, while rendering chooses when a published root must produce a frame.

Stable current behavior

  • New engines start in manual mode. RenderFrame(time) renders every bound context once and waits for completion. StartLoop() switches to the automatic render thread loop.
  • Multiple contexts can share one engine, but each surface binds to at most one context at a time.
  • RuneNode callbacks record commands on the calling thread during commit; the render thread never reads mutable node state directly.
  • context.Submit(snapshot) is the presentation handoff. Contexts render the most recently submitted immutable root, not a live node tree.
  • The current audited backend clears the whole target and replays the whole submitted root whenever a frame is not skipped.
  • Frame skipping is conservative: a context can skip only when the submitted root pointer is unchanged, no animation remains unsettled at the requested time, a frame at or after the effective settle time has already rendered, and no force-render is pending.

Current limitations

  • The current audited backend is Direct2D on Windows. The architecture is explicit, but the published implementation is documented only for that backend today.
  • Full-target clear plus full-root replay is the current render strategy. The engine does not currently publish damage rectangles or partial redraw behavior.
  • RuneContext.Capture() is intentionally limited to manual runtimes, where commit and capture stay serialized on the caller thread.

How the pieces connect

Story and other managed callers usually keep one engine alive, build or update RuneNode state, commit a root snapshot, submit it to a context, and then either:

  • let the automatic loop present frames in real time, or
  • drive SetFrameTime / RenderFrame manually for deterministic preview, capture, and export.

Because commit and submission are separate, one snapshot can be captured for inspection, reused across contexts, or redirected from preview to export without rewriting the scene model.

Go deeper

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