diff --git a/.cargo/config_fast_builds b/.cargo/config_fast_builds index fa492453fa..71ae452ac4 100644 --- a/.cargo/config_fast_builds +++ b/.cargo/config_fast_builds @@ -10,8 +10,6 @@ rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"] [target.x86_64-apple-darwin] rustflags = ["-Zshare-generics=y"] -# NOTE: you must manually install lld on windows. you can easily do this with the "scoop" package manager: -# `scoop install llvm` [target.x86_64-pc-windows-msvc] -linker = "lld-link.exe" -rustflags = ["-Clinker=lld", "-Zshare-generics=y"] \ No newline at end of file +linker = "rust-lld.exe" +rustflags = ["-Zshare-generics=y"] \ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e57ebcef48..cceafa0dbc 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,14 +17,26 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 with: toolchain: stable override: true + + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + components: rustfmt + - name: Install alsa run: sudo apt-get install libasound2-dev + - name: Build run: cargo check + + - name: Check the format + run: cargo +nightly fmt --all -- --check + - name: Run tests run: cargo test --workspace diff --git a/Cargo.toml b/Cargo.toml index 392646dc9d..cb5fbf4d54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ exclude = ["assets/**/*", "tools/**/*", ".github/**/*", "crates/**/*"] [features] default = ["bevy_audio", "bevy_gltf", "bevy_wgpu", "bevy_winit", "png", "hdr", "mp3"] profiler = ["bevy_ecs/profiler", "bevy_diagnostic/profiler"] +wgpu_trace = ["bevy_wgpu/trace"] # Image format support for texture loading (PNG and HDR are enabled by default) png = ["bevy_render/png"] @@ -122,6 +123,10 @@ path = "examples/app/headless.rs" name = "plugin" path = "examples/app/plugin.rs" +[[example]] +name = "thread_pool_resources" +path = "examples/app/thread_pool_resources.rs" + [[example]] name = "hot_asset_reloading" path = "examples/asset/hot_asset_reloading.rs" diff --git a/crates/bevy_app/src/event.rs b/crates/bevy_app/src/event.rs index bb197c6966..8a907cc38e 100644 --- a/crates/bevy_app/src/event.rs +++ b/crates/bevy_app/src/event.rs @@ -82,7 +82,7 @@ fn map_instance_event(event_instance: &EventInstance) -> &T { &event_instance.event } -/// Reads events of type `T` in order and tracks which events have already been read. +/// Reads events of type `T` in order and tracks which events have already been read. pub struct EventReader { last_event_count: usize, _marker: PhantomData, diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index b60604d30e..01b43df487 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -24,7 +24,7 @@ impl HandleId { /// A handle into a specific Asset of type `T` /// -/// Handles contain a unique id that corresponds to a specific asset in the [Assets](crate::Assets) collection. +/// Handles contain a unique id that corresponds to a specific asset in the [Assets](crate::Assets) collection. #[derive(Properties)] pub struct Handle where diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index 8dd3635bcf..b2751a37fe 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -1,7 +1,7 @@ -#[cfg(feature = "filesystem_watcher")] -mod filesystem_watcher; mod asset_server; mod assets; +#[cfg(feature = "filesystem_watcher")] +mod filesystem_watcher; mod handle; mod load_request; mod loader; diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 6b4a0c1533..e0dda22fbe 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -53,7 +53,7 @@ impl AssetChannel { } } -/// Reads [AssetResult]s from an [AssetChannel] and updates the [Assets] collection and [LoadState] accordingly +/// Reads [AssetResult]s from an [AssetChannel] and updates the [Assets] collection and [LoadState] accordingly pub fn update_asset_storage_system( asset_channel: Res>, asset_server: Res, diff --git a/crates/bevy_core/src/float_ord.rs b/crates/bevy_core/src/float_ord.rs index 7e55e8db1e..29d1545cdb 100644 --- a/crates/bevy_core/src/float_ord.rs +++ b/crates/bevy_core/src/float_ord.rs @@ -7,7 +7,7 @@ use std::{ /// A wrapper type that enables ordering floats. This is a work around for the famous "rust float ordering" problem. /// By using it, you acknowledge that sorting NaN is undefined according to spec. This implementation treats NaN as the -/// "smallest" float. +/// "smallest" float. #[derive(Debug, Copy, Clone, PartialOrd)] pub struct FloatOrd(pub f32); diff --git a/crates/bevy_diagnostic/Cargo.toml b/crates/bevy_diagnostic/Cargo.toml index af8279c3bb..4d704dabe8 100644 --- a/crates/bevy_diagnostic/Cargo.toml +++ b/crates/bevy_diagnostic/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT" keywords = ["bevy"] [features] -profiler = [] +profiler = ["bevy_ecs/profiler"] [dependencies] # bevy diff --git a/crates/bevy_diagnostic/src/lib.rs b/crates/bevy_diagnostic/src/lib.rs index 98f647a37c..c5f9b4c394 100644 --- a/crates/bevy_diagnostic/src/lib.rs +++ b/crates/bevy_diagnostic/src/lib.rs @@ -19,7 +19,7 @@ impl Plugin for DiagnosticsPlugin { #[cfg(feature = "profiler")] { use bevy_ecs::IntoQuerySystem; - app.add_resource::>(Box::new( + app.add_resource::>(Box::new( system_profiler::SystemProfiler::default(), )) .add_system_to_stage( diff --git a/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs b/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs index ad0ee8198b..9409485e15 100644 --- a/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs +++ b/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs @@ -4,7 +4,7 @@ use bevy_core::{Time, Timer}; use bevy_ecs::{IntoQuerySystem, Res, ResMut}; use std::time::Duration; -/// An App Plugin that prints diagnostics to the console +/// An App Plugin that prints diagnostics to the console pub struct PrintDiagnosticsPlugin { pub debug: bool, pub wait_duration: Duration, diff --git a/crates/bevy_diagnostic/src/system_profiler.rs b/crates/bevy_diagnostic/src/system_profiler.rs index 7a6577ac93..f10d72a5a1 100644 --- a/crates/bevy_diagnostic/src/system_profiler.rs +++ b/crates/bevy_diagnostic/src/system_profiler.rs @@ -1,5 +1,5 @@ use crate::{Diagnostic, DiagnosticId, Diagnostics}; -use bevy_ecs::{profiler::Profiler, Res, ResMut}; +use bevy_ecs::{Profiler, Res, ResMut}; use std::{ borrow::Cow, collections::HashMap, diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index 7222f282c6..28de4c835c 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -18,4 +18,5 @@ bevy_hecs = { path = "hecs", features = ["macros", "serialize"], version = "0.1" rand = "0.7.2" rayon = "1.3" crossbeam-channel = "0.4.2" -fixedbitset = "0.3.0" \ No newline at end of file +fixedbitset = "0.3.0" +downcast-rs = "1.1.1" diff --git a/crates/bevy_ecs/hecs/examples/format.rs b/crates/bevy_ecs/hecs/examples/format.rs index 2dd33cbb60..942c4eaa98 100644 --- a/crates/bevy_ecs/hecs/examples/format.rs +++ b/crates/bevy_ecs/hecs/examples/format.rs @@ -4,7 +4,9 @@ //! also be useful for serialization, or other row-oriented generic operations. fn format_entity(entity: bevy_hecs::EntityRef<'_>) -> String { - fn fmt(entity: bevy_hecs::EntityRef<'_>) -> Option { + fn fmt( + entity: bevy_hecs::EntityRef<'_>, + ) -> Option { Some(entity.get::()?.to_string()) } diff --git a/crates/bevy_ecs/hecs/src/query.rs b/crates/bevy_ecs/hecs/src/query.rs index 14e008ec7e..5c11297af3 100644 --- a/crates/bevy_ecs/hecs/src/query.rs +++ b/crates/bevy_ecs/hecs/src/query.rs @@ -182,6 +182,12 @@ impl<'a, T: Component> DerefMut for Mut<'a, T> { } } +impl<'a, T: Component + core::fmt::Debug> core::fmt::Debug for Mut<'a, T> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + self.value.fmt(f) + } +} + impl<'a, T: Component> Query for Mut<'a, T> { type Fetch = FetchMut; } diff --git a/crates/bevy_ecs/src/resource/resource_query.rs b/crates/bevy_ecs/src/resource/resource_query.rs index 0a48022d14..bae6498ce8 100644 --- a/crates/bevy_ecs/src/resource/resource_query.rs +++ b/crates/bevy_ecs/src/resource/resource_query.rs @@ -3,12 +3,12 @@ use crate::{ system::{SystemId, TypeAccess}, Resource, ResourceIndex, }; +use bevy_hecs::smaller_tuples_too; use core::{ any::TypeId, ops::{Deref, DerefMut}, ptr::NonNull, }; -use bevy_hecs::smaller_tuples_too; use std::marker::PhantomData; /// Shared borrow of a Resource diff --git a/crates/bevy_ecs/src/resource/resources.rs b/crates/bevy_ecs/src/resource/resources.rs index 8495e9c58c..f0561ef997 100644 --- a/crates/bevy_ecs/src/resource/resources.rs +++ b/crates/bevy_ecs/src/resource/resources.rs @@ -1,7 +1,7 @@ use super::{FetchResource, ResourceQuery}; use crate::system::SystemId; -use core::any::TypeId; use bevy_hecs::{Archetype, Ref, RefMut, TypeInfo}; +use core::any::TypeId; use std::{collections::HashMap, ptr::NonNull}; /// A Resource type @@ -19,7 +19,7 @@ pub enum ResourceIndex { System(SystemId), } -/// A collection of resource instances identified by their type. +/// A collection of resource instances identified by their type. #[derive(Default)] pub struct Resources { pub(crate) resource_data: HashMap, diff --git a/crates/bevy_ecs/src/schedule/parallel_executor.rs b/crates/bevy_ecs/src/schedule/parallel_executor.rs index 0208d739a3..db51e29333 100644 --- a/crates/bevy_ecs/src/schedule/parallel_executor.rs +++ b/crates/bevy_ecs/src/schedule/parallel_executor.rs @@ -3,9 +3,9 @@ use crate::{ resource::Resources, system::{ArchetypeAccess, System, ThreadLocalExecution, TypeAccess}, }; +use bevy_hecs::{ArchetypesGeneration, World}; use crossbeam_channel::{Receiver, Sender}; use fixedbitset::FixedBitSet; -use bevy_hecs::{ArchetypesGeneration, World}; use rayon::ScopeFifo; use std::{ ops::Range, @@ -68,6 +68,52 @@ impl ParallelExecutor { } } +/// This can be added as an app resource to control the global `rayon::ThreadPool` used by ecs. +// Dev internal note: We cannot directly expose a ThreadPoolBuilder here as it does not implement Send and Sync. +#[derive(Debug, Default, Clone)] +pub struct ParallelExecutorOptions { + /// If some value, we'll set up the thread pool to use at most n threads. See `rayon::ThreadPoolBuilder::num_threads`. + num_threads: Option, + /// If some value, we'll set up the thread pool's' workers to the given stack size. See `rayon::ThreadPoolBuilder::stack_size`. + stack_size: Option, + // TODO: Do we also need/want to expose other features (*_handler, etc.) +} + +impl ParallelExecutorOptions { + /// Creates a new ParallelExecutorOptions instance + pub fn new() -> Self { + Self::default() + } + + /// Sets the num_threads option, using the builder pattern + pub fn with_num_threads(mut self, num_threads: Option) -> Self { + self.num_threads = num_threads; + self + } + + /// Sets the stack_size option, using the builder pattern. WARNING: Only use this if you know what you're doing, + /// otherwise your application may run into stability and performance issues. + pub fn with_stack_size(mut self, stack_size: Option) -> Self { + self.stack_size = stack_size; + self + } + + /// Creates a new ThreadPoolBuilder based on the current options. + pub(crate) fn create_builder(&self) -> rayon::ThreadPoolBuilder { + let mut builder = rayon::ThreadPoolBuilder::new(); + + if let Some(num_threads) = self.num_threads { + builder = builder.num_threads(num_threads); + } + + if let Some(stack_size) = self.stack_size { + builder = builder.stack_size(stack_size); + } + + builder + } +} + #[derive(Debug, Clone)] pub struct ExecutorStage { /// each system's set of dependencies @@ -313,19 +359,22 @@ impl ExecutorStage { self.running_systems.clear(); let mut run_ready_result = RunReadyResult::Ok; - let run_ready_system_index_range = if let Some(index) = self - .thread_local_system_indices - .get(0) - { - // if there is an upcoming thread local system, run up to (and including) it - 0..(*index + 1) - } else { - // if there are no upcoming thread local systems, run everything right now - 0..systems.len() - }; + let run_ready_system_index_range = + if let Some(index) = self.thread_local_system_indices.get(0) { + // if there is an upcoming thread local system, run up to (and including) it + 0..(*index + 1) + } else { + // if there are no upcoming thread local systems, run everything right now + 0..systems.len() + }; rayon::scope_fifo(|scope| { - run_ready_result = - self.run_ready_systems(systems, RunReadyType::Range(run_ready_system_index_range), scope, world, resources); + run_ready_result = self.run_ready_systems( + systems, + RunReadyType::Range(run_ready_system_index_range), + scope, + world, + resources, + ); }); loop { // if all systems in the stage are finished, break out of the loop @@ -395,8 +444,8 @@ mod tests { system::{IntoQuerySystem, IntoThreadLocalSystem, Query}, Commands, }; - use fixedbitset::FixedBitSet; use bevy_hecs::{Entity, World}; + use fixedbitset::FixedBitSet; use std::sync::{Arc, Mutex}; #[derive(Default)] diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 41e658af57..77a72237dc 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -1,5 +1,6 @@ use crate::{ resource::Resources, + schedule::ParallelExecutorOptions, system::{System, SystemId, ThreadLocalExecution}, }; use bevy_hecs::World; @@ -130,9 +131,9 @@ impl Schedule { for stage_name in self.stage_order.iter() { if let Some(stage_systems) = self.stages.get_mut(stage_name) { for system in stage_systems.iter_mut() { - #[cfg(feature = "profiler")] - crate::profiler::profiler_start(resources, system.name().clone()); let mut system = system.lock().unwrap(); + #[cfg(feature = "profiler")] + crate::profiler_start(resources, system.name().clone()); system.update_archetype_access(world); match system.thread_local_execution() { ThreadLocalExecution::NextFlush => system.run(world, resources), @@ -143,7 +144,7 @@ impl Schedule { } } #[cfg(feature = "profiler")] - crate::profiler::profiler_stop(resources, system.name().clone()); + crate::profiler_stop(resources, system.name().clone()); } // "flush" @@ -169,6 +170,15 @@ impl Schedule { return; } + let thread_pool_builder = resources + .get::() + .map(|options| (*options).clone()) + .unwrap_or_else(|| ParallelExecutorOptions::default()) + .create_builder(); + // For now, bevy_ecs only uses the global thread pool so it is sufficient to configure it once here. + // Dont call .unwrap() as the function is called twice.. + let _ = thread_pool_builder.build_global(); + for stage in self.stages.values_mut() { for system in stage.iter_mut() { let mut system = system.lock().unwrap(); diff --git a/crates/bevy_ecs/src/system/commands.rs b/crates/bevy_ecs/src/system/commands.rs index 9086f83aa7..7191fb5f76 100644 --- a/crates/bevy_ecs/src/system/commands.rs +++ b/crates/bevy_ecs/src/system/commands.rs @@ -1,9 +1,12 @@ use super::SystemId; use crate::resource::{Resource, Resources}; use bevy_hecs::{Bundle, Component, DynamicBundle, Entity, World}; -use std::sync::{Arc, Mutex}; +use std::{ + marker::PhantomData, + sync::{Arc, Mutex}, +}; -/// A queued command to mutate the current [World] or [Resources] +/// A queued command to mutate the current [World] or [Resources] pub enum Command { WriteWorld(Box), WriteResources(Box), @@ -109,6 +112,25 @@ where } } +pub(crate) struct RemoveOne +where + T: Component, +{ + entity: Entity, + phantom: PhantomData, +} + +impl WorldWriter for RemoveOne +where + T: Component, +{ + fn write(self: Box, world: &mut World) { + if world.get::(self.entity).is_ok() { + world.remove_one::(self.entity).unwrap(); + } + } +} + pub trait ResourcesWriter: Send + Sync { fn write(self: Box, resources: &mut Resources); } @@ -321,6 +343,16 @@ impl Commands { } self } + + pub fn remove_one(&mut self, entity: Entity) -> &mut Self + where + T: Component, + { + self.write_world(RemoveOne:: { + entity, + phantom: PhantomData, + }) + } } #[cfg(test)] diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index ea15404f59..e9441684f0 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -2,12 +2,12 @@ mod commands; mod into_system; #[cfg(feature = "profiler")] mod profiler; -mod system; mod query; +mod system; pub use commands::*; pub use into_system::*; #[cfg(feature = "profiler")] pub use profiler::*; -pub use system::*; pub use query::*; +pub use system::*; diff --git a/crates/bevy_ecs/src/system/profiler.rs b/crates/bevy_ecs/src/system/profiler.rs index 553dd6f8f2..04914bde37 100644 --- a/crates/bevy_ecs/src/system/profiler.rs +++ b/crates/bevy_ecs/src/system/profiler.rs @@ -11,13 +11,13 @@ pub trait Profiler: Downcast + Send + Sync + 'static { } pub fn profiler_start(resources: &Resources, scope: Cow<'static, str>) { - if let Ok(profiler) = resources.get::>() { + if let Some(profiler) = resources.get::>() { profiler.start(scope); } } pub fn profiler_stop(resources: &Resources, scope: Cow<'static, str>) { - if let Ok(profiler) = resources.get::>() { + if let Some(profiler) = resources.get::>() { profiler.stop(scope); } } diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index c19bbf0959..7eee2f257a 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -1,6 +1,6 @@ use crate::resource::Resources; -use fixedbitset::FixedBitSet; use bevy_hecs::{Access, Query, World}; +use fixedbitset::FixedBitSet; use std::{any::TypeId, borrow::Cow, collections::HashSet}; /// Determines the strategy used to run the `run_thread_local` function in a [System] @@ -19,7 +19,7 @@ impl SystemId { } } -/// An ECS system that can be added to a [Schedule](crate::Schedule) +/// An ECS system that can be added to a [Schedule](crate::Schedule) pub trait System: Send + Sync { fn name(&self) -> Cow<'static, str>; fn id(&self) -> SystemId; diff --git a/crates/bevy_input/src/keyboard.rs b/crates/bevy_input/src/keyboard.rs index 9fa037312a..0763c5d3b8 100644 --- a/crates/bevy_input/src/keyboard.rs +++ b/crates/bevy_input/src/keyboard.rs @@ -1,6 +1,6 @@ use crate::Input; use bevy_app::prelude::*; -use bevy_ecs::{Res, ResMut, Local}; +use bevy_ecs::{Local, Res, ResMut}; /// A key input event from a keyboard device #[derive(Debug, Clone)] diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index 2eac1dcbb5..fdfe65e17d 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -11,9 +11,7 @@ pub mod prelude { use bevy_app::prelude::*; use keyboard::{keyboard_input_system, KeyCode, KeyboardInput}; -use mouse::{ - mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion, -}; +use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion}; use bevy_ecs::IntoQuerySystem; diff --git a/crates/bevy_input/src/mouse.rs b/crates/bevy_input/src/mouse.rs index e47ebdbe96..26376b155f 100644 --- a/crates/bevy_input/src/mouse.rs +++ b/crates/bevy_input/src/mouse.rs @@ -1,7 +1,7 @@ use super::keyboard::ElementState; use crate::Input; use bevy_app::prelude::{EventReader, Events}; -use bevy_ecs::{Res, ResMut, Local}; +use bevy_ecs::{Local, Res, ResMut}; use bevy_math::Vec2; /// A mouse button input event diff --git a/crates/bevy_pbr/src/render_graph/mod.rs b/crates/bevy_pbr/src/render_graph/mod.rs index 130c86f554..89899731d0 100644 --- a/crates/bevy_pbr/src/render_graph/mod.rs +++ b/crates/bevy_pbr/src/render_graph/mod.rs @@ -16,6 +16,7 @@ pub mod uniform { pub const LIGHTS: &str = "Lights"; } +use crate::prelude::StandardMaterial; use bevy_asset::Assets; use bevy_ecs::Resources; use bevy_render::{ @@ -24,7 +25,6 @@ use bevy_render::{ shader::Shader, }; use bevy_transform::prelude::Transform; -use crate::prelude::StandardMaterial; pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) { graph.add_system_node(node::TRANSFORM, RenderResourcesNode::::new(true)); @@ -41,10 +41,13 @@ pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) { ); // TODO: replace these with "autowire" groups - graph.add_node_edge(node::STANDARD_MATERIAL, base::node::MAIN_PASS) + graph + .add_node_edge(node::STANDARD_MATERIAL, base::node::MAIN_PASS) .unwrap(); - graph.add_node_edge(node::TRANSFORM, base::node::MAIN_PASS) + graph + .add_node_edge(node::TRANSFORM, base::node::MAIN_PASS) .unwrap(); - graph.add_node_edge(node::LIGHTS, base::node::MAIN_PASS) + graph + .add_node_edge(node::LIGHTS, base::node::MAIN_PASS) .unwrap(); } diff --git a/crates/bevy_property/src/impl_property/impl_property_std.rs b/crates/bevy_property/src/impl_property/impl_property_std.rs index e0f3656dd1..fe3dfc40dd 100644 --- a/crates/bevy_property/src/impl_property/impl_property_std.rs +++ b/crates/bevy_property/src/impl_property/impl_property_std.rs @@ -68,7 +68,7 @@ where if let Some(properties) = value.as_properties() { let len = properties.prop_len(); self.resize_with(len, || T::default()); - + if properties.property_type() != self.property_type() { panic!( "Properties type mismatch. This type is {:?} but the applied type is {:?}", diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index bd7789ec08..461f647039 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -38,7 +38,8 @@ once_cell = "1.4.0" downcast-rs = "1.1.1" thiserror = "1.0" anyhow = "1.0" +hexasphere = "0.1.5" [features] png = ["image/png"] -hdr = ["image/hdr"] \ No newline at end of file +hdr = ["image/hdr"] diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 413b39f048..f560045217 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -1,7 +1,7 @@ +use super::DepthCalculation; use bevy_math::Mat4; use bevy_property::{Properties, Property}; use serde::{Deserialize, Serialize}; -use super::DepthCalculation; pub trait CameraProjection { fn get_projection_matrix(&self) -> Mat4; diff --git a/crates/bevy_render/src/camera/visible_entities.rs b/crates/bevy_render/src/camera/visible_entities.rs index 09ba77dffd..a7c2b3da59 100644 --- a/crates/bevy_render/src/camera/visible_entities.rs +++ b/crates/bevy_render/src/camera/visible_entities.rs @@ -2,8 +2,8 @@ use super::{Camera, DepthCalculation}; use crate::Draw; use bevy_core::FloatOrd; use bevy_ecs::{Entity, Query}; -use bevy_transform::prelude::Transform; use bevy_property::Properties; +use bevy_transform::prelude::Transform; #[derive(Debug)] pub struct VisibleEntity { diff --git a/crates/bevy_render/src/mesh/mesh.rs b/crates/bevy_render/src/mesh/mesh.rs index 2dbed5a000..439468b367 100644 --- a/crates/bevy_render/src/mesh/mesh.rs +++ b/crates/bevy_render/src/mesh/mesh.rs @@ -165,12 +165,16 @@ impl Mesh { } } +/// Generation for some primitive shape meshes. pub mod shape { use super::{Mesh, VertexAttribute}; use crate::pipeline::PrimitiveTopology; use bevy_math::*; + use hexasphere::Hexasphere; + /// A cube. pub struct Cube { + /// Half the side length of the cube. pub size: f32, } @@ -246,8 +250,11 @@ pub mod shape { } } + /// A rectangle on the XY plane. pub struct Quad { + /// Full width and height of the rectangle. pub size: Vec2, + /// Flips the texture coords of the resulting vertices. pub flip: bool, } @@ -341,7 +348,9 @@ pub mod shape { } } + /// A square on the XZ plane. pub struct Plane { + /// The total side length of the square. pub size: f32, } @@ -378,6 +387,68 @@ pub mod shape { } } } + + /// A sphere made from a subdivided Icosahedron. + pub struct Icosphere { + /// The radius of the sphere. + pub radius: f32, + /// The number of subdivisions applied. + pub subdivisions: usize, + } + + impl Default for Icosphere { + fn default() -> Self { + Self { + radius: 1.0, + subdivisions: 5, + } + } + } + + impl From for Mesh { + fn from(sphere: Icosphere) -> Self { + let hexasphere = Hexasphere::new(sphere.subdivisions, |point| { + let inclination = point.z().acos(); + let azumith = point.y().atan2(point.x()); + + let norm_inclination = 1.0 - (inclination / std::f32::consts::PI); + let norm_azumith = (azumith / std::f32::consts::PI) * 0.5; + + [norm_inclination, norm_azumith] + }); + + let raw_points = hexasphere.raw_points(); + + let points = raw_points + .iter() + .map(|&p| (p * sphere.radius).into()) + .collect::>(); + + let normals = raw_points + .iter() + .copied() + .map(Into::into) + .collect::>(); + + let uvs = hexasphere.raw_data().to_owned(); + + let mut indices = Vec::with_capacity(hexasphere.indices_per_main_triangle() * 20); + + for i in 0..20 { + hexasphere.get_indices(i, &mut indices); + } + + Mesh { + primitive_topology: PrimitiveTopology::TriangleList, + attributes: vec![ + VertexAttribute::position(points), + VertexAttribute::normal(normals), + VertexAttribute::uv(uvs), + ], + indices: Some(indices), + } + } + } } fn remove_current_mesh_resources( diff --git a/crates/bevy_render/src/pipeline/pipeline_compiler.rs b/crates/bevy_render/src/pipeline/pipeline_compiler.rs index c72584a941..6f636d6329 100644 --- a/crates/bevy_render/src/pipeline/pipeline_compiler.rs +++ b/crates/bevy_render/src/pipeline/pipeline_compiler.rs @@ -4,10 +4,10 @@ use crate::{ shader::{Shader, ShaderSource}, }; use bevy_asset::{Assets, Handle}; -use once_cell::sync::Lazy; -use std::collections::{HashMap, HashSet}; use bevy_property::{Properties, Property}; -use serde::{Serialize, Deserialize}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; +use std::collections::{HashMap, HashSet}; #[derive(Clone, Eq, PartialEq, Debug, Properties)] pub struct PipelineSpecialization { pub shader_specialization: ShaderSpecialization, diff --git a/crates/bevy_render/src/pipeline/render_pipelines.rs b/crates/bevy_render/src/pipeline/render_pipelines.rs index 9e38a3df37..9f26bd6fbd 100644 --- a/crates/bevy_render/src/pipeline/render_pipelines.rs +++ b/crates/bevy_render/src/pipeline/render_pipelines.rs @@ -77,6 +77,9 @@ pub fn draw_render_pipelines_system( mut query: Query<(&mut Draw, &mut RenderPipelines)>, ) { for (mut draw, mut render_pipelines) in &mut query.iter() { + if !draw.is_visible { + continue; + } let render_pipelines = &mut *render_pipelines; for pipeline in render_pipelines.pipelines.iter_mut() { pipeline.specialization.sample_count = msaa.samples; diff --git a/crates/bevy_render/src/pipeline/state_descriptors.rs b/crates/bevy_render/src/pipeline/state_descriptors.rs index ca3f90c811..92f6b396db 100644 --- a/crates/bevy_render/src/pipeline/state_descriptors.rs +++ b/crates/bevy_render/src/pipeline/state_descriptors.rs @@ -1,6 +1,6 @@ use crate::texture::TextureFormat; -use serde::{Serialize, Deserialize}; use bevy_property::Property; +use serde::{Deserialize, Serialize}; #[derive(Clone, Debug)] pub struct DepthStencilStateDescriptor { diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index 7dc17568fb..56089d8e9c 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -3,8 +3,8 @@ use crate::{ draw::{Draw, RenderCommand}, pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment}, pipeline::{ - BindGroupDescriptor, BindType, BindingDescriptor, PipelineDescriptor, UniformProperty, - BindingShaderStage, + BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, PipelineDescriptor, + UniformProperty, }, render_graph::{Node, ResourceSlotInfo, ResourceSlots}, renderer::{ @@ -12,7 +12,7 @@ use crate::{ }, }; use bevy_asset::{Assets, Handle}; -use bevy_ecs::{Resources, World, HecsQuery}; +use bevy_ecs::{HecsQuery, Resources, World}; use std::marker::PhantomData; struct CameraInfo { @@ -136,8 +136,9 @@ impl Node for PassNode { TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap()); } if let Some(input_index) = self.color_resolve_target_indices[i] { - color_attachment.resolve_target = - Some(TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap())); + color_attachment.resolve_target = Some(TextureAttachment::Id( + input.get(input_index).unwrap().get_texture().unwrap(), + )); } } diff --git a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs index a99a7ae467..530027d306 100644 --- a/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/render_resources_node.rs @@ -658,7 +658,10 @@ fn asset_render_resources_node_system( } } - for (asset_handle, _draw, mut render_pipelines) in &mut query.iter() { + for (asset_handle, draw, mut render_pipelines) in &mut query.iter() { + if !draw.is_visible { + continue; + } if let Some(asset_bindings) = asset_render_resource_bindings.get(*asset_handle) { render_pipelines.bindings.extend(asset_bindings); } diff --git a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs index ad12252a44..1536531107 100644 --- a/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs +++ b/crates/bevy_render/src/renderer/render_resource/render_resource_bindings.rs @@ -261,7 +261,7 @@ impl Default for RenderResourceBindingsId { #[cfg(test)] mod tests { use super::*; - use crate::pipeline::{BindType, BindingDescriptor, UniformProperty, BindingShaderStage}; + use crate::pipeline::{BindType, BindingDescriptor, BindingShaderStage, UniformProperty}; #[test] fn test_bind_groups() { diff --git a/crates/bevy_render/src/shader/shader.rs b/crates/bevy_render/src/shader/shader.rs index 9196259f60..f963c0c90a 100644 --- a/crates/bevy_render/src/shader/shader.rs +++ b/crates/bevy_render/src/shader/shader.rs @@ -56,7 +56,7 @@ impl ShaderSource { } } -/// A shader, as defined by its [ShaderSource] and [ShaderStage] +/// A shader, as defined by its [ShaderSource] and [ShaderStage] #[derive(Clone, Debug)] pub struct Shader { pub source: ShaderSource, diff --git a/crates/bevy_render/src/shader/shader_reflect.rs b/crates/bevy_render/src/shader/shader_reflect.rs index a89bac6083..9221f36e1f 100644 --- a/crates/bevy_render/src/shader/shader_reflect.rs +++ b/crates/bevy_render/src/shader/shader_reflect.rs @@ -1,7 +1,7 @@ use crate::{ pipeline::{ - BindGroupDescriptor, BindType, BindingDescriptor, InputStepMode, UniformProperty, - VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, BindingShaderStage, + BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, InputStepMode, + UniformProperty, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, }, texture::{TextureComponentType, TextureViewDimension}, }; diff --git a/crates/bevy_render/src/texture/hdr_texture_loader.rs b/crates/bevy_render/src/texture/hdr_texture_loader.rs index a1bb99c491..c9b4628a99 100644 --- a/crates/bevy_render/src/texture/hdr_texture_loader.rs +++ b/crates/bevy_render/src/texture/hdr_texture_loader.rs @@ -4,7 +4,7 @@ use bevy_asset::AssetLoader; use bevy_math::Vec2; use std::path::Path; -/// Loads HDR textures as Texture assets +/// Loads HDR textures as Texture assets #[derive(Clone, Default)] pub struct HdrTextureLoader; diff --git a/crates/bevy_ron/src/ser/mod.rs b/crates/bevy_ron/src/ser/mod.rs index f76f595fc5..d3b8c7ab5f 100644 --- a/crates/bevy_ron/src/ser/mod.rs +++ b/crates/bevy_ron/src/ser/mod.rs @@ -1,8 +1,10 @@ use serde::{ser, Deserialize, Serialize}; use std::io; -use crate::error::{Error, Result}; -use crate::extensions::Extensions; +use crate::{ + error::{Error, Result}, + extensions::Extensions, +}; mod value; diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 3300bc8b0b..32dab7b9ba 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -44,7 +44,10 @@ impl Scene { } // TODO: move to AssetSaver when it is implemented - pub fn serialize_ron(&self, registry: &PropertyTypeRegistry) -> Result { + pub fn serialize_ron( + &self, + registry: &PropertyTypeRegistry, + ) -> Result { serialize_ron(SceneSerializer::new(self, registry)) } } diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index ed15d22c82..c4f659fb86 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -113,7 +113,6 @@ impl SceneSpawner { component_registration.apply_component_to_entity(world, entity, component); } } - } else { world.spawn_as_entity(entity, (1,)); for component in scene_entity.components.iter() { @@ -122,7 +121,8 @@ impl SceneSpawner { .ok_or_else(|| SceneSpawnError::UnregisteredComponent { type_name: component.type_name.to_string(), })?; - component_registration.add_component_to_entity(world, resources, entity, component); + component_registration + .add_component_to_entity(world, resources, entity, component); } } } @@ -209,7 +209,6 @@ pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) { } } - scene_spawner.load_queued_scenes(world, resources).unwrap(); scene_spawner.spawn_queued_scenes(world, resources).unwrap(); scene_spawner diff --git a/crates/bevy_text/src/draw.rs b/crates/bevy_text/src/draw.rs index 52fc7127ef..a6c8e7e6d4 100644 --- a/crates/bevy_text/src/draw.rs +++ b/crates/bevy_text/src/draw.rs @@ -7,10 +7,11 @@ use bevy_render::{ draw::{Draw, DrawContext, DrawError, Drawable}, mesh, pipeline::PipelineSpecialization, + prelude::Msaa, renderer::{ AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings, RenderResourceId, - }, prelude::Msaa, + }, }; use bevy_sprite::{TextureAtlas, TextureAtlasSprite}; diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index 6bc23a6880..7cad33605b 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -4,8 +4,9 @@ use bevy_ecs::{Changed, Query, Res, ResMut}; use bevy_math::{Size, Vec3}; use bevy_render::{ draw::{Draw, DrawContext, Drawable}, + prelude::Msaa, renderer::{AssetRenderResourceBindings, RenderResourceBindings}, - texture::Texture, prelude::Msaa, + texture::Texture, }; use bevy_sprite::TextureAtlas; use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle}; @@ -59,7 +60,8 @@ pub fn draw_text_system( mut query: Query<(&mut Draw, &Text, &Node, &Transform)>, ) { for (mut draw, text, node, transform) in &mut query.iter() { - let position = Vec3::from(transform.value.w_axis().truncate()) - (node.size / 2.0).extend(0.0); + let position = + Vec3::from(transform.value.w_axis().truncate()) - (node.size / 2.0).extend(0.0); let mut drawable_text = DrawableText { font: fonts.get(&text.font).unwrap(), diff --git a/crates/bevy_wgpu/Cargo.toml b/crates/bevy_wgpu/Cargo.toml index 4d5eb8dbbd..11a9807aa6 100644 --- a/crates/bevy_wgpu/Cargo.toml +++ b/crates/bevy_wgpu/Cargo.toml @@ -11,6 +11,7 @@ keywords = ["bevy"] [features] default = ["bevy_winit"] +trace = ["wgpu/trace"] [dependencies] # bevy diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index 26ab64743e..f32696b0b4 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -5,7 +5,9 @@ use crate::{ use bevy_asset::{Assets, Handle, HandleUntyped}; use bevy_render::{ - pipeline::{BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor}, + pipeline::{ + BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor, + }, renderer::{ BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext, RenderResourceId, SamplerId, TextureId, @@ -113,7 +115,9 @@ impl WgpuRenderResourceContext { .bindings .iter() .map(|binding| { - let shader_stage = if binding.shader_stage == BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT { + let shader_stage = if binding.shader_stage + == BindingShaderStage::VERTEX | BindingShaderStage::FRAGMENT + { wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT } else if binding.shader_stage == BindingShaderStage::VERTEX { wgpu::ShaderStage::VERTEX diff --git a/crates/bevy_wgpu/src/wgpu_renderer.rs b/crates/bevy_wgpu/src/wgpu_renderer.rs index 06837ca039..11da00a263 100644 --- a/crates/bevy_wgpu/src/wgpu_renderer.rs +++ b/crates/bevy_wgpu/src/wgpu_renderer.rs @@ -27,6 +27,11 @@ impl WgpuRenderer { .await .expect("Unable to find a GPU! Make sure you have installed required drivers!"); + #[cfg(feature = "trace")] + let trace_path = Some(std::path::Path::new("wgpu_trace")); + #[cfg(not(feature = "trace"))] + let trace_path = None; + let (device, queue) = adapter .request_device( &wgpu::DeviceDescriptor { @@ -34,7 +39,7 @@ impl WgpuRenderer { limits: wgpu::Limits::default(), shader_validation: true, }, - None, + trace_path, ) .await .unwrap(); diff --git a/docs/debugging.md b/docs/debugging.md index a704a9d415..759176623d 100644 --- a/docs/debugging.md +++ b/docs/debugging.md @@ -2,7 +2,16 @@ ## Macro Debugging -- Print the final output of a macro using `cargo rustc --profile=check -- -Zunstable-options --pretty=expanded` - - Alternatively you could install and use [cargo expand](https://github.com/dtolnay/cargo-expand) which adds syntax highlighting to the terminal output. - - Additionally get pager by piping to `less` ( on Unix systems ): `cargo expand --color always | less -R` -- Print output during macro compilation using `eprintln!("hi");` +* Print the final output of a macro using `cargo rustc --profile=check -- -Zunstable-options --pretty=expanded` + * Alternatively you could install and use [cargo expand](https://github.com/dtolnay/cargo-expand) which adds syntax highlighting to the terminal output. + * Additionally get pager by piping to `less` ( on Unix systems ): `cargo expand --color always | less -R` +* Print output during macro compilation using `eprintln!("hi");` + +## WGPU Tracing + +When a suspected wgpu error occurs, you should capture a wgpu trace so that Bevy and wgpu devs can debug using the [wgpu player tool](https://github.com/gfx-rs/wgpu/wiki/Debugging-wgpu-Applications#tracing-infrastructure). + +To capture a wgpu trace: +1. Create a new `wgpu_trace` folder in the root of your cargo workspace +2. Add the "wgpu_trace" feature to the bevy crate. (ex: `cargo run --example features wgpu_trace`) +3. Zip up the wgpu_trace folder and attach it to the relevant issue. New wgpu issues should generally be created here https://github.com/gfx-rs/wgpu. Please include the wgpu revision in your bug reports. You can find the revision in the Cargo.lock file in your workspace. diff --git a/docs/linux_dependencies.md b/docs/linux_dependencies.md index 41acef77dd..74c194a797 100644 --- a/docs/linux_dependencies.md +++ b/docs/linux_dependencies.md @@ -6,3 +6,6 @@ If you don't see your distro present in the list, feel free to add the instructi ## Ubuntu 20.04 `sudo apt-get install libx11-dev libasound2-dev` + +## Fedora 32 +`sudo dnf install gcc-c++ libX11-devel alsa-lib-devel` diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index e5a4a6d2cb..3f219d087d 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -29,6 +29,16 @@ fn setup( translation: Translation::new(0.0, 1.0, 0.0), ..Default::default() }) + // sphere + .spawn(PbrComponents { + mesh: meshes.add(Mesh::from(shape::Icosphere { + subdivisions: 4, + radius: 0.5, + })), + material: materials.add(Color::rgb(0.1, 0.4, 0.8).into()), + translation: Translation::new(1.5, 1.5, 1.5), + ..Default::default() + }) // light .spawn(LightComponents { translation: Translation::new(4.0, 8.0, 4.0), diff --git a/examples/3d/load_model.rs b/examples/3d/load_model.rs index f759c5e18b..6781b44a40 100644 --- a/examples/3d/load_model.rs +++ b/examples/3d/load_model.rs @@ -18,7 +18,9 @@ fn setup( // mesh .spawn(PbrComponents { // load the mesh - mesh: asset_server.load("assets/models/monkey/Monkey.gltf").unwrap(), + mesh: asset_server + .load("assets/models/monkey/Monkey.gltf") + .unwrap(), // create a material for the mesh material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()), ..Default::default() diff --git a/examples/app/thread_pool_resources.rs b/examples/app/thread_pool_resources.rs new file mode 100644 index 0000000000..99f3016236 --- /dev/null +++ b/examples/app/thread_pool_resources.rs @@ -0,0 +1,10 @@ +use bevy::{ecs::ParallelExecutorOptions, prelude::*}; + +/// This example illustrates how to customize the thread pool used internally (e.g. to only use a +/// certain number of threads). +fn main() { + App::build() + .add_resource(ParallelExecutorOptions::new().with_num_threads(Some(4))) + .add_default_plugins() + .run(); +} diff --git a/examples/scene/scene.rs b/examples/scene/scene.rs index 97e22563c6..9de1d2d3d4 100644 --- a/examples/scene/scene.rs +++ b/examples/scene/scene.rs @@ -13,6 +13,7 @@ fn main() { .register_component::() .add_startup_system(save_scene_system.thread_local_system()) .add_startup_system(load_scene_system.system()) + .add_startup_system(infotext_system.system()) .add_system(print_system.system()) .run(); } @@ -128,3 +129,25 @@ fn save_scene_system(_world: &mut World, resources: &mut Resources) { // TODO: save scene } + +// This is only necessary for the info message in the UI. See examples/ui/text.rs for a standalone text example. +fn infotext_system(mut commands: Commands, asset_server: Res) { + let font_handle = asset_server.load("assets/fonts/FiraSans-Bold.ttf").unwrap(); + commands + .spawn(UiCameraComponents::default()) + .spawn(TextComponents { + style: Style { + align_self: AlignSelf::FlexEnd, + ..Default::default() + }, + text: Text { + value: "Nothing to see in this window! Check the console output!".to_string(), + font: font_handle, + style: TextStyle { + font_size: 50.0, + color: Color::WHITE, + }, + }, + ..Default::default() + }); +} diff --git a/examples/shader/shader_custom_material.rs b/examples/shader/shader_custom_material.rs index 5ef191309b..f672eca94c 100644 --- a/examples/shader/shader_custom_material.rs +++ b/examples/shader/shader_custom_material.rs @@ -68,7 +68,7 @@ fn setup( AssetRenderResourcesNode::::new(true), ); - // Add a Render Graph edge connecting our new "my_material" node to the main pass node. This ensures "my_material" runs before the main pass + // Add a Render Graph edge connecting our new "my_material" node to the main pass node. This ensures "my_material" runs before the main pass render_graph .add_node_edge("my_material", base::node::MAIN_PASS) .unwrap(); diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index d6c5704692..79b10cf19e 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -80,7 +80,7 @@ fn setup( AssetRenderResourcesNode::::new(true), ); - // Add a Render Graph edge connecting our new "my_material" node to the main pass node. This ensures "my_material" runs before the main pass + // Add a Render Graph edge connecting our new "my_material" node to the main pass node. This ensures "my_material" runs before the main pass render_graph .add_node_edge("my_material", base::node::MAIN_PASS) .unwrap(); diff --git a/rustfmt.toml b/rustfmt.toml index ffdf397ed2..94853d522f 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,4 +1,5 @@ +unstable_features = true merge_imports = true use_field_init_shorthand = true reorder_impl_items = true -newline_style = "Unix" \ No newline at end of file +newline_style = "Unix" diff --git a/src/lib.rs b/src/lib.rs index e26312234d..ae29f1b089 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,4 +69,4 @@ pub use bevy_gltf as gltf; pub use bevy_winit as winit; #[cfg(feature = "bevy_wgpu")] -pub use bevy_wgpu as wgpu; \ No newline at end of file +pub use bevy_wgpu as wgpu; diff --git a/src/prelude.rs b/src/prelude.rs index 0963070ef2..6996f1d07b 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,8 +1,8 @@ pub use crate::{ - app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, - input::prelude::*, math::prelude::*, pbr::prelude::*, property::prelude::*, render::prelude::*, - scene::prelude::*, sprite::prelude::*, text::prelude::*, transform::prelude::*, - type_registry::RegisterType, ui::prelude::*, window::prelude::*, AddDefaultPlugins, + app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, input::prelude::*, + math::prelude::*, pbr::prelude::*, property::prelude::*, render::prelude::*, scene::prelude::*, + sprite::prelude::*, text::prelude::*, transform::prelude::*, type_registry::RegisterType, + ui::prelude::*, window::prelude::*, AddDefaultPlugins, }; #[cfg(feature = "bevy_audio")]