Skip to content

[Runtime] Add asynchronous asset and world streaming with budgets and HLOD #137

Description

@proggeramlug

Parent: #126
Corresponds to EN-032 in docs/tickets.md

Problem

Model/world loads are synchronous and handle APIs assume data is immediately resident. Large scenes need asynchronous IO, decode, cook-chunk reads, GPU upload, world-cell activation, and eviction without blocking the game/render thread. This must remain simple at the TypeScript surface.

Outcome

Handle-based asynchronous asset and world streaming with priorities, cancellation, memory budgets, stable placeholders, progress/error reporting, and deterministic world-cell activation.

Public API contract

Design one small API shape compatible with Perry—for example:

  • loadModelAsync(pathOrAssetId) -> AssetHandle<Model>;
  • handle states Queued | Loading | Ready | Failed | Cancelled;
  • isReady, getError, getProgress, retain/release or scoped ownership;
  • optional callback/event or polling that does not allocate heavily per frame;
  • synchronous development convenience may remain, implemented on top or clearly documented as blocking.

Exact naming is open, but callers may create scene nodes immediately with a placeholder and receive an atomic swap when ready. No raw pointers or JS-only Promises that cannot work in native Perry builds.

Runtime pipeline

  1. Resolve logical asset ID and platform variant from cooked manifest.
  2. Prioritized IO on worker(s), supporting loose files and package ranges.
  3. Decode/decompress/validate off the render thread.
  4. Stage bounded GPU uploads and resource-table updates.
  5. Publish ready state only after all required GPU/resources are safe to reference.
  6. Retire/evict after reference loss and GPU completion fences.

Backpressure must bound queued bytes, decode memory, staging memory, and GPU uploads per frame.

World streaming

  • Partition world data into cells/chunks with dependency lists and coarse bounds.
  • Load/unload by camera/interest volumes plus hysteresis and priorities.
  • Separate data readiness from activation; activate a cell atomically at a frame boundary.
  • Keep stable entity/asset IDs across unload/reload.
  • Generate or consume HLOD/coarse proxies so missing fine cells do not reveal holes.
  • Physics/nav/audio activation order must be explicit and testable.

Failure and cancellation

  • Missing/corrupt/version-mismatched assets enter Failed with an actionable message and render a diagnostic placeholder.
  • Cancellation releases queued/intermediate resources without racing a completion callback.
  • Device loss/recreation has a documented reupload/reload policy.
  • A late result cannot populate a handle whose generation was reused.

Acceptance criteria

  • Loading a large model/world produces no game-thread or render-thread stall over an approved budget; attach frame-time percentile traces.
  • Per-frame upload and total CPU/GPU memory remain within configured budgets under a forced slow-IO test.
  • Priorities cause visible/near assets to become ready before background assets.
  • Cancel/release/churn tests show no stale-handle use, leak, double free, or late publish.
  • A moving camera streams world cells with no holes when HLOD/coarse data is available and no activation half-state for render/physics.
  • Native desktop, web fetch, and one mobile target exercise the same public state machine with platform-specific IO adapters.
  • Existing synchronous examples keep working; new docs show the recommended async path in fewer than ~15 lines of game code.

Likely files

  • new asset manager under native/shared/src/
  • native/shared/src/models*.rs, textures.rs, staging.rs, renderer resource tables
  • src/models/, src/world/loader.ts, src/world/render.ts
  • platform file/fetch adapters under native/*/
  • cooked asset format from the cooker issue

Non-goals

  • General-purpose task runtime exposed to games.
  • Network multiplayer replication.
  • Runtime mesh simplification.

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions