🦊 Internal API (Rust Core)

This is an internal engineering document. It describes how the Rust core is structured and how commands flow internally. It is not intended for end users of the engine.


1. Runtime Stack

Key crates used by the core:

  • Platform proxies
    • winit (desktop)
    • web-sys (browser/WASM)
  • Rendering: wgpu
  • Input: gilrs (desktop) + Web Gamepad API (browser)
  • Images: image
  • Math & packing: glam, bytemuck
  • Serialization: serde, serde_repr, rmp-serde

2. Engine State and Ownership

At runtime the core is driven by an EngineState held inside a singleton. Key responsibilities inside the state:

  • Window and surface management
  • WGPU device/queue and buffer storage
  • Command, event, and response queues
  • Gamepad and input caches
  • Profiling data

The singleton also owns the platform proxy (desktop or browser).


3. Resources and Components

Resources (current)

  • Geometry
  • Texture
  • Material
  • Shadow configuration

Components (current)

  • Camera
  • Model
  • Light

Each component has a record that stores the latest payload and derived runtime data (layer masks, transforms, render target, etc.).


4. Command Flow (End-to-End)

4.1 ABI → Internal Queue

  1. vulfram_send_queue receives a MessagePack buffer.
  2. The buffer is deserialized into a batch of command envelopes.
  3. Commands are pushed into EngineState::cmd_queue.

4.2 Tick Processing

During vulfram_tick:

  1. Drain cmd_queue.
  2. Route each command to its subsystem (window, resources, components).
  3. Update derived render data (uniform buffers, visibility, etc.).

This separation ensures the ABI stays thin and all logic happens on tick.


5. Upload Handling

Uploads are stored as (BufferId → UploadBuffer) entries:

  • Inserted by vulfram_upload_buffer.
  • Consumed by Create* commands.
  • Removed after use.
  • Can be cleared with CmdUploadBufferDiscardAll.

This enforces one-shot semantics and predictable memory usage.


6. Rendering System (High-Level)

Per frame:

  1. Update uniform buffers (frame, camera, model).
  2. For each camera:
    • Configure render target and viewport.
    • Filter visible models by layer mask.
    • Resolve pipelines and bind groups.
    • Issue draw calls (batched by material/geometry).
  3. Submit to the GPU queue.

Opaque objects are sorted for batching; transparent objects are depth-sorted.


7. Event System

Events are collected from the active platform proxy:

  • Keyboard, pointer, touch
  • Gamepad (native or web)
  • Window events (resize, focus, close)

They are serialized into MessagePack when the host calls vulfram_receive_events.


8. Profiling

vulfram_get_profiling returns MessagePack snapshots including:

  • Timing metrics (command processing, render passes, total frame time)
  • Derived FPS
  • Per-window frame stats
  • Event counters

These are intended for tooling overlays or external profilers.


9. Where to Start in Code

If you are new to the core, a practical tour is:

  1. src/core/queue.rs (ABI queues and ownership)
  2. src/core/cmd.rs (command routing)
  3. src/core/tick.rs (frame flow)
  4. src/core/render/ (pipelines and render passes)
  5. src/core/platforms/ (desktop vs browser proxies)
Documentation Vulfram Core