Merge branch 'master' into bind-group-reflect-fix
This commit is contained in:
commit
131a5e9167
@ -10,8 +10,6 @@ rustflags = ["-Clink-arg=-fuse-ld=lld", "-Zshare-generics=y"]
|
|||||||
[target.x86_64-apple-darwin]
|
[target.x86_64-apple-darwin]
|
||||||
rustflags = ["-Zshare-generics=y"]
|
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]
|
[target.x86_64-pc-windows-msvc]
|
||||||
linker = "lld-link.exe"
|
linker = "rust-lld.exe"
|
||||||
rustflags = ["-Clinker=lld", "-Zshare-generics=y"]
|
rustflags = ["-Zshare-generics=y"]
|
||||||
12
.github/workflows/rust.yml
vendored
12
.github/workflows/rust.yml
vendored
@ -17,14 +17,26 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
components: rustfmt
|
||||||
|
|
||||||
- name: Install alsa
|
- name: Install alsa
|
||||||
run: sudo apt-get install libasound2-dev
|
run: sudo apt-get install libasound2-dev
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo check
|
run: cargo check
|
||||||
|
|
||||||
|
- name: Check the format
|
||||||
|
run: cargo +nightly fmt --all -- --check
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --workspace
|
run: cargo test --workspace
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ exclude = ["assets/**/*", "tools/**/*", ".github/**/*", "crates/**/*"]
|
|||||||
[features]
|
[features]
|
||||||
default = ["bevy_audio", "bevy_gltf", "bevy_wgpu", "bevy_winit", "png", "hdr", "mp3"]
|
default = ["bevy_audio", "bevy_gltf", "bevy_wgpu", "bevy_winit", "png", "hdr", "mp3"]
|
||||||
profiler = ["bevy_ecs/profiler", "bevy_diagnostic/profiler"]
|
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)
|
# Image format support for texture loading (PNG and HDR are enabled by default)
|
||||||
png = ["bevy_render/png"]
|
png = ["bevy_render/png"]
|
||||||
@ -122,6 +123,10 @@ path = "examples/app/headless.rs"
|
|||||||
name = "plugin"
|
name = "plugin"
|
||||||
path = "examples/app/plugin.rs"
|
path = "examples/app/plugin.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "thread_pool_resources"
|
||||||
|
path = "examples/app/thread_pool_resources.rs"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "hot_asset_reloading"
|
name = "hot_asset_reloading"
|
||||||
path = "examples/asset/hot_asset_reloading.rs"
|
path = "examples/asset/hot_asset_reloading.rs"
|
||||||
|
|||||||
@ -82,7 +82,7 @@ fn map_instance_event<T>(event_instance: &EventInstance<T>) -> &T {
|
|||||||
&event_instance.event
|
&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<T> {
|
pub struct EventReader<T> {
|
||||||
last_event_count: usize,
|
last_event_count: usize,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
|
|||||||
@ -24,7 +24,7 @@ impl HandleId {
|
|||||||
|
|
||||||
/// A handle into a specific Asset of type `T`
|
/// 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)]
|
#[derive(Properties)]
|
||||||
pub struct Handle<T>
|
pub struct Handle<T>
|
||||||
where
|
where
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#[cfg(feature = "filesystem_watcher")]
|
|
||||||
mod filesystem_watcher;
|
|
||||||
mod asset_server;
|
mod asset_server;
|
||||||
mod assets;
|
mod assets;
|
||||||
|
#[cfg(feature = "filesystem_watcher")]
|
||||||
|
mod filesystem_watcher;
|
||||||
mod handle;
|
mod handle;
|
||||||
mod load_request;
|
mod load_request;
|
||||||
mod loader;
|
mod loader;
|
||||||
|
|||||||
@ -53,7 +53,7 @@ impl<T> AssetChannel<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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<T: Resource>(
|
pub fn update_asset_storage_system<T: Resource>(
|
||||||
asset_channel: Res<AssetChannel<T>>,
|
asset_channel: Res<AssetChannel<T>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
|||||||
@ -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.
|
/// 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
|
/// 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)]
|
#[derive(Debug, Copy, Clone, PartialOrd)]
|
||||||
pub struct FloatOrd(pub f32);
|
pub struct FloatOrd(pub f32);
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ license = "MIT"
|
|||||||
keywords = ["bevy"]
|
keywords = ["bevy"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
profiler = []
|
profiler = ["bevy_ecs/profiler"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# bevy
|
# bevy
|
||||||
|
|||||||
@ -19,7 +19,7 @@ impl Plugin for DiagnosticsPlugin {
|
|||||||
#[cfg(feature = "profiler")]
|
#[cfg(feature = "profiler")]
|
||||||
{
|
{
|
||||||
use bevy_ecs::IntoQuerySystem;
|
use bevy_ecs::IntoQuerySystem;
|
||||||
app.add_resource::<Box<dyn bevy_ecs::profiler::Profiler>>(Box::new(
|
app.add_resource::<Box<dyn bevy_ecs::Profiler>>(Box::new(
|
||||||
system_profiler::SystemProfiler::default(),
|
system_profiler::SystemProfiler::default(),
|
||||||
))
|
))
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use bevy_core::{Time, Timer};
|
|||||||
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
||||||
use std::time::Duration;
|
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 struct PrintDiagnosticsPlugin {
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
pub wait_duration: Duration,
|
pub wait_duration: Duration,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::{Diagnostic, DiagnosticId, Diagnostics};
|
use crate::{Diagnostic, DiagnosticId, Diagnostics};
|
||||||
use bevy_ecs::{profiler::Profiler, Res, ResMut};
|
use bevy_ecs::{Profiler, Res, ResMut};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
|||||||
@ -18,4 +18,5 @@ bevy_hecs = { path = "hecs", features = ["macros", "serialize"], version = "0.1"
|
|||||||
rand = "0.7.2"
|
rand = "0.7.2"
|
||||||
rayon = "1.3"
|
rayon = "1.3"
|
||||||
crossbeam-channel = "0.4.2"
|
crossbeam-channel = "0.4.2"
|
||||||
fixedbitset = "0.3.0"
|
fixedbitset = "0.3.0"
|
||||||
|
downcast-rs = "1.1.1"
|
||||||
|
|||||||
@ -4,7 +4,9 @@
|
|||||||
//! also be useful for serialization, or other row-oriented generic operations.
|
//! also be useful for serialization, or other row-oriented generic operations.
|
||||||
|
|
||||||
fn format_entity(entity: bevy_hecs::EntityRef<'_>) -> String {
|
fn format_entity(entity: bevy_hecs::EntityRef<'_>) -> String {
|
||||||
fn fmt<T: bevy_hecs::Component + std::fmt::Display>(entity: bevy_hecs::EntityRef<'_>) -> Option<String> {
|
fn fmt<T: bevy_hecs::Component + std::fmt::Display>(
|
||||||
|
entity: bevy_hecs::EntityRef<'_>,
|
||||||
|
) -> Option<String> {
|
||||||
Some(entity.get::<T>()?.to_string())
|
Some(entity.get::<T>()?.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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> {
|
impl<'a, T: Component> Query for Mut<'a, T> {
|
||||||
type Fetch = FetchMut<T>;
|
type Fetch = FetchMut<T>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,12 +3,12 @@ use crate::{
|
|||||||
system::{SystemId, TypeAccess},
|
system::{SystemId, TypeAccess},
|
||||||
Resource, ResourceIndex,
|
Resource, ResourceIndex,
|
||||||
};
|
};
|
||||||
|
use bevy_hecs::smaller_tuples_too;
|
||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
use bevy_hecs::smaller_tuples_too;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Shared borrow of a Resource
|
/// Shared borrow of a Resource
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use super::{FetchResource, ResourceQuery};
|
use super::{FetchResource, ResourceQuery};
|
||||||
use crate::system::SystemId;
|
use crate::system::SystemId;
|
||||||
use core::any::TypeId;
|
|
||||||
use bevy_hecs::{Archetype, Ref, RefMut, TypeInfo};
|
use bevy_hecs::{Archetype, Ref, RefMut, TypeInfo};
|
||||||
|
use core::any::TypeId;
|
||||||
use std::{collections::HashMap, ptr::NonNull};
|
use std::{collections::HashMap, ptr::NonNull};
|
||||||
|
|
||||||
/// A Resource type
|
/// A Resource type
|
||||||
@ -19,7 +19,7 @@ pub enum ResourceIndex {
|
|||||||
System(SystemId),
|
System(SystemId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of resource instances identified by their type.
|
/// A collection of resource instances identified by their type.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Resources {
|
pub struct Resources {
|
||||||
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
||||||
|
|||||||
@ -3,9 +3,9 @@ use crate::{
|
|||||||
resource::Resources,
|
resource::Resources,
|
||||||
system::{ArchetypeAccess, System, ThreadLocalExecution, TypeAccess},
|
system::{ArchetypeAccess, System, ThreadLocalExecution, TypeAccess},
|
||||||
};
|
};
|
||||||
|
use bevy_hecs::{ArchetypesGeneration, World};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
use fixedbitset::FixedBitSet;
|
use fixedbitset::FixedBitSet;
|
||||||
use bevy_hecs::{ArchetypesGeneration, World};
|
|
||||||
use rayon::ScopeFifo;
|
use rayon::ScopeFifo;
|
||||||
use std::{
|
use std::{
|
||||||
ops::Range,
|
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<usize>,
|
||||||
|
/// 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<usize>,
|
||||||
|
// 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<usize>) -> 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<usize>) -> 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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ExecutorStage {
|
pub struct ExecutorStage {
|
||||||
/// each system's set of dependencies
|
/// each system's set of dependencies
|
||||||
@ -313,19 +359,22 @@ impl ExecutorStage {
|
|||||||
self.running_systems.clear();
|
self.running_systems.clear();
|
||||||
|
|
||||||
let mut run_ready_result = RunReadyResult::Ok;
|
let mut run_ready_result = RunReadyResult::Ok;
|
||||||
let run_ready_system_index_range = if let Some(index) = self
|
let run_ready_system_index_range =
|
||||||
.thread_local_system_indices
|
if let Some(index) = self.thread_local_system_indices.get(0) {
|
||||||
.get(0)
|
// if there is an upcoming thread local system, run up to (and including) it
|
||||||
{
|
0..(*index + 1)
|
||||||
// if there is an upcoming thread local system, run up to (and including) it
|
} else {
|
||||||
0..(*index + 1)
|
// if there are no upcoming thread local systems, run everything right now
|
||||||
} else {
|
0..systems.len()
|
||||||
// if there are no upcoming thread local systems, run everything right now
|
};
|
||||||
0..systems.len()
|
|
||||||
};
|
|
||||||
rayon::scope_fifo(|scope| {
|
rayon::scope_fifo(|scope| {
|
||||||
run_ready_result =
|
run_ready_result = self.run_ready_systems(
|
||||||
self.run_ready_systems(systems, RunReadyType::Range(run_ready_system_index_range), scope, world, resources);
|
systems,
|
||||||
|
RunReadyType::Range(run_ready_system_index_range),
|
||||||
|
scope,
|
||||||
|
world,
|
||||||
|
resources,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
loop {
|
loop {
|
||||||
// if all systems in the stage are finished, break out of the loop
|
// if all systems in the stage are finished, break out of the loop
|
||||||
@ -395,8 +444,8 @@ mod tests {
|
|||||||
system::{IntoQuerySystem, IntoThreadLocalSystem, Query},
|
system::{IntoQuerySystem, IntoThreadLocalSystem, Query},
|
||||||
Commands,
|
Commands,
|
||||||
};
|
};
|
||||||
use fixedbitset::FixedBitSet;
|
|
||||||
use bevy_hecs::{Entity, World};
|
use bevy_hecs::{Entity, World};
|
||||||
|
use fixedbitset::FixedBitSet;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
resource::Resources,
|
resource::Resources,
|
||||||
|
schedule::ParallelExecutorOptions,
|
||||||
system::{System, SystemId, ThreadLocalExecution},
|
system::{System, SystemId, ThreadLocalExecution},
|
||||||
};
|
};
|
||||||
use bevy_hecs::World;
|
use bevy_hecs::World;
|
||||||
@ -130,9 +131,9 @@ impl Schedule {
|
|||||||
for stage_name in self.stage_order.iter() {
|
for stage_name in self.stage_order.iter() {
|
||||||
if let Some(stage_systems) = self.stages.get_mut(stage_name) {
|
if let Some(stage_systems) = self.stages.get_mut(stage_name) {
|
||||||
for system in stage_systems.iter_mut() {
|
for system in stage_systems.iter_mut() {
|
||||||
#[cfg(feature = "profiler")]
|
|
||||||
crate::profiler::profiler_start(resources, system.name().clone());
|
|
||||||
let mut system = system.lock().unwrap();
|
let mut system = system.lock().unwrap();
|
||||||
|
#[cfg(feature = "profiler")]
|
||||||
|
crate::profiler_start(resources, system.name().clone());
|
||||||
system.update_archetype_access(world);
|
system.update_archetype_access(world);
|
||||||
match system.thread_local_execution() {
|
match system.thread_local_execution() {
|
||||||
ThreadLocalExecution::NextFlush => system.run(world, resources),
|
ThreadLocalExecution::NextFlush => system.run(world, resources),
|
||||||
@ -143,7 +144,7 @@ impl Schedule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(feature = "profiler")]
|
||||||
crate::profiler::profiler_stop(resources, system.name().clone());
|
crate::profiler_stop(resources, system.name().clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// "flush"
|
// "flush"
|
||||||
@ -169,6 +170,15 @@ impl Schedule {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let thread_pool_builder = resources
|
||||||
|
.get::<ParallelExecutorOptions>()
|
||||||
|
.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 stage in self.stages.values_mut() {
|
||||||
for system in stage.iter_mut() {
|
for system in stage.iter_mut() {
|
||||||
let mut system = system.lock().unwrap();
|
let mut system = system.lock().unwrap();
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
use super::SystemId;
|
use super::SystemId;
|
||||||
use crate::resource::{Resource, Resources};
|
use crate::resource::{Resource, Resources};
|
||||||
use bevy_hecs::{Bundle, Component, DynamicBundle, Entity, World};
|
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 {
|
pub enum Command {
|
||||||
WriteWorld(Box<dyn WorldWriter>),
|
WriteWorld(Box<dyn WorldWriter>),
|
||||||
WriteResources(Box<dyn ResourcesWriter>),
|
WriteResources(Box<dyn ResourcesWriter>),
|
||||||
@ -109,6 +112,25 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct RemoveOne<T>
|
||||||
|
where
|
||||||
|
T: Component,
|
||||||
|
{
|
||||||
|
entity: Entity,
|
||||||
|
phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WorldWriter for RemoveOne<T>
|
||||||
|
where
|
||||||
|
T: Component,
|
||||||
|
{
|
||||||
|
fn write(self: Box<Self>, world: &mut World) {
|
||||||
|
if world.get::<T>(self.entity).is_ok() {
|
||||||
|
world.remove_one::<T>(self.entity).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ResourcesWriter: Send + Sync {
|
pub trait ResourcesWriter: Send + Sync {
|
||||||
fn write(self: Box<Self>, resources: &mut Resources);
|
fn write(self: Box<Self>, resources: &mut Resources);
|
||||||
}
|
}
|
||||||
@ -321,6 +343,16 @@ impl Commands {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_one<T>(&mut self, entity: Entity) -> &mut Self
|
||||||
|
where
|
||||||
|
T: Component,
|
||||||
|
{
|
||||||
|
self.write_world(RemoveOne::<T> {
|
||||||
|
entity,
|
||||||
|
phantom: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -2,12 +2,12 @@ mod commands;
|
|||||||
mod into_system;
|
mod into_system;
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(feature = "profiler")]
|
||||||
mod profiler;
|
mod profiler;
|
||||||
mod system;
|
|
||||||
mod query;
|
mod query;
|
||||||
|
mod system;
|
||||||
|
|
||||||
pub use commands::*;
|
pub use commands::*;
|
||||||
pub use into_system::*;
|
pub use into_system::*;
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(feature = "profiler")]
|
||||||
pub use profiler::*;
|
pub use profiler::*;
|
||||||
pub use system::*;
|
|
||||||
pub use query::*;
|
pub use query::*;
|
||||||
|
pub use system::*;
|
||||||
|
|||||||
@ -11,13 +11,13 @@ pub trait Profiler: Downcast + Send + Sync + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn profiler_start(resources: &Resources, scope: Cow<'static, str>) {
|
pub fn profiler_start(resources: &Resources, scope: Cow<'static, str>) {
|
||||||
if let Ok(profiler) = resources.get::<Box<dyn Profiler>>() {
|
if let Some(profiler) = resources.get::<Box<dyn Profiler>>() {
|
||||||
profiler.start(scope);
|
profiler.start(scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn profiler_stop(resources: &Resources, scope: Cow<'static, str>) {
|
pub fn profiler_stop(resources: &Resources, scope: Cow<'static, str>) {
|
||||||
if let Ok(profiler) = resources.get::<Box<dyn Profiler>>() {
|
if let Some(profiler) = resources.get::<Box<dyn Profiler>>() {
|
||||||
profiler.stop(scope);
|
profiler.stop(scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::resource::Resources;
|
use crate::resource::Resources;
|
||||||
use fixedbitset::FixedBitSet;
|
|
||||||
use bevy_hecs::{Access, Query, World};
|
use bevy_hecs::{Access, Query, World};
|
||||||
|
use fixedbitset::FixedBitSet;
|
||||||
use std::{any::TypeId, borrow::Cow, collections::HashSet};
|
use std::{any::TypeId, borrow::Cow, collections::HashSet};
|
||||||
|
|
||||||
/// Determines the strategy used to run the `run_thread_local` function in a [System]
|
/// 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 {
|
pub trait System: Send + Sync {
|
||||||
fn name(&self) -> Cow<'static, str>;
|
fn name(&self) -> Cow<'static, str>;
|
||||||
fn id(&self) -> SystemId;
|
fn id(&self) -> SystemId;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::Input;
|
use crate::Input;
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_ecs::{Res, ResMut, Local};
|
use bevy_ecs::{Local, Res, ResMut};
|
||||||
|
|
||||||
/// A key input event from a keyboard device
|
/// A key input event from a keyboard device
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@ -11,9 +11,7 @@ pub mod prelude {
|
|||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
||||||
use mouse::{
|
use mouse::{mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion};
|
||||||
mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion,
|
|
||||||
};
|
|
||||||
|
|
||||||
use bevy_ecs::IntoQuerySystem;
|
use bevy_ecs::IntoQuerySystem;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use super::keyboard::ElementState;
|
use super::keyboard::ElementState;
|
||||||
use crate::Input;
|
use crate::Input;
|
||||||
use bevy_app::prelude::{EventReader, Events};
|
use bevy_app::prelude::{EventReader, Events};
|
||||||
use bevy_ecs::{Res, ResMut, Local};
|
use bevy_ecs::{Local, Res, ResMut};
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
|
|
||||||
/// A mouse button input event
|
/// A mouse button input event
|
||||||
|
|||||||
@ -16,6 +16,7 @@ pub mod uniform {
|
|||||||
pub const LIGHTS: &str = "Lights";
|
pub const LIGHTS: &str = "Lights";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::prelude::StandardMaterial;
|
||||||
use bevy_asset::Assets;
|
use bevy_asset::Assets;
|
||||||
use bevy_ecs::Resources;
|
use bevy_ecs::Resources;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
@ -24,7 +25,6 @@ use bevy_render::{
|
|||||||
shader::Shader,
|
shader::Shader,
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::Transform;
|
use bevy_transform::prelude::Transform;
|
||||||
use crate::prelude::StandardMaterial;
|
|
||||||
|
|
||||||
pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) {
|
pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) {
|
||||||
graph.add_system_node(node::TRANSFORM, RenderResourcesNode::<Transform>::new(true));
|
graph.add_system_node(node::TRANSFORM, RenderResourcesNode::<Transform>::new(true));
|
||||||
@ -41,10 +41,13 @@ pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// TODO: replace these with "autowire" groups
|
// 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();
|
.unwrap();
|
||||||
graph.add_node_edge(node::TRANSFORM, base::node::MAIN_PASS)
|
graph
|
||||||
|
.add_node_edge(node::TRANSFORM, base::node::MAIN_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
graph.add_node_edge(node::LIGHTS, base::node::MAIN_PASS)
|
graph
|
||||||
|
.add_node_edge(node::LIGHTS, base::node::MAIN_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,7 +68,7 @@ where
|
|||||||
if let Some(properties) = value.as_properties() {
|
if let Some(properties) = value.as_properties() {
|
||||||
let len = properties.prop_len();
|
let len = properties.prop_len();
|
||||||
self.resize_with(len, || T::default());
|
self.resize_with(len, || T::default());
|
||||||
|
|
||||||
if properties.property_type() != self.property_type() {
|
if properties.property_type() != self.property_type() {
|
||||||
panic!(
|
panic!(
|
||||||
"Properties type mismatch. This type is {:?} but the applied type is {:?}",
|
"Properties type mismatch. This type is {:?} but the applied type is {:?}",
|
||||||
|
|||||||
@ -38,7 +38,8 @@ once_cell = "1.4.0"
|
|||||||
downcast-rs = "1.1.1"
|
downcast-rs = "1.1.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
hexasphere = "0.1.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
png = ["image/png"]
|
png = ["image/png"]
|
||||||
hdr = ["image/hdr"]
|
hdr = ["image/hdr"]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
use super::DepthCalculation;
|
||||||
use bevy_math::Mat4;
|
use bevy_math::Mat4;
|
||||||
use bevy_property::{Properties, Property};
|
use bevy_property::{Properties, Property};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use super::DepthCalculation;
|
|
||||||
|
|
||||||
pub trait CameraProjection {
|
pub trait CameraProjection {
|
||||||
fn get_projection_matrix(&self) -> Mat4;
|
fn get_projection_matrix(&self) -> Mat4;
|
||||||
|
|||||||
@ -2,8 +2,8 @@ use super::{Camera, DepthCalculation};
|
|||||||
use crate::Draw;
|
use crate::Draw;
|
||||||
use bevy_core::FloatOrd;
|
use bevy_core::FloatOrd;
|
||||||
use bevy_ecs::{Entity, Query};
|
use bevy_ecs::{Entity, Query};
|
||||||
use bevy_transform::prelude::Transform;
|
|
||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
|
use bevy_transform::prelude::Transform;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VisibleEntity {
|
pub struct VisibleEntity {
|
||||||
|
|||||||
@ -165,12 +165,16 @@ impl Mesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generation for some primitive shape meshes.
|
||||||
pub mod shape {
|
pub mod shape {
|
||||||
use super::{Mesh, VertexAttribute};
|
use super::{Mesh, VertexAttribute};
|
||||||
use crate::pipeline::PrimitiveTopology;
|
use crate::pipeline::PrimitiveTopology;
|
||||||
use bevy_math::*;
|
use bevy_math::*;
|
||||||
|
use hexasphere::Hexasphere;
|
||||||
|
|
||||||
|
/// A cube.
|
||||||
pub struct Cube {
|
pub struct Cube {
|
||||||
|
/// Half the side length of the cube.
|
||||||
pub size: f32,
|
pub size: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,8 +250,11 @@ pub mod shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A rectangle on the XY plane.
|
||||||
pub struct Quad {
|
pub struct Quad {
|
||||||
|
/// Full width and height of the rectangle.
|
||||||
pub size: Vec2,
|
pub size: Vec2,
|
||||||
|
/// Flips the texture coords of the resulting vertices.
|
||||||
pub flip: bool,
|
pub flip: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +348,9 @@ pub mod shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A square on the XZ plane.
|
||||||
pub struct Plane {
|
pub struct Plane {
|
||||||
|
/// The total side length of the square.
|
||||||
pub size: f32,
|
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<Icosphere> 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::<Vec<[f32; 3]>>();
|
||||||
|
|
||||||
|
let normals = raw_points
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect::<Vec<[f32; 3]>>();
|
||||||
|
|
||||||
|
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(
|
fn remove_current_mesh_resources(
|
||||||
|
|||||||
@ -4,10 +4,10 @@ use crate::{
|
|||||||
shader::{Shader, ShaderSource},
|
shader::{Shader, ShaderSource},
|
||||||
};
|
};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use bevy_property::{Properties, Property};
|
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)]
|
#[derive(Clone, Eq, PartialEq, Debug, Properties)]
|
||||||
pub struct PipelineSpecialization {
|
pub struct PipelineSpecialization {
|
||||||
pub shader_specialization: ShaderSpecialization,
|
pub shader_specialization: ShaderSpecialization,
|
||||||
|
|||||||
@ -77,6 +77,9 @@ pub fn draw_render_pipelines_system(
|
|||||||
mut query: Query<(&mut Draw, &mut RenderPipelines)>,
|
mut query: Query<(&mut Draw, &mut RenderPipelines)>,
|
||||||
) {
|
) {
|
||||||
for (mut draw, mut render_pipelines) in &mut query.iter() {
|
for (mut draw, mut render_pipelines) in &mut query.iter() {
|
||||||
|
if !draw.is_visible {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let render_pipelines = &mut *render_pipelines;
|
let render_pipelines = &mut *render_pipelines;
|
||||||
for pipeline in render_pipelines.pipelines.iter_mut() {
|
for pipeline in render_pipelines.pipelines.iter_mut() {
|
||||||
pipeline.specialization.sample_count = msaa.samples;
|
pipeline.specialization.sample_count = msaa.samples;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::texture::TextureFormat;
|
use crate::texture::TextureFormat;
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
use bevy_property::Property;
|
use bevy_property::Property;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct DepthStencilStateDescriptor {
|
pub struct DepthStencilStateDescriptor {
|
||||||
|
|||||||
@ -3,8 +3,8 @@ use crate::{
|
|||||||
draw::{Draw, RenderCommand},
|
draw::{Draw, RenderCommand},
|
||||||
pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment},
|
pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment},
|
||||||
pipeline::{
|
pipeline::{
|
||||||
BindGroupDescriptor, BindType, BindingDescriptor, PipelineDescriptor, UniformProperty,
|
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, PipelineDescriptor,
|
||||||
BindingShaderStage,
|
UniformProperty,
|
||||||
},
|
},
|
||||||
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
||||||
renderer::{
|
renderer::{
|
||||||
@ -12,7 +12,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_ecs::{Resources, World, HecsQuery};
|
use bevy_ecs::{HecsQuery, Resources, World};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
struct CameraInfo {
|
struct CameraInfo {
|
||||||
@ -136,8 +136,9 @@ impl<Q: HecsQuery + Send + Sync + 'static> Node for PassNode<Q> {
|
|||||||
TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
|
TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap());
|
||||||
}
|
}
|
||||||
if let Some(input_index) = self.color_resolve_target_indices[i] {
|
if let Some(input_index) = self.color_resolve_target_indices[i] {
|
||||||
color_attachment.resolve_target =
|
color_attachment.resolve_target = Some(TextureAttachment::Id(
|
||||||
Some(TextureAttachment::Id(input.get(input_index).unwrap().get_texture().unwrap()));
|
input.get(input_index).unwrap().get_texture().unwrap(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -658,7 +658,10 @@ fn asset_render_resources_node_system<T: RenderResources>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if let Some(asset_bindings) = asset_render_resource_bindings.get(*asset_handle) {
|
||||||
render_pipelines.bindings.extend(asset_bindings);
|
render_pipelines.bindings.extend(asset_bindings);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -261,7 +261,7 @@ impl Default for RenderResourceBindingsId {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::pipeline::{BindType, BindingDescriptor, UniformProperty, BindingShaderStage};
|
use crate::pipeline::{BindType, BindingDescriptor, BindingShaderStage, UniformProperty};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bind_groups() {
|
fn test_bind_groups() {
|
||||||
|
|||||||
@ -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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Shader {
|
pub struct Shader {
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
pipeline::{
|
pipeline::{
|
||||||
BindGroupDescriptor, BindType, BindingDescriptor, InputStepMode, UniformProperty,
|
BindGroupDescriptor, BindType, BindingDescriptor, BindingShaderStage, InputStepMode,
|
||||||
VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat, BindingShaderStage,
|
UniformProperty, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||||
},
|
},
|
||||||
texture::{TextureComponentType, TextureViewDimension},
|
texture::{TextureComponentType, TextureViewDimension},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use bevy_asset::AssetLoader;
|
|||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
/// Loads HDR textures as Texture assets
|
/// Loads HDR textures as Texture assets
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct HdrTextureLoader;
|
pub struct HdrTextureLoader;
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
use serde::{ser, Deserialize, Serialize};
|
use serde::{ser, Deserialize, Serialize};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::{
|
||||||
use crate::extensions::Extensions;
|
error::{Error, Result},
|
||||||
|
extensions::Extensions,
|
||||||
|
};
|
||||||
|
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,10 @@ impl Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to AssetSaver when it is implemented
|
// TODO: move to AssetSaver when it is implemented
|
||||||
pub fn serialize_ron(&self, registry: &PropertyTypeRegistry) -> Result<String, bevy_ron::Error> {
|
pub fn serialize_ron(
|
||||||
|
&self,
|
||||||
|
registry: &PropertyTypeRegistry,
|
||||||
|
) -> Result<String, bevy_ron::Error> {
|
||||||
serialize_ron(SceneSerializer::new(self, registry))
|
serialize_ron(SceneSerializer::new(self, registry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,7 +113,6 @@ impl SceneSpawner {
|
|||||||
component_registration.apply_component_to_entity(world, entity, component);
|
component_registration.apply_component_to_entity(world, entity, component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
world.spawn_as_entity(entity, (1,));
|
world.spawn_as_entity(entity, (1,));
|
||||||
for component in scene_entity.components.iter() {
|
for component in scene_entity.components.iter() {
|
||||||
@ -122,7 +121,8 @@ impl SceneSpawner {
|
|||||||
.ok_or_else(|| SceneSpawnError::UnregisteredComponent {
|
.ok_or_else(|| SceneSpawnError::UnregisteredComponent {
|
||||||
type_name: component.type_name.to_string(),
|
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.load_queued_scenes(world, resources).unwrap();
|
||||||
scene_spawner.spawn_queued_scenes(world, resources).unwrap();
|
scene_spawner.spawn_queued_scenes(world, resources).unwrap();
|
||||||
scene_spawner
|
scene_spawner
|
||||||
|
|||||||
@ -7,10 +7,11 @@ use bevy_render::{
|
|||||||
draw::{Draw, DrawContext, DrawError, Drawable},
|
draw::{Draw, DrawContext, DrawError, Drawable},
|
||||||
mesh,
|
mesh,
|
||||||
pipeline::PipelineSpecialization,
|
pipeline::PipelineSpecialization,
|
||||||
|
prelude::Msaa,
|
||||||
renderer::{
|
renderer::{
|
||||||
AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings,
|
AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings,
|
||||||
RenderResourceId,
|
RenderResourceId,
|
||||||
}, prelude::Msaa,
|
},
|
||||||
};
|
};
|
||||||
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
|
||||||
|
|
||||||
|
|||||||
@ -4,8 +4,9 @@ use bevy_ecs::{Changed, Query, Res, ResMut};
|
|||||||
use bevy_math::{Size, Vec3};
|
use bevy_math::{Size, Vec3};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
draw::{Draw, DrawContext, Drawable},
|
draw::{Draw, DrawContext, Drawable},
|
||||||
|
prelude::Msaa,
|
||||||
renderer::{AssetRenderResourceBindings, RenderResourceBindings},
|
renderer::{AssetRenderResourceBindings, RenderResourceBindings},
|
||||||
texture::Texture, prelude::Msaa,
|
texture::Texture,
|
||||||
};
|
};
|
||||||
use bevy_sprite::TextureAtlas;
|
use bevy_sprite::TextureAtlas;
|
||||||
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
|
||||||
@ -59,7 +60,8 @@ pub fn draw_text_system(
|
|||||||
mut query: Query<(&mut Draw, &Text, &Node, &Transform)>,
|
mut query: Query<(&mut Draw, &Text, &Node, &Transform)>,
|
||||||
) {
|
) {
|
||||||
for (mut draw, text, node, transform) in &mut query.iter() {
|
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 {
|
let mut drawable_text = DrawableText {
|
||||||
font: fonts.get(&text.font).unwrap(),
|
font: fonts.get(&text.font).unwrap(),
|
||||||
|
|||||||
@ -11,6 +11,7 @@ keywords = ["bevy"]
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["bevy_winit"]
|
default = ["bevy_winit"]
|
||||||
|
trace = ["wgpu/trace"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# bevy
|
# bevy
|
||||||
|
|||||||
@ -5,7 +5,9 @@ use crate::{
|
|||||||
|
|
||||||
use bevy_asset::{Assets, Handle, HandleUntyped};
|
use bevy_asset::{Assets, Handle, HandleUntyped};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
pipeline::{BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor},
|
pipeline::{
|
||||||
|
BindGroupDescriptor, BindGroupDescriptorId, BindingShaderStage, PipelineDescriptor,
|
||||||
|
},
|
||||||
renderer::{
|
renderer::{
|
||||||
BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext,
|
BindGroup, BufferId, BufferInfo, RenderResourceBinding, RenderResourceContext,
|
||||||
RenderResourceId, SamplerId, TextureId,
|
RenderResourceId, SamplerId, TextureId,
|
||||||
@ -113,7 +115,9 @@ impl WgpuRenderResourceContext {
|
|||||||
.bindings
|
.bindings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|binding| {
|
.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
|
wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT
|
||||||
} else if binding.shader_stage == BindingShaderStage::VERTEX {
|
} else if binding.shader_stage == BindingShaderStage::VERTEX {
|
||||||
wgpu::ShaderStage::VERTEX
|
wgpu::ShaderStage::VERTEX
|
||||||
|
|||||||
@ -27,6 +27,11 @@ impl WgpuRenderer {
|
|||||||
.await
|
.await
|
||||||
.expect("Unable to find a GPU! Make sure you have installed required drivers!");
|
.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
|
let (device, queue) = adapter
|
||||||
.request_device(
|
.request_device(
|
||||||
&wgpu::DeviceDescriptor {
|
&wgpu::DeviceDescriptor {
|
||||||
@ -34,7 +39,7 @@ impl WgpuRenderer {
|
|||||||
limits: wgpu::Limits::default(),
|
limits: wgpu::Limits::default(),
|
||||||
shader_validation: true,
|
shader_validation: true,
|
||||||
},
|
},
|
||||||
None,
|
trace_path,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@ -2,7 +2,16 @@
|
|||||||
|
|
||||||
## Macro Debugging
|
## Macro Debugging
|
||||||
|
|
||||||
- Print the final output of a macro using `cargo rustc --profile=check -- -Zunstable-options --pretty=expanded`
|
* 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.
|
* 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`
|
* 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 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.
|
||||||
|
|||||||
@ -6,3 +6,6 @@ If you don't see your distro present in the list, feel free to add the instructi
|
|||||||
|
|
||||||
## Ubuntu 20.04
|
## Ubuntu 20.04
|
||||||
`sudo apt-get install libx11-dev libasound2-dev`
|
`sudo apt-get install libx11-dev libasound2-dev`
|
||||||
|
|
||||||
|
## Fedora 32
|
||||||
|
`sudo dnf install gcc-c++ libX11-devel alsa-lib-devel`
|
||||||
|
|||||||
@ -29,6 +29,16 @@ fn setup(
|
|||||||
translation: Translation::new(0.0, 1.0, 0.0),
|
translation: Translation::new(0.0, 1.0, 0.0),
|
||||||
..Default::default()
|
..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
|
// light
|
||||||
.spawn(LightComponents {
|
.spawn(LightComponents {
|
||||||
translation: Translation::new(4.0, 8.0, 4.0),
|
translation: Translation::new(4.0, 8.0, 4.0),
|
||||||
|
|||||||
@ -18,7 +18,9 @@ fn setup(
|
|||||||
// mesh
|
// mesh
|
||||||
.spawn(PbrComponents {
|
.spawn(PbrComponents {
|
||||||
// load the mesh
|
// 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
|
// create a material for the mesh
|
||||||
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
material: materials.add(Color::rgb(0.5, 0.4, 0.3).into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|||||||
10
examples/app/thread_pool_resources.rs
Normal file
10
examples/app/thread_pool_resources.rs
Normal file
@ -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();
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@ fn main() {
|
|||||||
.register_component::<ComponentB>()
|
.register_component::<ComponentB>()
|
||||||
.add_startup_system(save_scene_system.thread_local_system())
|
.add_startup_system(save_scene_system.thread_local_system())
|
||||||
.add_startup_system(load_scene_system.system())
|
.add_startup_system(load_scene_system.system())
|
||||||
|
.add_startup_system(infotext_system.system())
|
||||||
.add_system(print_system.system())
|
.add_system(print_system.system())
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -128,3 +129,25 @@ fn save_scene_system(_world: &mut World, resources: &mut Resources) {
|
|||||||
|
|
||||||
// TODO: save scene
|
// 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<AssetServer>) {
|
||||||
|
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()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -68,7 +68,7 @@ fn setup(
|
|||||||
AssetRenderResourcesNode::<MyMaterial>::new(true),
|
AssetRenderResourcesNode::<MyMaterial>::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
|
render_graph
|
||||||
.add_node_edge("my_material", base::node::MAIN_PASS)
|
.add_node_edge("my_material", base::node::MAIN_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@ -80,7 +80,7 @@ fn setup(
|
|||||||
AssetRenderResourcesNode::<MyMaterial>::new(true),
|
AssetRenderResourcesNode::<MyMaterial>::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
|
render_graph
|
||||||
.add_node_edge("my_material", base::node::MAIN_PASS)
|
.add_node_edge("my_material", base::node::MAIN_PASS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
|
unstable_features = true
|
||||||
merge_imports = true
|
merge_imports = true
|
||||||
use_field_init_shorthand = true
|
use_field_init_shorthand = true
|
||||||
reorder_impl_items = true
|
reorder_impl_items = true
|
||||||
newline_style = "Unix"
|
newline_style = "Unix"
|
||||||
|
|||||||
@ -69,4 +69,4 @@ pub use bevy_gltf as gltf;
|
|||||||
pub use bevy_winit as winit;
|
pub use bevy_winit as winit;
|
||||||
|
|
||||||
#[cfg(feature = "bevy_wgpu")]
|
#[cfg(feature = "bevy_wgpu")]
|
||||||
pub use bevy_wgpu as wgpu;
|
pub use bevy_wgpu as wgpu;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*,
|
app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, input::prelude::*,
|
||||||
input::prelude::*, math::prelude::*, pbr::prelude::*, property::prelude::*, render::prelude::*,
|
math::prelude::*, pbr::prelude::*, property::prelude::*, render::prelude::*, scene::prelude::*,
|
||||||
scene::prelude::*, sprite::prelude::*, text::prelude::*, transform::prelude::*,
|
sprite::prelude::*, text::prelude::*, transform::prelude::*, type_registry::RegisterType,
|
||||||
type_registry::RegisterType, ui::prelude::*, window::prelude::*, AddDefaultPlugins,
|
ui::prelude::*, window::prelude::*, AddDefaultPlugins,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "bevy_audio")]
|
#[cfg(feature = "bevy_audio")]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user