Resource storage and loading
Work with Byte Engine's stored resource format and payload-reading APIs.
Use this page when you change the resource-storage contracts, ReDB implementation, or payload-reading APIs. Read the resource-management reference first if you need the high-level resource model.
Each resource exposed by a backend has two parts:
- metadata, represented by
SerializableResource - binary payload bytes, exposed through a resource reader
The metadata contains the public ID, hashed UID, resource class, decoded and stored binary sizes, content hash, payload encoding, serialized typed model, optional stream descriptions, and queryable properties. The binary payload contains the actual bytes consumed by a renderer, audio system, or other runtime system.
Typed references
ResourceManager::request<T>().await returns a typed Reference<T>.
The reference contains the typed resource metadata and a reader for the payload.
For example, a material reference resolves shader references and parameter resources. A mesh reference resolves primitive materials and exposes stream descriptions for packed vertex and index data.
Resource storage backends
A resource storage backend connects resource producers and consumers to stored metadata and payloads. The contract defines resource operations without prescribing a database, directory layout, or reader backing.
The resource module separates that contract by capability:
ReadStorageBackendlists, reads, and queries resources. A read returns serialized metadata and a reader for the decoded payload.WriteStorageBackendclears or deletes resources and provides complete and incremental authoring paths.StorageBackendcomposes both capabilities for aResourceManager.- The
Dyn*StorageBackendtraits provide the same boundaries when the implementation is selected at runtime.
Backend implementations decide how to map resource IDs to storage, publish metadata and payloads, support queries, and provide reader-owned backing. Code that uses the contracts must not assume that a backend uses ReDB, files, memory mapping, or any other physical layout.
Asset storage is a separate boundary
asset::StorageBackend resolves and versions authored source assets.
resource::StorageBackend stores the resources produced from those assets.
Every model exposes at least a name queryable property by default. Specific
models can add properties as editor and tooling needs grow. A backend can choose
how it evaluates those queries as long as it preserves the query contract.
Payload authoring and encoding
The default complete-payload authoring path uses CPU LZ4 compression. It keeps a payload uncompressed when it is smaller than 1 KiB, compression would not save more than 12.5 percent, or the temporary compression output cannot be prepared safely. Set ProcessedAsset::with_compression(ResourceCompressionPolicy::Disabled) when one resource must remain uncompressed. A backend can override the CPU compression policy when it needs another transport path.
The resource hash always identifies decoded bytes, so changing the storage encoding does not change resource identity. Each resource stores one encoding: raw, cpu-lz4, or metal-io-lz4. CPU and GPU encodings are mutually exclusive by construction. Inspect encoding, size, and stored_size when you need to distinguish the client-facing payload from its physical extent.
Only complete payload store calls apply CPU compression. A ResourceTransaction created with begin_resource stays uncompressed because its bytes can arrive through partial writes.
ReDB storage backend
ReDBStorageBackend is Byte Engine's persistent resource-storage
implementation. It stores metadata in resources.db and supports two payload
layouts:
filesstores each resource payload in a separate extensionless file named from its resource ID, decoded hash, and encoding. This mode is the default. Read the resource's persistedencodingto interpret the file contents.packedstores every payload in a reusable range ofresources.packand records each resource offset inresources.db.
One mode applies to the whole ReDB resource store. The implementation records that mode when it creates the store and discovers it when the store is reopened. It rejects a conflicting mode instead of mixing payload layouts.
ResourceStorageSettings can also select native Metal I/O LZ4 transport for
compatible textures in file mode. The per-resource CPU policy and this ReDB
store setting select the final payload encoding; they are not additional
resource state.
Packed replacements use copy-on-write publication so an interrupted bake cannot replace valid metadata with partial bytes. After publication, the backend reuses the old range when no mapped reader still owns it. Deletion also returns its range. The allocator merges adjacent free ranges, chooses the smallest range that fits, and grows resources.pack only when no free range is large enough. When you reopen the store, it reconstructs free ranges from the live offsets in resources.db, which also recovers space left by an interrupted bake.
Use one ReDB backend instance for a resource directory while it can be updated. Drop read-only ReDB backends and their mapped resource backings before reopening the directory for writing.
Repeated rebuilds with changing payload sizes can split free space into many small ranges. The backend warns you when a pack of at least 64 MiB has at least 32 free ranges, at least 25 percent of the file is free, and no single range holds half of that free space. Delete the resource directory and bake the application resources again when you see this warning.
The ReDB implementation converts resource URLs into stable resource IDs for storage lookup. It maintains class and property indexes so BELD and editor tools can query resources without scanning and deserializing every entry.
Streams
Some resources contain multiple logical byte ranges in one payload. Meshes are the common example: positions, normals, UVs, triangle indices, meshlet data, and other streams can live in one packed buffer.
StreamDescription names those byte ranges. Provide stream read targets when you
need selected streams instead of the complete payload.
Loading bytes
The default load path requests backing storage from the reader. A backend can provide any reader-owned backing that satisfies that contract. For example, the ReDB file layout can provide a mapped file. Use an explicit buffer, boxed buffer, or stream target when you need ownership or preallocated memory.
Use the default target when the consumer can borrow the backing storage directly. Use explicit targets when the consumer needs a specific allocation, lifetime, or stream layout.
A CPU-compressed resource is always decoded before a client receives it. Load it into either an exact buffer sized to Reference::size or reader-owned backing storage. Partial ranges and separate stream targets are unavailable for one compressed block. If you need named ranges, load reader-owned backing storage first, then use the resource's StreamDescription values to select ranges from the decoded bytes.
Rust API
ResourceManagerReferenceresource::ReadStorageBackendresource::WriteStorageBackendresource::StorageBackendasset::StorageBackendReDBStorageBackendResourceStorageModeResourceStorageSettingsStreamDescriptionReadTargetsMutResourceCompressionPolicyResourcePayloadEncodingResourceGpuCompressionPolicy