mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Don't implement Send or Sync on Wasm (#3691)
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
This commit is contained in:
parent
7c34cc86e8
commit
88f18ed190
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -138,6 +138,7 @@ jobs:
|
||||
set -e
|
||||
|
||||
# build for WebGPU
|
||||
cargo clippy --target ${{ matrix.target }} --tests --features glsl,spirv,fragile-send-sync-non-atomic-wasm
|
||||
cargo clippy --target ${{ matrix.target }} --tests --features glsl,spirv
|
||||
cargo doc --target ${{ matrix.target }} --no-deps --features glsl,spirv
|
||||
|
||||
|
||||
@ -68,6 +68,7 @@ Bottom level categories:
|
||||
- Document feature requirements for `DEPTH32FLOAT_STENCIL8` by @ErichDonGubler in [#3734](https://github.com/gfx-rs/wgpu/pull/3734).
|
||||
- Flesh out docs. for `AdapterInfo::{device,vendor}` by @ErichDonGubler in [#3763](https://github.com/gfx-rs/wgpu/pull/3763).
|
||||
- Spell out which sizes are in bytes. By @jimblandy in [#3773](https://github.com/gfx-rs/wgpu/pull/3773).
|
||||
- On Web, types don't implement `Send` or `Sync` anymore. By @daxpedda in [#3691](https://github.com/gfx-rs/wgpu/pull/3691)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
@ -51,6 +51,8 @@ serial-pass = ["serde", "wgt/serde", "arrayvec/serde"]
|
||||
id32 = []
|
||||
# Enable `ShaderModuleSource::Wgsl`
|
||||
wgsl = ["naga/wgsl-in"]
|
||||
# Implement `Send` and `Sync` on Wasm.
|
||||
fragile-send-sync-non-atomic-wasm = ["hal/fragile-send-sync-non-atomic-wasm", "wgt/fragile-send-sync-non-atomic-wasm"]
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.7"
|
||||
|
||||
@ -746,7 +746,21 @@ pub struct RenderBundle<A: HalApi> {
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl<A: HalApi> Send for RenderBundle<A> {}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl<A: HalApi> Sync for RenderBundle<A> {}
|
||||
|
||||
impl<A: HalApi> RenderBundle<A> {
|
||||
|
||||
@ -37,6 +37,13 @@ pub struct SubmittedWorkDoneClosureC {
|
||||
pub user_data: *mut u8,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl Send for SubmittedWorkDoneClosureC {}
|
||||
|
||||
pub struct SubmittedWorkDoneClosure {
|
||||
@ -45,17 +52,30 @@ pub struct SubmittedWorkDoneClosure {
|
||||
inner: SubmittedWorkDoneClosureInner,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
type SubmittedWorkDoneCallback = Box<dyn FnOnce() + Send + 'static>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
type SubmittedWorkDoneCallback = Box<dyn FnOnce() + 'static>;
|
||||
|
||||
enum SubmittedWorkDoneClosureInner {
|
||||
Rust {
|
||||
callback: Box<dyn FnOnce() + Send + 'static>,
|
||||
},
|
||||
C {
|
||||
inner: SubmittedWorkDoneClosureC,
|
||||
},
|
||||
Rust { callback: SubmittedWorkDoneCallback },
|
||||
C { inner: SubmittedWorkDoneClosureC },
|
||||
}
|
||||
|
||||
impl SubmittedWorkDoneClosure {
|
||||
pub fn from_rust(callback: Box<dyn FnOnce() + Send + 'static>) -> Self {
|
||||
pub fn from_rust(callback: SubmittedWorkDoneCallback) -> Self {
|
||||
Self {
|
||||
inner: SubmittedWorkDoneClosureInner::Rust { callback },
|
||||
}
|
||||
|
||||
@ -162,7 +162,22 @@ pub fn format_pretty_any(
|
||||
#[derive(Debug)]
|
||||
pub struct ContextError {
|
||||
pub string: &'static str,
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub cause: Box<dyn Error + Send + Sync + 'static>,
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub cause: Box<dyn Error + 'static>,
|
||||
pub label_key: &'static str,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
@ -155,7 +155,16 @@ impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(all(
|
||||
test,
|
||||
any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)
|
||||
))]
|
||||
fn _test_send_sync(global: &Global<crate::identity::IdentityManagerFactory>) {
|
||||
fn test_internal<T: Send + Sync>(_: T) {}
|
||||
test_internal(global)
|
||||
|
||||
@ -79,7 +79,21 @@ pub(crate) enum BufferMapState<A: hal::Api> {
|
||||
Idle,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl<A: hal::Api> Send for BufferMapState<A> {}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl<A: hal::Api> Sync for BufferMapState<A> {}
|
||||
|
||||
#[repr(C)]
|
||||
@ -88,6 +102,13 @@ pub struct BufferMapCallbackC {
|
||||
pub user_data: *mut u8,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl Send for BufferMapCallbackC {}
|
||||
|
||||
pub struct BufferMapCallback {
|
||||
@ -96,17 +117,30 @@ pub struct BufferMapCallback {
|
||||
inner: Option<BufferMapCallbackInner>,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
type BufferMapCallbackCallback = Box<dyn FnOnce(BufferAccessResult) + Send + 'static>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
type BufferMapCallbackCallback = Box<dyn FnOnce(BufferAccessResult) + 'static>;
|
||||
|
||||
enum BufferMapCallbackInner {
|
||||
Rust {
|
||||
callback: Box<dyn FnOnce(BufferAccessResult) + Send + 'static>,
|
||||
},
|
||||
C {
|
||||
inner: BufferMapCallbackC,
|
||||
},
|
||||
Rust { callback: BufferMapCallbackCallback },
|
||||
C { inner: BufferMapCallbackC },
|
||||
}
|
||||
|
||||
impl BufferMapCallback {
|
||||
pub fn from_rust(callback: Box<dyn FnOnce(BufferAccessResult) + Send + 'static>) -> Self {
|
||||
pub fn from_rust(callback: BufferMapCallbackCallback) -> Self {
|
||||
Self {
|
||||
inner: Some(BufferMapCallbackInner::Rust { callback }),
|
||||
}
|
||||
|
||||
@ -43,6 +43,7 @@ dx12 = ["naga/hlsl-out", "d3d12", "bit-set", "range-alloc", "winapi/std", "winap
|
||||
windows_rs = ["gpu-allocator"]
|
||||
dxc_shader_compiler = ["hassle-rs"]
|
||||
renderdoc = ["libloading", "renderdoc-sys"]
|
||||
fragile-send-sync-non-atomic-wasm = ["wgt/fragile-send-sync-non-atomic-wasm"]
|
||||
link = ["metal/link"]
|
||||
|
||||
[[example]]
|
||||
|
||||
@ -936,10 +936,17 @@ impl super::AdapterShared {
|
||||
}
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for super::Adapter {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for super::Adapter {}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1321,8 +1321,15 @@ impl crate::Device<super::Api> for super::Device {
|
||||
}
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for super::Device {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for super::Device {}
|
||||
|
||||
@ -246,10 +246,17 @@ pub struct Buffer {
|
||||
data: Option<Arc<std::sync::Mutex<Vec<u8>>>>,
|
||||
}
|
||||
|
||||
// Safe: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for Buffer {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for Buffer {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -268,11 +275,18 @@ pub enum TextureInner {
|
||||
},
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
unsafe impl Send for TextureInner {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for TextureInner {}
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for TextureInner {}
|
||||
|
||||
impl TextureInner {
|
||||
fn as_native(&self) -> (glow::Texture, BindTarget) {
|
||||
@ -462,10 +476,17 @@ struct UniformDesc {
|
||||
utype: u32,
|
||||
}
|
||||
|
||||
// Safe: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for UniformDesc {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for UniformDesc {}
|
||||
|
||||
/// For each texture in the pipeline layout, store the index of the only
|
||||
@ -530,21 +551,35 @@ pub struct RenderPipeline {
|
||||
alpha_to_coverage_enabled: bool,
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
unsafe impl Send for RenderPipeline {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for RenderPipeline {}
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for RenderPipeline {}
|
||||
|
||||
pub struct ComputePipeline {
|
||||
inner: Arc<PipelineInner>,
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
unsafe impl Send for ComputePipeline {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for ComputePipeline {}
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for ComputePipeline {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct QuerySet {
|
||||
@ -558,7 +593,21 @@ pub struct Fence {
|
||||
pending: Vec<(crate::FenceValue, glow::Fence)>,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl Send for Fence {}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl Sync for Fence {}
|
||||
|
||||
impl Fence {
|
||||
|
||||
@ -1525,8 +1525,15 @@ impl crate::Queue<super::Api> for super::Queue {
|
||||
}
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for super::Queue {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for super::Queue {}
|
||||
|
||||
@ -106,8 +106,15 @@ impl Instance {
|
||||
}
|
||||
}
|
||||
|
||||
// SAFE: Wasm doesn't have threads
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for Instance {}
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for Instance {}
|
||||
|
||||
impl crate::Instance<super::Api> for Instance {
|
||||
@ -171,16 +178,23 @@ pub struct Surface {
|
||||
srgb_present_program: Option<glow::Program>,
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for Surface {}
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for Surface {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum Canvas {
|
||||
Canvas(web_sys::HtmlCanvasElement),
|
||||
Offscreen(web_sys::OffscreenCanvas),
|
||||
}
|
||||
|
||||
// SAFE: Because web doesn't have threads ( yet )
|
||||
unsafe impl Sync for Surface {}
|
||||
unsafe impl Send for Surface {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Swapchain {
|
||||
pub(crate) extent: wgt::Extent3d,
|
||||
|
||||
@ -95,6 +95,7 @@ use std::{
|
||||
|
||||
use bitflags::bitflags;
|
||||
use thiserror::Error;
|
||||
use wgt::{WasmNotSend, WasmNotSync};
|
||||
|
||||
pub const MAX_ANISOTROPY: u8 = 16;
|
||||
pub const MAX_BIND_GROUPS: usize = 8;
|
||||
@ -161,25 +162,25 @@ pub trait Api: Clone + Sized {
|
||||
|
||||
type Queue: Queue<Self>;
|
||||
type CommandEncoder: CommandEncoder<Self>;
|
||||
type CommandBuffer: Send + Sync + fmt::Debug;
|
||||
type CommandBuffer: WasmNotSend + WasmNotSync + fmt::Debug;
|
||||
|
||||
type Buffer: fmt::Debug + Send + Sync + 'static;
|
||||
type Texture: fmt::Debug + Send + Sync + 'static;
|
||||
type SurfaceTexture: fmt::Debug + Send + Sync + Borrow<Self::Texture>;
|
||||
type TextureView: fmt::Debug + Send + Sync;
|
||||
type Sampler: fmt::Debug + Send + Sync;
|
||||
type QuerySet: fmt::Debug + Send + Sync;
|
||||
type Fence: fmt::Debug + Send + Sync;
|
||||
type Buffer: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
|
||||
type Texture: fmt::Debug + WasmNotSend + WasmNotSync + 'static;
|
||||
type SurfaceTexture: fmt::Debug + WasmNotSend + WasmNotSync + Borrow<Self::Texture>;
|
||||
type TextureView: fmt::Debug + WasmNotSend + WasmNotSync;
|
||||
type Sampler: fmt::Debug + WasmNotSend + WasmNotSync;
|
||||
type QuerySet: fmt::Debug + WasmNotSend + WasmNotSync;
|
||||
type Fence: fmt::Debug + WasmNotSend + WasmNotSync;
|
||||
|
||||
type BindGroupLayout: Send + Sync;
|
||||
type BindGroup: fmt::Debug + Send + Sync;
|
||||
type PipelineLayout: Send + Sync;
|
||||
type ShaderModule: fmt::Debug + Send + Sync;
|
||||
type RenderPipeline: Send + Sync;
|
||||
type ComputePipeline: Send + Sync;
|
||||
type BindGroupLayout: WasmNotSend + WasmNotSync;
|
||||
type BindGroup: fmt::Debug + WasmNotSend + WasmNotSync;
|
||||
type PipelineLayout: WasmNotSend + WasmNotSync;
|
||||
type ShaderModule: fmt::Debug + WasmNotSend + WasmNotSync;
|
||||
type RenderPipeline: WasmNotSend + WasmNotSync;
|
||||
type ComputePipeline: WasmNotSend + WasmNotSync;
|
||||
}
|
||||
|
||||
pub trait Instance<A: Api>: Sized + Send + Sync {
|
||||
pub trait Instance<A: Api>: Sized + WasmNotSend + WasmNotSync {
|
||||
unsafe fn init(desc: &InstanceDescriptor) -> Result<Self, InstanceError>;
|
||||
unsafe fn create_surface(
|
||||
&self,
|
||||
@ -190,7 +191,7 @@ pub trait Instance<A: Api>: Sized + Send + Sync {
|
||||
unsafe fn enumerate_adapters(&self) -> Vec<ExposedAdapter<A>>;
|
||||
}
|
||||
|
||||
pub trait Surface<A: Api>: Send + Sync {
|
||||
pub trait Surface<A: Api>: WasmNotSend + WasmNotSync {
|
||||
unsafe fn configure(
|
||||
&mut self,
|
||||
device: &A::Device,
|
||||
@ -216,7 +217,7 @@ pub trait Surface<A: Api>: Send + Sync {
|
||||
unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture);
|
||||
}
|
||||
|
||||
pub trait Adapter<A: Api>: Send + Sync {
|
||||
pub trait Adapter<A: Api>: WasmNotSend + WasmNotSync {
|
||||
unsafe fn open(
|
||||
&self,
|
||||
features: wgt::Features,
|
||||
@ -240,7 +241,7 @@ pub trait Adapter<A: Api>: Send + Sync {
|
||||
unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp;
|
||||
}
|
||||
|
||||
pub trait Device<A: Api>: Send + Sync {
|
||||
pub trait Device<A: Api>: WasmNotSend + WasmNotSync {
|
||||
/// Exit connection to this logical device.
|
||||
unsafe fn exit(self, queue: A::Queue);
|
||||
/// Creates a new buffer.
|
||||
@ -336,7 +337,7 @@ pub trait Device<A: Api>: Send + Sync {
|
||||
unsafe fn stop_capture(&self);
|
||||
}
|
||||
|
||||
pub trait Queue<A: Api>: Send + Sync {
|
||||
pub trait Queue<A: Api>: WasmNotSend + WasmNotSync {
|
||||
/// Submits the command buffers for execution on GPU.
|
||||
///
|
||||
/// Valid usage:
|
||||
@ -360,7 +361,7 @@ pub trait Queue<A: Api>: Send + Sync {
|
||||
/// Serves as a parent for all the encoded command buffers.
|
||||
/// Works in bursts of action: one or more command buffers are recorded,
|
||||
/// then submitted to a queue, and then it needs to be `reset_all()`.
|
||||
pub trait CommandEncoder<A: Api>: Send + Sync + fmt::Debug {
|
||||
pub trait CommandEncoder<A: Api>: WasmNotSend + WasmNotSync + fmt::Debug {
|
||||
/// Begin encoding a new command buffer.
|
||||
unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>;
|
||||
/// Discard currently recorded list, if any.
|
||||
|
||||
@ -25,6 +25,7 @@ targets = [
|
||||
trace = ["serde"]
|
||||
replay = ["serde"]
|
||||
strict_asserts = []
|
||||
fragile-send-sync-non-atomic-wasm = []
|
||||
|
||||
[dependencies]
|
||||
bitflags = "2"
|
||||
|
||||
@ -5917,9 +5917,17 @@ impl std::ops::Deref for ExternalImageSource {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for ExternalImageSource {}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(all(
|
||||
target_arch = "wasm32",
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for ExternalImageSource {}
|
||||
|
||||
/// Color spaces supported on the web.
|
||||
@ -6317,3 +6325,74 @@ impl Default for InstanceDescriptor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use send_sync::*;
|
||||
|
||||
#[doc(hidden)]
|
||||
mod send_sync {
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub trait WasmNotSend: Send {}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
impl<T: Send> WasmNotSend for T {}
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub trait WasmNotSend {}
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
impl<T> WasmNotSend for T {}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub trait WasmNotSync: Sync {}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
impl<T: Sync> WasmNotSync for T {}
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub trait WasmNotSync {}
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
impl<T> WasmNotSync for T {}
|
||||
}
|
||||
|
||||
@ -38,6 +38,8 @@ angle = ["wgc/angle"]
|
||||
webgl = ["hal", "wgc"]
|
||||
vulkan-portability = ["wgc/vulkan"]
|
||||
expose-ids = []
|
||||
# Implement `Send` and `Sync` on Wasm.
|
||||
fragile-send-sync-non-atomic-wasm = ["hal/fragile-send-sync-non-atomic-wasm", "wgc/fragile-send-sync-non-atomic-wasm", "wgt/fragile-send-sync-non-atomic-wasm"]
|
||||
|
||||
# wgpu-core is always available as an optional dependency, "wgc".
|
||||
# Whenever wgpu-core is selected, we want the GLES backend and raw
|
||||
|
||||
@ -23,6 +23,7 @@ use std::{
|
||||
};
|
||||
use wgc::command::{bundle_ffi::*, compute_ffi::*, render_ffi::*};
|
||||
use wgc::id::TypedId;
|
||||
use wgt::{WasmNotSend, WasmNotSync};
|
||||
|
||||
const LABEL: &str = "label";
|
||||
|
||||
@ -263,7 +264,7 @@ impl Context {
|
||||
fn handle_error(
|
||||
&self,
|
||||
sink_mutex: &Mutex<ErrorSinkRaw>,
|
||||
cause: impl Error + Send + Sync + 'static,
|
||||
cause: impl Error + WasmNotSend + WasmNotSync + 'static,
|
||||
label_key: &'static str,
|
||||
label: Label,
|
||||
string: &'static str,
|
||||
@ -297,7 +298,7 @@ impl Context {
|
||||
fn handle_error_nolabel(
|
||||
&self,
|
||||
sink_mutex: &Mutex<ErrorSinkRaw>,
|
||||
cause: impl Error + Send + Sync + 'static,
|
||||
cause: impl Error + WasmNotSend + WasmNotSync + 'static,
|
||||
string: &'static str,
|
||||
) {
|
||||
self.handle_error(sink_mutex, cause, "", None, string)
|
||||
@ -306,7 +307,7 @@ impl Context {
|
||||
#[track_caller]
|
||||
fn handle_error_fatal(
|
||||
&self,
|
||||
cause: impl Error + Send + Sync + 'static,
|
||||
cause: impl Error + WasmNotSend + WasmNotSync + 'static,
|
||||
operation: &'static str,
|
||||
) -> ! {
|
||||
panic!("Error in {operation}: {f}", f = self.format_error(&cause));
|
||||
@ -1467,7 +1468,7 @@ impl crate::Context for Context {
|
||||
buffer_data: &Self::BufferData,
|
||||
mode: MapMode,
|
||||
range: Range<wgt::BufferAddress>,
|
||||
callback: Box<dyn FnOnce(Result<(), crate::BufferAsyncError>) + Send + 'static>,
|
||||
callback: crate::context::BufferMapCallback,
|
||||
) {
|
||||
let operation = wgc::resource::BufferMapOperation {
|
||||
host: match mode {
|
||||
@ -2279,7 +2280,7 @@ impl crate::Context for Context {
|
||||
&self,
|
||||
queue: &Self::QueueId,
|
||||
_queue_data: &Self::QueueData,
|
||||
callback: Box<dyn FnOnce() + Send + 'static>,
|
||||
callback: crate::context::SubmittedWorkDoneCallback,
|
||||
) {
|
||||
let closure = wgc::device::queue::SubmittedWorkDoneClosure::from_rust(callback);
|
||||
|
||||
@ -3051,7 +3052,21 @@ pub struct BufferMappedRange {
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl Send for BufferMappedRange {}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
unsafe impl Sync for BufferMappedRange {}
|
||||
|
||||
impl crate::context::BufferMappedRange for BufferMappedRange {
|
||||
|
||||
@ -65,7 +65,15 @@ impl<T> From<Identified<T>> for ObjectId {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Sendable<T>(T);
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl<T> Send for Sendable<T> {}
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl<T> Sync for Sendable<T> {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -73,11 +81,27 @@ pub(crate) struct Identified<T>(
|
||||
#[cfg(feature = "expose-ids")] std::num::NonZeroU64,
|
||||
PhantomData<T>,
|
||||
);
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl<T> Send for Identified<T> {}
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl<T> Sync for Identified<T> {}
|
||||
|
||||
pub(crate) struct Context(web_sys::Gpu);
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Send for Context {}
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl Sync for Context {}
|
||||
|
||||
impl fmt::Debug for Context {
|
||||
@ -134,6 +158,10 @@ impl<F, M> MakeSendFuture<F, M> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
))]
|
||||
unsafe impl<F, M> Send for MakeSendFuture<F, M> {}
|
||||
|
||||
fn map_texture_format(texture_format: wgt::TextureFormat) -> web_sys::GpuTextureFormat {
|
||||
@ -1838,7 +1866,7 @@ impl crate::context::Context for Context {
|
||||
buffer_data: &Self::BufferData,
|
||||
mode: crate::MapMode,
|
||||
range: Range<wgt::BufferAddress>,
|
||||
callback: Box<dyn FnOnce(Result<(), crate::BufferAsyncError>) + Send + 'static>,
|
||||
callback: crate::context::BufferMapCallback,
|
||||
) {
|
||||
let map_promise = buffer_data.0.map_async_with_f64_and_f64(
|
||||
map_map_mode(mode),
|
||||
@ -2531,7 +2559,7 @@ impl crate::context::Context for Context {
|
||||
&self,
|
||||
_queue: &Self::QueueId,
|
||||
_queue_data: &Self::QueueData,
|
||||
_callback: Box<dyn FnOnce() + Send + 'static>,
|
||||
_callback: crate::context::SubmittedWorkDoneCallback,
|
||||
) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -4,13 +4,13 @@ use wgt::{
|
||||
strict_assert, strict_assert_eq, AdapterInfo, BufferAddress, BufferSize, Color,
|
||||
DownlevelCapabilities, DynamicOffset, Extent3d, Features, ImageDataLayout,
|
||||
ImageSubresourceRange, IndexFormat, Limits, ShaderStages, SurfaceStatus, TextureFormat,
|
||||
TextureFormatFeatures,
|
||||
TextureFormatFeatures, WasmNotSend, WasmNotSync,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, BufferAsyncError, BufferDescriptor,
|
||||
CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, DeviceDescriptor,
|
||||
Error, ErrorFilter, ImageCopyBuffer, ImageCopyTexture, Maintain, MapMode,
|
||||
AnyWasmNotSendSync, BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, BufferAsyncError,
|
||||
BufferDescriptor, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor,
|
||||
DeviceDescriptor, Error, ErrorFilter, ImageCopyBuffer, ImageCopyTexture, Maintain, MapMode,
|
||||
PipelineLayoutDescriptor, QuerySetDescriptor, RenderBundleDescriptor,
|
||||
RenderBundleEncoderDescriptor, RenderPassDescriptor, RenderPipelineDescriptor,
|
||||
RequestAdapterOptions, RequestDeviceError, SamplerDescriptor, ShaderModuleDescriptor,
|
||||
@ -27,59 +27,59 @@ impl<T: Into<ObjectId> + From<ObjectId> + Debug + 'static> ContextId for T {}
|
||||
/// Meta trait for an data associated with an id tracked by a context.
|
||||
///
|
||||
/// There is no need to manually implement this trait since there is a blanket implementation for this trait.
|
||||
pub trait ContextData: Debug + Send + Sync + 'static {}
|
||||
impl<T: Debug + Send + Sync + 'static> ContextData for T {}
|
||||
pub trait ContextData: Debug + WasmNotSend + WasmNotSync + 'static {}
|
||||
impl<T: Debug + WasmNotSend + WasmNotSync + 'static> ContextData for T {}
|
||||
|
||||
pub trait Context: Debug + Send + Sized + Sync {
|
||||
type AdapterId: ContextId + Send + Sync;
|
||||
pub trait Context: Debug + WasmNotSend + WasmNotSync + Sized {
|
||||
type AdapterId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type AdapterData: ContextData;
|
||||
type DeviceId: ContextId + Send + Sync;
|
||||
type DeviceId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type DeviceData: ContextData;
|
||||
type QueueId: ContextId + Send + Sync;
|
||||
type QueueId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type QueueData: ContextData;
|
||||
type ShaderModuleId: ContextId + Send + Sync;
|
||||
type ShaderModuleId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type ShaderModuleData: ContextData;
|
||||
type BindGroupLayoutId: ContextId + Send + Sync;
|
||||
type BindGroupLayoutId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type BindGroupLayoutData: ContextData;
|
||||
type BindGroupId: ContextId + Send + Sync;
|
||||
type BindGroupId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type BindGroupData: ContextData;
|
||||
type TextureViewId: ContextId + Send + Sync;
|
||||
type TextureViewId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type TextureViewData: ContextData;
|
||||
type SamplerId: ContextId + Send + Sync;
|
||||
type SamplerId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type SamplerData: ContextData;
|
||||
type BufferId: ContextId + Send + Sync;
|
||||
type BufferId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type BufferData: ContextData;
|
||||
type TextureId: ContextId + Send + Sync;
|
||||
type TextureId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type TextureData: ContextData;
|
||||
type QuerySetId: ContextId + Send + Sync;
|
||||
type QuerySetId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type QuerySetData: ContextData;
|
||||
type PipelineLayoutId: ContextId + Send + Sync;
|
||||
type PipelineLayoutId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type PipelineLayoutData: ContextData;
|
||||
type RenderPipelineId: ContextId + Send + Sync;
|
||||
type RenderPipelineId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type RenderPipelineData: ContextData;
|
||||
type ComputePipelineId: ContextId + Send + Sync;
|
||||
type ComputePipelineId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type ComputePipelineData: ContextData;
|
||||
type CommandEncoderId: ContextId + Send + Sync;
|
||||
type CommandEncoderId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type CommandEncoderData: ContextData;
|
||||
type ComputePassId: ContextId;
|
||||
type ComputePassData: ContextData;
|
||||
type RenderPassId: ContextId;
|
||||
type RenderPassData: ContextData;
|
||||
type CommandBufferId: ContextId + Send + Sync;
|
||||
type CommandBufferId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type CommandBufferData: ContextData;
|
||||
type RenderBundleEncoderId: ContextId;
|
||||
type RenderBundleEncoderData: ContextData;
|
||||
type RenderBundleId: ContextId + Send + Sync;
|
||||
type RenderBundleId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type RenderBundleData: ContextData;
|
||||
type SurfaceId: ContextId + Send + Sync;
|
||||
type SurfaceId: ContextId + WasmNotSend + WasmNotSync;
|
||||
type SurfaceData: ContextData;
|
||||
|
||||
type SurfaceOutputDetail: Send + Sync + 'static;
|
||||
type SubmissionIndex: ContextId + Clone + Copy + Send + Sync;
|
||||
type SurfaceOutputDetail: WasmNotSend + WasmNotSync + 'static;
|
||||
type SubmissionIndex: ContextId + Clone + Copy + WasmNotSend + WasmNotSync;
|
||||
type SubmissionIndexData: ContextData + Copy;
|
||||
|
||||
type RequestAdapterFuture: Future<Output = Option<(Self::AdapterId, Self::AdapterData)>>
|
||||
+ Send
|
||||
+ WasmNotSend
|
||||
+ 'static;
|
||||
type RequestDeviceFuture: Future<
|
||||
Output = Result<
|
||||
@ -91,9 +91,9 @@ pub trait Context: Debug + Send + Sized + Sync {
|
||||
),
|
||||
RequestDeviceError,
|
||||
>,
|
||||
> + Send
|
||||
> + WasmNotSend
|
||||
+ 'static;
|
||||
type PopErrorScopeFuture: Future<Output = Option<Error>> + Send + 'static;
|
||||
type PopErrorScopeFuture: Future<Output = Option<Error>> + WasmNotSend + 'static;
|
||||
|
||||
fn init(instance_desc: wgt::InstanceDescriptor) -> Self;
|
||||
fn instance_create_surface(
|
||||
@ -299,7 +299,7 @@ pub trait Context: Debug + Send + Sized + Sync {
|
||||
buffer_data: &Self::BufferData,
|
||||
mode: MapMode,
|
||||
range: Range<BufferAddress>,
|
||||
callback: Box<dyn FnOnce(Result<(), BufferAsyncError>) + Send + 'static>,
|
||||
callback: BufferMapCallback,
|
||||
);
|
||||
fn buffer_get_mapped_range(
|
||||
&self,
|
||||
@ -585,7 +585,7 @@ pub trait Context: Debug + Send + Sized + Sync {
|
||||
&self,
|
||||
queue: &Self::QueueId,
|
||||
queue_data: &Self::QueueData,
|
||||
callback: Box<dyn FnOnce() + Send + 'static>,
|
||||
callback: SubmittedWorkDoneCallback,
|
||||
);
|
||||
|
||||
fn device_start_capture(&self, device: &Self::DeviceId, device_data: &Self::DeviceData);
|
||||
@ -1039,15 +1039,24 @@ impl ObjectId {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ObjectId: Send, Sync);
|
||||
|
||||
pub(crate) fn downcast_ref<T: Debug + Send + Sync + 'static>(data: &crate::Data) -> &T {
|
||||
pub(crate) fn downcast_ref<T: Debug + WasmNotSend + WasmNotSync + 'static>(
|
||||
data: &crate::Data,
|
||||
) -> &T {
|
||||
strict_assert!(data.is::<T>());
|
||||
// Copied from std.
|
||||
unsafe { &*(data as *const dyn Any as *const T) }
|
||||
}
|
||||
|
||||
fn downcast_mut<T: Debug + Send + Sync + 'static>(data: &mut crate::Data) -> &mut T {
|
||||
fn downcast_mut<T: Debug + WasmNotSend + WasmNotSync + 'static>(data: &mut crate::Data) -> &mut T {
|
||||
strict_assert!(data.is::<T>());
|
||||
// Copied from std.
|
||||
unsafe { &mut *(data as *mut dyn Any as *mut T) }
|
||||
@ -1079,8 +1088,97 @@ pub(crate) struct DeviceRequest {
|
||||
pub queue_data: Box<crate::Data>,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub type BufferMapCallback = Box<dyn FnOnce(Result<(), BufferAsyncError>) + Send + 'static>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub type BufferMapCallback = Box<dyn FnOnce(Result<(), BufferAsyncError>) + 'static>;
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub(crate) type AdapterRequestDeviceFuture =
|
||||
Box<dyn Future<Output = Result<DeviceRequest, RequestDeviceError>> + Send>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub(crate) type AdapterRequestDeviceFuture =
|
||||
Box<dyn Future<Output = Result<DeviceRequest, RequestDeviceError>>>;
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub type InstanceRequestAdapterFuture =
|
||||
Box<dyn Future<Output = Option<(ObjectId, Box<crate::Data>)>> + Send>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub type InstanceRequestAdapterFuture =
|
||||
Box<dyn Future<Output = Option<(ObjectId, Box<crate::Data>)>>>;
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub type DevicePopErrorFuture = Box<dyn Future<Output = Option<Error>> + Send>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub type DevicePopErrorFuture = Box<dyn Future<Output = Option<Error>>>;
|
||||
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
pub type SubmittedWorkDoneCallback = Box<dyn FnOnce() + Send + 'static>;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
pub type SubmittedWorkDoneCallback = Box<dyn FnOnce() + 'static>;
|
||||
|
||||
/// An object safe variant of [`Context`] implemented by all types that implement [`Context`].
|
||||
pub(crate) trait DynContext: Debug + Send + Sync {
|
||||
pub(crate) trait DynContext: Debug + WasmNotSend + WasmNotSync {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
fn instance_create_surface(
|
||||
@ -1092,14 +1190,14 @@ pub(crate) trait DynContext: Debug + Send + Sync {
|
||||
fn instance_request_adapter(
|
||||
&self,
|
||||
options: &RequestAdapterOptions<'_>,
|
||||
) -> Pin<Box<dyn Future<Output = Option<(ObjectId, Box<crate::Data>)>> + Send>>;
|
||||
) -> Pin<InstanceRequestAdapterFuture>;
|
||||
fn adapter_request_device(
|
||||
&self,
|
||||
adapter: &ObjectId,
|
||||
adapter_data: &crate::Data,
|
||||
desc: &DeviceDescriptor,
|
||||
trace_dir: Option<&std::path::Path>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<DeviceRequest, RequestDeviceError>> + Send>>;
|
||||
) -> Pin<AdapterRequestDeviceFuture>;
|
||||
|
||||
fn instance_poll_all_devices(&self, force_wait: bool) -> bool;
|
||||
fn adapter_is_surface_supported(
|
||||
@ -1152,10 +1250,10 @@ pub(crate) trait DynContext: Debug + Send + Sync {
|
||||
Option<ObjectId>,
|
||||
Option<Box<crate::Data>>,
|
||||
SurfaceStatus,
|
||||
Box<dyn Any + Send + Sync>,
|
||||
Box<dyn AnyWasmNotSendSync>,
|
||||
);
|
||||
fn surface_present(&self, texture: &ObjectId, detail: &(dyn Any + Send + Sync));
|
||||
fn surface_texture_discard(&self, texture: &ObjectId, detail: &(dyn Any + Send + Sync));
|
||||
fn surface_present(&self, texture: &ObjectId, detail: &dyn AnyWasmNotSendSync);
|
||||
fn surface_texture_discard(&self, texture: &ObjectId, detail: &dyn AnyWasmNotSendSync);
|
||||
|
||||
fn device_features(&self, device: &ObjectId, device_data: &crate::Data) -> Features;
|
||||
fn device_limits(&self, device: &ObjectId, device_data: &crate::Data) -> Limits;
|
||||
@ -1262,14 +1360,14 @@ pub(crate) trait DynContext: Debug + Send + Sync {
|
||||
&self,
|
||||
device: &ObjectId,
|
||||
device_data: &crate::Data,
|
||||
) -> Pin<Box<dyn Future<Output = Option<Error>> + Send + 'static>>;
|
||||
) -> Pin<DevicePopErrorFuture>;
|
||||
fn buffer_map_async(
|
||||
&self,
|
||||
buffer: &ObjectId,
|
||||
buffer_data: &crate::Data,
|
||||
mode: MapMode,
|
||||
range: Range<BufferAddress>,
|
||||
callback: Box<dyn FnOnce(Result<(), BufferAsyncError>) + Send + 'static>,
|
||||
callback: BufferMapCallback,
|
||||
);
|
||||
fn buffer_get_mapped_range(
|
||||
&self,
|
||||
@ -1511,7 +1609,7 @@ pub(crate) trait DynContext: Debug + Send + Sync {
|
||||
&self,
|
||||
queue: &ObjectId,
|
||||
queue_data: &crate::Data,
|
||||
callback: Box<dyn FnOnce() + Send + 'static>,
|
||||
callback: SubmittedWorkDoneCallback,
|
||||
);
|
||||
|
||||
fn device_start_capture(&self, device: &ObjectId, data: &crate::Data);
|
||||
@ -1931,7 +2029,7 @@ where
|
||||
fn instance_request_adapter(
|
||||
&self,
|
||||
options: &RequestAdapterOptions<'_>,
|
||||
) -> Pin<Box<dyn Future<Output = Option<(ObjectId, Box<crate::Data>)>> + Send>> {
|
||||
) -> Pin<InstanceRequestAdapterFuture> {
|
||||
let future: T::RequestAdapterFuture = Context::instance_request_adapter(self, options);
|
||||
Box::pin(async move {
|
||||
let result: Option<(T::AdapterId, T::AdapterData)> = future.await;
|
||||
@ -1945,7 +2043,7 @@ where
|
||||
adapter_data: &crate::Data,
|
||||
desc: &DeviceDescriptor,
|
||||
trace_dir: Option<&std::path::Path>,
|
||||
) -> Pin<Box<dyn Future<Output = Result<DeviceRequest, RequestDeviceError>> + Send>> {
|
||||
) -> Pin<AdapterRequestDeviceFuture> {
|
||||
let adapter = <T::AdapterId>::from(*adapter);
|
||||
let adapter_data = downcast_ref(adapter_data);
|
||||
let future = Context::adapter_request_device(self, &adapter, adapter_data, desc, trace_dir);
|
||||
@ -2064,13 +2162,13 @@ where
|
||||
Option<ObjectId>,
|
||||
Option<Box<crate::Data>>,
|
||||
SurfaceStatus,
|
||||
Box<dyn Any + Send + Sync>,
|
||||
Box<dyn AnyWasmNotSendSync>,
|
||||
) {
|
||||
let surface = <T::SurfaceId>::from(*surface);
|
||||
let surface_data = downcast_ref(surface_data);
|
||||
let (texture, texture_data, status, detail) =
|
||||
Context::surface_get_current_texture(self, &surface, surface_data);
|
||||
let detail = Box::new(detail) as Box<dyn Any + Send + Sync>;
|
||||
let detail = Box::new(detail) as Box<dyn AnyWasmNotSendSync>;
|
||||
(
|
||||
texture.map(Into::into),
|
||||
texture_data.map(|b| Box::new(b) as _),
|
||||
@ -2079,12 +2177,12 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
fn surface_present(&self, texture: &ObjectId, detail: &(dyn Any + Send + Sync)) {
|
||||
fn surface_present(&self, texture: &ObjectId, detail: &dyn AnyWasmNotSendSync) {
|
||||
let texture = <T::TextureId>::from(*texture);
|
||||
Context::surface_present(self, &texture, detail.downcast_ref().unwrap())
|
||||
}
|
||||
|
||||
fn surface_texture_discard(&self, texture: &ObjectId, detail: &(dyn Any + Send + Sync)) {
|
||||
fn surface_texture_discard(&self, texture: &ObjectId, detail: &dyn AnyWasmNotSendSync) {
|
||||
let texture = <T::TextureId>::from(*texture);
|
||||
Context::surface_texture_discard(self, &texture, detail.downcast_ref().unwrap())
|
||||
}
|
||||
@ -2325,7 +2423,7 @@ where
|
||||
&self,
|
||||
device: &ObjectId,
|
||||
device_data: &crate::Data,
|
||||
) -> Pin<Box<dyn Future<Output = Option<Error>> + Send + 'static>> {
|
||||
) -> Pin<DevicePopErrorFuture> {
|
||||
let device = <T::DeviceId>::from(*device);
|
||||
let device_data = downcast_ref(device_data);
|
||||
Box::pin(Context::device_pop_error_scope(self, &device, device_data))
|
||||
@ -2337,7 +2435,7 @@ where
|
||||
buffer_data: &crate::Data,
|
||||
mode: MapMode,
|
||||
range: Range<BufferAddress>,
|
||||
callback: Box<dyn FnOnce(Result<(), BufferAsyncError>) + Send + 'static>,
|
||||
callback: BufferMapCallback,
|
||||
) {
|
||||
let buffer = <T::BufferId>::from(*buffer);
|
||||
let buffer_data = downcast_ref(buffer_data);
|
||||
@ -2928,7 +3026,7 @@ where
|
||||
&self,
|
||||
queue: &ObjectId,
|
||||
queue_data: &crate::Data,
|
||||
callback: Box<dyn FnOnce() + Send + 'static>,
|
||||
callback: SubmittedWorkDoneCallback,
|
||||
) {
|
||||
let queue = <T::QueueId>::from(*queue);
|
||||
let queue_data = downcast_ref(queue_data);
|
||||
@ -3861,7 +3959,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait QueueWriteBuffer: Send + Sync {
|
||||
pub trait QueueWriteBuffer: WasmNotSend + WasmNotSync {
|
||||
fn slice(&self) -> &[u8];
|
||||
|
||||
fn slice_mut(&mut self) -> &mut [u8];
|
||||
|
||||
383
wgpu/src/lib.rs
383
wgpu/src/lib.rs
@ -43,8 +43,9 @@ pub use wgt::{
|
||||
StorageTextureAccess, SurfaceCapabilities, SurfaceStatus, TextureAspect, TextureDimension,
|
||||
TextureFormat, TextureFormatFeatureFlags, TextureFormatFeatures, TextureSampleType,
|
||||
TextureUsages, TextureViewDimension, VertexAttribute, VertexFormat, VertexStepMode,
|
||||
COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT,
|
||||
QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_STRIDE_ALIGNMENT,
|
||||
WasmNotSend, WasmNotSync, COPY_BUFFER_ALIGNMENT, COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT,
|
||||
PUSH_CONSTANT_ALIGNMENT, QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE,
|
||||
VERTEX_STRIDE_ALIGNMENT,
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
@ -66,8 +67,6 @@ pub use ::wgc as core;
|
||||
// specific, but these need to depend on web-sys.
|
||||
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
||||
pub use wgt::{ExternalImageSource, ImageCopyExternalImage};
|
||||
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
||||
static_assertions::assert_impl_all!(ExternalImageSource: Send, Sync);
|
||||
|
||||
/// Filter for error scopes.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)]
|
||||
@ -80,7 +79,22 @@ pub enum ErrorFilter {
|
||||
static_assertions::assert_impl_all!(ErrorFilter: Send, Sync);
|
||||
|
||||
type C = dyn DynContext;
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
type Data = dyn Any + Send + Sync;
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
type Data = dyn Any;
|
||||
|
||||
/// Context for all other wgpu objects. Instance of wgpu.
|
||||
///
|
||||
@ -94,6 +108,13 @@ type Data = dyn Any + Send + Sync;
|
||||
pub struct Instance {
|
||||
context: Arc<C>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Instance: Send, Sync);
|
||||
|
||||
/// Handle to a physical graphics and/or compute device.
|
||||
@ -110,6 +131,13 @@ pub struct Adapter {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Adapter: Send, Sync);
|
||||
|
||||
impl Drop for Adapter {
|
||||
@ -134,6 +162,13 @@ pub struct Device {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Device: Send, Sync);
|
||||
|
||||
/// Identifier for a particular call to [`Queue::submit`]. Can be used
|
||||
@ -144,6 +179,13 @@ static_assertions::assert_impl_all!(Device: Send, Sync);
|
||||
/// There is no analogue in the WebGPU specification.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SubmissionIndex(ObjectId, Arc<crate::Data>);
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync);
|
||||
|
||||
/// The main purpose of this struct is to resolve mapped ranges (convert sizes
|
||||
@ -220,6 +262,13 @@ pub struct Buffer {
|
||||
usage: BufferUsages,
|
||||
// Todo: missing map_state https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapstate
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Buffer: Send, Sync);
|
||||
|
||||
/// Slice into a [`Buffer`].
|
||||
@ -236,6 +285,13 @@ pub struct BufferSlice<'a> {
|
||||
offset: BufferAddress,
|
||||
size: Option<BufferSize>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BufferSlice: Send, Sync);
|
||||
|
||||
/// Handle to a texture on the GPU.
|
||||
@ -251,6 +307,13 @@ pub struct Texture {
|
||||
owned: bool,
|
||||
descriptor: TextureDescriptor<'static>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Texture: Send, Sync);
|
||||
|
||||
/// Handle to a texture view.
|
||||
@ -265,6 +328,13 @@ pub struct TextureView {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(TextureView: Send, Sync);
|
||||
|
||||
/// Handle to a sampler.
|
||||
@ -282,6 +352,13 @@ pub struct Sampler {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Sampler: Send, Sync);
|
||||
|
||||
impl Drop for Sampler {
|
||||
@ -322,6 +399,13 @@ pub struct Surface {
|
||||
// been created is is additionally wrapped in an option.
|
||||
config: Mutex<Option<SurfaceConfiguration>>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Surface: Send, Sync);
|
||||
|
||||
impl Drop for Surface {
|
||||
@ -349,6 +433,13 @@ pub struct BindGroupLayout {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BindGroupLayout: Send, Sync);
|
||||
|
||||
impl Drop for BindGroupLayout {
|
||||
@ -374,6 +465,13 @@ pub struct BindGroup {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BindGroup: Send, Sync);
|
||||
|
||||
impl Drop for BindGroup {
|
||||
@ -398,6 +496,13 @@ pub struct ShaderModule {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ShaderModule: Send, Sync);
|
||||
|
||||
impl Drop for ShaderModule {
|
||||
@ -490,6 +595,13 @@ pub struct PipelineLayout {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(PipelineLayout: Send, Sync);
|
||||
|
||||
impl Drop for PipelineLayout {
|
||||
@ -513,6 +625,13 @@ pub struct RenderPipeline {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RenderPipeline: Send, Sync);
|
||||
|
||||
impl Drop for RenderPipeline {
|
||||
@ -547,6 +666,13 @@ pub struct ComputePipeline {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ComputePipeline: Send, Sync);
|
||||
|
||||
impl Drop for ComputePipeline {
|
||||
@ -584,6 +710,13 @@ pub struct CommandBuffer {
|
||||
id: Option<ObjectId>,
|
||||
data: Option<Box<Data>>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(CommandBuffer: Send, Sync);
|
||||
|
||||
impl Drop for CommandBuffer {
|
||||
@ -612,6 +745,13 @@ pub struct CommandEncoder {
|
||||
id: Option<ObjectId>,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(CommandEncoder: Send, Sync);
|
||||
|
||||
impl Drop for CommandEncoder {
|
||||
@ -688,6 +828,13 @@ pub struct RenderBundle {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RenderBundle: Send, Sync);
|
||||
|
||||
impl Drop for RenderBundle {
|
||||
@ -709,6 +856,13 @@ pub struct QuerySet {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(QuerySet: Send, Sync);
|
||||
|
||||
impl Drop for QuerySet {
|
||||
@ -732,6 +886,13 @@ pub struct Queue {
|
||||
id: ObjectId,
|
||||
data: Box<Data>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Queue: Send, Sync);
|
||||
|
||||
/// Resource that can be bound to a pipeline.
|
||||
@ -777,6 +938,13 @@ pub enum BindingResource<'a> {
|
||||
/// [`BindGroupLayoutEntry::count`] set to Some.
|
||||
TextureViewArray(&'a [&'a TextureView]),
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BindingResource: Send, Sync);
|
||||
|
||||
/// Describes the segment of a buffer to bind.
|
||||
@ -808,6 +976,13 @@ pub struct BufferBinding<'a> {
|
||||
/// Size of the binding in bytes, or `None` for using the rest of the buffer.
|
||||
pub size: Option<BufferSize>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BufferBinding: Send, Sync);
|
||||
|
||||
/// Operation to perform to the output attachment at the start of a render pass.
|
||||
@ -869,6 +1044,13 @@ pub struct RenderPassColorAttachment<'tex> {
|
||||
/// What operations will be performed on this color attachment.
|
||||
pub ops: Operations<Color>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RenderPassColorAttachment: Send, Sync);
|
||||
|
||||
/// Describes a depth/stencil attachment to a [`RenderPass`].
|
||||
@ -886,6 +1068,13 @@ pub struct RenderPassDepthStencilAttachment<'tex> {
|
||||
/// What operations will be performed on the stencil part of the attachment.
|
||||
pub stencil_ops: Option<Operations<u32>>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RenderPassDepthStencilAttachment: Send, Sync);
|
||||
|
||||
// The underlying types are also exported so that documentation shows up for them
|
||||
@ -900,6 +1089,13 @@ pub use wgt::RequestAdapterOptions as RequestAdapterOptionsBase;
|
||||
/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
|
||||
pub type RequestAdapterOptions<'a> = RequestAdapterOptionsBase<&'a Surface>;
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RequestAdapterOptions: Send, Sync);
|
||||
/// Describes a [`Device`].
|
||||
///
|
||||
@ -952,6 +1148,13 @@ static_assertions::assert_impl_all!(QuerySetDescriptor: Send, Sync);
|
||||
pub use wgt::Maintain as MaintainBase;
|
||||
/// Passed to [`Device::poll`] to control how and if it should block.
|
||||
pub type Maintain = wgt::Maintain<SubmissionIndex>;
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Maintain: Send, Sync);
|
||||
|
||||
/// Describes a [`TextureView`].
|
||||
@ -1007,6 +1210,13 @@ pub struct PipelineLayoutDescriptor<'a> {
|
||||
/// If this array is non-empty, the [`Features::PUSH_CONSTANTS`] must be enabled.
|
||||
pub push_constant_ranges: &'a [PushConstantRange],
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(PipelineLayoutDescriptor: Send, Sync);
|
||||
|
||||
/// Describes a [`Sampler`].
|
||||
@ -1076,6 +1286,13 @@ pub struct BindGroupEntry<'a> {
|
||||
/// Resource to attach to the binding
|
||||
pub resource: BindingResource<'a>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BindGroupEntry: Send, Sync);
|
||||
|
||||
/// Describes a group of bindings and the resources to be bound.
|
||||
@ -1093,6 +1310,13 @@ pub struct BindGroupDescriptor<'a> {
|
||||
/// The resources to bind to this bind group.
|
||||
pub entries: &'a [BindGroupEntry<'a>],
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(BindGroupDescriptor: Send, Sync);
|
||||
|
||||
/// Describes the attachments of a render pass.
|
||||
@ -1113,6 +1337,13 @@ pub struct RenderPassDescriptor<'tex, 'desc> {
|
||||
/// The depth and stencil attachment of the render pass, if any.
|
||||
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachment<'tex>>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RenderPassDescriptor: Send, Sync);
|
||||
|
||||
/// Describes how the vertex buffer is interpreted.
|
||||
@ -1148,6 +1379,13 @@ pub struct VertexState<'a> {
|
||||
/// The format of any vertex buffers used with this pipeline.
|
||||
pub buffers: &'a [VertexBufferLayout<'a>],
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(VertexState: Send, Sync);
|
||||
|
||||
/// Describes the fragment processing in a render pipeline.
|
||||
@ -1166,6 +1404,13 @@ pub struct FragmentState<'a> {
|
||||
/// The color state of the render targets.
|
||||
pub targets: &'a [Option<ColorTargetState>],
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(FragmentState: Send, Sync);
|
||||
|
||||
/// Describes a render (graphics) pipeline.
|
||||
@ -1194,6 +1439,13 @@ pub struct RenderPipelineDescriptor<'a> {
|
||||
/// layers the attachments will have.
|
||||
pub multiview: Option<NonZeroU32>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(RenderPipelineDescriptor: Send, Sync);
|
||||
|
||||
/// Describes the attachments of a compute pass.
|
||||
@ -1227,6 +1479,13 @@ pub struct ComputePipelineDescriptor<'a> {
|
||||
/// and no return value in the shader.
|
||||
pub entry_point: &'a str,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ComputePipelineDescriptor: Send, Sync);
|
||||
|
||||
pub use wgt::ImageCopyBuffer as ImageCopyBufferBase;
|
||||
@ -1235,6 +1494,13 @@ pub use wgt::ImageCopyBuffer as ImageCopyBufferBase;
|
||||
/// Corresponds to [WebGPU `GPUImageCopyBuffer`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopybuffer).
|
||||
pub type ImageCopyBuffer<'a> = ImageCopyBufferBase<&'a Buffer>;
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ImageCopyBuffer: Send, Sync);
|
||||
|
||||
pub use wgt::ImageCopyTexture as ImageCopyTextureBase;
|
||||
@ -1243,6 +1509,13 @@ pub use wgt::ImageCopyTexture as ImageCopyTextureBase;
|
||||
/// Corresponds to [WebGPU `GPUImageCopyTexture`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexture).
|
||||
pub type ImageCopyTexture<'a> = ImageCopyTextureBase<&'a Texture>;
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync);
|
||||
|
||||
pub use wgt::ImageCopyTextureTagged as ImageCopyTextureTaggedBase;
|
||||
@ -1252,6 +1525,13 @@ pub use wgt::ImageCopyTextureTagged as ImageCopyTextureTaggedBase;
|
||||
/// Corresponds to [WebGPU `GPUImageCopyTextureTagged`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexturetagged).
|
||||
pub type ImageCopyTextureTagged<'a> = ImageCopyTextureTaggedBase<&'a Texture>;
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync);
|
||||
|
||||
/// Describes a [`BindGroupLayout`].
|
||||
@ -1308,8 +1588,15 @@ pub struct SurfaceTexture {
|
||||
/// but should be recreated for maximum performance.
|
||||
pub suboptimal: bool,
|
||||
presented: bool,
|
||||
detail: Box<dyn Any + Send + Sync>,
|
||||
detail: Box<dyn AnyWasmNotSendSync>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync);
|
||||
|
||||
/// Result of an unsuccessful call to [`Surface::get_current_texture`].
|
||||
@ -1463,7 +1750,7 @@ impl Instance {
|
||||
pub fn request_adapter(
|
||||
&self,
|
||||
options: &RequestAdapterOptions,
|
||||
) -> impl Future<Output = Option<Adapter>> + Send {
|
||||
) -> impl Future<Output = Option<Adapter>> + WasmNotSend {
|
||||
let context = Arc::clone(&self.context);
|
||||
let adapter = self.context.instance_request_adapter(options);
|
||||
async move {
|
||||
@ -1743,7 +2030,7 @@ impl Adapter {
|
||||
&self,
|
||||
desc: &DeviceDescriptor,
|
||||
trace_path: Option<&std::path::Path>,
|
||||
) -> impl Future<Output = Result<(Device, Queue), RequestDeviceError>> + Send {
|
||||
) -> impl Future<Output = Result<(Device, Queue), RequestDeviceError>> + WasmNotSend {
|
||||
let context = Arc::clone(&self.context);
|
||||
let device = DynContext::adapter_request_device(
|
||||
&*self.context,
|
||||
@ -2257,7 +2544,7 @@ impl Device {
|
||||
}
|
||||
|
||||
/// Pop an error scope.
|
||||
pub fn pop_error_scope(&self) -> impl Future<Output = Option<Error>> + Send {
|
||||
pub fn pop_error_scope(&self) -> impl Future<Output = Option<Error>> + WasmNotSend {
|
||||
self.context
|
||||
.device_pop_error_scope(&self.id, self.data.as_ref())
|
||||
}
|
||||
@ -2562,7 +2849,7 @@ impl<'a> BufferSlice<'a> {
|
||||
pub fn map_async(
|
||||
&self,
|
||||
mode: MapMode,
|
||||
callback: impl FnOnce(Result<(), BufferAsyncError>) + Send + 'static,
|
||||
callback: impl FnOnce(Result<(), BufferAsyncError>) + WasmNotSend + 'static,
|
||||
) {
|
||||
let mut mc = self.buffer.map_context.lock();
|
||||
assert_eq!(
|
||||
@ -3970,6 +4257,13 @@ pub struct QueueWriteBufferView<'a> {
|
||||
offset: BufferAddress,
|
||||
inner: Box<dyn context::QueueWriteBuffer>,
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(QueueWriteBufferView: Send, Sync);
|
||||
|
||||
impl Deref for QueueWriteBufferView<'_> {
|
||||
@ -4609,16 +4903,55 @@ pub enum Error {
|
||||
/// Out of memory error
|
||||
OutOfMemory {
|
||||
/// Lower level source of the error.
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
source: Box<dyn error::Error + Send + 'static>,
|
||||
/// Lower level source of the error.
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
source: Box<dyn error::Error + 'static>,
|
||||
},
|
||||
/// Validation error, signifying a bug in code or data
|
||||
Validation {
|
||||
/// Lower level source of the error.
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
source: Box<dyn error::Error + Send + 'static>,
|
||||
/// Lower level source of the error.
|
||||
#[cfg(not(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
)))]
|
||||
source: Box<dyn error::Error + 'static>,
|
||||
/// Description of the validation error.
|
||||
description: String,
|
||||
},
|
||||
}
|
||||
#[cfg(any(
|
||||
not(target_arch = "wasm32"),
|
||||
all(
|
||||
feature = "fragile-send-sync-non-atomic-wasm",
|
||||
not(target_feature = "atomics")
|
||||
)
|
||||
))]
|
||||
static_assertions::assert_impl_all!(Error: Send);
|
||||
|
||||
impl error::Error for Error {
|
||||
@ -4638,3 +4971,35 @@ impl Display for Error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use send_sync::*;
|
||||
|
||||
mod send_sync {
|
||||
use std::any::Any;
|
||||
use std::fmt;
|
||||
|
||||
use wgt::{WasmNotSend, WasmNotSync};
|
||||
|
||||
pub trait AnyWasmNotSendSync: Any + WasmNotSend + WasmNotSync {
|
||||
fn upcast_any_ref(&self) -> &dyn Any;
|
||||
}
|
||||
impl<T: Any + WasmNotSend + WasmNotSync> AnyWasmNotSendSync for T {
|
||||
#[inline]
|
||||
fn upcast_any_ref(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn AnyWasmNotSendSync + 'static {
|
||||
#[inline]
|
||||
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
|
||||
self.upcast_any_ref().downcast_ref::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for dyn AnyWasmNotSendSync {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Any").finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user