Replace std synchronization primitives with parking_lot (#210)
* Replace std::sync::Mutex with parking_lot::Mutex * Replace std::sync::RwLock with parking_lot::RwLock
This commit is contained in:
		
							parent
							
								
									fc53ff9a71
								
							
						
					
					
						commit
						1eca55e571
					
				@ -28,3 +28,4 @@ anyhow = "1.0"
 | 
			
		||||
thiserror = "1.0"
 | 
			
		||||
log = { version = "0.4", features = ["release_max_level_info"] }
 | 
			
		||||
notify = { version = "5.0.0-pre.2", optional = true }
 | 
			
		||||
parking_lot = "0.10.2"
 | 
			
		||||
 | 
			
		||||
@ -5,11 +5,12 @@ use crate::{
 | 
			
		||||
use anyhow::Result;
 | 
			
		||||
use bevy_ecs::{Res, Resource, Resources};
 | 
			
		||||
use crossbeam_channel::TryRecvError;
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::{HashMap, HashSet},
 | 
			
		||||
    env, fs, io,
 | 
			
		||||
    path::{Path, PathBuf},
 | 
			
		||||
    sync::{Arc, RwLock},
 | 
			
		||||
    sync::Arc,
 | 
			
		||||
    thread,
 | 
			
		||||
};
 | 
			
		||||
use thiserror::Error;
 | 
			
		||||
@ -107,7 +108,7 @@ impl AssetServer {
 | 
			
		||||
    where
 | 
			
		||||
        T: AssetLoadRequestHandler,
 | 
			
		||||
    {
 | 
			
		||||
        let mut asset_handlers = self.asset_handlers.write().unwrap();
 | 
			
		||||
        let mut asset_handlers = self.asset_handlers.write();
 | 
			
		||||
        let handler_index = asset_handlers.len();
 | 
			
		||||
        for extension in asset_handler.extensions().iter() {
 | 
			
		||||
            self.extension_to_handler_index
 | 
			
		||||
@ -140,14 +141,13 @@ impl AssetServer {
 | 
			
		||||
        let root_path = self.get_root_path()?;
 | 
			
		||||
        let asset_folder = root_path.join(path);
 | 
			
		||||
        let handle_ids = self.load_assets_in_folder_recursive(&asset_folder)?;
 | 
			
		||||
        self.asset_folders.write().unwrap().push(asset_folder);
 | 
			
		||||
        self.asset_folders.write().push(asset_folder);
 | 
			
		||||
        Ok(handle_ids)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_handle<T, P: AsRef<Path>>(&self, path: P) -> Option<Handle<T>> {
 | 
			
		||||
        self.asset_info_paths
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(path.as_ref())
 | 
			
		||||
            .map(|handle_id| Handle::from(*handle_id))
 | 
			
		||||
    }
 | 
			
		||||
@ -170,11 +170,11 @@ impl AssetServer {
 | 
			
		||||
 | 
			
		||||
    #[cfg(feature = "filesystem_watcher")]
 | 
			
		||||
    pub fn watch_for_changes(&self) -> Result<(), AssetServerError> {
 | 
			
		||||
        let mut filesystem_watcher = self.filesystem_watcher.write().unwrap();
 | 
			
		||||
        let mut filesystem_watcher = self.filesystem_watcher.write();
 | 
			
		||||
 | 
			
		||||
        let _ = filesystem_watcher.get_or_insert_with(FilesystemWatcher::default);
 | 
			
		||||
        // watch current files
 | 
			
		||||
        let asset_info_paths = self.asset_info_paths.read().unwrap();
 | 
			
		||||
        let asset_info_paths = self.asset_info_paths.read();
 | 
			
		||||
        for asset_path in asset_info_paths.keys() {
 | 
			
		||||
            Self::watch_path_for_changes(&mut filesystem_watcher, asset_path)?;
 | 
			
		||||
        }
 | 
			
		||||
@ -187,9 +187,7 @@ impl AssetServer {
 | 
			
		||||
        use notify::event::{Event, EventKind, ModifyKind};
 | 
			
		||||
        let mut changed = HashSet::new();
 | 
			
		||||
 | 
			
		||||
        while let Some(filesystem_watcher) =
 | 
			
		||||
            asset_server.filesystem_watcher.read().unwrap().as_ref()
 | 
			
		||||
        {
 | 
			
		||||
        while let Some(filesystem_watcher) = asset_server.filesystem_watcher.read().as_ref() {
 | 
			
		||||
            let result = match filesystem_watcher.receiver.try_recv() {
 | 
			
		||||
                Ok(result) => result,
 | 
			
		||||
                Err(TryRecvError::Empty) => {
 | 
			
		||||
@ -280,8 +278,8 @@ impl AssetServer {
 | 
			
		||||
            ) {
 | 
			
		||||
                let mut new_version = 0;
 | 
			
		||||
                let handle_id = {
 | 
			
		||||
                    let mut asset_info = self.asset_info.write().unwrap();
 | 
			
		||||
                    let mut asset_info_paths = self.asset_info_paths.write().unwrap();
 | 
			
		||||
                    let mut asset_info = self.asset_info.write();
 | 
			
		||||
                    let mut asset_info_paths = self.asset_info_paths.write();
 | 
			
		||||
                    if let Some(asset_info) = asset_info_paths
 | 
			
		||||
                        .get(path)
 | 
			
		||||
                        .and_then(|handle_id| asset_info.get_mut(&handle_id))
 | 
			
		||||
@ -319,7 +317,7 @@ impl AssetServer {
 | 
			
		||||
                // TODO: watching each asset explicitly is a simpler implementation, its possible it would be more efficient to watch
 | 
			
		||||
                // folders instead (when possible)
 | 
			
		||||
                #[cfg(feature = "filesystem_watcher")]
 | 
			
		||||
                Self::watch_path_for_changes(&mut self.filesystem_watcher.write().unwrap(), path)?;
 | 
			
		||||
                Self::watch_path_for_changes(&mut self.filesystem_watcher.write(), path)?;
 | 
			
		||||
                Ok(handle_id)
 | 
			
		||||
            } else {
 | 
			
		||||
                Err(AssetServerError::MissingAssetHandler)
 | 
			
		||||
@ -330,7 +328,7 @@ impl AssetServer {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_load_state(&self, handle_id: HandleId, load_state: LoadState) {
 | 
			
		||||
        if let Some(asset_info) = self.asset_info.write().unwrap().get_mut(&handle_id) {
 | 
			
		||||
        if let Some(asset_info) = self.asset_info.write().get_mut(&handle_id) {
 | 
			
		||||
            if load_state.get_version() >= asset_info.load_state.get_version() {
 | 
			
		||||
                asset_info.load_state = load_state;
 | 
			
		||||
            }
 | 
			
		||||
@ -340,7 +338,6 @@ impl AssetServer {
 | 
			
		||||
    pub fn get_load_state_untyped(&self, handle_id: HandleId) -> Option<LoadState> {
 | 
			
		||||
        self.asset_info
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&handle_id)
 | 
			
		||||
            .map(|asset_info| asset_info.load_state.clone())
 | 
			
		||||
    }
 | 
			
		||||
@ -367,7 +364,7 @@ impl AssetServer {
 | 
			
		||||
 | 
			
		||||
    fn send_request_to_loader_thread(&self, load_request: LoadRequest) {
 | 
			
		||||
        // NOTE: This lock makes the call to Arc::strong_count safe. Removing (or reordering) it could result in undefined behavior
 | 
			
		||||
        let mut loader_threads = self.loader_threads.write().unwrap();
 | 
			
		||||
        let mut loader_threads = self.loader_threads.write();
 | 
			
		||||
        if loader_threads.len() < self.max_loader_threads {
 | 
			
		||||
            let loader_thread = LoaderThread {
 | 
			
		||||
                requests: Arc::new(RwLock::new(vec![load_request])),
 | 
			
		||||
@ -378,9 +375,9 @@ impl AssetServer {
 | 
			
		||||
        } else {
 | 
			
		||||
            let most_free_thread = loader_threads
 | 
			
		||||
                .iter()
 | 
			
		||||
                .min_by_key(|l| l.requests.read().unwrap().len())
 | 
			
		||||
                .min_by_key(|l| l.requests.read().len())
 | 
			
		||||
                .unwrap();
 | 
			
		||||
            let mut requests = most_free_thread.requests.write().unwrap();
 | 
			
		||||
            let mut requests = most_free_thread.requests.write();
 | 
			
		||||
            requests.push(load_request);
 | 
			
		||||
            // if most free thread only has one reference, the thread as spun down. if so, we need to spin it back up!
 | 
			
		||||
            if Arc::strong_count(&most_free_thread.requests) == 1 {
 | 
			
		||||
@ -399,7 +396,7 @@ impl AssetServer {
 | 
			
		||||
        thread::spawn(move || {
 | 
			
		||||
            loop {
 | 
			
		||||
                let request = {
 | 
			
		||||
                    let mut current_requests = requests.write().unwrap();
 | 
			
		||||
                    let mut current_requests = requests.write();
 | 
			
		||||
                    if current_requests.len() == 0 {
 | 
			
		||||
                        // if there are no requests, spin down the thread
 | 
			
		||||
                        break;
 | 
			
		||||
@ -408,7 +405,7 @@ impl AssetServer {
 | 
			
		||||
                    current_requests.pop().unwrap()
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                let handlers = request_handlers.read().unwrap();
 | 
			
		||||
                let handlers = request_handlers.read();
 | 
			
		||||
                let request_handler = &handlers[request.handler_index];
 | 
			
		||||
                request_handler.handle_request(&request);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ bevy_ecs = {path = "../bevy_ecs", version = "0.1"}
 | 
			
		||||
# other
 | 
			
		||||
anyhow = "1.0"
 | 
			
		||||
rodio = {version = "0.11", default-features = false}
 | 
			
		||||
parking_lot = "0.10.2"
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
mp3 = ["rodio/mp3"]
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
use crate::AudioSource;
 | 
			
		||||
use bevy_asset::{Assets, Handle};
 | 
			
		||||
use bevy_ecs::Res;
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use rodio::{Decoder, Device, Sink};
 | 
			
		||||
use std::{collections::VecDeque, io::Cursor, sync::RwLock};
 | 
			
		||||
use std::{collections::VecDeque, io::Cursor};
 | 
			
		||||
 | 
			
		||||
/// Used to play audio on the current "audio device"
 | 
			
		||||
pub struct AudioOutput {
 | 
			
		||||
@ -27,11 +28,11 @@ impl AudioOutput {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn play(&self, audio_source: Handle<AudioSource>) {
 | 
			
		||||
        self.queue.write().unwrap().push_front(audio_source);
 | 
			
		||||
        self.queue.write().push_front(audio_source);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn try_play_queued(&self, audio_sources: &Assets<AudioSource>) {
 | 
			
		||||
        let mut queue = self.queue.write().unwrap();
 | 
			
		||||
        let mut queue = self.queue.write();
 | 
			
		||||
        let len = queue.len();
 | 
			
		||||
        let mut i = 0;
 | 
			
		||||
        while i < len {
 | 
			
		||||
 | 
			
		||||
@ -20,3 +20,4 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.1" }
 | 
			
		||||
 | 
			
		||||
# other
 | 
			
		||||
uuid = { version = "0.8", features = ["v4", "serde"] }
 | 
			
		||||
parking_lot = "0.10"
 | 
			
		||||
@ -1,11 +1,7 @@
 | 
			
		||||
use crate::{Diagnostic, DiagnosticId, Diagnostics};
 | 
			
		||||
use bevy_ecs::{Profiler, Res, ResMut};
 | 
			
		||||
use std::{
 | 
			
		||||
    borrow::Cow,
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    sync::{Arc, RwLock},
 | 
			
		||||
    time::Instant,
 | 
			
		||||
};
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use std::{borrow::Cow, collections::HashMap, sync::Arc, time::Instant};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct SystemRunInfo {
 | 
			
		||||
@ -28,7 +24,7 @@ pub struct SystemProfiler {
 | 
			
		||||
 | 
			
		||||
impl Profiler for SystemProfiler {
 | 
			
		||||
    fn start(&self, scope: Cow<'static, str>) {
 | 
			
		||||
        let mut system_profiles = self.system_profiles.write().unwrap();
 | 
			
		||||
        let mut system_profiles = self.system_profiles.write();
 | 
			
		||||
        let profiles = system_profiles
 | 
			
		||||
            .entry(scope.clone())
 | 
			
		||||
            .or_insert_with(SystemProfiles::default);
 | 
			
		||||
@ -38,7 +34,7 @@ impl Profiler for SystemProfiler {
 | 
			
		||||
 | 
			
		||||
    fn stop(&self, scope: Cow<'static, str>) {
 | 
			
		||||
        let now = Instant::now();
 | 
			
		||||
        let mut system_profiles = self.system_profiles.write().unwrap();
 | 
			
		||||
        let mut system_profiles = self.system_profiles.write();
 | 
			
		||||
        let profiles = system_profiles.get_mut(&scope).unwrap();
 | 
			
		||||
        if let Some(current_start) = profiles.current_start.take() {
 | 
			
		||||
            profiles.history.push(SystemRunInfo {
 | 
			
		||||
@ -54,7 +50,7 @@ pub fn profiler_diagnostic_system(
 | 
			
		||||
    system_profiler: Res<Box<dyn Profiler>>,
 | 
			
		||||
) {
 | 
			
		||||
    let system_profiler = system_profiler.downcast_ref::<SystemProfiler>().unwrap();
 | 
			
		||||
    let mut system_profiles = system_profiler.system_profiles.write().unwrap();
 | 
			
		||||
    let mut system_profiles = system_profiler.system_profiles.write();
 | 
			
		||||
    for (scope, profiles) in system_profiles.iter_mut() {
 | 
			
		||||
        if diagnostics.get(profiles.diagnostic_id).is_none() {
 | 
			
		||||
            diagnostics.add(Diagnostic::new(profiles.diagnostic_id, &scope, 20))
 | 
			
		||||
 | 
			
		||||
@ -20,3 +20,4 @@ rayon = "1.3"
 | 
			
		||||
crossbeam-channel = "0.4.2"
 | 
			
		||||
fixedbitset = "0.3.0"
 | 
			
		||||
downcast-rs = "1.1.1"
 | 
			
		||||
parking_lot = "0.10"
 | 
			
		||||
 | 
			
		||||
@ -6,11 +6,9 @@ use crate::{
 | 
			
		||||
use bevy_hecs::{ArchetypesGeneration, World};
 | 
			
		||||
use crossbeam_channel::{Receiver, Sender};
 | 
			
		||||
use fixedbitset::FixedBitSet;
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
use rayon::ScopeFifo;
 | 
			
		||||
use std::{
 | 
			
		||||
    ops::Range,
 | 
			
		||||
    sync::{Arc, Mutex},
 | 
			
		||||
};
 | 
			
		||||
use std::{ops::Range, sync::Arc};
 | 
			
		||||
 | 
			
		||||
/// Executes each schedule stage in parallel by analyzing system dependencies.
 | 
			
		||||
/// System execution order is undefined except under the following conditions:
 | 
			
		||||
@ -194,7 +192,7 @@ impl ExecutorStage {
 | 
			
		||||
        if schedule_changed || archetypes_generation_changed {
 | 
			
		||||
            // update each system's archetype access to latest world archetypes
 | 
			
		||||
            for system_index in prepare_system_index_range.clone() {
 | 
			
		||||
                let mut system = systems[system_index].lock().unwrap();
 | 
			
		||||
                let mut system = systems[system_index].lock();
 | 
			
		||||
                system.update_archetype_access(world);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -202,7 +200,7 @@ impl ExecutorStage {
 | 
			
		||||
            let mut current_archetype_access = ArchetypeAccess::default();
 | 
			
		||||
            let mut current_resource_access = TypeAccess::default();
 | 
			
		||||
            for system_index in prepare_system_index_range.clone() {
 | 
			
		||||
                let system = systems[system_index].lock().unwrap();
 | 
			
		||||
                let system = systems[system_index].lock();
 | 
			
		||||
                let archetype_access = system.archetype_access();
 | 
			
		||||
                match system.thread_local_execution() {
 | 
			
		||||
                    ThreadLocalExecution::NextFlush => {
 | 
			
		||||
@ -215,7 +213,7 @@ impl ExecutorStage {
 | 
			
		||||
                            for earlier_system_index in
 | 
			
		||||
                                prepare_system_index_range.start..system_index
 | 
			
		||||
                            {
 | 
			
		||||
                                let earlier_system = systems[earlier_system_index].lock().unwrap();
 | 
			
		||||
                                let earlier_system = systems[earlier_system_index].lock();
 | 
			
		||||
 | 
			
		||||
                                // due to how prepare ranges work, previous systems should all be "NextFlush"
 | 
			
		||||
                                debug_assert_eq!(
 | 
			
		||||
@ -295,7 +293,7 @@ impl ExecutorStage {
 | 
			
		||||
 | 
			
		||||
                // handle thread local system
 | 
			
		||||
                {
 | 
			
		||||
                    let system = system.lock().unwrap();
 | 
			
		||||
                    let system = system.lock();
 | 
			
		||||
                    if let ThreadLocalExecution::Immediate = system.thread_local_execution() {
 | 
			
		||||
                        if systems_currently_running {
 | 
			
		||||
                            // if systems are currently running, we can't run this thread local system yet
 | 
			
		||||
@ -311,7 +309,7 @@ impl ExecutorStage {
 | 
			
		||||
                let sender = self.sender.clone();
 | 
			
		||||
                self.running_systems.insert(system_index);
 | 
			
		||||
                scope.spawn_fifo(move |_| {
 | 
			
		||||
                    let mut system = system.lock().unwrap();
 | 
			
		||||
                    let mut system = system.lock();
 | 
			
		||||
                    system.run(world, resources);
 | 
			
		||||
                    sender.send(system_index).unwrap();
 | 
			
		||||
                });
 | 
			
		||||
@ -344,7 +342,7 @@ impl ExecutorStage {
 | 
			
		||||
            self.running_systems.grow(systems.len());
 | 
			
		||||
 | 
			
		||||
            for (system_index, system) in systems.iter().enumerate() {
 | 
			
		||||
                let system = system.lock().unwrap();
 | 
			
		||||
                let system = system.lock();
 | 
			
		||||
                if system.thread_local_execution() == ThreadLocalExecution::Immediate {
 | 
			
		||||
                    self.thread_local_system_indices.push(system_index);
 | 
			
		||||
                }
 | 
			
		||||
@ -383,7 +381,7 @@ impl ExecutorStage {
 | 
			
		||||
 | 
			
		||||
            if let RunReadyResult::ThreadLocalReady(thread_local_index) = run_ready_result {
 | 
			
		||||
                // if a thread local system is ready to run, run it exclusively on the main thread
 | 
			
		||||
                let mut system = systems[thread_local_index].lock().unwrap();
 | 
			
		||||
                let mut system = systems[thread_local_index].lock();
 | 
			
		||||
                self.running_systems.insert(thread_local_index);
 | 
			
		||||
                system.run(world, resources);
 | 
			
		||||
                system.run_thread_local(world, resources);
 | 
			
		||||
@ -423,7 +421,7 @@ impl ExecutorStage {
 | 
			
		||||
 | 
			
		||||
        // "flush"
 | 
			
		||||
        for system in systems.iter() {
 | 
			
		||||
            let mut system = system.lock().unwrap();
 | 
			
		||||
            let mut system = system.lock();
 | 
			
		||||
            match system.thread_local_execution() {
 | 
			
		||||
                ThreadLocalExecution::NextFlush => system.run_thread_local(world, resources),
 | 
			
		||||
                ThreadLocalExecution::Immediate => { /* already ran */ }
 | 
			
		||||
@ -445,7 +443,8 @@ mod tests {
 | 
			
		||||
    };
 | 
			
		||||
    use bevy_hecs::{Entity, World};
 | 
			
		||||
    use fixedbitset::FixedBitSet;
 | 
			
		||||
    use std::sync::{Arc, Mutex};
 | 
			
		||||
    use parking_lot::Mutex;
 | 
			
		||||
    use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
    #[derive(Default)]
 | 
			
		||||
    struct Counter {
 | 
			
		||||
@ -529,25 +528,25 @@ mod tests {
 | 
			
		||||
        // A systems
 | 
			
		||||
 | 
			
		||||
        fn read_u32(counter: Res<Counter>, _query: Query<&u32>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert!(*count < 2, "should be one of the first two systems to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn write_float(counter: Res<Counter>, _query: Query<&f32>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert!(*count < 2, "should be one of the first two systems to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn read_u32_write_u64(counter: Res<Counter>, _query: Query<(&u32, &mut u64)>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 2, "should always be the 3rd system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn read_u64(counter: Res<Counter>, _query: Query<&u64>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 3, "should always be the 4th system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
@ -560,20 +559,20 @@ mod tests {
 | 
			
		||||
        // B systems
 | 
			
		||||
 | 
			
		||||
        fn write_u64(counter: Res<Counter>, _query: Query<&mut u64>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 4, "should always be the 5th system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn thread_local_system(_world: &mut World, resources: &mut Resources) {
 | 
			
		||||
            let counter = resources.get::<Counter>().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 5, "should always be the 6th system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn write_f32(counter: Res<Counter>, _query: Query<&mut f32>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 6, "should always be the 7th system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
@ -585,7 +584,7 @@ mod tests {
 | 
			
		||||
        // C systems
 | 
			
		||||
 | 
			
		||||
        fn read_f64_res(counter: Res<Counter>, _f64_res: Res<f64>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert!(
 | 
			
		||||
                7 == *count || *count == 8,
 | 
			
		||||
                "should always be the 8th or 9th system to run"
 | 
			
		||||
@ -594,7 +593,7 @@ mod tests {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn read_isize_res(counter: Res<Counter>, _isize_res: Res<isize>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert!(
 | 
			
		||||
                7 == *count || *count == 8,
 | 
			
		||||
                "should always be the 8th or 9th system to run"
 | 
			
		||||
@ -607,13 +606,13 @@ mod tests {
 | 
			
		||||
            _isize_res: Res<isize>,
 | 
			
		||||
            _f64_res: ResMut<f64>,
 | 
			
		||||
        ) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 9, "should always be the 10th system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn write_f64_res(counter: Res<Counter>, _f64_res: ResMut<f64>) {
 | 
			
		||||
            let mut count = counter.count.lock().unwrap();
 | 
			
		||||
            let mut count = counter.count.lock();
 | 
			
		||||
            assert_eq!(*count, 10, "should always be the 11th system to run");
 | 
			
		||||
            *count += 1;
 | 
			
		||||
        }
 | 
			
		||||
@ -692,7 +691,7 @@ mod tests {
 | 
			
		||||
 | 
			
		||||
            let counter = resources.get::<Counter>().unwrap();
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                *counter.count.lock().unwrap(),
 | 
			
		||||
                *counter.count.lock(),
 | 
			
		||||
                11,
 | 
			
		||||
                "counter should have been incremented once for each system"
 | 
			
		||||
            );
 | 
			
		||||
@ -701,7 +700,7 @@ mod tests {
 | 
			
		||||
        let mut executor = ParallelExecutor::default();
 | 
			
		||||
        run_executor_and_validate(&mut executor, &mut schedule, &mut world, &mut resources);
 | 
			
		||||
        // run again (with counter reset) to ensure executor works correctly across runs
 | 
			
		||||
        *resources.get::<Counter>().unwrap().count.lock().unwrap() = 0;
 | 
			
		||||
        *resources.get::<Counter>().unwrap().count.lock() = 0;
 | 
			
		||||
        run_executor_and_validate(&mut executor, &mut schedule, &mut world, &mut resources);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,11 @@ use crate::{
 | 
			
		||||
    system::{System, SystemId, ThreadLocalExecution},
 | 
			
		||||
};
 | 
			
		||||
use bevy_hecs::World;
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
use std::{
 | 
			
		||||
    borrow::Cow,
 | 
			
		||||
    collections::{HashMap, HashSet},
 | 
			
		||||
    sync::{Arc, Mutex},
 | 
			
		||||
    sync::Arc,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// An ordered collection of stages, which each contain an ordered list of [System]s.
 | 
			
		||||
@ -131,7 +132,7 @@ 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() {
 | 
			
		||||
                    let mut system = system.lock().unwrap();
 | 
			
		||||
                    let mut system = system.lock();
 | 
			
		||||
                    #[cfg(feature = "profiler")]
 | 
			
		||||
                    crate::profiler_start(resources, system.name().clone());
 | 
			
		||||
                    system.update_archetype_access(world);
 | 
			
		||||
@ -150,7 +151,7 @@ impl Schedule {
 | 
			
		||||
                // "flush"
 | 
			
		||||
                // NOTE: when this is made parallel a full sync is required here
 | 
			
		||||
                for system in stage_systems.iter_mut() {
 | 
			
		||||
                    let mut system = system.lock().unwrap();
 | 
			
		||||
                    let mut system = system.lock();
 | 
			
		||||
                    match system.thread_local_execution() {
 | 
			
		||||
                        ThreadLocalExecution::NextFlush => {
 | 
			
		||||
                            system.run_thread_local(world, resources)
 | 
			
		||||
@ -181,7 +182,7 @@ impl Schedule {
 | 
			
		||||
 | 
			
		||||
        for stage in self.stages.values_mut() {
 | 
			
		||||
            for system in stage.iter_mut() {
 | 
			
		||||
                let mut system = system.lock().unwrap();
 | 
			
		||||
                let mut system = system.lock();
 | 
			
		||||
                system.initialize(resources);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,8 @@
 | 
			
		||||
use super::SystemId;
 | 
			
		||||
use crate::resource::{Resource, Resources};
 | 
			
		||||
use bevy_hecs::{Bundle, Component, DynamicBundle, Entity, World};
 | 
			
		||||
use std::{
 | 
			
		||||
    marker::PhantomData,
 | 
			
		||||
    sync::{Arc, Mutex},
 | 
			
		||||
};
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
use std::{marker::PhantomData, sync::Arc};
 | 
			
		||||
 | 
			
		||||
/// A queued command to mutate the current [World] or [Resources]
 | 
			
		||||
pub enum Command {
 | 
			
		||||
@ -235,7 +233,7 @@ impl Commands {
 | 
			
		||||
        components: impl DynamicBundle + Send + Sync + 'static,
 | 
			
		||||
    ) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
            let mut commands = self.commands.lock();
 | 
			
		||||
            commands.spawn_as_entity(entity, components);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
@ -256,7 +254,7 @@ impl Commands {
 | 
			
		||||
 | 
			
		||||
    pub fn with(&mut self, component: impl Component) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
            let mut commands = self.commands.lock();
 | 
			
		||||
            commands.with(component);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
@ -267,7 +265,7 @@ impl Commands {
 | 
			
		||||
        components: impl DynamicBundle + Send + Sync + 'static,
 | 
			
		||||
    ) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
            let mut commands = self.commands.lock();
 | 
			
		||||
            commands.with_bundle(components);
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
@ -301,7 +299,7 @@ impl Commands {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn write_world<W: WorldWriter + 'static>(&mut self, world_writer: W) -> &mut Self {
 | 
			
		||||
        self.commands.lock().unwrap().write_world(world_writer);
 | 
			
		||||
        self.commands.lock().write_world(world_writer);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -309,15 +307,12 @@ impl Commands {
 | 
			
		||||
        &mut self,
 | 
			
		||||
        resources_writer: W,
 | 
			
		||||
    ) -> &mut Self {
 | 
			
		||||
        self.commands
 | 
			
		||||
            .lock()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .write_resources(resources_writer);
 | 
			
		||||
        self.commands.lock().write_resources(resources_writer);
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn apply(&self, world: &mut World, resources: &mut Resources) {
 | 
			
		||||
        let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
        let mut commands = self.commands.lock();
 | 
			
		||||
        for command in commands.commands.drain(..) {
 | 
			
		||||
            match command {
 | 
			
		||||
                Command::WriteWorld(writer) => {
 | 
			
		||||
@ -329,13 +324,13 @@ impl Commands {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn current_entity(&self) -> Option<Entity> {
 | 
			
		||||
        let commands = self.commands.lock().unwrap();
 | 
			
		||||
        let commands = self.commands.lock();
 | 
			
		||||
        commands.current_entity
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn for_current_entity(&mut self, mut f: impl FnMut(Entity)) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let commands = self.commands.lock().unwrap();
 | 
			
		||||
            let commands = self.commands.lock();
 | 
			
		||||
            let current_entity = commands
 | 
			
		||||
                .current_entity
 | 
			
		||||
                .expect("The 'current entity' is not set. You should spawn an entity first.");
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ downcast-rs = "1.1.1"
 | 
			
		||||
thiserror = "1.0"
 | 
			
		||||
anyhow = "1.0"
 | 
			
		||||
hexasphere = "0.1.5"
 | 
			
		||||
parking_lot = "0.10"
 | 
			
		||||
 | 
			
		||||
[features]
 | 
			
		||||
png = ["image/png"]
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,8 @@ use crate::{
 | 
			
		||||
    renderer::{BufferId, RenderContext, TextureId},
 | 
			
		||||
    texture::Extent3d,
 | 
			
		||||
};
 | 
			
		||||
use std::sync::{Arc, Mutex};
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub enum Command {
 | 
			
		||||
@ -34,7 +35,7 @@ pub struct CommandQueue {
 | 
			
		||||
 | 
			
		||||
impl CommandQueue {
 | 
			
		||||
    fn push(&mut self, command: Command) {
 | 
			
		||||
        self.queue.lock().unwrap().push(command);
 | 
			
		||||
        self.queue.lock().push(command);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn copy_buffer_to_buffer(
 | 
			
		||||
@ -81,11 +82,11 @@ impl CommandQueue {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn clear(&mut self) {
 | 
			
		||||
        self.queue.lock().unwrap().clear();
 | 
			
		||||
        self.queue.lock().clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn execute(&mut self, render_context: &mut dyn RenderContext) {
 | 
			
		||||
        for command in self.queue.lock().unwrap().drain(..) {
 | 
			
		||||
        for command in self.queue.lock().drain(..) {
 | 
			
		||||
            match command {
 | 
			
		||||
                Command::CopyBufferToBuffer {
 | 
			
		||||
                    source_buffer,
 | 
			
		||||
 | 
			
		||||
@ -7,11 +7,8 @@ use crate::{
 | 
			
		||||
};
 | 
			
		||||
use bevy_asset::{Assets, Handle, HandleUntyped};
 | 
			
		||||
use bevy_window::Window;
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    ops::Range,
 | 
			
		||||
    sync::{Arc, RwLock},
 | 
			
		||||
};
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use std::{collections::HashMap, ops::Range, sync::Arc};
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct HeadlessRenderResourceContext {
 | 
			
		||||
@ -22,14 +19,11 @@ pub struct HeadlessRenderResourceContext {
 | 
			
		||||
 | 
			
		||||
impl HeadlessRenderResourceContext {
 | 
			
		||||
    pub fn add_buffer_info(&self, buffer: BufferId, info: BufferInfo) {
 | 
			
		||||
        self.buffer_info.write().unwrap().insert(buffer, info);
 | 
			
		||||
        self.buffer_info.write().insert(buffer, info);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_texture_descriptor(&self, texture: TextureId, descriptor: TextureDescriptor) {
 | 
			
		||||
        self.texture_descriptors
 | 
			
		||||
            .write()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .insert(texture, descriptor);
 | 
			
		||||
        self.texture_descriptors.write().insert(texture, descriptor);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -66,7 +60,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
 | 
			
		||||
        _range: Range<u64>,
 | 
			
		||||
        write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
 | 
			
		||||
    ) {
 | 
			
		||||
        let size = self.buffer_info.read().unwrap().get(&id).unwrap().size;
 | 
			
		||||
        let size = self.buffer_info.read().get(&id).unwrap().size;
 | 
			
		||||
        let mut buffer = vec![0; size];
 | 
			
		||||
        write(&mut buffer, self);
 | 
			
		||||
    }
 | 
			
		||||
@ -84,11 +78,11 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
 | 
			
		||||
    fn create_shader_module(&self, _shader_handle: Handle<Shader>, _shaders: &Assets<Shader>) {}
 | 
			
		||||
 | 
			
		||||
    fn remove_buffer(&self, buffer: BufferId) {
 | 
			
		||||
        self.buffer_info.write().unwrap().remove(&buffer);
 | 
			
		||||
        self.buffer_info.write().remove(&buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_texture(&self, texture: TextureId) {
 | 
			
		||||
        self.texture_descriptors.write().unwrap().remove(&texture);
 | 
			
		||||
        self.texture_descriptors.write().remove(&texture);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_sampler(&self, _sampler: SamplerId) {}
 | 
			
		||||
@ -101,7 +95,6 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
 | 
			
		||||
    ) {
 | 
			
		||||
        self.asset_resources
 | 
			
		||||
            .write()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .insert((handle, index), render_resource);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -110,11 +103,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
 | 
			
		||||
        handle: HandleUntyped,
 | 
			
		||||
        index: usize,
 | 
			
		||||
    ) -> Option<RenderResourceId> {
 | 
			
		||||
        self.asset_resources
 | 
			
		||||
            .write()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&(handle, index))
 | 
			
		||||
            .cloned()
 | 
			
		||||
        self.asset_resources.write().get(&(handle, index)).cloned()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn create_render_pipeline(
 | 
			
		||||
@ -135,16 +124,13 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
 | 
			
		||||
    fn create_shader_module_from_source(&self, _shader_handle: Handle<Shader>, _shader: &Shader) {}
 | 
			
		||||
 | 
			
		||||
    fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: usize) {
 | 
			
		||||
        self.asset_resources
 | 
			
		||||
            .write()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .remove(&(handle, index));
 | 
			
		||||
        self.asset_resources.write().remove(&(handle, index));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn clear_bind_groups(&self) {}
 | 
			
		||||
 | 
			
		||||
    fn get_buffer_info(&self, buffer: BufferId) -> Option<BufferInfo> {
 | 
			
		||||
        self.buffer_info.read().unwrap().get(&buffer).cloned()
 | 
			
		||||
        self.buffer_info.read().get(&buffer).cloned()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn bind_group_descriptor_exists(
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,8 @@ use crate::{
 | 
			
		||||
    renderer::{BufferUsage, RenderResourceContext},
 | 
			
		||||
};
 | 
			
		||||
use bevy_ecs::Res;
 | 
			
		||||
use std::sync::{Arc, RwLock};
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
// TODO: Instead of allocating small "exact size" buffers each frame, this should use multiple large shared buffers and probably
 | 
			
		||||
// a long-living "cpu mapped" staging buffer. Im punting that for now because I don't know the best way to use wgpu's new async
 | 
			
		||||
@ -53,7 +54,7 @@ impl SharedBuffers {
 | 
			
		||||
                ..Default::default()
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            let mut command_queue = self.command_queue.write().unwrap();
 | 
			
		||||
            let mut command_queue = self.command_queue.write();
 | 
			
		||||
            command_queue.copy_buffer_to_buffer(
 | 
			
		||||
                staging_buffer,
 | 
			
		||||
                0,
 | 
			
		||||
@ -62,7 +63,7 @@ impl SharedBuffers {
 | 
			
		||||
                size as u64,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            let mut buffers = self.buffers.write().unwrap();
 | 
			
		||||
            let mut buffers = self.buffers.write();
 | 
			
		||||
            buffers.push(staging_buffer);
 | 
			
		||||
            buffers.push(destination_buffer);
 | 
			
		||||
            Some(RenderResourceBinding::Buffer {
 | 
			
		||||
@ -77,14 +78,14 @@ impl SharedBuffers {
 | 
			
		||||
 | 
			
		||||
    // TODO: remove this when this actually uses shared buffers
 | 
			
		||||
    pub fn free_buffers(&self) {
 | 
			
		||||
        let mut buffers = self.buffers.write().unwrap();
 | 
			
		||||
        let mut buffers = self.buffers.write();
 | 
			
		||||
        for buffer in buffers.drain(..) {
 | 
			
		||||
            self.render_resource_context.remove_buffer(buffer)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn reset_command_queue(&self) -> CommandQueue {
 | 
			
		||||
        let mut command_queue = self.command_queue.write().unwrap();
 | 
			
		||||
        let mut command_queue = self.command_queue.write();
 | 
			
		||||
        std::mem::take(&mut *command_queue)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,3 +23,4 @@ bevy_ron = { path = "../bevy_ron", version = "0.1.0" }
 | 
			
		||||
uuid = { version = "0.8", features = ["v4", "serde"] }
 | 
			
		||||
anyhow = "1.0"
 | 
			
		||||
thiserror = "1.0"
 | 
			
		||||
parking_lot = "0.10.2"
 | 
			
		||||
 | 
			
		||||
@ -4,11 +4,9 @@ use bevy_asset::AssetLoader;
 | 
			
		||||
use bevy_ecs::{FromResources, Resources};
 | 
			
		||||
use bevy_property::PropertyTypeRegistry;
 | 
			
		||||
use bevy_type_registry::TypeRegistry;
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use serde::de::DeserializeSeed;
 | 
			
		||||
use std::{
 | 
			
		||||
    path::Path,
 | 
			
		||||
    sync::{Arc, RwLock},
 | 
			
		||||
};
 | 
			
		||||
use std::{path::Path, sync::Arc};
 | 
			
		||||
 | 
			
		||||
pub struct SceneLoader {
 | 
			
		||||
    property_type_registry: Arc<RwLock<PropertyTypeRegistry>>,
 | 
			
		||||
@ -25,7 +23,7 @@ impl FromResources for SceneLoader {
 | 
			
		||||
 | 
			
		||||
impl AssetLoader<Scene> for SceneLoader {
 | 
			
		||||
    fn from_bytes(&self, _asset_path: &Path, bytes: Vec<u8>) -> Result<Scene> {
 | 
			
		||||
        let registry = self.property_type_registry.read().unwrap();
 | 
			
		||||
        let registry = self.property_type_registry.read();
 | 
			
		||||
        let mut deserializer = bevy_ron::de::Deserializer::from_bytes(&bytes)?;
 | 
			
		||||
        let scene_deserializer = SceneDeserializer {
 | 
			
		||||
            property_type_registry: ®istry,
 | 
			
		||||
 | 
			
		||||
@ -85,7 +85,7 @@ impl SceneSpawner {
 | 
			
		||||
        mut instance_info: Option<&mut InstanceInfo>,
 | 
			
		||||
    ) -> Result<(), SceneSpawnError> {
 | 
			
		||||
        let type_registry = resources.get::<TypeRegistry>().unwrap();
 | 
			
		||||
        let component_registry = type_registry.component.read().unwrap();
 | 
			
		||||
        let component_registry = type_registry.component.read();
 | 
			
		||||
        let scenes = resources.get::<Assets<Scene>>().unwrap();
 | 
			
		||||
        let scene = scenes
 | 
			
		||||
            .get(&scene_handle)
 | 
			
		||||
 | 
			
		||||
@ -127,7 +127,7 @@ pub trait BuildChildren {
 | 
			
		||||
impl BuildChildren for Commands {
 | 
			
		||||
    fn with_children(&mut self, mut parent: impl FnMut(&mut ChildBuilder)) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
            let mut commands = self.commands.lock();
 | 
			
		||||
            let current_entity = commands.current_entity.expect("Cannot add children because the 'current entity' is not set. You should spawn an entity first.");
 | 
			
		||||
            commands.current_entity = None;
 | 
			
		||||
            let push_children = {
 | 
			
		||||
@ -150,7 +150,7 @@ impl BuildChildren for Commands {
 | 
			
		||||
 | 
			
		||||
    fn push_children(&mut self, parent: Entity, children: &[Entity]) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
            let mut commands = self.commands.lock();
 | 
			
		||||
            commands.write_world(PushChildren {
 | 
			
		||||
                children: SmallVec::from(children),
 | 
			
		||||
                parent,
 | 
			
		||||
@ -161,7 +161,7 @@ impl BuildChildren for Commands {
 | 
			
		||||
 | 
			
		||||
    fn insert_children(&mut self, parent: Entity, index: usize, children: &[Entity]) -> &mut Self {
 | 
			
		||||
        {
 | 
			
		||||
            let mut commands = self.commands.lock().unwrap();
 | 
			
		||||
            let mut commands = self.commands.lock();
 | 
			
		||||
            commands.write_world(InsertChildren {
 | 
			
		||||
                children: SmallVec::from(children),
 | 
			
		||||
                index,
 | 
			
		||||
 | 
			
		||||
@ -17,3 +17,4 @@ bevy_property = { path = "../bevy_property", version = "0.1" }
 | 
			
		||||
 | 
			
		||||
# other
 | 
			
		||||
serde = { version = "1", features = ["derive"] }
 | 
			
		||||
parking_lot = "0.10.2"
 | 
			
		||||
 | 
			
		||||
@ -22,8 +22,8 @@ impl RegisterType for AppBuilder {
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            let type_registry = self.app.resources.get::<TypeRegistry>().unwrap();
 | 
			
		||||
            type_registry.component.write().unwrap().register::<T>();
 | 
			
		||||
            type_registry.property.write().unwrap().register::<T>();
 | 
			
		||||
            type_registry.component.write().register::<T>();
 | 
			
		||||
            type_registry.property.write().register::<T>();
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
@ -34,7 +34,7 @@ impl RegisterType for AppBuilder {
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            let type_registry = self.app.resources.get::<TypeRegistry>().unwrap();
 | 
			
		||||
            type_registry.property.write().unwrap().register::<T>();
 | 
			
		||||
            type_registry.property.write().register::<T>();
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
@ -45,7 +45,7 @@ impl RegisterType for AppBuilder {
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            let type_registry = self.app.resources.get::<TypeRegistry>().unwrap();
 | 
			
		||||
            type_registry.property.write().unwrap().register::<T>();
 | 
			
		||||
            type_registry.property.write().register::<T>();
 | 
			
		||||
        }
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,10 @@
 | 
			
		||||
use bevy_ecs::{Archetype, Component, Entity, FromResources, Resources, World};
 | 
			
		||||
use bevy_property::{Properties, Property, PropertyTypeRegistration, PropertyTypeRegistry};
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use std::{
 | 
			
		||||
    any::TypeId,
 | 
			
		||||
    collections::{HashMap, HashSet},
 | 
			
		||||
    sync::{Arc, RwLock},
 | 
			
		||||
    sync::Arc,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Default)]
 | 
			
		||||
 | 
			
		||||
@ -30,3 +30,4 @@ pollster = "0.2.0"
 | 
			
		||||
log = { version = "0.4", features = ["release_max_level_info"] }
 | 
			
		||||
crossbeam-channel = "0.4.2"
 | 
			
		||||
crossbeam-utils = "0.7.2"
 | 
			
		||||
parking_lot = "0.10.2"
 | 
			
		||||
 | 
			
		||||
@ -95,7 +95,6 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
                .resources
 | 
			
		||||
                .window_surfaces
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
@ -105,7 +104,6 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
                .resources
 | 
			
		||||
                .window_swap_chains
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
@ -115,58 +113,32 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
                .resources
 | 
			
		||||
                .swap_chain_frames
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        diagnostics.add_measurement(
 | 
			
		||||
            Self::BUFFERS,
 | 
			
		||||
            render_resource_context
 | 
			
		||||
                .resources
 | 
			
		||||
                .buffers
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
            render_resource_context.resources.buffers.read().len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        diagnostics.add_measurement(
 | 
			
		||||
            Self::TEXTURES,
 | 
			
		||||
            render_resource_context
 | 
			
		||||
                .resources
 | 
			
		||||
                .textures
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
            render_resource_context.resources.textures.read().len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        diagnostics.add_measurement(
 | 
			
		||||
            Self::TEXTURE_VIEWS,
 | 
			
		||||
            render_resource_context
 | 
			
		||||
                .resources
 | 
			
		||||
                .texture_views
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
            render_resource_context.resources.texture_views.read().len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        diagnostics.add_measurement(
 | 
			
		||||
            Self::SAMPLERS,
 | 
			
		||||
            render_resource_context
 | 
			
		||||
                .resources
 | 
			
		||||
                .samplers
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
            render_resource_context.resources.samplers.read().len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        diagnostics.add_measurement(
 | 
			
		||||
            Self::BIND_GROUP_IDS,
 | 
			
		||||
            render_resource_context
 | 
			
		||||
                .resources
 | 
			
		||||
                .bind_groups
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
            render_resource_context.resources.bind_groups.read().len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let mut bind_group_count = 0;
 | 
			
		||||
@ -174,7 +146,6 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
            .resources
 | 
			
		||||
            .bind_groups
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .values()
 | 
			
		||||
        {
 | 
			
		||||
            bind_group_count += bind_group.bind_groups.len();
 | 
			
		||||
@ -188,7 +159,6 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
                .resources
 | 
			
		||||
                .bind_group_layouts
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
@ -198,7 +168,6 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
                .resources
 | 
			
		||||
                .shader_modules
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
@ -208,7 +177,6 @@ impl WgpuResourceDiagnosticsPlugin {
 | 
			
		||||
                .resources
 | 
			
		||||
                .render_pipelines
 | 
			
		||||
                .read()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .len() as f64,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,8 @@ use bevy_render::{
 | 
			
		||||
    render_graph::{Edge, NodeId, ResourceSlots, StageBorrow},
 | 
			
		||||
    renderer::RenderResourceContext,
 | 
			
		||||
};
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    sync::{Arc, RwLock},
 | 
			
		||||
};
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use std::{collections::HashMap, sync::Arc};
 | 
			
		||||
 | 
			
		||||
pub struct WgpuRenderGraphExecutor {
 | 
			
		||||
    pub max_thread_count: usize,
 | 
			
		||||
@ -56,7 +54,7 @@ impl WgpuRenderGraphExecutor {
 | 
			
		||||
                                ..
 | 
			
		||||
                            } = node_state.edges.get_input_slot_edge(i).unwrap()
 | 
			
		||||
                            {
 | 
			
		||||
                                let node_outputs = node_outputs.read().unwrap();
 | 
			
		||||
                                let node_outputs = node_outputs.read();
 | 
			
		||||
                                let outputs = if let Some(outputs) = node_outputs.get(output_node) {
 | 
			
		||||
                                    outputs
 | 
			
		||||
                                } else {
 | 
			
		||||
@ -80,7 +78,6 @@ impl WgpuRenderGraphExecutor {
 | 
			
		||||
 | 
			
		||||
                        node_outputs
 | 
			
		||||
                            .write()
 | 
			
		||||
                            .unwrap()
 | 
			
		||||
                            .insert(node_state.id, node_state.output_slots.clone());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ impl WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set_window_surface(&self, window_id: WindowId, surface: wgpu::Surface) {
 | 
			
		||||
        let mut window_surfaces = self.resources.window_surfaces.write().unwrap();
 | 
			
		||||
        let mut window_surfaces = self.resources.window_surfaces.write();
 | 
			
		||||
        window_surfaces.insert(window_id, surface);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@ impl WgpuRenderResourceContext {
 | 
			
		||||
        destination_offset: u64,
 | 
			
		||||
        size: u64,
 | 
			
		||||
    ) {
 | 
			
		||||
        let buffers = self.resources.buffers.read().unwrap();
 | 
			
		||||
        let buffers = self.resources.buffers.read();
 | 
			
		||||
 | 
			
		||||
        let source = buffers.get(&source_buffer).unwrap();
 | 
			
		||||
        let destination = buffers.get(&destination_buffer).unwrap();
 | 
			
		||||
@ -71,8 +71,8 @@ impl WgpuRenderResourceContext {
 | 
			
		||||
        destination_mip_level: u32,
 | 
			
		||||
        size: Extent3d,
 | 
			
		||||
    ) {
 | 
			
		||||
        let buffers = self.resources.buffers.read().unwrap();
 | 
			
		||||
        let textures = self.resources.textures.read().unwrap();
 | 
			
		||||
        let buffers = self.resources.buffers.read();
 | 
			
		||||
        let textures = self.resources.textures.read();
 | 
			
		||||
 | 
			
		||||
        let source = buffers.get(&source_buffer).unwrap();
 | 
			
		||||
        let destination = textures.get(&destination_texture).unwrap();
 | 
			
		||||
@ -103,14 +103,13 @@ impl WgpuRenderResourceContext {
 | 
			
		||||
            .resources
 | 
			
		||||
            .bind_group_layouts
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&descriptor.id)
 | 
			
		||||
            .is_some()
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut bind_group_layouts = self.resources.bind_group_layouts.write().unwrap();
 | 
			
		||||
        let mut bind_group_layouts = self.resources.bind_group_layouts.write();
 | 
			
		||||
        // TODO: consider re-checking existence here
 | 
			
		||||
        let bind_group_layout_binding = descriptor
 | 
			
		||||
            .bindings
 | 
			
		||||
@ -143,8 +142,8 @@ impl WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn try_next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> Option<TextureId> {
 | 
			
		||||
        let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap();
 | 
			
		||||
        let mut swap_chain_outputs = self.resources.swap_chain_frames.write().unwrap();
 | 
			
		||||
        let mut window_swap_chains = self.resources.window_swap_chains.write();
 | 
			
		||||
        let mut swap_chain_outputs = self.resources.swap_chain_frames.write();
 | 
			
		||||
 | 
			
		||||
        let window_swap_chain = window_swap_chains.get_mut(&window_id).unwrap();
 | 
			
		||||
        let next_texture = window_swap_chain.get_next_frame().ok()?;
 | 
			
		||||
@ -156,7 +155,7 @@ impl WgpuRenderResourceContext {
 | 
			
		||||
 | 
			
		||||
impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> SamplerId {
 | 
			
		||||
        let mut samplers = self.resources.samplers.write().unwrap();
 | 
			
		||||
        let mut samplers = self.resources.samplers.write();
 | 
			
		||||
 | 
			
		||||
        let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).wgpu_into();
 | 
			
		||||
        let sampler = self.device.create_sampler(&descriptor);
 | 
			
		||||
@ -167,9 +166,9 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn create_texture(&self, texture_descriptor: TextureDescriptor) -> TextureId {
 | 
			
		||||
        let mut textures = self.resources.textures.write().unwrap();
 | 
			
		||||
        let mut texture_views = self.resources.texture_views.write().unwrap();
 | 
			
		||||
        let mut texture_descriptors = self.resources.texture_descriptors.write().unwrap();
 | 
			
		||||
        let mut textures = self.resources.textures.write();
 | 
			
		||||
        let mut texture_views = self.resources.texture_views.write();
 | 
			
		||||
        let mut texture_descriptors = self.resources.texture_descriptors.write();
 | 
			
		||||
 | 
			
		||||
        let descriptor: wgpu::TextureDescriptor = (&texture_descriptor).wgpu_into();
 | 
			
		||||
        let texture = self.device.create_texture(&descriptor);
 | 
			
		||||
@ -184,8 +183,8 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
 | 
			
		||||
    fn create_buffer(&self, buffer_info: BufferInfo) -> BufferId {
 | 
			
		||||
        // TODO: consider moving this below "create" for efficiency
 | 
			
		||||
        let mut buffer_infos = self.resources.buffer_infos.write().unwrap();
 | 
			
		||||
        let mut buffers = self.resources.buffers.write().unwrap();
 | 
			
		||||
        let mut buffer_infos = self.resources.buffer_infos.write();
 | 
			
		||||
        let mut buffers = self.resources.buffers.write();
 | 
			
		||||
 | 
			
		||||
        let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
 | 
			
		||||
            label: None,
 | 
			
		||||
@ -202,8 +201,8 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
 | 
			
		||||
    fn create_buffer_with_data(&self, mut buffer_info: BufferInfo, data: &[u8]) -> BufferId {
 | 
			
		||||
        // TODO: consider moving this below "create" for efficiency
 | 
			
		||||
        let mut buffer_infos = self.resources.buffer_infos.write().unwrap();
 | 
			
		||||
        let mut buffers = self.resources.buffers.write().unwrap();
 | 
			
		||||
        let mut buffer_infos = self.resources.buffer_infos.write();
 | 
			
		||||
        let mut buffers = self.resources.buffers.write();
 | 
			
		||||
 | 
			
		||||
        buffer_info.size = data.len();
 | 
			
		||||
        let buffer = self
 | 
			
		||||
@ -217,17 +216,17 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_buffer(&self, buffer: BufferId) {
 | 
			
		||||
        let mut buffers = self.resources.buffers.write().unwrap();
 | 
			
		||||
        let mut buffer_infos = self.resources.buffer_infos.write().unwrap();
 | 
			
		||||
        let mut buffers = self.resources.buffers.write();
 | 
			
		||||
        let mut buffer_infos = self.resources.buffer_infos.write();
 | 
			
		||||
 | 
			
		||||
        buffers.remove(&buffer);
 | 
			
		||||
        buffer_infos.remove(&buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_texture(&self, texture: TextureId) {
 | 
			
		||||
        let mut textures = self.resources.textures.write().unwrap();
 | 
			
		||||
        let mut texture_views = self.resources.texture_views.write().unwrap();
 | 
			
		||||
        let mut texture_descriptors = self.resources.texture_descriptors.write().unwrap();
 | 
			
		||||
        let mut textures = self.resources.textures.write();
 | 
			
		||||
        let mut texture_views = self.resources.texture_views.write();
 | 
			
		||||
        let mut texture_descriptors = self.resources.texture_descriptors.write();
 | 
			
		||||
 | 
			
		||||
        textures.remove(&texture);
 | 
			
		||||
        texture_views.remove(&texture);
 | 
			
		||||
@ -235,12 +234,12 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_sampler(&self, sampler: SamplerId) {
 | 
			
		||||
        let mut samplers = self.resources.samplers.write().unwrap();
 | 
			
		||||
        let mut samplers = self.resources.samplers.write();
 | 
			
		||||
        samplers.remove(&sampler);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn create_shader_module_from_source(&self, shader_handle: Handle<Shader>, shader: &Shader) {
 | 
			
		||||
        let mut shader_modules = self.resources.shader_modules.write().unwrap();
 | 
			
		||||
        let mut shader_modules = self.resources.shader_modules.write();
 | 
			
		||||
        let shader_module = self
 | 
			
		||||
            .device
 | 
			
		||||
            .create_shader_module(wgpu::ShaderModuleSource::SpirV(&shader.get_spirv(None)));
 | 
			
		||||
@ -252,7 +251,6 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
            .resources
 | 
			
		||||
            .shader_modules
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&shader_handle)
 | 
			
		||||
            .is_some()
 | 
			
		||||
        {
 | 
			
		||||
@ -263,8 +261,8 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn create_swap_chain(&self, window: &Window) {
 | 
			
		||||
        let surfaces = self.resources.window_surfaces.read().unwrap();
 | 
			
		||||
        let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap();
 | 
			
		||||
        let surfaces = self.resources.window_surfaces.read();
 | 
			
		||||
        let mut window_swap_chains = self.resources.window_swap_chains.write();
 | 
			
		||||
 | 
			
		||||
        let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into();
 | 
			
		||||
        let surface = surfaces
 | 
			
		||||
@ -281,11 +279,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
        if let Some(texture_id) = self.try_next_swap_chain_texture(window.id) {
 | 
			
		||||
            texture_id
 | 
			
		||||
        } else {
 | 
			
		||||
            self.resources
 | 
			
		||||
                .window_swap_chains
 | 
			
		||||
                .write()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .remove(&window.id);
 | 
			
		||||
            self.resources.window_swap_chains.write().remove(&window.id);
 | 
			
		||||
            self.create_swap_chain(window);
 | 
			
		||||
            self.try_next_swap_chain_texture(window.id)
 | 
			
		||||
                .expect("Failed to acquire next swap chain texture!")
 | 
			
		||||
@ -293,12 +287,12 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn drop_swap_chain_texture(&self, texture: TextureId) {
 | 
			
		||||
        let mut swap_chain_outputs = self.resources.swap_chain_frames.write().unwrap();
 | 
			
		||||
        let mut swap_chain_outputs = self.resources.swap_chain_frames.write();
 | 
			
		||||
        swap_chain_outputs.remove(&texture);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn drop_all_swap_chain_textures(&self) {
 | 
			
		||||
        let mut swap_chain_outputs = self.resources.swap_chain_frames.write().unwrap();
 | 
			
		||||
        let mut swap_chain_outputs = self.resources.swap_chain_frames.write();
 | 
			
		||||
        swap_chain_outputs.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -308,7 +302,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
        render_resource: RenderResourceId,
 | 
			
		||||
        index: usize,
 | 
			
		||||
    ) {
 | 
			
		||||
        let mut asset_resources = self.resources.asset_resources.write().unwrap();
 | 
			
		||||
        let mut asset_resources = self.resources.asset_resources.write();
 | 
			
		||||
        asset_resources.insert((handle, index), render_resource);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -317,12 +311,12 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
        handle: HandleUntyped,
 | 
			
		||||
        index: usize,
 | 
			
		||||
    ) -> Option<RenderResourceId> {
 | 
			
		||||
        let asset_resources = self.resources.asset_resources.read().unwrap();
 | 
			
		||||
        let asset_resources = self.resources.asset_resources.read();
 | 
			
		||||
        asset_resources.get(&(handle, index)).cloned()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn remove_asset_resource_untyped(&self, handle: HandleUntyped, index: usize) {
 | 
			
		||||
        let mut asset_resources = self.resources.asset_resources.write().unwrap();
 | 
			
		||||
        let mut asset_resources = self.resources.asset_resources.write();
 | 
			
		||||
        asset_resources.remove(&(handle, index));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -336,7 +330,6 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
            .resources
 | 
			
		||||
            .render_pipelines
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&pipeline_handle)
 | 
			
		||||
            .is_some()
 | 
			
		||||
        {
 | 
			
		||||
@ -348,7 +341,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
            self.create_bind_group_layout(&bind_group_descriptor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap();
 | 
			
		||||
        let bind_group_layouts = self.resources.bind_group_layouts.read();
 | 
			
		||||
        // setup and collect bind group layouts
 | 
			
		||||
        let bind_group_layouts = layout
 | 
			
		||||
            .bind_groups
 | 
			
		||||
@ -380,7 +373,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
            self.create_shader_module(fragment_handle, shaders);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let shader_modules = self.resources.shader_modules.read().unwrap();
 | 
			
		||||
        let shader_modules = self.resources.shader_modules.read();
 | 
			
		||||
        let vertex_shader_module = shader_modules
 | 
			
		||||
            .get(&pipeline_descriptor.shader_stages.vertex)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
@ -428,7 +421,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
        let render_pipeline = self
 | 
			
		||||
            .device
 | 
			
		||||
            .create_render_pipeline(&render_pipeline_descriptor);
 | 
			
		||||
        let mut render_pipelines = self.resources.render_pipelines.write().unwrap();
 | 
			
		||||
        let mut render_pipelines = self.resources.render_pipelines.write();
 | 
			
		||||
        render_pipelines.insert(pipeline_handle, render_pipeline);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -436,7 +429,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
        &self,
 | 
			
		||||
        bind_group_descriptor_id: BindGroupDescriptorId,
 | 
			
		||||
    ) -> bool {
 | 
			
		||||
        let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap();
 | 
			
		||||
        let bind_group_layouts = self.resources.bind_group_layouts.read();
 | 
			
		||||
        bind_group_layouts.get(&bind_group_descriptor_id).is_some()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -453,11 +446,11 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
                "start creating bind group for RenderResourceSet {:?}",
 | 
			
		||||
                bind_group.id
 | 
			
		||||
            );
 | 
			
		||||
            let texture_views = self.resources.texture_views.read().unwrap();
 | 
			
		||||
            let samplers = self.resources.samplers.read().unwrap();
 | 
			
		||||
            let buffers = self.resources.buffers.read().unwrap();
 | 
			
		||||
            let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap();
 | 
			
		||||
            let mut bind_groups = self.resources.bind_groups.write().unwrap();
 | 
			
		||||
            let texture_views = self.resources.texture_views.read();
 | 
			
		||||
            let samplers = self.resources.samplers.read();
 | 
			
		||||
            let buffers = self.resources.buffers.read();
 | 
			
		||||
            let bind_group_layouts = self.resources.bind_group_layouts.read();
 | 
			
		||||
            let mut bind_groups = self.resources.bind_groups.write();
 | 
			
		||||
 | 
			
		||||
            let bindings = bind_group
 | 
			
		||||
                .indexed_bindings
 | 
			
		||||
@ -508,16 +501,11 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn clear_bind_groups(&self) {
 | 
			
		||||
        self.resources.bind_groups.write().unwrap().clear();
 | 
			
		||||
        self.resources.bind_groups.write().clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_buffer_info(&self, buffer: BufferId) -> Option<BufferInfo> {
 | 
			
		||||
        self.resources
 | 
			
		||||
            .buffer_infos
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&buffer)
 | 
			
		||||
            .cloned()
 | 
			
		||||
        self.resources.buffer_infos.read().get(&buffer).cloned()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn write_mapped_buffer(
 | 
			
		||||
@ -527,7 +515,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
        write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
 | 
			
		||||
    ) {
 | 
			
		||||
        let buffer = {
 | 
			
		||||
            let buffers = self.resources.buffers.read().unwrap();
 | 
			
		||||
            let buffers = self.resources.buffers.read();
 | 
			
		||||
            buffers.get(&id).unwrap().clone()
 | 
			
		||||
        };
 | 
			
		||||
        let buffer_slice = buffer.slice(range);
 | 
			
		||||
@ -536,7 +524,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn map_buffer(&self, id: BufferId) {
 | 
			
		||||
        let buffers = self.resources.buffers.read().unwrap();
 | 
			
		||||
        let buffers = self.resources.buffers.read();
 | 
			
		||||
        let buffer = buffers.get(&id).unwrap();
 | 
			
		||||
        let buffer_slice = buffer.slice(..);
 | 
			
		||||
        let data = buffer_slice.map_async(wgpu::MapMode::Write);
 | 
			
		||||
@ -547,7 +535,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn unmap_buffer(&self, id: BufferId) {
 | 
			
		||||
        let buffers = self.resources.buffers.read().unwrap();
 | 
			
		||||
        let buffers = self.resources.buffers.read();
 | 
			
		||||
        let buffer = buffers.get(&id).unwrap();
 | 
			
		||||
        buffer.unmap();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -6,10 +6,8 @@ use bevy_render::{
 | 
			
		||||
    texture::TextureDescriptor,
 | 
			
		||||
};
 | 
			
		||||
use bevy_window::WindowId;
 | 
			
		||||
use std::{
 | 
			
		||||
    collections::HashMap,
 | 
			
		||||
    sync::{Arc, RwLock, RwLockReadGuard},
 | 
			
		||||
};
 | 
			
		||||
use parking_lot::{RwLock, RwLockReadGuard};
 | 
			
		||||
use std::{collections::HashMap, sync::Arc};
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
pub struct WgpuBindGroupInfo {
 | 
			
		||||
@ -89,11 +87,11 @@ pub struct WgpuResources {
 | 
			
		||||
impl WgpuResources {
 | 
			
		||||
    pub fn read(&self) -> WgpuResourcesReadLock {
 | 
			
		||||
        WgpuResourcesReadLock {
 | 
			
		||||
            buffers: self.buffers.read().unwrap(),
 | 
			
		||||
            textures: self.texture_views.read().unwrap(),
 | 
			
		||||
            swap_chain_frames: self.swap_chain_frames.read().unwrap(),
 | 
			
		||||
            render_pipelines: self.render_pipelines.read().unwrap(),
 | 
			
		||||
            bind_groups: self.bind_groups.read().unwrap(),
 | 
			
		||||
            buffers: self.buffers.read(),
 | 
			
		||||
            textures: self.texture_views.read(),
 | 
			
		||||
            swap_chain_frames: self.swap_chain_frames.read(),
 | 
			
		||||
            render_pipelines: self.render_pipelines.read(),
 | 
			
		||||
            bind_groups: self.bind_groups.read(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -102,12 +100,7 @@ impl WgpuResources {
 | 
			
		||||
        bind_group_descriptor_id: BindGroupDescriptorId,
 | 
			
		||||
        bind_group_id: BindGroupId,
 | 
			
		||||
    ) -> bool {
 | 
			
		||||
        if let Some(bind_group_info) = self
 | 
			
		||||
            .bind_groups
 | 
			
		||||
            .read()
 | 
			
		||||
            .unwrap()
 | 
			
		||||
            .get(&bind_group_descriptor_id)
 | 
			
		||||
        {
 | 
			
		||||
        if let Some(bind_group_info) = self.bind_groups.read().get(&bind_group_descriptor_id) {
 | 
			
		||||
            bind_group_info.bind_groups.get(&bind_group_id).is_some()
 | 
			
		||||
        } else {
 | 
			
		||||
            false
 | 
			
		||||
 | 
			
		||||
@ -65,7 +65,7 @@ fn setup(type_registry: Res<TypeRegistry>) {
 | 
			
		||||
 | 
			
		||||
    // All properties can be serialized.
 | 
			
		||||
    // If you #[derive(Properties)] your type doesn't even need to directly implement the Serde trait!
 | 
			
		||||
    let registry = type_registry.property.read().unwrap();
 | 
			
		||||
    let registry = type_registry.property.read();
 | 
			
		||||
    let ron_string = serialize_property(&test, ®istry);
 | 
			
		||||
    println!("{}\n", ron_string);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -117,14 +117,12 @@ fn save_scene_system(_world: &mut World, resources: &mut Resources) {
 | 
			
		||||
 | 
			
		||||
    // The component registry resource contains information about all registered components. This is used to construct scenes.
 | 
			
		||||
    let type_registry = resources.get::<TypeRegistry>().unwrap();
 | 
			
		||||
    let scene = Scene::from_world(&world, &type_registry.component.read().unwrap());
 | 
			
		||||
    let scene = Scene::from_world(&world, &type_registry.component.read());
 | 
			
		||||
 | 
			
		||||
    // Scenes can be serialized like this:
 | 
			
		||||
    println!(
 | 
			
		||||
        "{}",
 | 
			
		||||
        scene
 | 
			
		||||
            .serialize_ron(&type_registry.property.read().unwrap())
 | 
			
		||||
            .unwrap()
 | 
			
		||||
        scene.serialize_ron(&type_registry.property.read()).unwrap()
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // TODO: save scene
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user