Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into microoptimize-queue-m…
Browse files Browse the repository at this point in the history
…aterial-meshes
  • Loading branch information
pcwalton committed Mar 30, 2024
2 parents c82e92b + 70c69cd commit e6ae951
Show file tree
Hide file tree
Showing 55 changed files with 1,662 additions and 553 deletions.
2 changes: 2 additions & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
* FiraMono by The Mozilla Foundation and Telefonica S.A (SIL Open Font License, Version 1.1: assets/fonts/FiraMono-LICENSE)
* Barycentric from [mk_bary_gltf](https://github.com/komadori/mk_bary_gltf) (MIT OR Apache-2.0)
* `MorphStressTest.gltf`, [MorphStressTest] ([CC-BY 4.0] by Analytical Graphics, Inc, Model and textures by Ed Mackey)
* Mysterious acoustic guitar music sample from [florianreichelt](https://freesound.org/people/florianreichelt/sounds/412429/) (CC0 license)
* Epic orchestra music sample, modified to loop, from [Migfus20](https://freesound.org/people/Migfus20/sounds/560449/) ([CC BY 4.0 DEED](https://creativecommons.org/licenses/by/4.0/))

[MorphStressTest]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/MorphStressTest
[fox]: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Fox
Expand Down
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,17 @@ description = "Shows how to create and register a custom audio source by impleme
category = "Audio"
wasm = true

[[example]]
name = "soundtrack"
path = "examples/audio/soundtrack.rs"
doc-scrape-examples = true

[package.metadata.example.soundtrack]
name = "Soundtrack"
description = "Shows how to play different soundtracks based on game state"
category = "Audio"
wasm = true

[[example]]
name = "spatial_audio_2d"
path = "examples/audio/spatial_audio_2d.rs"
Expand Down
Binary file added assets/sounds/Epic orchestra music.ogg
Binary file not shown.
Binary file added assets/sounds/Mysterious acoustic guitar.ogg
Binary file not shown.
6 changes: 6 additions & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ bevy_reflect = { path = "../crates/bevy_reflect" }
bevy_tasks = { path = "../crates/bevy_tasks" }
bevy_utils = { path = "../crates/bevy_utils" }
bevy_math = { path = "../crates/bevy_math" }
bevy_render = { path = "../crates/bevy_render" }

[profile.release]
opt-level = 3
Expand Down Expand Up @@ -62,6 +63,11 @@ name = "bezier"
path = "benches/bevy_math/bezier.rs"
harness = false

[[bench]]
name = "torus"
path = "benches/bevy_render/torus.rs"
harness = false

[[bench]]
name = "entity_hash"
path = "benches/bevy_ecs/world/entity_hash.rs"
Expand Down
15 changes: 15 additions & 0 deletions benches/benches/bevy_render/torus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};

use bevy_render::mesh::TorusMeshBuilder;

fn torus(c: &mut Criterion) {
c.bench_function("build_torus", |b| {
b.iter(|| black_box(TorusMeshBuilder::new(black_box(0.5),black_box(1.0))));
});
}

criterion_group!(
benches,
torus,
);
criterion_main!(benches);
16 changes: 14 additions & 2 deletions crates/bevy_asset/src/io/file/sync_file_asset.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use futures_io::{AsyncRead, AsyncWrite};
use futures_io::{AsyncRead, AsyncSeek, AsyncWrite};
use futures_lite::Stream;

use crate::io::{
Expand All @@ -8,7 +8,7 @@ use crate::io::{

use std::{
fs::{read_dir, File},
io::{Read, Write},
io::{Read, Seek, Write},
path::{Path, PathBuf},
pin::Pin,
task::Poll,
Expand All @@ -30,6 +30,18 @@ impl AsyncRead for FileReader {
}
}

impl AsyncSeek for FileReader {
fn poll_seek(
self: Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
pos: std::io::SeekFrom,
) -> Poll<std::io::Result<u64>> {
let this = self.get_mut();
let seek = this.0.seek(pos);
Poll::Ready(seek)
}
}

struct FileWriter(File);

impl AsyncWrite for FileWriter {
Expand Down
43 changes: 42 additions & 1 deletion crates/bevy_asset/src/io/memory.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::io::{AssetReader, AssetReaderError, PathStream, Reader};
use bevy_utils::HashMap;
use futures_io::AsyncRead;
use futures_io::{AsyncRead, AsyncSeek};
use futures_lite::{ready, Stream};
use parking_lot::RwLock;
use std::io::SeekFrom;
use std::{
path::{Path, PathBuf},
pin::Pin,
Expand Down Expand Up @@ -236,6 +237,46 @@ impl AsyncRead for DataReader {
}
}

impl AsyncSeek for DataReader {
fn poll_seek(
mut self: Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
pos: SeekFrom,
) -> Poll<std::io::Result<u64>> {
let result = match pos {
SeekFrom::Start(offset) => offset.try_into(),
SeekFrom::End(offset) => self
.data
.value()
.len()
.try_into()
.map(|len: i64| len - offset),
SeekFrom::Current(offset) => self
.bytes_read
.try_into()
.map(|bytes_read: i64| bytes_read + offset),
};

if let Ok(new_pos) = result {
if new_pos < 0 {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek position is out of range",
)))
} else {
self.bytes_read = new_pos as _;

Poll::Ready(Ok(new_pos as _))
}
} else {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek position is out of range",
)))
}
}
}

