-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bevy Asset Saving and Improvements #11216
Comments
Agreed on all three of these: the split makes sense, and the additional functionality is clearly useful. Do try to add examples as you work: we're quite low on asset examples, especially for non-trivial workflows. |
# Objective One of a few Bevy Asset improvements I would like to make: #11216. Currently asset processing and asset saving are handled by the same trait, `AssetSaver`. This makes it difficult to reuse saving implementations and impossible to have a single "universal" saver for a given asset type. ## Solution This PR splits off the processing portion of `AssetSaver` into `AssetTransformer`, which is responsible for transforming assets. This change involves adding the `LoadTransformAndSave` processor, which utilizes the new API. The `LoadAndSave` still exists since it remains useful in situations where no "transformation" of the asset is done, such as when compressing assets. ## Notes: As an aside, Bikeshedding is welcome on the names. I'm not entirely convinced by `AssetTransformer`, which was chosen mostly because `AssetProcessor` is taken. Additionally, `LoadTransformSave` may be sufficient instead of `LoadTransformAndSave`. --- ## Changelog ### Added - `AssetTransformer` which is responsible for transforming Assets. - `LoadTransformAndSave`, a `Process` implementation. ### Changed - Changed `AssetSaver`'s responsibilities from processing and saving to just saving. - Updated `asset_processing` example to use new API. - Old asset .meta files regenerated with new processor.
# Objective One of a few Bevy Asset improvements I would like to make: bevyengine#11216. Currently asset processing and asset saving are handled by the same trait, `AssetSaver`. This makes it difficult to reuse saving implementations and impossible to have a single "universal" saver for a given asset type. ## Solution This PR splits off the processing portion of `AssetSaver` into `AssetTransformer`, which is responsible for transforming assets. This change involves adding the `LoadTransformAndSave` processor, which utilizes the new API. The `LoadAndSave` still exists since it remains useful in situations where no "transformation" of the asset is done, such as when compressing assets. ## Notes: As an aside, Bikeshedding is welcome on the names. I'm not entirely convinced by `AssetTransformer`, which was chosen mostly because `AssetProcessor` is taken. Additionally, `LoadTransformSave` may be sufficient instead of `LoadTransformAndSave`. --- ## Changelog ### Added - `AssetTransformer` which is responsible for transforming Assets. - `LoadTransformAndSave`, a `Process` implementation. ### Changed - Changed `AssetSaver`'s responsibilities from processing and saving to just saving. - Updated `asset_processing` example to use new API. - Old asset .meta files regenerated with new processor.
First, I think we can call the first checkbox finished. Second, we need to resolve #11595. Third (the big one), I think we've sort of designed ourselves into a corner.
So we either must:
Each of these comes with significant tradeoffs and pretty much all of these are in tension with #11266. I'm not sure what people are willing to give up! |
I would like to comment on the theoretical interface proposed for saving above: asset_server.save(path: Path, asset: Asset) The
The reasons for this are all on display with the GLTF loader (and I assume with any upcoming 'scene' loader as well). Firstly, the contents of the GLTF file are "flattened" by the loader: the meshes are placed individually into In order to reverse this process for saving, following things must be assumed
Therefore, I would suggest a two-step process for asset saving:
I think this would suffice for everything other than, possibly, extremely large assets. However, I would personally suggest that large archives (or stream-optimized DBs) would be better modeled as an asset source, not an asset with sub-objects. |
Another challenge for the Saving interaction is managing the path-to-asset mapping in the server. For the purpose of general asset sharing and live-reloading, A strategy will be needed for handling situations such as the following:
|
So first, Arc-ing assets doesn't work - that means assets in Assets would not be safely mutable. So we can scratch that suggestion of mine. Another problem is figuring out what "counts" as a subasset. If we want to do something like @mrtracy's "gather" step, we need to be able to figure out which assets to gather in the first place. We could have a We could also just do saving in an exclusive system to serialize all the bytes, and then write them to disk in an async task. Saving seems like a less common operation than loading so optimizing for it might not matter. Then again, someone might want to make save data for a user's game an asset, or have user generated content as an asset, which they both might want to be saved and in a timely fashion. |
I wanted to bring up a suggestion I read in the Bevy Discord: asset locking. The idea is that an asset can be locked (moving it from asset dense storage into an Arc), at which point you are given an Arc (or similar) to it. This Arc can then be passed in to an asset saver which can do the actual saving. At some point in the future, if all the Arcs have been dropped, the asset can be unlocked, which returns the asset back to dense storage. Direct advantages of this approach:
Some disadvantages of this:
|
I also think this could also reduce overhead with asset loading/processing. Currently if you have "load dependencies", as far as I can tell, the assets must be loaded from scratch. This means even if the load dependency is already loaded, the asset has to be reloaded. I think we could have the asset loader send a message to the asset server through a channel asking it to lock an asset and returning its Arc back to the loader once that completes. This should allow us to dedup the loading code between |
What problem does this solve or what need does it fill?
Bevy Asset is currently designed around loading and processing assets, however with just a little bit of work it could be improved with additional functionality such as saving assets. This issue is to track my efforts in accomplishing this.
I have three goals:
AssetSaver
intoAssetSaver
andAssetTransformer
AssetServer
What solution would you like?
Split
AssetSaver
intoAssetSaver
andAssetTransformer
AssetSaver
currently holds two responsibilities: processing assets and then converting them to bytes for anAssetWriter
to save. By splitting it into two parts we can reduce code duplication and make the asset API more ergonomic.This change will require modifying
LoadAndSave<L: AssetLoader, S: AssetSaver>
to something like:Although this is technically a breaking change, it has a very limited surface area (just
LoadAndSave
and any custom implementations ofAssetSaver
), and a very easy migration (useLoadTransformAndSave
and split yourAssetSaver
implementation into its two parts), so I believe that it is worth it to enable ergonomic saving and improve the Bevy Asset data model.Note: I'm note entirely set on the name
AssetTransformer
, butAssetProcessor
is taken. Bikeshedding is welcome on this.Add saving functionality to the
AssetServer
I would like to modify the
AssetServer
to expose an API such as:With events to indicate saving progress.
Add manual Asset processing
Although the current
AssetProcessor
usage of preprocessing assets is preferable for the vast majority of use cases, it would still be handy to be able to manually process an asset from time to time. For example, transforming aDynamicScene
to prep it for saving, or processing something once-off. I'm currently undecided about how to fit this into the API (AssetServer
?AssetProcessor
? Manually calling something likeAssetTransformer::transform()
?), but I will consider this further as I complete the first two tasks.The text was updated successfully, but these errors were encountered: