Skip to content

Interop and capture

Rune Engine exposes explicit runtime, surface, context, node, snapshot, and resource handles across a cdecl C ABI, then mirrors those handles almost one-for-one in the managed .NET wrapper.

Mental model

text
C ABI handle
  <-> thin C# wrapper
  -> explicit create / submit / render / release
  -> offscreen readback or export when the frame is ready

Responsibilities and boundaries

  • The native ABI defines opaque handles, ownership, status codes, and thread-safety boundaries.
  • The managed wrapper keeps those boundaries visible with blittable value types and lightweight handle structs instead of hiding them behind a new lifecycle model.
  • Capture paths are explicit: snapshot capture, CPU pixel readback, image export, and D3D11 interop each serve different stages of inspection or media pipelines.

Stable current behavior

The ABI is explicit and handle-based

  • There is no process-global init/shutdown lifecycle.
  • Callers create engines, surfaces, contexts, nodes, and resources directly.
  • Ownership stays explicit: creators own handles unless an API says it retains them, such as context.Submit(snapshot).
  • The published ABI requires a 64-bit process.

The managed wrapper stays thin

RuneEngine, Surface, RuneContext, RuneNode, RuneValue, and the shared resource structs are typed wrappers over native handles or ABI-compatible data layouts. That keeps P/Invoke cheap while still matching native ownership concepts closely.

Capture and export have separate jobs

  • RuneContext.Capture() retains the currently committed snapshot tree for later inspection or reuse.
  • Surface.ReadPixels() copies RGBA8 pixels from an offscreen surface into caller memory.
  • Surface.ExportImage() returns an image snapshot of the latest rendered offscreen contents.
  • D3D11 extensions expose borrowed same-process pointers for supported D2D surfaces and images.

Dynamic-image pipelines stay explicit

The D2D extensions can create a dynamic image, update it from a D3D11 texture, and query borrowed D3D11 pointers from supported image kinds. When that update changes pixels without changing the submitted snapshot pointer, callers use RequestRender() to publish the new frame.

Current limitations

  • RuneContext.Capture() is only safe on manual runtimes today.
  • ReadPixels() and ExportImage() apply to offscreen surfaces, not window targets.
  • D3D11 pointer export is same-process and borrowed. Callers that need to hold those pointers independently must add their own COM references.
  • The current audited implementation is Windows-first and Direct2D-backed.

How the pieces connect

The interop model is what makes the engine usable both as a realtime UI runtime and as a deterministic media backend. Managed callers can author and submit snapshots through thin wrappers, render exact times manually, read back pixels, export GPU-backed images, or hand borrowed D3D11 resources to downstream media pipelines.

Story builds on that same contract for preview, frame capture, and export rather than maintaining a separate rendering backend.

Go deeper

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