impl AssetReader for MemoryAssetReader {
async fn read<'a>(&'a self, path: &'a Path) -> Result<Box<Reader<'a>>, AssetReaderError> {
self.root
Expand Down
112 changes: 110 additions & 2 deletions crates/bevy_asset/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ pub use futures_lite::{AsyncReadExt, AsyncWriteExt};
pub use source::*;

use bevy_utils::{BoxedFuture, ConditionalSendFuture};
use futures_io::{AsyncRead, AsyncWrite};
use futures_io::{AsyncRead, AsyncSeek, AsyncWrite};
use futures_lite::{ready, Stream};
use std::io::SeekFrom;
use std::task::Context;
use std::{
path::{Path, PathBuf},
pin::Pin,
Expand Down Expand Up @@ -55,7 +57,11 @@ impl From<std::io::Error> for AssetReaderError {
}
}

pub type Reader<'a> = dyn AsyncRead + Unpin + Send + Sync + 'a;
pub trait AsyncReadAndSeek: AsyncRead + AsyncSeek {}

impl<T: AsyncRead + AsyncSeek> AsyncReadAndSeek for T {}

pub type Reader<'a> = dyn AsyncReadAndSeek + Unpin + Send + Sync + 'a;

/// Performs read operations on an asset storage. [`AssetReader`] exposes a "virtual filesystem"
/// API, where asset bytes and asset metadata bytes are both stored and accessible for a given
Expand Down Expand Up @@ -442,6 +448,108 @@ impl AsyncRead for VecReader {
}
}

impl AsyncSeek for VecReader {
fn poll_seek(
mut self: Pin<&mut Self>,
_cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<std::io::Result<u64>> {
let result = match pos {
SeekFrom::Start(offset) => offset.try_into(),
SeekFrom::End(offset) => self.bytes.len().try_into().map(|len: i64| len - offset),
SeekFrom::Current(offset) => self
.bytes_read
.try_into()
.map(|bytes_read: i64| bytes_read + offset),
};

if let Ok(new_pos) = result {
if new_pos < 0 {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek position is out of range",
)))
} else {
self.bytes_read = new_pos as _;

Poll::Ready(Ok(new_pos as _))
}
} else {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek position is out of range",
)))
}
}
}

/// An [`AsyncRead`] implementation capable of reading a [`&[u8]`].
pub struct SliceReader<'a> {
bytes: &'a [u8],
bytes_read: usize,
}

