mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
MVP no_std for wgpu (#7747)
Co-authored-by: Andreas Reich <1220815+Wumpf@users.noreply.github.com>
This commit is contained in:
parent
e10bceb1dc
commit
e72c4d8326
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -300,11 +300,13 @@ jobs:
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu-types --no-default-features
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p naga --no-default-features
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu-hal --no-default-features
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu --no-default-features
|
||||
|
||||
# Check with all compatible features
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu-types --no-default-features --features strict_asserts,fragile-send-sync-non-atomic-wasm,serde,counters
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p naga --no-default-features --features dot-out,compact
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu-hal --no-default-features --features fragile-send-sync-non-atomic-wasm
|
||||
cargo clippy --target ${{ matrix.target }} ${{ matrix.extra-flags }} -p wgpu --no-default-features --features serde
|
||||
|
||||
# Building for native platforms with standard tests.
|
||||
- name: Check native
|
||||
|
||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4760,6 +4760,7 @@ dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 2.9.1",
|
||||
"bytemuck",
|
||||
"cfg-if",
|
||||
"cfg_aliases 0.2.1",
|
||||
"document-features",
|
||||
"hashbrown",
|
||||
|
||||
@ -29,7 +29,16 @@ ignored = ["cfg_aliases"]
|
||||
[lib]
|
||||
|
||||
[features]
|
||||
default = ["dx12", "metal", "gles", "vulkan", "wgsl", "webgpu"]
|
||||
default = [
|
||||
"std",
|
||||
"parking_lot",
|
||||
"dx12",
|
||||
"metal",
|
||||
"gles",
|
||||
"vulkan",
|
||||
"wgsl",
|
||||
"webgpu",
|
||||
]
|
||||
|
||||
#! ### Backends
|
||||
# --------------------------------------------------------------------
|
||||
@ -155,6 +164,19 @@ fragile-send-sync-non-atomic-wasm = [
|
||||
## context around the WASM VM, e.g., when the WASM binary is used in a browser.
|
||||
web = ["dep:wasm-bindgen", "dep:js-sys", "dep:web-sys", "wgpu-types/web"]
|
||||
|
||||
## Enables use of the standard library within `wgpu` and its dependencies.
|
||||
##
|
||||
## This can allow for better error reporting and for improved multithreading
|
||||
## support.
|
||||
std = ["raw-window-handle/std", "wgpu-types/std", "wgpu-core?/std"]
|
||||
|
||||
## Uses `parking_lot` as the implementation for locking primitives.
|
||||
##
|
||||
## This is a recommended feature for most users and should only be disabled when
|
||||
## required, e.g., for `no_std` support.
|
||||
## If disabled, either `std::sync::Mutex` or `core::cell::RefCell` will be used,
|
||||
## based on whether `std` is enabled or not.
|
||||
parking_lot = ["dep:parking_lot"]
|
||||
|
||||
#########################
|
||||
# Standard Dependencies #
|
||||
@ -168,12 +190,13 @@ wgpu-types.workspace = true
|
||||
# Needed for both wgpu-core and webgpu
|
||||
arrayvec.workspace = true
|
||||
bitflags.workspace = true
|
||||
cfg-if.workspace = true
|
||||
document-features.workspace = true
|
||||
hashbrown.workspace = true
|
||||
log.workspace = true
|
||||
parking_lot.workspace = true
|
||||
parking_lot = { workspace = true, optional = true }
|
||||
profiling.workspace = true
|
||||
raw-window-handle = { workspace = true, features = ["std"] }
|
||||
raw-window-handle = { workspace = true, features = ["alloc"] }
|
||||
static_assertions.workspace = true
|
||||
|
||||
########################################
|
||||
|
||||
@ -47,6 +47,16 @@ fn main() {
|
||||
// ⚠️ Keep in sync with target.cfg() definition in wgpu-hal/Cargo.toml and cfg_alias in `wgpu-hal` crate ⚠️
|
||||
static_dxc: { all(target_os = "windows", feature = "static-dxc", not(target_arch = "aarch64")) },
|
||||
supports_64bit_atomics: { target_has_atomic = "64" },
|
||||
custom: {any(feature = "custom")}
|
||||
custom: {any(feature = "custom")},
|
||||
std: { any(
|
||||
feature = "std",
|
||||
// TODO: Remove this when an alternative Mutex implementation is available for `no_std`.
|
||||
// send_sync requires an appropriate Mutex implementation, which is only currently
|
||||
// possible with `std` enabled.
|
||||
send_sync,
|
||||
// Unwinding panics necessitate access to `std` to determine if a thread is panicking
|
||||
panic = "unwind"
|
||||
) },
|
||||
no_std: { not(std) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,7 @@ use core::{
|
||||
ops::{Bound, Deref, DerefMut, Range, RangeBounds},
|
||||
};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use crate::util::Mutex;
|
||||
use crate::*;
|
||||
|
||||
/// Handle to a GPU-accessible buffer.
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
use alloc::{boxed::Box, string::String, sync::Arc};
|
||||
use core::{error, fmt, future::Future};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use crate::api::blas::{Blas, BlasGeometrySizeDescriptors, CreateBlasDescriptor};
|
||||
use crate::api::tlas::{CreateTlasDescriptor, Tlas};
|
||||
use crate::util::Mutex;
|
||||
use crate::*;
|
||||
|
||||
/// Open connection to a graphics and/or compute device.
|
||||
|
||||
@ -2,9 +2,7 @@
|
||||
use alloc::vec::Vec;
|
||||
use core::future::Future;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use crate::{dispatch::InstanceInterface, *};
|
||||
use crate::{dispatch::InstanceInterface, util::Mutex, *};
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// WGSL language extensions.
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use alloc::{boxed::Box, string::String, vec, vec::Vec};
|
||||
use core::{error, fmt};
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||
|
||||
use crate::util::Mutex;
|
||||
use crate::*;
|
||||
|
||||
/// Describes a [`Surface`].
|
||||
@ -413,7 +413,10 @@ impl error::Error for CreateSurfaceError {
|
||||
#[cfg(wgpu_core)]
|
||||
CreateSurfaceErrorKind::Hal(e) => e.source(),
|
||||
CreateSurfaceErrorKind::Web(_) => None,
|
||||
#[cfg(feature = "std")]
|
||||
CreateSurfaceErrorKind::RawHandle(e) => e.source(),
|
||||
#[cfg(not(feature = "std"))]
|
||||
CreateSurfaceErrorKind::RawHandle(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
use core::{error, fmt};
|
||||
use std::thread;
|
||||
|
||||
use crate::*;
|
||||
|
||||
@ -48,7 +47,7 @@ impl SurfaceTexture {
|
||||
|
||||
impl Drop for SurfaceTexture {
|
||||
fn drop(&mut self) {
|
||||
if !self.presented && !thread::panicking() {
|
||||
if !self.presented && !thread_panicking() {
|
||||
self.detail.texture_discard();
|
||||
}
|
||||
}
|
||||
@ -83,3 +82,22 @@ impl fmt::Display for SurfaceError {
|
||||
}
|
||||
|
||||
impl error::Error for SurfaceError {}
|
||||
|
||||
fn thread_panicking() -> bool {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(std)] {
|
||||
std::thread::panicking()
|
||||
} else if #[cfg(panic = "abort")] {
|
||||
// If `panic = "abort"` then a thread _cannot_ be observably panicking by definition.
|
||||
false
|
||||
} else {
|
||||
// TODO: This is potentially overly pessimistic; it may be appropriate to instead allow a
|
||||
// texture to not be discarded.
|
||||
// Alternatively, this could _also_ be a `panic!`, since we only care if the thread is panicking
|
||||
// when the surface has not been presented.
|
||||
compile_error!(
|
||||
"cannot determine if a thread is panicking without either `panic = \"abort\"` or `std`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,11 +10,11 @@ use alloc::{
|
||||
use core::{error::Error, fmt, future::ready, ops::Range, pin::Pin, ptr::NonNull, slice};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use parking_lot::Mutex;
|
||||
use smallvec::SmallVec;
|
||||
use wgc::{command::bundle_ffi::*, error::ContextErrorSource, pipeline::CreateShaderModuleError};
|
||||
use wgt::WasmNotSendSync;
|
||||
|
||||
use crate::util::Mutex;
|
||||
use crate::{
|
||||
api,
|
||||
dispatch::{self, BufferMappedRangeInterface},
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#![cfg_attr(not(any(wgpu_core, webgpu)), allow(unused))]
|
||||
|
||||
extern crate alloc;
|
||||
#[cfg(std)]
|
||||
extern crate std;
|
||||
#[cfg(wgpu_core)]
|
||||
pub extern crate wgpu_core as wgc;
|
||||
|
||||
@ -9,10 +9,16 @@ pub fn initialize_adapter_from_env(
|
||||
instance: &Instance,
|
||||
compatible_surface: Option<&Surface<'_>>,
|
||||
) -> Result<Adapter, wgt::RequestAdapterError> {
|
||||
let desired_adapter_name = std::env::var("WGPU_ADAPTER_NAME")
|
||||
.as_deref()
|
||||
.map(str::to_lowercase)
|
||||
.map_err(|_| wgt::RequestAdapterError::EnvNotSet)?;
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(std)] {
|
||||
let desired_adapter_name = std::env::var("WGPU_ADAPTER_NAME")
|
||||
.as_deref()
|
||||
.map(str::to_lowercase)
|
||||
.map_err(|_| wgt::RequestAdapterError::EnvNotSet)?;
|
||||
} else {
|
||||
return Err(wgt::RequestAdapterError::EnvNotSet);
|
||||
}
|
||||
}
|
||||
|
||||
let adapters = instance.enumerate_adapters(crate::Backends::all());
|
||||
|
||||
|
||||
@ -3,15 +3,20 @@
|
||||
//! Nothing in this module is a part of the WebGPU API specification;
|
||||
//! they are unique to the `wgpu` library.
|
||||
|
||||
// TODO: For [`belt::StagingBelt`] to be available in `no_std` its usage of [`std::sync::mpsc`]
|
||||
// must be replaced with an appropriate alternative.
|
||||
#[cfg(std)]
|
||||
mod belt;
|
||||
mod device;
|
||||
mod encoder;
|
||||
mod init;
|
||||
mod mutex;
|
||||
mod texture_blitter;
|
||||
|
||||
use alloc::{borrow::Cow, format, string::String, vec};
|
||||
use core::ptr::copy_nonoverlapping;
|
||||
|
||||
#[cfg(std)]
|
||||
pub use belt::StagingBelt;
|
||||
pub use device::{BufferInitDescriptor, DeviceExt};
|
||||
pub use encoder::RenderEncoder;
|
||||
@ -22,6 +27,8 @@ pub use wgt::{
|
||||
math::*, DispatchIndirectArgs, DrawIndexedIndirectArgs, DrawIndirectArgs, TextureDataOrder,
|
||||
};
|
||||
|
||||
pub(crate) use mutex::Mutex;
|
||||
|
||||
use crate::dispatch;
|
||||
|
||||
/// Treat the given byte slice as a SPIR-V module.
|
||||
|
||||
60
wgpu/src/util/mutex.rs
Normal file
60
wgpu/src/util/mutex.rs
Normal file
@ -0,0 +1,60 @@
|
||||
//! Provides a [`Mutex`] for internal use based on what features are available.
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "parking_lot")] {
|
||||
use parking_lot::Mutex as MutexInner;
|
||||
} else if #[cfg(std)] {
|
||||
use std::sync::Mutex as MutexInner;
|
||||
} else {
|
||||
use core::cell::RefCell as MutexInner;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Mutex<T: ?Sized> {
|
||||
inner: MutexInner<T>,
|
||||
}
|
||||
|
||||
impl<T: ?Sized> core::fmt::Debug for Mutex<T>
|
||||
where
|
||||
MutexInner<T>: core::fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
<MutexInner<T> as core::fmt::Debug>::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for Mutex<T> {
|
||||
fn default() -> Self {
|
||||
Self::new(<T as Default>::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
pub const fn new(value: T) -> Self {
|
||||
Self {
|
||||
inner: MutexInner::new(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Mutex<T> {
|
||||
pub fn lock(&self) -> impl core::ops::DerefMut<Target = T> + '_ {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "parking_lot")] {
|
||||
self.inner.lock()
|
||||
} else if #[cfg(std)] {
|
||||
self.inner.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
} else {
|
||||
loop {
|
||||
let Ok(lock) = self.inner.try_borrow_mut() else {
|
||||
// Without `std` all we can do is spin until the current lock is released
|
||||
core::hint::spin_loop();
|
||||
continue;
|
||||
};
|
||||
|
||||
break lock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user