Open
0 of 3 issues completedDescription
Bevy Asset V2 PR is merged, but there is still plenty of followup work to do! This issue exists to enumerate and track all of this work, although I suspect once the dust settles and we resolve the important stuff, we'll eventually want to close this rather than keep it alive indefinitely.
Immediate Short Term Followups And Tweaks
These are relatively scoped tweaks and fixes that should be resolved in the short term, prior to kicking off other larger efforts.
- Add a migration guide entry to the Bevy Asset V2 PR (@viridia added an initial guide)
-
Add a changelog entry to the Bevy Asset V2 PR - Fix hot reloading for assets that are still alive, but whose root / source asset is no longer alive
- Calling
load
for non-existent labeled assets fails silently - Replace "eager unchanged processed asset loading" behavior with "don't returned unchanged processed asset until dependencies have been checked" (see "eager asset loading" section in the Bevy Asset V2 PR).
- Add true
Ignore
AssetAction that does not copy the asset to the imported_assets folder. - Try replacing the "channel based" asset id recycling with something a bit more efficient (ex: we might be able to use raw atomic ints with some cleverness)
- Store "last modified" source asset and meta timestamps in processed meta files to enable skipping expensive hashing when the file wasn't changed
- Fix "slow loop" handle drop fix (see
TODO
comment inassets.rs
) - Migrate to TypeName
- ProcessorTransactionLog path will be out of sync with AssetWriter if the assetwriter path is customized.
Larger Next Steps / Things to Investigate
These are larger changes and features that we will ultimately want.
- Relative Asset Paths: support and encourage the use of "relative asset paths", which fixes issues like this one.
- Live asset unloading: We should free up CPU asset memory after uploading an image to the GPU. We should rethink RenderAssets and port renderer features to whatever system we build. The
Assets
collection currently usesOption<T>
for internal asset storage, which should allow us to remove a value while still keeping it "alive" ... is this the right path? This will require some investigation. - Configurable per-type defaults for AssetMeta: It should be possible to add configuration like "all png image meta should default to using nearest sampling" (currently this hard-coded per-loader/processor Settings::default() impls). Also see the "Folder Meta" bullet point.
- Avoid Reprocessing on Asset Renames / Moves: See the "canonical asset ids" discussion in Open Questions and the relevant bullet point in Draft TODO. Even without canonical ids, folder renames could avoid reprocessing in some cases.
- Multiple Asset Sources: Expand AssetPath to support "asset source names" and support multiple AssetReaders in the asset server (ex:
webserver://some_path/image.png
backed by an Http webserver AssetReader). The "default" asset reader would use normalsome_path/image.png
paths. Ideally this works in combination with multiple AssetWatchers for hot-reloading - Stable Type Names: this pr removes the TypeUuid requirement from assets in favor of
std::any::type_name
. This makes defining assets easier (no need to generate a new uuid / use weird proc macro syntax). It also makes reading meta files easier (because things have "friendly names"). We also use type names for components in scene files. If they are good enough for components, they are good enough for assets. And consistency across Bevy pillars is desirable. However,std::any::type_name
is not guaranteed to be stable (although in practice it is). We've developed a stable type path to resolve this, which should be adopted when it is ready. - Command Line Interface: It should be possible to run the asset processor in a separate process from the command line. This will also require building a network-server-backed AssetReader to communicate between the app and the processor. We've been planning to build a "bevy cli" for awhile. This seems like a good excuse to build it.
- Asset Packing: This is largely an additive feature, so it made sense to me to punt this until we've laid the foundations in this PR.
- Per-Platform Processed Assets: It should be possible to generate assets for multiple platforms by supporting multiple "processor profiles" per asset (ex: compress with format X on PC and Y on iOS). I think there should probably be arbitrary "profiles" (which can be separate from actual platforms), which are then assigned to a given platform when generating the final asset distribution for that platform. Ex: maybe devs want a "Mobile" profile that is shared between iOS and Android. Or a "LowEnd" profile shared between web and mobile.
- Versioning and Migrations: Assets, Loaders, Savers, and Processors need to have versions to determine if their schema is valid. If an asset / loader version is incompatible with the current version expected at runtime, the processor should be able to migrate them. I think we should try using Bevy Reflect for this, as it would allow us to load the old version as a dynamic Reflect type without actually having the old Rust type. It would also allow us to define "patches" to migrate between versions (Bevy Reflect devs are currently working on patching). The
.meta
file already has its own format version. Migrating that to new versions should also be possible. We should support migrations well before the release after Bevy Asset V2 lands (aka before Bevy 0.13). - Real Copy-on-write AssetPaths: Rust's actual Cow (clone-on-write type) currently used by AssetPath can still result in String clones that aren't actually necessary (cloning an Owned Cow clones the contents). Bevy's asset system requires cloning AssetPaths in a number of places, which result in actual clones of the internal Strings. This is not efficient. AssetPath internals should be reworked to exhibit truer cow-like-behavior that reduces String clones to the absolute minimum.
- Consider processor-less processing: In theory the AssetServer could run processors "inline" even if the background AssetProcessor is disabled. If we decide this is actually desirable, we could add this. But I don't think its a priority in the short or medium term.
- Pre-emptive dependency loading: We could encode dependencies in processed meta files, which could then be used by the Asset Server to kick of dependency loads as early as possible (prior to starting the actual asset load). Is this desirable? How much time would this save in practice?
- Optimize Processor With UntypedAssetIds: The processor exclusively uses AssetPath to identify assets currently. It might be possible to swap these out for UntypedAssetIds in some places, which are smaller / cheaper to hash and compare.
- One to Many Asset Processing: An asset source file that produces many assets currently must be processed into a single "processed" asset source. If labeled assets can be written separately they can each have their own configured savers and they could be loaded more granularly. Definitely worth exploring!
- Automatically Track "Runtime-only" Asset Dependencies: Right now, tracking "created at runtime" asset dependencies requires adding them via
asset_server.load_asset(StandardMaterial::default())
. I think with some cleverness we could also do this formaterials.add(StandardMaterial::default())
, making tracking work "everywhere". There are challenges here relating to change detection / ensuring the server is made aware of dependency changes. This could be expensive in some cases. - "Dependency Changed" events: Some assets have runtime artifacts that need to be re-generated when one of their dependencies change (ex: regenerate a material's bind group when a Texture needs to change). We are generating the dependency graph so we can definitely produce these events. Buuuuut generating these events will have a cost / they could be high frequency for some assets, so we might want this to be opt-in for specific cases.
- Investigate Storing More Information In Handles: Handles can now store arbitrary information, which makes it cheaper and easier to access. How much should we move into them? Canonical asset load states (via atomics)? (
handle.is_loaded()
would be very cool). Should we store the entire asset and remove theAssets<T>
collection? (Arc<RwLock<Option<Image>>>
?) - Support processing and loading files without extensions: This is a pretty arbitrary restriction and could be supported with very minimal changes.
- Folder Meta: It would be nice if we could define per folder processor configuration defaults (likely in a
.meta
or.folder_meta
file). Things like "default to linear filtering for all Images in this folder". - Replace async_broadcast with event-listener? This might be approximately drop-in for some uses and it feels more light weight
- Support Running the AssetProcessor on the Web: Most of the hard work is done here, but there are some easy straggling TODOs (make the transaction log an interface instead of a direct file writer so we can write a web storage backend, implement an AssetReader/AssetWriter that reads/writes to something like LocalStorage).
- Consider identifying and preventing circular dependencies: This is especially important for "processor dependencies", as processing will silently never finish in these cases.
- Built-in/Inlined Asset Hot Reloading: This PR regresses "built-in/inlined" asset hot reloading (previously provided by the DebugAssetServer). I'm intentionally punting this because I think it can be cleanly implemented with "multiple asset sources" by registering a "debug asset source" (ex:
debug://bevy_pbr/src/render/pbr.wgsl
asset paths) in combination with an AssetWatcher for that asset source and support for "manually loading pats with asset bytes instead of AssetReaders". The old DebugAssetServer was quite nasty and I'd love to avoid that hackery going forward. - Investigate ways to remove double-parsing meta files: Parsing meta files currently involves parsing once with "minimal" versions of the meta file to extract the type name of the loader/processor config, then parsing again to parse the "full" meta. This is suboptimal. We should be able to define custom deserializers that (1) assume the loader/processor type name comes first (2) dynamically looks up the loader/processor registrations to deserialize settings in-line (similar to components in the bevy scene format). Another alternative: deserialize as dynamic Reflect objects and then convert.
- More runtime loading configuration: Support using the Handle type as a hint to select an asset loader (instead of relying on AssetPath extensions)
- More high level Processor trait implementations: For example, it might be worth adding support for arbitrary chains of "asset transforms" that modify an in-memory asset representation between loading and saving. (ex: load a Mesh, run a
subdivide_mesh
transform, followed by aflip_normals
transform, then save the mesh to an efficient compressed format). - Bevy Scene Handle Deserialization: (see the relevant Draft TODO item for context)
- Explore High Level Load Interfaces: See this discussion for one prototype.
- Asset Streaming: It would be great if we could stream Assets (ex: stream a long video file piece by piece). See Add Support for Asset Streaming #8530
- ID Exchanging: In this PR Asset Handles/AssetIds are bigger than they need to be because they have a Uuid enum variant. If we implement an "id exchanging" system that trades Uuids for "efficient runtime ids", we can cut down on the size of AssetIds, making them more efficient. This has some open design questions, such as how to spawn entities with "default" handle values (as these wouldn't have access to the exchange api in the current system).
- Asset Path Fixup Tooling: Assets that inline asset paths inside them will break when an asset moves. The asset system provides the functionality to detect when paths break. We should build a framework that enables formats to define "path migrations". This is especially important for scene files. For editor-generated files, we should also consider using UUIDs (see other bullet point) to avoid the need to migrate in these cases.
- Load Folders In Asset Loaders: Assets V2 - Error whilst using load_context.load_direct() to load a LoadedFolder asset #9932
- Asset Archive Lifetimes: Supporting archive assets #12279
Sub-issues
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Big Picture