mirror of
https://github.com/bevyengine/bevy
synced 2024-11-26 22:50:19 +00:00
012ae07dc8
Right now, a direct reference to the target TaskPool is required to launch tasks on the pools, despite the three newtyped pools (AsyncComputeTaskPool, ComputeTaskPool, and IoTaskPool) effectively acting as global instances. The need to pass a TaskPool reference adds notable friction to spawning subtasks within existing tasks. Possible use cases for this may include chaining tasks within the same pool like spawning separate send/receive I/O tasks after waiting on a network connection to be established, or allowing cross-pool dependent tasks like starting dependent multi-frame computations following a long I/O load. Other task execution runtimes provide static access to spawning tasks (i.e. `tokio::spawn`), which is notably easier to use than the reference passing required by `bevy_tasks` right now. This PR makes does the following: * Adds `*TaskPool::init` which initializes a `OnceCell`'ed with a provided TaskPool. Failing if the pool has already been initialized. * Adds `*TaskPool::get` which fetches the initialized global pool of the respective type or panics. This generally should not be an issue in normal Bevy use, as the pools are initialized before they are accessed. * Updated default task pool initialization to either pull the global handles and save them as resources, or if they are already initialized, pull the a cloned global handle as the resource. This should make it notably easier to build more complex task hierarchies for dependent tasks. It should also make writing bevy-adjacent, but not strictly bevy-only plugin crates easier, as the global pools ensure it's all running on the same threads. One alternative considered is keeping a thread-local reference to the pool for all threads in each pool to enable the same `tokio::spawn` interface. This would spawn tasks on the same pool that a task is currently running in. However this potentially leads to potential footgun situations where long running blocking tasks run on `ComputeTaskPool`.
93 lines
3.1 KiB
Rust
93 lines
3.1 KiB
Rust
//! Implements a custom asset io loader.
|
|
//! An [`AssetIo`] is what the asset server uses to read the raw bytes of assets.
|
|
//! It does not know anything about the asset formats, only how to talk to the underlying storage.
|
|
|
|
use bevy::{
|
|
asset::{AssetIo, AssetIoError, Metadata},
|
|
prelude::*,
|
|
utils::BoxedFuture,
|
|
};
|
|
use std::path::{Path, PathBuf};
|
|
|
|
/// A custom asset io implementation that simply defers to the platform default
|
|
/// implementation.
|
|
///
|
|
/// This can be used as a starting point for developing a useful implementation
|
|
/// that can defer to the default when needed.
|
|
struct CustomAssetIo(Box<dyn AssetIo>);
|
|
|
|
impl AssetIo for CustomAssetIo {
|
|
fn load_path<'a>(&'a self, path: &'a Path) -> BoxedFuture<'a, Result<Vec<u8>, AssetIoError>> {
|
|
info!("load_path({:?})", path);
|
|
self.0.load_path(path)
|
|
}
|
|
|
|
fn read_directory(
|
|
&self,
|
|
path: &Path,
|
|
) -> Result<Box<dyn Iterator<Item = PathBuf>>, AssetIoError> {
|
|
info!("read_directory({:?})", path);
|
|
self.0.read_directory(path)
|
|
}
|
|
|
|
fn watch_path_for_changes(&self, path: &Path) -> Result<(), AssetIoError> {
|
|
info!("watch_path_for_changes({:?})", path);
|
|
self.0.watch_path_for_changes(path)
|
|
}
|
|
|
|
fn watch_for_changes(&self) -> Result<(), AssetIoError> {
|
|
info!("watch_for_changes()");
|
|
self.0.watch_for_changes()
|
|
}
|
|
|
|
fn get_metadata(&self, path: &Path) -> Result<Metadata, AssetIoError> {
|
|
info!("get_metadata({:?})", path);
|
|
self.0.get_metadata(path)
|
|
}
|
|
}
|
|
|
|
/// A plugin used to execute the override of the asset io
|
|
struct CustomAssetIoPlugin;
|
|
|
|
impl Plugin for CustomAssetIoPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
let asset_io = {
|
|
// the platform default asset io requires a reference to the app
|
|
// builder to find its configuration
|
|
|
|
let default_io = bevy::asset::create_platform_default_asset_io(app);
|
|
|
|
// create the custom asset io instance
|
|
|
|
CustomAssetIo(default_io)
|
|
};
|
|
|
|
// the asset server is constructed and added the resource manager
|
|
|
|
app.insert_resource(AssetServer::new(asset_io));
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
App::new()
|
|
.add_plugins_with(DefaultPlugins, |group| {
|
|
// the custom asset io plugin must be inserted in-between the
|
|
// `CorePlugin' and `AssetPlugin`. It needs to be after the
|
|
// CorePlugin, so that the IO task pool has already been constructed.
|
|
// And it must be before the `AssetPlugin` so that the asset plugin
|
|
// doesn't create another instance of an asset server. In general,
|
|
// the AssetPlugin should still run so that other aspects of the
|
|
// asset system are initialized correctly.
|
|
group.add_before::<bevy::asset::AssetPlugin, _>(CustomAssetIoPlugin)
|
|
})
|
|
.add_startup_system(setup)
|
|
.run();
|
|
}
|
|
|
|
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|
commands.spawn_bundle(Camera2dBundle::default());
|
|
commands.spawn_bundle(SpriteBundle {
|
|
texture: asset_server.load("branding/icon.png"),
|
|
..default()
|
|
});
|
|
}
|