Create bevy_platform_support
Crate (#17250)
# Objective - Contributes to #16877 ## Solution - Initial creation of `bevy_platform_support` crate. - Moved `bevy_utils::Instant` into new `bevy_platform_support` crate. - Moved `portable-atomic`, `portable-atomic-util`, and `critical-section` into new `bevy_platform_support` crate. ## Testing - CI --- ## Showcase Instead of needing code like this to import an `Arc`: ```rust #[cfg(feature = "portable-atomic")] use portable_atomic_util::Arc; #[cfg(not(feature = "portable-atomic"))] use alloc::sync::Arc; ``` We can now use: ```rust use bevy_platform_support::sync::Arc; ``` This applies to many other types, but the goal is overall the same: allowing crates to use `std`-like types without the boilerplate of conditional compilation and platform-dependencies. ## Migration Guide - Replace imports of `bevy_utils::Instant` with `bevy_platform_support::time::Instant` - Replace imports of `bevy::utils::Instant` with `bevy::platform_support::time::Instant` ## Notes - `bevy_platform_support` hasn't been reserved on `crates.io` - ~~`bevy_platform_support` is not re-exported from `bevy` at this time. It may be worthwhile exporting this crate, but I am unsure of a reasonable name to export it under (`platform_support` may be a bit wordy for user-facing).~~ - I've included an implementation of `Instant` which is suitable for `no_std` platforms that are not Wasm for the sake of eliminating feature gates around its use. It may be a controversial inclusion, so I'm happy to remove it if required. - There are many other items (`spin`, `bevy_utils::Sync(Unsafe)Cell`, etc.) which should be added to this crate. I have kept the initial scope small to demonstrate utility without making this too unwieldy. --------- Co-authored-by: TimJentzsch <TimJentzsch@users.noreply.github.com> Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com> Co-authored-by: François Mockers <francois.mockers@vleue.com>
This commit is contained in:
parent
edb34cd2dd
commit
a64446b77e
@ -48,23 +48,25 @@ std = [
|
||||
"downcast-rs/std",
|
||||
"bevy_utils/std",
|
||||
"bevy_tasks?/std",
|
||||
"bevy_platform_support/std",
|
||||
]
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = [
|
||||
"portable-atomic?/critical-section",
|
||||
"bevy_tasks?/critical-section",
|
||||
"bevy_ecs/critical-section",
|
||||
"bevy_platform_support/critical-section",
|
||||
"bevy_reflect?/critical-section",
|
||||
]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = [
|
||||
"dep:portable-atomic",
|
||||
"dep:portable-atomic-util",
|
||||
"bevy_tasks?/portable-atomic",
|
||||
"bevy_ecs/portable-atomic",
|
||||
"bevy_platform_support/portable-atomic",
|
||||
"bevy_reflect?/portable-atomic",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
@ -76,6 +78,7 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features
|
||||
"alloc",
|
||||
] }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev", default-features = false, optional = true }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false }
|
||||
|
||||
# other
|
||||
downcast-rs = { version = "2", default-features = false }
|
||||
@ -83,12 +86,6 @@ thiserror = { version = "2", default-features = false }
|
||||
variadics_please = "1.1"
|
||||
tracing = { version = "0.1", default-features = false, optional = true }
|
||||
log = { version = "0.4", default-features = false }
|
||||
portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
], optional = true }
|
||||
portable-atomic-util = { version = "0.2.4", features = [
|
||||
"alloc",
|
||||
], optional = true }
|
||||
|
||||
[target.'cfg(any(unix, windows))'.dependencies]
|
||||
ctrlc = { version = "3.4.4", optional = true }
|
||||
|
@ -3,11 +3,9 @@ use crate::{
|
||||
plugin::Plugin,
|
||||
PluginsState,
|
||||
};
|
||||
use bevy_platform_support::time::Instant;
|
||||
use core::time::Duration;
|
||||
|
||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
||||
use bevy_utils::Instant;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use {
|
||||
alloc::{boxed::Box, rc::Rc},
|
||||
@ -100,7 +98,6 @@ impl Plugin for ScheduleRunnerPlugin {
|
||||
let tick = move |app: &mut App,
|
||||
_wait: Option<Duration>|
|
||||
-> Result<Option<Duration>, AppExit> {
|
||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
||||
let start_time = Instant::now();
|
||||
|
||||
app.update();
|
||||
@ -109,10 +106,8 @@ impl Plugin for ScheduleRunnerPlugin {
|
||||
return Err(exit);
|
||||
};
|
||||
|
||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
||||
let end_time = Instant::now();
|
||||
|
||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
||||
if let Some(wait) = _wait {
|
||||
let exe_time = end_time - start_time;
|
||||
if exe_time < wait {
|
||||
|
@ -2,13 +2,14 @@
|
||||
feature = "portable-atomic",
|
||||
expect(
|
||||
clippy::redundant_closure,
|
||||
reason = "portable_atomic_util::Arc has subtly different implicit behavior"
|
||||
reason = "bevy_platform_support::sync::Arc has subtly different implicit behavior"
|
||||
)
|
||||
)]
|
||||
|
||||
use crate::{App, Plugin};
|
||||
|
||||
use alloc::string::ToString;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
use log::trace;
|
||||
@ -16,12 +17,6 @@ use log::trace;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use {crate::Last, bevy_ecs::prelude::NonSend};
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use bevy_tasks::tick_global_task_pools_on_main_thread;
|
||||
|
||||
|
@ -35,6 +35,9 @@ bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.16.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
bitflags = "2.3"
|
||||
|
@ -4,6 +4,7 @@ use bevy_app::prelude::*;
|
||||
use bevy_asset::{load_internal_asset, Handle};
|
||||
use bevy_ecs::{component::*, prelude::*};
|
||||
use bevy_math::UVec2;
|
||||
use bevy_platform_support::time::Instant;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_render::{
|
||||
camera::{Camera, ExtractedCamera},
|
||||
@ -16,7 +17,7 @@ use bevy_render::{
|
||||
view::Msaa,
|
||||
Render, RenderApp, RenderSet,
|
||||
};
|
||||
use bevy_utils::{HashSet, Instant};
|
||||
use bevy_utils::HashSet;
|
||||
use bevy_window::PrimaryWindow;
|
||||
use resolve::{
|
||||
node::{OitResolveNode, OitResolvePass},
|
||||
|
@ -21,6 +21,9 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev" }
|
||||
bevy_time = { path = "../bevy_time", version = "0.16.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
|
||||
# other
|
||||
const-fnv1a-hash = "1.1.0"
|
||||
|
@ -6,7 +6,8 @@ use core::{
|
||||
|
||||
use bevy_app::{App, SubApp};
|
||||
use bevy_ecs::system::{Deferred, Res, Resource, SystemBuffer, SystemParam};
|
||||
use bevy_utils::{HashMap, Instant, PassHash};
|
||||
use bevy_platform_support::time::Instant;
|
||||
use bevy_utils::{HashMap, PassHash};
|
||||
use const_fnv1a_hash::fnv1a_hash_str_64;
|
||||
|
||||
use crate::DEFAULT_MAX_HISTORY_LENGTH;
|
||||
|
@ -76,24 +76,25 @@ std = [
|
||||
"nonmax/std",
|
||||
"arrayvec?/std",
|
||||
"log/std",
|
||||
"bevy_platform_support/std",
|
||||
]
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = [
|
||||
"dep:critical-section",
|
||||
"bevy_tasks?/critical-section",
|
||||
"portable-atomic?/critical-section",
|
||||
"bevy_platform_support/critical-section",
|
||||
"bevy_reflect?/critical-section",
|
||||
]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = [
|
||||
"dep:portable-atomic",
|
||||
"dep:portable-atomic-util",
|
||||
"bevy_tasks?/portable-atomic",
|
||||
"bevy_platform_support/portable-atomic",
|
||||
"concurrent-queue/portable-atomic",
|
||||
"spin/portable_atomic",
|
||||
"bevy_reflect?/portable-atomic",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
@ -104,6 +105,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features
|
||||
"alloc",
|
||||
] }
|
||||
bevy_ecs_macros = { path = "macros", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
|
||||
bitflags = { version = "2.3", default-features = false }
|
||||
concurrent-queue = { version = "2.5.0", default-features = false }
|
||||
@ -124,13 +128,6 @@ arrayvec = { version = "0.7.4", default-features = false, optional = true }
|
||||
smallvec = { version = "1", features = ["union"] }
|
||||
indexmap = { version = "2.5.0", default-features = false }
|
||||
variadics_please = { version = "1.1", default-features = false }
|
||||
critical-section = { version = "1.2.0", optional = true }
|
||||
portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
], optional = true }
|
||||
portable-atomic-util = { version = "0.2.4", features = [
|
||||
"alloc",
|
||||
], optional = true }
|
||||
spin = { version = "0.9.8", default-features = false, features = [
|
||||
"spin_mutex",
|
||||
"rwlock",
|
||||
|
@ -15,6 +15,7 @@ use crate::{
|
||||
use alloc::boxed::Box;
|
||||
use alloc::{borrow::Cow, format, vec::Vec};
|
||||
pub use bevy_ecs_macros::Component;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_ptr::{OwningPtr, UnsafeCellDeref};
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
@ -32,12 +33,6 @@ use core::{
|
||||
use disqualified::ShortName;
|
||||
use thiserror::Error;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
|
||||
pub use bevy_ecs_macros::require;
|
||||
|
||||
/// A data type that can be used to store data for an [entity].
|
||||
|
@ -1,19 +1,13 @@
|
||||
use alloc::{borrow::ToOwned, vec::Vec};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_ptr::{Ptr, PtrMut};
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
use bumpalo::Bump;
|
||||
use core::{any::TypeId, ptr::NonNull};
|
||||
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
bundle::Bundle,
|
||||
component::{Component, ComponentCloneHandler, ComponentId, ComponentInfo, Components},
|
||||
|
@ -13,11 +13,7 @@ use core::{
|
||||
|
||||
use super::Entity;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
|
||||
/// A trait for entity borrows.
|
||||
///
|
||||
|
@ -70,6 +70,7 @@ use crate::{
|
||||
storage::{SparseSetIndex, TableId, TableRow},
|
||||
};
|
||||
use alloc::vec::Vec;
|
||||
use bevy_platform_support::sync::atomic::Ordering;
|
||||
use core::{fmt, hash::Hash, mem, num::NonZero};
|
||||
use log::warn;
|
||||
|
||||
@ -79,26 +80,16 @@ use core::panic::Location;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic::Ordering;
|
||||
|
||||
#[cfg(all(target_has_atomic = "64", not(feature = "portable-atomic")))]
|
||||
use core::sync::atomic::AtomicI64 as AtomicIdCursor;
|
||||
#[cfg(all(target_has_atomic = "64", feature = "portable-atomic"))]
|
||||
use portable_atomic::AtomicI64 as AtomicIdCursor;
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
use bevy_platform_support::sync::atomic::AtomicI64 as AtomicIdCursor;
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
type IdCursor = i64;
|
||||
|
||||
/// Most modern platforms support 64-bit atomics, but some less-common platforms
|
||||
/// do not. This fallback allows compilation using a 32-bit cursor instead, with
|
||||
/// the caveat that some conversions may fail (and panic) at runtime.
|
||||
#[cfg(all(not(target_has_atomic = "64"), not(feature = "portable-atomic")))]
|
||||
use core::sync::atomic::AtomicIsize as AtomicIdCursor;
|
||||
#[cfg(all(not(target_has_atomic = "64"), feature = "portable-atomic"))]
|
||||
use portable_atomic::AtomicIsize as AtomicIdCursor;
|
||||
#[cfg(not(target_has_atomic = "64"))]
|
||||
use bevy_platform_support::sync::atomic::AtomicIsize as AtomicIdCursor;
|
||||
#[cfg(not(target_has_atomic = "64"))]
|
||||
type IdCursor = isize;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_tasks::{ComputeTaskPool, Scope, TaskPool, ThreadExecutor};
|
||||
use bevy_utils::{default, syncunsafecell::SyncUnsafeCell};
|
||||
use concurrent_queue::ConcurrentQueue;
|
||||
@ -12,12 +13,6 @@ use std::{
|
||||
#[cfg(feature = "trace")]
|
||||
use tracing::{info_span, Span};
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
archetype::ArchetypeComponentId,
|
||||
prelude::Resource,
|
||||
|
@ -4,12 +4,7 @@ use crate::{
|
||||
system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam},
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic::{AtomicUsize, Ordering};
|
||||
use bevy_platform_support::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use super::unsafe_world_cell::UnsafeWorldCell;
|
||||
|
||||
|
@ -53,23 +53,15 @@ use crate::{
|
||||
},
|
||||
};
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use bevy_platform_support::sync::atomic::{AtomicU32, Ordering};
|
||||
use bevy_ptr::{OwningPtr, Ptr};
|
||||
use core::{any::TypeId, fmt};
|
||||
use core::{any::TypeId, fmt, panic::Location};
|
||||
use log::warn;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic::{AtomicU32, Ordering};
|
||||
use unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell};
|
||||
|
||||
#[cfg(feature = "track_location")]
|
||||
use bevy_ptr::UnsafeCellDeref;
|
||||
|
||||
use core::panic::Location;
|
||||
|
||||
use unsafe_world_cell::{UnsafeEntityCell, UnsafeWorldCell};
|
||||
|
||||
/// Stores and exposes operations on [entities](Entity), [components](Component), resources,
|
||||
/// and their associated metadata.
|
||||
///
|
||||
|
@ -15,19 +15,13 @@ use crate::{
|
||||
system::Resource,
|
||||
world::RawCommandQueue,
|
||||
};
|
||||
use bevy_platform_support::sync::atomic::Ordering;
|
||||
use bevy_ptr::Ptr;
|
||||
#[cfg(feature = "track_location")]
|
||||
use bevy_ptr::UnsafeCellDeref;
|
||||
#[cfg(feature = "track_location")]
|
||||
use core::panic::Location;
|
||||
use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr};
|
||||
use thiserror::Error;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic::Ordering;
|
||||
#[cfg(feature = "track_location")]
|
||||
use {bevy_ptr::UnsafeCellDeref, core::panic::Location};
|
||||
|
||||
/// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid
|
||||
/// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.
|
||||
|
@ -47,11 +47,19 @@ std = [
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = ["bevy_app/critical-section", "bevy_ecs/critical-section"]
|
||||
critical-section = [
|
||||
"bevy_app/critical-section",
|
||||
"bevy_ecs/critical-section",
|
||||
"bevy_reflect?/critical-section",
|
||||
]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = ["bevy_app/portable-atomic", "bevy_ecs/portable-atomic"]
|
||||
portable-atomic = [
|
||||
"bevy_app/portable-atomic",
|
||||
"bevy_ecs/portable-atomic",
|
||||
"bevy_reflect?/portable-atomic",
|
||||
]
|
||||
|
||||
## Uses the `libm` maths library instead of the one provided in `std` and `core`.
|
||||
libm = ["bevy_math/libm"]
|
||||
|
@ -278,6 +278,7 @@ bevy_log = { path = "../bevy_log", version = "0.16.0-dev" }
|
||||
bevy_math = { path = "../bevy_math", version = "0.16.0-dev", features = [
|
||||
"bevy_reflect",
|
||||
] }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev" }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [
|
||||
"bevy",
|
||||
|
@ -46,6 +46,7 @@ pub use bevy_math as math;
|
||||
pub use bevy_pbr as pbr;
|
||||
#[cfg(feature = "bevy_picking")]
|
||||
pub use bevy_picking as picking;
|
||||
pub use bevy_platform_support as platform_support;
|
||||
pub use bevy_ptr as ptr;
|
||||
pub use bevy_reflect as reflect;
|
||||
#[cfg(feature = "bevy_remote")]
|
||||
|
@ -26,6 +26,9 @@ bevy_time = { path = "../bevy_time", version = "0.16.0-dev" }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.16.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
|
||||
# other
|
||||
crossbeam-channel = { version = "0.5", optional = true }
|
||||
|
@ -41,9 +41,10 @@ use core::{fmt::Debug, time::Duration};
|
||||
|
||||
use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_platform_support::time::Instant;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::camera::NormalizedRenderTarget;
|
||||
use bevy_utils::{HashMap, Instant};
|
||||
use bevy_utils::HashMap;
|
||||
use bevy_window::Window;
|
||||
use tracing::debug;
|
||||
|
||||
|
52
crates/bevy_platform_support/Cargo.toml
Normal file
52
crates/bevy_platform_support/Cargo.toml
Normal file
@ -0,0 +1,52 @@
|
||||
[package]
|
||||
name = "bevy_platform_support"
|
||||
version = "0.16.0-dev"
|
||||
edition = "2021"
|
||||
description = "Platform compatibility support for Bevy Engine"
|
||||
homepage = "https://bevyengine.org"
|
||||
repository = "https://github.com/bevyengine/bevy"
|
||||
license = "MIT OR Apache-2.0"
|
||||
keywords = ["bevy"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
||||
# Platform Compatibility
|
||||
|
||||
## Allows access to the `std` crate. Enabling this feature will prevent compilation
|
||||
## on `no_std` targets, but provides access to certain additional features on
|
||||
## supported platforms.
|
||||
std = [
|
||||
"alloc",
|
||||
"critical-section?/std",
|
||||
"portable-atomic?/std",
|
||||
"portable-atomic-util?/std",
|
||||
]
|
||||
|
||||
alloc = ["portable-atomic-util?/alloc"]
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = ["dep:critical-section", "portable-atomic?/critical-section"]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = ["dep:portable-atomic", "dep:portable-atomic-util"]
|
||||
|
||||
[dependencies]
|
||||
critical-section = { version = "1.2.0", default-features = false, optional = true }
|
||||
portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
], optional = true }
|
||||
portable-atomic-util = { version = "0.2.4", default-features = false, optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
web-time = { version = "1.1", default-features = false }
|
||||
getrandom = { version = "0.2.0", default-features = false, features = ["js"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["-Zunstable-options", "--generate-link-to-definition"]
|
||||
all-features = true
|
56
crates/bevy_platform_support/README.md
Normal file
56
crates/bevy_platform_support/README.md
Normal file
@ -0,0 +1,56 @@
|
||||
# Bevy Platform Support
|
||||
|
||||
[](https://github.com/bevyengine/bevy#license)
|
||||
[](https://crates.io/crates/bevy_platform_support)
|
||||
[](https://crates.io/crates/bevy_platform_support)
|
||||
[](https://docs.rs/bevy_platform_support/latest/bevy_platform_support/)
|
||||
[](https://discord.gg/bevy)
|
||||
|
||||
Rust is a fantastic multi-platform language with extensive support for modern targets through its [standard library](https://doc.rust-lang.org/stable/std/).
|
||||
However, some items within the standard library have alternatives that are better suited for [Bevy](https://crates.io/crates/bevy) and game engines in general.
|
||||
Additionally, to support embedded and other esoteric platforms, it's often necessary to shed reliance on `std`, making your crate [`no_std`](https://docs.rust-embedded.org/book/intro/no-std.html).
|
||||
|
||||
These needs are handled by this crate, `bevy_platform_support`.
|
||||
The goal of this crate is to provide alternatives and extensions to the Rust standard library which minimize friction when developing with and for Bevy across multiple platforms.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Like any dependency from [crates.io](https://crates.io/), use `cargo` to add it to your `Cargo.toml` file:
|
||||
|
||||
```sh
|
||||
cargo add bevy_platform_support
|
||||
```
|
||||
|
||||
Now, instead of importing from `std` you can use `bevy_platform_support` for items it has alternative for.
|
||||
See the documentation for what items are available, and explanations for _why_ you may want to use them.
|
||||
|
||||
## `no_std` Support
|
||||
|
||||
By default, `bevy_platform_support` will activate the `std` feature, requiring access to the `std` crate for whichever platforms you're targeting.
|
||||
To use this crate on `no_std` platforms, disable default features:
|
||||
|
||||
```toml
|
||||
bevy_platform_support = { version = "x.y.z", default-features = false }
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### `std` (_default_)
|
||||
|
||||
Enables usage of the standard library. Note that where this crate has alternatives to the standard library that it considers _better_ than what's provided, it will provide the alternative even when `std` is enabled.
|
||||
This is explicitly incompatible with `no_std` targets.
|
||||
|
||||
### `alloc` (_default_)
|
||||
|
||||
Enables usage of the [`alloc`](https://doc.rust-lang.org/stable/alloc/) crate. Note that this feature is automatically enabled when enabling `std`.
|
||||
This is compatible with most `no_std` targets, but not all.
|
||||
|
||||
### `portable-atomic`
|
||||
|
||||
Switches to using [`portable-atomic`](https://docs.rs/portable-atomic/latest/portable_atomic/) as a backend for atomic types, such as `Arc`, `AtomicU8`, etc.
|
||||
You may need to enable this feature on platforms without full support for atomic types or certain operations, such as [atomic CAS](https://en.wikipedia.org/wiki/Compare-and-swap).
|
||||
|
||||
### `critical-section`
|
||||
|
||||
Switches to using [`critical-section`](https://docs.rs/critical-section/latest/critical_section/) as a backend for synchronization.
|
||||
You may need to enable this feature on platforms with little to no support for atomic operations, and is often paired with the `portable-atomic` feature.
|
19
crates/bevy_platform_support/src/lib.rs
Normal file
19
crates/bevy_platform_support/src/lib.rs
Normal file
@ -0,0 +1,19 @@
|
||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc(
|
||||
html_logo_url = "https://bevyengine.org/assets/icon.png",
|
||||
html_favicon_url = "https://bevyengine.org/assets/icon.png"
|
||||
)]
|
||||
#![no_std]
|
||||
|
||||
//! Platform compatibility support for first-party [Bevy] engine crates.
|
||||
//!
|
||||
//! [Bevy]: https://bevyengine.org/
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
|
||||
pub mod sync;
|
||||
pub mod time;
|
30
crates/bevy_platform_support/src/sync.rs
Normal file
30
crates/bevy_platform_support/src/sync.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//! Provides various synchronization alternatives to language primitives.
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use arc::{Arc, Weak};
|
||||
|
||||
pub mod atomic {
|
||||
//! Provides various atomic alternatives to language primitives.
|
||||
//!
|
||||
//! Certain platforms lack complete atomic support, requiring the use of a fallback
|
||||
//! such as `portable-atomic`.
|
||||
//! Using these types will ensure the correct atomic provider is used without the need for
|
||||
//! feature gates in your own code.
|
||||
|
||||
pub use atomic::{
|
||||
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
|
||||
AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic as atomic;
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "alloc", feature = "portable-atomic"))]
|
||||
use portable_atomic_util as arc;
|
||||
|
||||
#[cfg(all(feature = "alloc", not(feature = "portable-atomic")))]
|
||||
use alloc::sync as arc;
|
194
crates/bevy_platform_support/src/time.rs
Normal file
194
crates/bevy_platform_support/src/time.rs
Normal file
@ -0,0 +1,194 @@
|
||||
//! Provides `Instant` for all platforms.
|
||||
|
||||
pub use time::Instant;
|
||||
|
||||
// TODO: Create a `web` feature to enable WASI compatibility.
|
||||
// See https://github.com/bevyengine/bevy/issues/4906
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use web_time as time;
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
|
||||
use std::time;
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
|
||||
use fallback as time;
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), not(feature = "std")))]
|
||||
mod fallback {
|
||||
//! Provides a fallback implementation of `Instant` from the standard library.
|
||||
|
||||
#![expect(
|
||||
unsafe_code,
|
||||
reason = "Instant fallback requires unsafe to allow users to update the internal value"
|
||||
)]
|
||||
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||
|
||||
use core::{
|
||||
fmt,
|
||||
ops::{Add, AddAssign, Sub, SubAssign},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
static ELAPSED_GETTER: AtomicPtr<fn() -> Duration> = AtomicPtr::new(unset_getter as *mut _);
|
||||
|
||||
/// Fallback implementation of `Instant` suitable for a `no_std` environment.
|
||||
///
|
||||
/// If you are on any of the following target architectures, this is a drop-in replacement:
|
||||
///
|
||||
/// - `x86`
|
||||
/// - `x86_64`
|
||||
/// - `aarch64`
|
||||
///
|
||||
/// On any other architecture, you must call [`Instant::set_elapsed`], providing a method
|
||||
/// which when called supplies a monotonically increasing count of elapsed nanoseconds relative
|
||||
/// to some arbitrary point in time.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Instant(Duration);
|
||||
|
||||
impl Instant {
|
||||
/// Returns an instant corresponding to "now".
|
||||
#[must_use]
|
||||
pub fn now() -> Instant {
|
||||
let getter = ELAPSED_GETTER.load(Ordering::Acquire);
|
||||
|
||||
// SAFETY: Function pointer is always valid
|
||||
let getter = unsafe { *getter };
|
||||
|
||||
Self((getter)())
|
||||
}
|
||||
|
||||
/// Provides a function returning the amount of time that has elapsed since execution began.
|
||||
/// The getter provided to this method will be used by [`now`](Instant::now).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The function provided must accurately represent the elapsed time.
|
||||
/// - The function must preserve all invariants of the [`Instant`] type.
|
||||
/// - The pointer to the function must be valid whenever [`Instant::now`] is called.
|
||||
pub unsafe fn set_elapsed(getter: *mut fn() -> Duration) {
|
||||
ELAPSED_GETTER.store(getter, Ordering::Release);
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or zero duration if that instant is later than this one.
|
||||
#[must_use]
|
||||
pub fn duration_since(&self, earlier: Instant) -> Duration {
|
||||
self.saturating_duration_since(earlier)
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or None if that instant is later than this one.
|
||||
///
|
||||
/// Due to monotonicity bugs, even under correct logical ordering of the passed `Instant`s,
|
||||
/// this method can return `None`.
|
||||
#[must_use]
|
||||
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
|
||||
self.0.checked_sub(earlier.0)
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or zero duration if that instant is later than this one.
|
||||
#[must_use]
|
||||
pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
|
||||
self.0.saturating_sub(earlier.0)
|
||||
}
|
||||
|
||||
/// Returns the amount of time elapsed since this instant.
|
||||
#[must_use]
|
||||
pub fn elapsed(&self) -> Duration {
|
||||
self.saturating_duration_since(Instant::now())
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
|
||||
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
|
||||
self.0.checked_add(duration).map(Instant)
|
||||
}
|
||||
|
||||
/// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
|
||||
/// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
|
||||
self.0.checked_sub(duration).map(Instant)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Duration> for Instant {
|
||||
type Output = Instant;
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// This function may panic if the resulting point in time cannot be represented by the
|
||||
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
|
||||
fn add(self, other: Duration) -> Instant {
|
||||
self.checked_add(other)
|
||||
.expect("overflow when adding duration to instant")
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Duration> for Instant {
|
||||
fn add_assign(&mut self, other: Duration) {
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Duration> for Instant {
|
||||
type Output = Instant;
|
||||
|
||||
fn sub(self, other: Duration) -> Instant {
|
||||
self.checked_sub(other)
|
||||
.expect("overflow when subtracting duration from instant")
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<Duration> for Instant {
|
||||
fn sub_assign(&mut self, other: Duration) {
|
||||
*self = *self - other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Instant> for Instant {
|
||||
type Output = Duration;
|
||||
|
||||
/// Returns the amount of time elapsed from another instant to this one,
|
||||
/// or zero duration if that instant is later than this one.
|
||||
fn sub(self, other: Instant) -> Duration {
|
||||
self.duration_since(other)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Instant {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn unset_getter() -> Duration {
|
||||
let _nanos: u64;
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
unsafe {
|
||||
_nanos = core::arch::x86::_rdtsc();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
_nanos = core::arch::x86_64::_rdtsc();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
unsafe {
|
||||
let mut ticks: u64;
|
||||
core::arch::asm!("mrs {}, cntvct_el0", out(reg) ticks);
|
||||
_nanos = ticks;
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))]
|
||||
panic!("An elapsed time getter has not been provided to `Instant`. Please use `Instant::set_elapsed(...)` before calling `Instant::now()`");
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))]
|
||||
return Duration::from_nanos(_nanos);
|
||||
}
|
||||
}
|
@ -11,6 +11,48 @@ rust-version = "1.81.0"
|
||||
|
||||
[features]
|
||||
default = ["std", "smallvec", "debug"]
|
||||
|
||||
# Features
|
||||
|
||||
## When enabled, allows documentation comments to be accessed via reflection
|
||||
documentation = ["bevy_reflect_derive/documentation"]
|
||||
|
||||
## Enables function reflection
|
||||
functions = ["bevy_reflect_derive/functions"]
|
||||
|
||||
# When enabled, provides Bevy-related reflection implementations
|
||||
bevy = ["smallvec", "smol_str"]
|
||||
|
||||
# Debugging Features
|
||||
|
||||
## Enables features useful for debugging reflection
|
||||
debug = ["debug_stack"]
|
||||
|
||||
## When enabled, keeps track of the current serialization/deserialization context for better error messages
|
||||
debug_stack = []
|
||||
|
||||
# Integrations
|
||||
|
||||
## Adds reflection support to `glam` types.
|
||||
glam = ["dep:glam"]
|
||||
|
||||
## Adds reflection support to `petgraph` types.
|
||||
petgraph = ["dep:petgraph", "std"]
|
||||
|
||||
## Adds reflection support to `smallvec` types.
|
||||
smallvec = ["dep:smallvec"]
|
||||
|
||||
## Adds reflection support to `uuid` types.
|
||||
uuid = ["dep:uuid"]
|
||||
|
||||
## Adds reflection support to `wgpu-types` types.
|
||||
wgpu-types = ["dep:wgpu-types", "std"]
|
||||
|
||||
# Platform Compatibility
|
||||
|
||||
## Allows access to the `std` crate. Enabling this feature will prevent compilation
|
||||
## on `no_std` targets, but provides access to certain additional features on
|
||||
## supported platforms.
|
||||
std = [
|
||||
"bevy_utils/std",
|
||||
"erased-serde/std",
|
||||
@ -20,22 +62,23 @@ std = [
|
||||
"glam?/std",
|
||||
"smol_str?/std",
|
||||
"uuid?/std",
|
||||
"bevy_platform_support/std",
|
||||
]
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = [
|
||||
"bevy_platform_support/critical-section",
|
||||
"bevy_utils/critical-section",
|
||||
]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = [
|
||||
"bevy_platform_support/portable-atomic",
|
||||
"spin/portable_atomic",
|
||||
"bevy_utils/portable-atomic",
|
||||
]
|
||||
# When enabled, provides Bevy-related reflection implementations
|
||||
bevy = ["smallvec", "smol_str"]
|
||||
glam = ["dep:glam"]
|
||||
petgraph = ["dep:petgraph", "std"]
|
||||
smallvec = ["dep:smallvec"]
|
||||
uuid = ["dep:uuid"]
|
||||
wgpu-types = ["dep:wgpu-types", "std"]
|
||||
# Enables features useful for debugging reflection
|
||||
debug = ["debug_stack"]
|
||||
# When enabled, keeps track of the current serialization/deserialization context for better error messages
|
||||
debug_stack = []
|
||||
# When enabled, allows documentation comments to be accessed via reflection
|
||||
documentation = ["bevy_reflect_derive/documentation"]
|
||||
# Enables function reflection
|
||||
functions = ["bevy_reflect_derive/functions"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
@ -44,6 +87,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev", default-features
|
||||
"alloc",
|
||||
] }
|
||||
bevy_ptr = { path = "../bevy_ptr", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
|
||||
# used by bevy-utils, but it also needs reflect impls
|
||||
foldhash = { version = "0.1.3", default-features = false }
|
||||
@ -62,7 +108,6 @@ spin = { version = "0.9.8", default-features = false, features = [
|
||||
"rwlock",
|
||||
] }
|
||||
assert_type_match = "0.1.1"
|
||||
|
||||
smallvec = { version = "1.11", default-features = false, optional = true }
|
||||
glam = { version = "0.29", default-features = false, features = [
|
||||
"serde",
|
||||
|
@ -4,7 +4,8 @@ use crate::{
|
||||
type_info::impl_type_methods,
|
||||
DynamicEnum, Generics, PartialReflect, Type, TypePath, VariantInfo, VariantType,
|
||||
};
|
||||
use alloc::{boxed::Box, format, string::String, sync::Arc};
|
||||
use alloc::{boxed::Box, format, string::String};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_utils::HashMap;
|
||||
use core::slice::Iter;
|
||||
|
||||
|
@ -3,7 +3,7 @@ use crate::{
|
||||
NamedField, UnnamedField,
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::sync::Arc;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_utils::HashMap;
|
||||
use core::slice::Iter;
|
||||
use thiserror::Error;
|
||||
|
@ -3,7 +3,7 @@ use crate::{
|
||||
type_info::impl_type_methods,
|
||||
MaybeTyped, PartialReflect, Type, TypeInfo, TypePath,
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
|
||||
/// The named field of a reflected struct.
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -11,7 +11,8 @@ use crate::{
|
||||
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||
ReflectRef, TypeInfo, TypePath,
|
||||
};
|
||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
||||
use alloc::{borrow::Cow, boxed::Box};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_reflect_derive::impl_type_path;
|
||||
use core::fmt::{Debug, Formatter};
|
||||
|
||||
@ -92,8 +93,21 @@ impl<'env> DynamicFunction<'env> {
|
||||
func: F,
|
||||
info: impl TryInto<FunctionInfo, Error: Debug>,
|
||||
) -> Self {
|
||||
let arc = Arc::new(func);
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
#[expect(
|
||||
unsafe_code,
|
||||
reason = "unsized coercion is an unstable feature for non-std types"
|
||||
)]
|
||||
// SAFETY:
|
||||
// - Coercion from `T` to `dyn for<'a> Fn(ArgList<'a>) -> FunctionResult<'a> + Send + Sync + 'env`
|
||||
// is valid as `T: for<'a> Fn(ArgList<'a>) -> FunctionResult<'a> + Send + Sync + 'env`
|
||||
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
|
||||
let arc = unsafe { ArcFn::<'env>::from_raw(Arc::into_raw(arc) as *const _) };
|
||||
|
||||
Self {
|
||||
internal: DynamicFunctionInternal::new(Arc::new(func), info.try_into().unwrap()),
|
||||
internal: DynamicFunctionInternal::new(arc, info.try_into().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
||||
use alloc::{borrow::Cow, boxed::Box};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use core::fmt::{Debug, Formatter};
|
||||
|
||||
use crate::func::{
|
||||
|
@ -1,9 +1,9 @@
|
||||
use alloc::{borrow::Cow, sync::Arc};
|
||||
use alloc::borrow::Cow;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_utils::HashMap;
|
||||
use core::fmt::Debug;
|
||||
use std::sync::{PoisonError, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use bevy_utils::HashMap;
|
||||
|
||||
use crate::func::{
|
||||
ArgList, DynamicFunction, FunctionRegistrationError, FunctionResult, IntoFunction,
|
||||
};
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::type_info::impl_type_methods;
|
||||
use crate::{Reflect, Type, TypePath};
|
||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc};
|
||||
use alloc::{borrow::Cow, boxed::Box};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use core::ops::Deref;
|
||||
use derive_more::derive::From;
|
||||
|
||||
@ -180,7 +181,19 @@ impl ConstParamInfo {
|
||||
|
||||
/// Sets the default value for the parameter.
|
||||
pub fn with_default<T: Reflect + 'static>(mut self, default: T) -> Self {
|
||||
self.default = Some(Arc::new(default));
|
||||
let arc = Arc::new(default);
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
#[expect(
|
||||
unsafe_code,
|
||||
reason = "unsized coercion is an unstable feature for non-std types"
|
||||
)]
|
||||
// SAFETY:
|
||||
// - Coercion from `T` to `dyn Reflect` is valid as `T: Reflect + 'static`
|
||||
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
|
||||
let arc = unsafe { Arc::from_raw(Arc::into_raw(arc) as *const dyn Reflect) };
|
||||
|
||||
self.default = Some(arc);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,9 @@ impl_reflect_opaque!(::core::time::Duration(
|
||||
Default
|
||||
));
|
||||
#[cfg(any(target_arch = "wasm32", feature = "std"))]
|
||||
impl_reflect_opaque!(::bevy_utils::Instant(Debug, Hash, PartialEq));
|
||||
impl_reflect_opaque!(::bevy_platform_support::time::Instant(
|
||||
Debug, Hash, PartialEq
|
||||
));
|
||||
impl_reflect_opaque!(::core::num::NonZeroI128(
|
||||
Debug,
|
||||
Hash,
|
||||
@ -214,6 +216,11 @@ impl_reflect_opaque!(::core::num::NonZeroI8(
|
||||
));
|
||||
impl_reflect_opaque!(::core::num::Wrapping<T: Clone + Send + Sync>());
|
||||
impl_reflect_opaque!(::core::num::Saturating<T: Clone + Send + Sync>());
|
||||
impl_reflect_opaque!(::bevy_platform_support::sync::Arc<T: Send + Sync + ?Sized>);
|
||||
|
||||
// We check despite `portable-atomic` being enabled, if the standard library `Arc` is
|
||||
// also available, and implement Reflect for it.
|
||||
#[cfg(all(feature = "portable-atomic", target_has_atomic = "ptr"))]
|
||||
impl_reflect_opaque!(::alloc::sync::Arc<T: Send + Sync + ?Sized>);
|
||||
|
||||
// `Serialize` and `Deserialize` only for platforms supported by serde:
|
||||
@ -2432,7 +2439,8 @@ mod tests {
|
||||
TypeInfo, TypeRegistry, Typed, VariantInfo, VariantType,
|
||||
};
|
||||
use alloc::{collections::BTreeMap, string::String, vec};
|
||||
use bevy_utils::{HashMap, Instant};
|
||||
use bevy_platform_support::time::Instant;
|
||||
use bevy_utils::HashMap;
|
||||
use core::{
|
||||
f32::consts::{PI, TAU},
|
||||
time::Duration,
|
||||
|
@ -189,7 +189,8 @@ mod tests {
|
||||
use crate::serde::{DeserializeWithRegistry, ReflectDeserializeWithRegistry};
|
||||
use crate::serde::{ReflectSerializeWithRegistry, SerializeWithRegistry};
|
||||
use crate::{ReflectFromReflect, TypePath};
|
||||
use alloc::{format, string::String, sync::Arc, vec, vec::Vec};
|
||||
use alloc::{format, string::String, vec, vec::Vec};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_reflect_derive::reflect_trait;
|
||||
use core::any::TypeId;
|
||||
use core::fmt::{Debug, Formatter};
|
||||
@ -336,6 +337,22 @@ mod tests {
|
||||
registry
|
||||
}
|
||||
|
||||
fn create_arc_dyn_enemy<T: Enemy>(enemy: T) -> Arc<dyn Enemy> {
|
||||
let arc = Arc::new(enemy);
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
#[expect(
|
||||
unsafe_code,
|
||||
reason = "unsized coercion is an unstable feature for non-std types"
|
||||
)]
|
||||
// SAFETY:
|
||||
// - Coercion from `T` to `dyn Enemy` is valid as `T: Enemy + 'static`
|
||||
// - `Arc::from_raw` receives a valid pointer from a previous call to `Arc::into_raw`
|
||||
let arc = unsafe { Arc::from_raw(Arc::into_raw(arc) as *const dyn Enemy) };
|
||||
|
||||
arc
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_serialize_with_serialize_with_registry() {
|
||||
let registry = create_registry();
|
||||
@ -343,8 +360,8 @@ mod tests {
|
||||
let level = Level {
|
||||
name: String::from("Level 1"),
|
||||
enemies: EnemyList(vec![
|
||||
Arc::new(Skeleton(10)),
|
||||
Arc::new(Zombie {
|
||||
create_arc_dyn_enemy(Skeleton(10)),
|
||||
create_arc_dyn_enemy(Zombie {
|
||||
health: 20,
|
||||
walk_speed: 0.5,
|
||||
}),
|
||||
@ -374,8 +391,8 @@ mod tests {
|
||||
let expected = Level {
|
||||
name: String::from("Level 1"),
|
||||
enemies: EnemyList(vec![
|
||||
Arc::new(Skeleton(10)),
|
||||
Arc::new(Zombie {
|
||||
create_arc_dyn_enemy(Skeleton(10)),
|
||||
create_arc_dyn_enemy(Zombie {
|
||||
health: 20,
|
||||
walk_speed: 0.5,
|
||||
}),
|
||||
@ -388,8 +405,8 @@ mod tests {
|
||||
let unexpected = Level {
|
||||
name: String::from("Level 1"),
|
||||
enemies: EnemyList(vec![
|
||||
Arc::new(Skeleton(20)),
|
||||
Arc::new(Zombie {
|
||||
create_arc_dyn_enemy(Skeleton(20)),
|
||||
create_arc_dyn_enemy(Zombie {
|
||||
health: 20,
|
||||
walk_speed: 5.0,
|
||||
}),
|
||||
|
@ -6,7 +6,8 @@ use crate::{
|
||||
ApplyError, Generics, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, Type, TypeInfo, TypePath,
|
||||
};
|
||||
use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloc::{borrow::Cow, boxed::Box, vec::Vec};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_reflect_derive::impl_type_path;
|
||||
use bevy_utils::HashMap;
|
||||
use core::{
|
||||
|
@ -8,7 +8,8 @@ use crate::{
|
||||
ApplyError, DynamicTuple, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField,
|
||||
};
|
||||
use alloc::{boxed::Box, sync::Arc, vec::Vec};
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use core::{
|
||||
fmt::{Debug, Formatter},
|
||||
slice::Iter,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{boxed::Box, string::String};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use bevy_ptr::{Ptr, PtrMut};
|
||||
use bevy_utils::{HashMap, HashSet, TypeIdMap};
|
||||
use core::{
|
||||
|
@ -56,6 +56,9 @@ bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
||||
bevy_image = { path = "../bevy_image", version = "0.16.0-dev" }
|
||||
bevy_mesh = { path = "../bevy_mesh", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
|
||||
# rendering
|
||||
image = { version = "0.25.2", default-features = false }
|
||||
|
@ -7,7 +7,7 @@ use std::thread::{self, ThreadId};
|
||||
|
||||
use bevy_diagnostic::{Diagnostic, DiagnosticMeasurement, DiagnosticPath, DiagnosticsStore};
|
||||
use bevy_ecs::system::{Res, ResMut, Resource};
|
||||
use bevy_utils::Instant;
|
||||
use bevy_platform_support::time::Instant;
|
||||
use std::sync::Mutex;
|
||||
use wgpu::{
|
||||
Buffer, BufferDescriptor, BufferUsages, CommandEncoder, ComputePass, Features, MapMode,
|
||||
|
@ -18,8 +18,8 @@ use crate::{
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
use bevy_ecs::{prelude::*, system::SystemState};
|
||||
use bevy_platform_support::time::Instant;
|
||||
use bevy_time::TimeSender;
|
||||
use bevy_utils::Instant;
|
||||
use wgpu::{
|
||||
Adapter, AdapterInfo, CommandBuffer, CommandEncoder, DeviceType, Instance, Queue,
|
||||
RequestAdapterOptions,
|
||||
|
@ -36,6 +36,7 @@ critical-section = [
|
||||
"bevy_ecs/critical-section",
|
||||
"bevy_utils/critical-section",
|
||||
"bevy_app?/critical-section",
|
||||
"bevy_reflect?/critical-section",
|
||||
]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
@ -44,6 +45,7 @@ portable-atomic = [
|
||||
"bevy_ecs/portable-atomic",
|
||||
"bevy_utils/portable-atomic",
|
||||
"bevy_app?/portable-atomic",
|
||||
"bevy_reflect?/portable-atomic",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
|
@ -15,25 +15,27 @@ std = [
|
||||
"async-task/std",
|
||||
"spin/std",
|
||||
"edge-executor?/std",
|
||||
"portable-atomic-util?/std",
|
||||
"bevy_platform_support/std",
|
||||
]
|
||||
multi_threaded = ["std", "dep:async-channel", "dep:concurrent-queue"]
|
||||
async_executor = ["std", "dep:async-executor"]
|
||||
edge_executor = ["dep:edge-executor"]
|
||||
critical-section = [
|
||||
"dep:critical-section",
|
||||
"bevy_platform_support/critical-section",
|
||||
"edge-executor?/critical-section",
|
||||
"portable-atomic?/critical-section",
|
||||
]
|
||||
portable-atomic = [
|
||||
"dep:portable-atomic",
|
||||
"dep:portable-atomic-util",
|
||||
"bevy_platform_support/portable-atomic",
|
||||
"edge-executor?/portable-atomic",
|
||||
"async-task/portable-atomic",
|
||||
"spin/portable_atomic",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
|
||||
futures-lite = { version = "2.0.1", default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
@ -53,13 +55,6 @@ edge-executor = { version = "0.4.1", default-features = false, optional = true }
|
||||
async-channel = { version = "2.3.0", optional = true }
|
||||
async-io = { version = "2.0.0", optional = true }
|
||||
concurrent-queue = { version = "2.0.0", optional = true }
|
||||
critical-section = { version = "1.2.0", optional = true }
|
||||
portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
], optional = true }
|
||||
portable-atomic-util = { version = "0.2.4", features = [
|
||||
"alloc",
|
||||
], optional = true }
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
wasm-bindgen-futures = "0.4"
|
||||
|
@ -1,4 +1,5 @@
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use core::{cell::RefCell, future::Future, marker::PhantomData, mem};
|
||||
|
||||
use crate::Task;
|
||||
@ -6,12 +7,6 @@ use crate::Task;
|
||||
#[cfg(feature = "std")]
|
||||
use std::thread_local;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
|
||||
#[cfg(all(
|
||||
feature = "std",
|
||||
any(feature = "async_executor", feature = "edge_executor")
|
||||
|
@ -6,15 +6,10 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::executor::FallibleTask;
|
||||
use bevy_platform_support::sync::Arc;
|
||||
use concurrent_queue::ConcurrentQueue;
|
||||
use futures_lite::FutureExt;
|
||||
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic_util::Arc;
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
block_on,
|
||||
thread_executor::{ThreadExecutor, ThreadExecutorTicker},
|
||||
|
@ -21,7 +21,9 @@ bevy_ecs = { path = "../bevy_ecs", version = "0.16.0-dev", features = [
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev", features = [
|
||||
"bevy",
|
||||
], optional = true }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
|
||||
# other
|
||||
crossbeam-channel = "0.5.0"
|
||||
|
@ -35,7 +35,7 @@ use bevy_ecs::{
|
||||
event::{event_update_system, signal_event_update_system, EventRegistry, ShouldUpdateEvents},
|
||||
prelude::*,
|
||||
};
|
||||
use bevy_utils::Instant;
|
||||
use bevy_platform_support::time::Instant;
|
||||
use core::time::Duration;
|
||||
pub use crossbeam_channel::TrySendError;
|
||||
use crossbeam_channel::{Receiver, Sender};
|
||||
|
@ -1,6 +1,6 @@
|
||||
use bevy_platform_support::time::Instant;
|
||||
#[cfg(feature = "bevy_reflect")]
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::Instant;
|
||||
use core::time::Duration;
|
||||
|
||||
use crate::time::Time;
|
||||
|
@ -160,7 +160,7 @@ use {
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # use bevy_time::prelude::*;
|
||||
/// # use bevy_utils::Instant;
|
||||
/// # use bevy_platform_support::time::Instant;
|
||||
/// #
|
||||
/// #[derive(Debug)]
|
||||
/// struct Custom {
|
||||
|
@ -21,37 +21,32 @@ serde = ["hashbrown/serde"]
|
||||
## Allows access to the `std` crate. Enabling this feature will prevent compilation
|
||||
## on `no_std` targets, but provides access to certain additional features on
|
||||
## supported platforms.
|
||||
std = ["alloc", "foldhash/std", "dep:thread_local"]
|
||||
std = ["alloc", "bevy_platform_support/std", "foldhash/std", "dep:thread_local"]
|
||||
|
||||
## Allows access to the `alloc` crate.
|
||||
alloc = ["hashbrown"]
|
||||
alloc = ["bevy_platform_support/alloc", "hashbrown"]
|
||||
|
||||
## `critical-section` provides the building blocks for synchronization primitives
|
||||
## on all platforms, including `no_std`.
|
||||
critical-section = ["portable-atomic?/critical-section"]
|
||||
critical-section = ["bevy_platform_support/critical-section"]
|
||||
|
||||
## `portable-atomic` provides additional platform support for atomic types and
|
||||
## operations, even on targets without native support.
|
||||
portable-atomic = ["dep:portable-atomic"]
|
||||
portable-atomic = ["bevy_platform_support/portable-atomic"]
|
||||
|
||||
[dependencies]
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false }
|
||||
|
||||
foldhash = { version = "0.1.3", default-features = false }
|
||||
hashbrown = { version = "0.15.1", features = [
|
||||
"equivalent",
|
||||
"raw-entry",
|
||||
], optional = true, default-features = false }
|
||||
thread_local = { version = "1.0", optional = true }
|
||||
portable-atomic = { version = "1", default-features = false, features = [
|
||||
"fallback",
|
||||
], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
static_assertions = "1.1.0"
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.2.0", features = ["js"] }
|
||||
web-time = { version = "1.1" }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
|
@ -29,7 +29,6 @@ mod default;
|
||||
mod once;
|
||||
#[cfg(feature = "std")]
|
||||
mod parallel_queue;
|
||||
mod time;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use once::OnceFlag;
|
||||
@ -59,8 +58,6 @@ pub use foldhash::fast::{FixedState, FoldHasher as DefaultHasher, RandomState};
|
||||
pub use hashbrown;
|
||||
#[cfg(feature = "std")]
|
||||
pub use parallel_queue::*;
|
||||
#[cfg(any(feature = "std", target_arch = "wasm32"))]
|
||||
pub use time::*;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use core::any::TypeId;
|
||||
|
@ -1,8 +1,4 @@
|
||||
#[cfg(feature = "portable-atomic")]
|
||||
use portable_atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[cfg(not(feature = "portable-atomic"))]
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use bevy_platform_support::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
/// Wrapper around an [`AtomicBool`], abstracting the backing implementation and
|
||||
/// ordering considerations.
|
||||
|
@ -1,5 +0,0 @@
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use web_time::Instant;
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
|
||||
pub use std::time::Instant;
|
@ -34,6 +34,9 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.16.0-dev" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.16.0-dev" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.16.0-dev" }
|
||||
bevy_tasks = { path = "../bevy_tasks", version = "0.16.0-dev" }
|
||||
bevy_platform_support = { path = "../bevy_platform_support", version = "0.16.0-dev", default-features = false, features = [
|
||||
"std",
|
||||
] }
|
||||
|
||||
# bevy optional
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.16.0-dev", optional = true }
|
||||
|
@ -20,11 +20,11 @@ use bevy_log::{error, trace, warn};
|
||||
#[cfg(feature = "custom_cursor")]
|
||||
use bevy_math::URect;
|
||||
use bevy_math::{ivec2, DVec2, Vec2};
|
||||
use bevy_platform_support::time::Instant;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use bevy_tasks::tick_global_task_pools_on_main_thread;
|
||||
#[cfg(feature = "custom_cursor")]
|
||||
use bevy_utils::HashMap;
|
||||
use bevy_utils::Instant;
|
||||
use core::marker::PhantomData;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use winit::platform::web::EventLoopExtWebSys;
|
||||
|
@ -1,5 +1,6 @@
|
||||
# if crate A depends on crate B, B must come before A in this list
|
||||
crates=(
|
||||
bevy_platform_support
|
||||
bevy_utils
|
||||
bevy_ptr
|
||||
bevy_macro_utils
|
||||
|
Loading…
Reference in New Issue
Block a user