impl<'a> SliceReader<'a> {
/// Create a new [`SliceReader`] for `bytes`.
pub fn new(bytes: &'a [u8]) -> Self {
Self {
bytes,
bytes_read: 0,
}
}
}

impl<'a> AsyncRead for SliceReader<'a> {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut [u8],
) -> Poll<std::io::Result<usize>> {
if self.bytes_read >= self.bytes.len() {
Poll::Ready(Ok(0))
} else {
let n = ready!(Pin::new(&mut &self.bytes[self.bytes_read..]).poll_read(cx, buf))?;
self.bytes_read += n;
Poll::Ready(Ok(n))
}
}
}

impl<'a> AsyncSeek for SliceReader<'a> {
fn poll_seek(
mut self: Pin<&mut Self>,
_cx: &mut Context<'_>,
pos: SeekFrom,
) -> Poll<std::io::Result<u64>> {
let result = match pos {
SeekFrom::Start(offset) => offset.try_into(),
SeekFrom::End(offset) => self.bytes.len().try_into().map(|len: i64| len - offset),
SeekFrom::Current(offset) => self
.bytes_read
.try_into()
.map(|bytes_read: i64| bytes_read + offset),
};

if let Ok(new_pos) = result {
if new_pos < 0 {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek position is out of range",
)))
} else {
self.bytes_read = new_pos as _;

Poll::Ready(Ok(new_pos as _))
}
} else {
Poll::Ready(Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"seek position is out of range",
)))
}
}
}

/// Appends `.meta` to the given path.
pub(crate) fn get_meta_path(path: &Path) -> PathBuf {
let mut meta_path = path.to_path_buf();
Expand Down
14 changes: 13 additions & 1 deletion crates/bevy_asset/src/io/processor_gated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use crate::{
};
use async_lock::RwLockReadGuardArc;
use bevy_utils::tracing::trace;
use futures_io::AsyncRead;
use futures_io::{AsyncRead, AsyncSeek};
use std::io::SeekFrom;
use std::task::Poll;
use std::{path::Path, pin::Pin, sync::Arc};

use super::ErasedAssetReader;
Expand Down Expand Up @@ -139,3 +141,13 @@ impl<'a> AsyncRead for TransactionLockedReader<'a> {
Pin::new(&mut self.reader).poll_read(cx, buf)
}
}

impl<'a> AsyncSeek for TransactionLockedReader<'a> {
fn poll_seek(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
pos: SeekFrom,
) -> Poll<std::io::Result<u64>> {
Pin::new(&mut self.reader).poll_seek(cx, pos)
}
}
4 changes: 3 additions & 1 deletion crates/bevy_asset/src/processor/process.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::io::SliceReader;
use crate::{
io::{
AssetReaderError, AssetWriterError, MissingAssetWriterError,
Expand Down Expand Up @@ -343,12 +344,13 @@ impl<'a> ProcessContext<'a> {
let server = &self.processor.server;
let loader_name = std::any::type_name::<L>();
let loader = server.get_asset_loader_with_type_name(loader_name).await?;
let mut reader = SliceReader::new(self.asset_bytes);
let loaded_asset = server
.load_with_meta_loader_and_reader(
self.path,
Box::new(meta),
&*loader,
&mut self.asset_bytes,
&mut reader,
false,
true,
)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bevy_render::{
camera::ExtractedCamera,
diagnostic::RecordDiagnostics,
render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::RenderPhase,
render_phase::SortedRenderPhase,
render_resource::RenderPassDescriptor,
renderer::RenderContext,
view::{ExtractedView, ViewTarget},
Expand All @@ -16,7 +16,7 @@ pub struct MainPass2dNode {
query: QueryState<
(
&'static ExtractedCamera,
&'static RenderPhase<Transparent2d>,
&'static SortedRenderPhase<Transparent2d>,
&'static ViewTarget,
),
With<ExtractedView>,
Expand Down
Loading

0 comments on commit e6ae951

Please sign in to comment.