Skip to content

Commit

Permalink
gltf: load textures asynchronously using io task pool
Browse files Browse the repository at this point in the history
  • Loading branch information
mockersf committed Mar 26, 2021
1 parent 9a78add commit 1a27958
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 29 deletions.
1 change: 1 addition & 0 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ impl AssetServer {
&self.server.asset_ref_counter.channel,
&*self.server.asset_io,
version,
&self.server.task_pool,
);
asset_loader
.load(&bytes, &mut load_context)
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use bevy_ecs::{
system::{Res, ResMut},
};
use bevy_reflect::{TypeUuid, TypeUuidDynamic};
use bevy_tasks::TaskPool;
use bevy_utils::{BoxedFuture, HashMap};
use crossbeam_channel::{Receiver, Sender};
use downcast_rs::{impl_downcast, Downcast};
Expand Down Expand Up @@ -78,6 +79,7 @@ pub struct LoadContext<'a> {
pub(crate) labeled_assets: HashMap<Option<String>, BoxedLoadedAsset>,
pub(crate) path: &'a Path,
pub(crate) version: usize,
pub(crate) task_pool: &'a TaskPool,
}

impl<'a> LoadContext<'a> {
Expand All @@ -86,13 +88,15 @@ impl<'a> LoadContext<'a> {
ref_change_channel: &'a RefChangeChannel,
asset_io: &'a dyn AssetIo,
version: usize,
task_pool: &'a TaskPool,
) -> Self {
Self {
ref_change_channel,
asset_io,
labeled_assets: Default::default(),
version,
path,
task_pool,
}
}

Expand Down Expand Up @@ -134,6 +138,10 @@ impl<'a> LoadContext<'a> {
}
asset_metas
}

pub fn task_pool(&self) -> &TaskPool {
self.task_pool
}
}

/// The result of loading an asset of type `T`
Expand Down
73 changes: 44 additions & 29 deletions crates/bevy_gltf/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,35 +213,50 @@ async fn load_gltf<'a, 'b>(
})
.collect();

for gltf_texture in gltf.textures() {
let mut texture = match gltf_texture.source().source() {
gltf::image::Source::View { view, mime_type } => {
let start = view.offset() as usize;
let end = (view.offset() + view.length()) as usize;
let buffer = &buffer_data[view.buffer().index()][start..end];
Texture::from_buffer(buffer, ImageType::MimeType(mime_type))?
}
gltf::image::Source::Uri { uri, mime_type } => {
let parent = load_context.path().parent().unwrap();
let image_path = parent.join(uri);
let bytes = load_context.read_asset_bytes(image_path.clone()).await?;
Texture::from_buffer(
&bytes,
mime_type
.map(|mt| ImageType::MimeType(mt))
.unwrap_or_else(|| {
ImageType::Extension(image_path.extension().unwrap().to_str().unwrap())
}),
)?
}
};
let texture_label = texture_label(&gltf_texture);
texture.sampler = texture_sampler(&gltf_texture);
if linear_textures.contains(&gltf_texture.index()) {
texture.format = TextureFormat::Rgba8Unorm;
}
load_context.set_labeled_asset::<Texture>(&texture_label, LoadedAsset::new(texture));
}
load_context
.task_pool()
.scope(|scope| {
gltf.textures().for_each(|gltf_texture| {
let linear_textures = &linear_textures;
let load_context: &LoadContext = load_context;
let buffer_data = &buffer_data;
scope.spawn(async move {
let mut texture = match gltf_texture.source().source() {
gltf::image::Source::View { view, mime_type } => {
let start = view.offset() as usize;
let end = (view.offset() + view.length()) as usize;
let buffer = &buffer_data[view.buffer().index()][start..end];
Texture::from_buffer(buffer, ImageType::MimeType(mime_type))?
}
gltf::image::Source::Uri { uri, mime_type } => {
let parent = load_context.path().parent().unwrap();
let image_path = parent.join(uri);
let bytes = load_context.read_asset_bytes(image_path.clone()).await?;
Texture::from_buffer(
&bytes,
mime_type
.map(|mt| ImageType::MimeType(mt))
.unwrap_or_else(|| {
ImageType::Extension(
image_path.extension().unwrap().to_str().unwrap(),
)
}),
)?
}
};
texture.sampler = texture_sampler(&gltf_texture);
if (linear_textures).contains(&gltf_texture.index()) {
texture.format = TextureFormat::Rgba8Unorm;
}
Result::<_, GltfError>::Ok((texture, texture_label(&gltf_texture)))
});
});
})
.into_iter()
.filter_map(|result| result.ok())
.for_each(|(texture, label)| {
load_context.set_labeled_asset::<Texture>(&label, LoadedAsset::new(texture));
});

let mut scenes = vec![];
let mut named_scenes = HashMap::new();
Expand Down

0 comments on commit 1a27958

Please sign in to comment.