Expand description
Async asset pipeline with a content-addressed handle cache.
spawn_pending_decodespicks up entities tagged withImageSourceand consults the global cache onAssetServer.- On a cache hit, the existing decoded
Handleis cloned in (Arc bump, no decode runs). - On a cold miss, the request is pushed onto a bounded
crossbeam-channeljob queue drained by an N-worker thread pool (N = available_parallelism().min(4)). Subsequent entities requesting the same path join a pending fan-out list. - Every request carries a monotonic per-entity
request_id; results whose id no longer matches the entity’s current id are discarded on completion. This kills the stale-decode race after rapidScriptCommand::SetSrcstorms. - What a path decodes into is decided by the loader registry: each
AssetLoaderclaims file extensions and produces oneAssetKind, and the built-in image and SVG paths are ordinary registered loaders. An app or plugin adds a format by registering another one; seeregister_asset_loader. - Where the bytes come from is decided by the
AssetSourcelist, consulted before the job is queued.BundleSource(.lpakarchives,lumen://app/...URIs) is installed by default. drain_completed_decodesdelivers the resultingHandleto every still-valid waiter; failures attachImageLoadFailedcarrying a typedLoadErrorKind.- Attaching a decoded payload raises
lumen_core::render_world::FrameDirty. An asset is the one piece of scene content that arrives ticks after the tree it belongs to, and a tick whose frame is not dirty is never extracted, so without the raise the arrival would wait for an unrelated repaint. keep_frame_loop_awake_for_assetsholds an event-driven loop open while anImageSourcein the tree has no verdict on it yet, so an element that enters the tree afterspawn_pending_decodeshas run is looked up on the next tick rather than at the next unrelated event. The claim is keyed on the element, so it retires when the element has its content or leaves the tree.- Handles are strong
Arcs to decoded data; the cache holdsHandle<T>entries that share identity across consumers. - A renderer’s image upload cache is keyed by the underlying
peniko::Blobidentity, so identical handles short-circuit the upload. - A [
notify::RecommendedWatcher] tracks every loaded file URL. On change the asset cache invalidates the affected entry, the request id of every entity referencing that path is bumped, and anAssetReloadRequestedmessage fires.reload_changed_imagesis the consumer that re-enqueues the load; the runtime installs it for a hot-reload session. The watcher wakes a parked frame loop so the change is picked up without waiting for input.
Eviction is true LRU bounded by max_bytes (default 256 MiB). Insert / evict mutate a running bytes_used: usize in O(1); a debug_assert! reconciles the running counter against a full sweep at most once per second when debug assertions are on.
Re-exports§
pub use bundle::BundleError;pub use bundle::LumenBundle;pub use bundle::parse_lumen_uri;pub use loader::AssetKind;pub use loader::AssetLoader;pub use loader::AssetLoaders;pub use loader::LoadContext;pub use loader::LoadedAsset;pub use loader::asset_extension;pub use loaders::ImageLoader;pub use loaders::SvgLoader;pub use source::AssetSource;pub use source::BundleSource;pub use source::SourceReader;
Modules§
- bundle
.lpakresource bundle: a zip-like archive that ships an entire Lumen app’s assets (main.lmn, main.css, scripts, images, fonts) as a single file. Mirrors Qt’sqrcand GTK’sGResource.- loader
- How a source path becomes a decoded asset.
- loaders
- The loaders the asset pipeline ships with.
- source
- Where an asset’s bytes come from before a loader sees them.
Structs§
- Asset
Reload Requested - Message fired when a watched asset file changes on disk.
reload_changed_imagesreacts by strippingLoadedImage/LoadedSvg/ImageLoadFailed/Enqueuedfrom every entity whoseImageSourcematchespathso the pipeline re-enqueues the load. The runtime installs that consumer only for a hot-reload session. - Asset
Server - Background-thread plumbing and content cache for the asset pipeline.
- Assets
Plugin - Plugin that installs
AssetServerand registersspawn_pending_decodes,drain_completed_decodes,process_watch_events, and the image/SVG extract fns. - Background
Image - Marks an element whose
ImageSourceis its background (bg: url(...)) rather than its content. The image loads and caches like any other source; it paints behind the element’s content, clipped to its box, and never sizes the element. - Enqueued
- Marker component on entities whose decode has been enqueued; excluded from the
spawn_pending_decodesquery. - Extracted
Image Blob - Render-world sidecar carrying a pre-built
peniko::Blobfor an extracted image. Queried alongsideExtractedImageby the renderer so the Blob reaches the painter unchanged, preserving its upload-cache identity. - Extracted
Svg - One SVG to draw this frame. Defined in
lumen-assets(notlumen-core) because the payload carries the parsed usvg tree. - Handle
- Strong, content-addressed handle to a decoded asset.
- Image
Data - Decoded image payload in RGBA8 with top-left origin.
- Image
Load Failed - Attached to the entity when its image fails to decode. Carries the typed
LoadErrorKindand a human-readable detail string. - Image
Source - Source path for an image asset, spawned by
<image src="...">in markup. Replaced byLoadedImage(orImageLoadFailed) once the asset plugin finishes decoding. - Loaded
Image - Strong handle to a decoded image, attached as a component once
<image src="...">resolves. ImplementsDeref<Target = ImageData>so field access (img.width,img.blob) flows through to the inner payload. - Loaded
Svg - Strong handle to a decoded SVG, with
Deref<Target = SvgData>enabling field access (svg.intrinsic,svg.tree). - PixBytes
- Newtype wrapper holding an
Arc<[u8]>and implementingAsRef<[u8]>so it can be passed topeniko::Blob::new, which requiresArc<T: ?Sized + AsRef<[u8]> + Send + Sync>. - Request
Id - Monotonic per-entity asset request id. Attached to every entity carrying an
ImageSource. EveryScriptCommand::SetSrcruns throughAssetServer::bump_request_idwhich increments this counter; in-flight decode jobs carrying an older id are discarded on completion. - SvgData
- Parsed SVG payload produced once at decode time and shared per-frame via
Handle<SvgData>clones.
Enums§
- Load
Error Kind - Typed asset load-failure category.
Constants§
- DEFAULT_
MAX_ BYTES - Default max bytes held across the image + SVG content caches (256 MiB).
Override with
AssetServer::with_max_bytes.
Traits§
- Asset
Size - Implemented by asset payload types so the cache can budget memory.
Functions§
- drain_
completed_ decodes - Drains completed decodes from the result channel.
- extract_
loaded_ images - Extracts every
(Transform, LoadedImage)entity into a pairedExtractedImage+ExtractedImageBlobin the render world. Clones theBlob(Arc-cheap) so the renderer’s upload-cache identity is preserved across frames. - extract_
loaded_ svgs - Extracts every
(Transform, LoadedSvg)entity into anExtractedSvgin the render world via keyed upsert. Despawns prior-frame render entries whose source entity no longer matches. - keep_
frame_ loop_ awake_ for_ assets - Keeps the frame loop scheduled while an element is still waiting on the content it named.
- process_
watch_ events - Drains filesystem-watch events and invalidates the cache for every changed path.
- register_
asset_ loader - Registers an
AssetLoaderfrom a plugin’sbuild, installing theAssetServerfirst if this plugin runs beforeAssetsPlugin. - reload_
changed_ images - Re-enqueues the load for every element showing a file that changed on disk.
- resolve_
source_ path - The path an authored asset reference loads from: a
lumen://URI as written, anything else resolved against the app directory. - spawn_
pending_ decodes - Consults the content cache for each
ImageSourceentity lacking aLoadedImage,LoadedSvg,ImageLoadFailed, orEnqueued. Cache hits attach the cached component synchronously; misses enqueue one decode job and append the entity (with its currentrequest_id) to the fan-out list. - stamp_
image_ natural_ size - D6: stamp the decoded bitmap’s intrinsic size onto
lumen_core::components::ImageComponentas soon as aLoadedImagelands on the entity (cache hit or decode completion - both surface asAdded/Changed<LoadedImage>).