Asset hot reloading #266
Comments
In order to prevent memory corruption issues we'll have to pause execution while the replacement occurs. My first reaction is to put assets in an Arc<RwLock> so we can track them and still hand out references to them. We could keep some kind of Boolean "dirty" bit (Per application, not per asset) representing that assets are ready to be replaced, and check that every frame. If they are ready to be replaced then pop the new assets from a queue and replace each one until the queue is empty. EDIT: This also gives us an easy answer to "what happens if an asset is unloaded that's still attached to an entity?" Well the asset won't unload until the entity in question is removed from the game. In my opinion that's the best answer we could give to that question as it means the code won't spontaneously have assets disappear until it is done with them. |
Global pauses are unnecessary. There are data structures which permit update of value while it is read. |
@omni-viral I don't know of any such data structures. Can you provide one for me to read about? |
@Xaeroxe I'll find link to the paper to post it here. |
Maybe there is no need of fancy data structures either if we can update assets between systems run |
Still, how would we trace the assets?
|
We would need some kind of central |
(Said structure would also require a way to remove references so that the memory the assets consume can be freed) |
Put all updates in a queue. Replace the queue atomically in maintenance phase. Flush updates into the world. |
@Xaeroxe no locks please) |
Then the update will have to occur in unsafe code, which is fine but we'll have to be much more careful about memory corruption. |
Well. We should wrap unsafe code into nice and safe type and test it heavily |
Not sure if the result is something we want, but what you're asking for
sounds like shred's `TrustCell`.
|
Ok here's a nice approach that gives us minimal pausing: Rather than locking the value while it is replaced you just atomically call "set" on the cell and replace the Box value. No unsafe code, no locking. |
Except that doesn't work because Box doesn't implement Copy. Yeah we'll have to use unsafe code, maybe TrustCell? |
The std `Cell` only works for `Copy` types IIRC.
|
@torkleyy I can't find any docs on |
@omni-viral It's not part of the official API, look here |
@torkleyy |
One more question. How many asset producers will be there? Single or multiple? |
@omni-viral Current code permits multiple, which is nice for asynchronous loading from multiple systems but we may require some kind of unification to implement hot reloading. |
I'm suggesting following algorithm.
|
|
I disagree, that's not performance critical code and in my opinion it doesn't warrant the risk of unsafety to replace Mutex in that type with a non-locking unsafe variant. |
Alternatively if blocking is really that undesirable, we could use a channel to send the |
@Xaeroxe mpsc channel is the data structure with internal unsafe you were opposed to one comment earlier 😄 |
Yeah I just thought you meant some kind of TrustCell for the queue, which seemed excessive to me. Channel works much better though :) |
The thing is, I'm not sure how deeply hot reloading should be integrated in
the design, since it is a development feature, not something that's
necessary for the actual game.
|
That is a good point. In order to make the feature work we need some kind of tracking and continuous updating though. This seems to be the easiest way to accomplish that. Perhaps we could use |
|
That's what we planned to use `amethyst_release` for.
|
If hot reloading is a pure development feature, some risk might be worth it, for a simpler solution? |
Ok, what are you proposing? Mpsc channel seems to be a best of all worlds approach. It's a non-locking std library type with internal unsafe and no need for us to write unsafe sections of code. |
Oh, I don't know what would be best, my suggestion is just to do the simplest solution that fits the bill if it's only gonna be used for dev, and not for released product :) |
So essentially that problem we discussed about (updating the asset) disappeared. This was part of my second assets rework, which introduced asset storages and handles, allowing us to control reads and writes in a central place. |
445: Add asset hot reloading r=Rhuagh a=torkleyy * Adds a new resource to the world, `Arc<rayon::ThreadPool>` (or short: `core::ThreadPool`) * Adds `WeakHandle`s * Automatically reloads assets (checked every second) Fixes #266 ## Problems * ~~If a file has been written only partially and the asset storage tries to load it, it fails :( I'm not sure if there's a check we can do~~ Fixed by using fallback
@erlend-sh I mostly like what we have currently, it fits nicely into ECS and works in parallel. But at a first glance we couldn't even use |
|
I've figured most parts out already, however I'm stuck at the last one. After a file has changed, it's been read, parsed and turned into an asset, how should we replace the old assets?
Most likely assets live as components in the world, but still, how should we track them? Or is limiting it to the
World
a good idea at all?I'm not sure whether or not we need this feature before 0.5 release, probably that needs discussion, too.
The text was updated successfully, but these errors were encountered: