From c2dcfa2143397a7ce8caf6654a32865a28d2ec95 Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Fri, 14 Apr 2023 22:59:07 +0200 Subject: [PATCH 1/3] Don't implement `Send` or `Sync` on Wasm --- CHANGELOG.md | 1 + wgpu-core/src/command/bundle.rs | 2 + wgpu-core/src/device/queue.rs | 16 +- wgpu-core/src/error.rs | 3 + wgpu-core/src/global.rs | 2 +- wgpu-core/src/resource.rs | 18 +- wgpu-hal/src/gles/adapter.rs | 6 - wgpu-hal/src/gles/device.rs | 6 - wgpu-hal/src/gles/mod.rs | 32 +- wgpu-hal/src/gles/queue.rs | 6 - wgpu-hal/src/gles/web.rs | 8 - wgpu-hal/src/lib.rs | 62 ++-- wgpu-types/src/lib.rs | 5 - wgpu/src/backend/direct.rs | 16 +- wgpu/src/backend/web.rs | 502 ++++++++++++++------------------ wgpu/src/context.rs | 136 +++++---- wgpu/src/lib.rs | 112 ++++++- 17 files changed, 481 insertions(+), 452 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94acb283f6..0cc8b9290b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,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 diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 7a99c90bd6..0b87cb6740 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -746,7 +746,9 @@ pub struct RenderBundle { pub(crate) life_guard: LifeGuard, } +#[cfg(not(target_arch = "wasm32"))] unsafe impl Send for RenderBundle {} +#[cfg(not(target_arch = "wasm32"))] unsafe impl Sync for RenderBundle {} impl RenderBundle { diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 98095f4490..de7c16755a 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -37,6 +37,7 @@ pub struct SubmittedWorkDoneClosureC { pub user_data: *mut u8, } +#[cfg(not(target_arch = "wasm32"))] unsafe impl Send for SubmittedWorkDoneClosureC {} pub struct SubmittedWorkDoneClosure { @@ -45,17 +46,18 @@ pub struct SubmittedWorkDoneClosure { inner: SubmittedWorkDoneClosureInner, } +#[cfg(not(target_arch = "wasm32"))] +type SubmittedWorkDoneCallback = Box; +#[cfg(target_arch = "wasm32")] +type SubmittedWorkDoneCallback = Box; + enum SubmittedWorkDoneClosureInner { - Rust { - callback: Box, - }, - C { - inner: SubmittedWorkDoneClosureC, - }, + Rust { callback: SubmittedWorkDoneCallback }, + C { inner: SubmittedWorkDoneClosureC }, } impl SubmittedWorkDoneClosure { - pub fn from_rust(callback: Box) -> Self { + pub fn from_rust(callback: SubmittedWorkDoneCallback) -> Self { Self { inner: SubmittedWorkDoneClosureInner::Rust { callback }, } diff --git a/wgpu-core/src/error.rs b/wgpu-core/src/error.rs index 3cdecc5369..1e38f67261 100644 --- a/wgpu-core/src/error.rs +++ b/wgpu-core/src/error.rs @@ -162,7 +162,10 @@ pub fn format_pretty_any( #[derive(Debug)] pub struct ContextError { pub string: &'static str, + #[cfg(not(target_arch = "wasm32"))] pub cause: Box, + #[cfg(target_arch = "wasm32")] + pub cause: Box, pub label_key: &'static str, pub label: String, } diff --git a/wgpu-core/src/global.rs b/wgpu-core/src/global.rs index 5331265962..2ef19e945e 100644 --- a/wgpu-core/src/global.rs +++ b/wgpu-core/src/global.rs @@ -155,7 +155,7 @@ impl Drop for Global { } } -#[cfg(test)] +#[cfg(all(test, not(target_arch = "wasm32")))] fn _test_send_sync(global: &Global) { fn test_internal(_: T) {} test_internal(global) diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 4aca271e9e..4f2c2f9ec1 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -79,7 +79,9 @@ pub(crate) enum BufferMapState { Idle, } +#[cfg(not(target_arch = "wasm32"))] unsafe impl Send for BufferMapState {} +#[cfg(not(target_arch = "wasm32"))] unsafe impl Sync for BufferMapState {} #[repr(C)] @@ -88,6 +90,7 @@ pub struct BufferMapCallbackC { pub user_data: *mut u8, } +#[cfg(not(target_arch = "wasm32"))] unsafe impl Send for BufferMapCallbackC {} pub struct BufferMapCallback { @@ -96,17 +99,18 @@ pub struct BufferMapCallback { inner: Option, } +#[cfg(not(target_arch = "wasm32"))] +type BufferMapCallbackCallback = Box; +#[cfg(target_arch = "wasm32")] +type BufferMapCallbackCallback = Box; + enum BufferMapCallbackInner { - Rust { - callback: Box, - }, - C { - inner: BufferMapCallbackC, - }, + Rust { callback: BufferMapCallbackCallback }, + C { inner: BufferMapCallbackC }, } impl BufferMapCallback { - pub fn from_rust(callback: Box) -> Self { + pub fn from_rust(callback: BufferMapCallbackCallback) -> Self { Self { inner: Some(BufferMapCallbackInner::Rust { callback }), } diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index fc68b437e8..20bf8a8e28 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -936,12 +936,6 @@ impl super::AdapterShared { } } -// SAFE: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for super::Adapter {} -#[cfg(target_arch = "wasm32")] -unsafe impl Send for super::Adapter {} - #[cfg(test)] mod tests { use super::super::Adapter; diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 14bbb36601..612483339e 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -1320,9 +1320,3 @@ impl crate::Device for super::Device { } } } - -// SAFE: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for super::Device {} -#[cfg(target_arch = "wasm32")] -unsafe impl Send for super::Device {} diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 1b5e3f1422..0566de3cdc 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -246,12 +246,6 @@ pub struct Buffer { data: Option>>>, } -// Safe: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for Buffer {} -#[cfg(target_arch = "wasm32")] -unsafe impl Send for Buffer {} - #[derive(Clone, Debug)] pub enum TextureInner { Renderbuffer { @@ -268,12 +262,6 @@ pub enum TextureInner { }, } -// SAFE: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Send for TextureInner {} -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for TextureInner {} - impl TextureInner { fn as_native(&self) -> (glow::Texture, BindTarget) { match *self { @@ -462,12 +450,6 @@ struct UniformDesc { utype: u32, } -// Safe: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for UniformDesc {} -#[cfg(target_arch = "wasm32")] -unsafe impl Send for UniformDesc {} - /// For each texture in the pipeline layout, store the index of the only /// sampler (in this layout) that the texture is used with. type SamplerBindMap = [Option; MAX_TEXTURE_SLOTS]; @@ -530,22 +512,10 @@ 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")] -unsafe impl Sync for RenderPipeline {} - pub struct ComputePipeline { inner: Arc, } -// SAFE: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Send for ComputePipeline {} -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for ComputePipeline {} - #[derive(Debug)] pub struct QuerySet { queries: Box<[glow::Query]>, @@ -558,7 +528,9 @@ pub struct Fence { pending: Vec<(crate::FenceValue, glow::Fence)>, } +#[cfg(not(target_arch = "wasm32"))] unsafe impl Send for Fence {} +#[cfg(not(target_arch = "wasm32"))] unsafe impl Sync for Fence {} impl Fence { diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index ec2a18d422..bfba315e5c 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -1524,9 +1524,3 @@ impl crate::Queue for super::Queue { 1.0 } } - -// SAFE: Wasm doesn't have threads -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for super::Queue {} -#[cfg(target_arch = "wasm32")] -unsafe impl Send for super::Queue {} diff --git a/wgpu-hal/src/gles/web.rs b/wgpu-hal/src/gles/web.rs index a6f807857b..820d108f23 100644 --- a/wgpu-hal/src/gles/web.rs +++ b/wgpu-hal/src/gles/web.rs @@ -106,10 +106,6 @@ impl Instance { } } -// SAFE: Wasm doesn't have threads -unsafe impl Sync for Instance {} -unsafe impl Send for Instance {} - impl crate::Instance for Instance { unsafe fn init(_desc: &crate::InstanceDescriptor) -> Result { Ok(Instance { @@ -177,10 +173,6 @@ enum Canvas { 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, diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 1758149380..0d0514faa8 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -161,25 +161,25 @@ pub trait Api: Clone + Sized { type Queue: Queue; type CommandEncoder: CommandEncoder; - type CommandBuffer: Send + Sync + fmt::Debug; + type CommandBuffer: MaybeSend + MaybeSync + fmt::Debug; - type Buffer: fmt::Debug + Send + Sync + 'static; - type Texture: fmt::Debug + Send + Sync + 'static; - type SurfaceTexture: fmt::Debug + Send + Sync + Borrow; - 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 + MaybeSend + MaybeSync + 'static; + type Texture: fmt::Debug + MaybeSend + MaybeSync + 'static; + type SurfaceTexture: fmt::Debug + MaybeSend + MaybeSync + Borrow; + type TextureView: fmt::Debug + MaybeSend + MaybeSync; + type Sampler: fmt::Debug + MaybeSend + MaybeSync; + type QuerySet: fmt::Debug + MaybeSend + MaybeSync; + type Fence: fmt::Debug + MaybeSend + MaybeSync; - 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: MaybeSend + MaybeSync; + type BindGroup: fmt::Debug + MaybeSend + MaybeSync; + type PipelineLayout: MaybeSend + MaybeSync; + type ShaderModule: fmt::Debug + MaybeSend + MaybeSync; + type RenderPipeline: MaybeSend + MaybeSync; + type ComputePipeline: MaybeSend + MaybeSync; } -pub trait Instance: Sized + Send + Sync { +pub trait Instance: Sized + MaybeSend + MaybeSync { unsafe fn init(desc: &InstanceDescriptor) -> Result; unsafe fn create_surface( &self, @@ -190,7 +190,7 @@ pub trait Instance: Sized + Send + Sync { unsafe fn enumerate_adapters(&self) -> Vec>; } -pub trait Surface: Send + Sync { +pub trait Surface: MaybeSend + MaybeSync { unsafe fn configure( &mut self, device: &A::Device, @@ -216,7 +216,7 @@ pub trait Surface: Send + Sync { unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture); } -pub trait Adapter: Send + Sync { +pub trait Adapter: MaybeSend + MaybeSync { unsafe fn open( &self, features: wgt::Features, @@ -240,7 +240,7 @@ pub trait Adapter: Send + Sync { unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp; } -pub trait Device: Send + Sync { +pub trait Device: MaybeSend + MaybeSync { /// Exit connection to this logical device. unsafe fn exit(self, queue: A::Queue); /// Creates a new buffer. @@ -336,7 +336,7 @@ pub trait Device: Send + Sync { unsafe fn stop_capture(&self); } -pub trait Queue: Send + Sync { +pub trait Queue: MaybeSend + MaybeSync { /// Submits the command buffers for execution on GPU. /// /// Valid usage: @@ -360,7 +360,7 @@ pub trait Queue: 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: Send + Sync + fmt::Debug { +pub trait CommandEncoder: MaybeSend + MaybeSync + fmt::Debug { /// Begin encoding a new command buffer. unsafe fn begin_encoding(&mut self, label: Label) -> Result<(), DeviceError>; /// Discard currently recorded list, if any. @@ -1309,6 +1309,28 @@ impl ValidationCanary { } } +use send_sync::*; + +mod send_sync { + #[cfg(not(target_arch = "wasm32"))] + pub trait MaybeSend: Send {} + #[cfg(not(target_arch = "wasm32"))] + impl MaybeSend for T {} + #[cfg(target_arch = "wasm32")] + pub trait MaybeSend {} + #[cfg(target_arch = "wasm32")] + impl MaybeSend for T {} + + #[cfg(not(target_arch = "wasm32"))] + pub trait MaybeSync: Sync {} + #[cfg(not(target_arch = "wasm32"))] + impl MaybeSync for T {} + #[cfg(target_arch = "wasm32")] + pub trait MaybeSync {} + #[cfg(target_arch = "wasm32")] + impl MaybeSync for T {} +} + #[test] fn test_default_limits() { let limits = wgt::Limits::default(); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index ebfc9f65aa..5d56a74e31 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5917,11 +5917,6 @@ impl std::ops::Deref for ExternalImageSource { } } -#[cfg(target_arch = "wasm32")] -unsafe impl Send for ExternalImageSource {} -#[cfg(target_arch = "wasm32")] -unsafe impl Sync for ExternalImageSource {} - /// Color spaces supported on the web. /// /// Corresponds to [HTML Canvas `PredefinedColorSpace`]( diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index d9e1085935..5b7dd3cd3f 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -2,8 +2,8 @@ use crate::{ context::{ObjectId, Unused}, AdapterInfo, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BufferBinding, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, - DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode, Operations, - PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor, + DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode, MaybeSend, MaybeSync, + Operations, PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor, SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, ShaderSource, SurfaceStatus, TextureDescriptor, TextureViewDescriptor, UncapturedErrorHandler, }; @@ -263,7 +263,7 @@ impl Context { fn handle_error( &self, sink_mutex: &Mutex, - cause: impl Error + Send + Sync + 'static, + cause: impl Error + MaybeSend + MaybeSync + 'static, label_key: &'static str, label: Label, string: &'static str, @@ -297,7 +297,7 @@ impl Context { fn handle_error_nolabel( &self, sink_mutex: &Mutex, - cause: impl Error + Send + Sync + 'static, + cause: impl Error + MaybeSend + MaybeSync + 'static, string: &'static str, ) { self.handle_error(sink_mutex, cause, "", None, string) @@ -306,7 +306,7 @@ impl Context { #[track_caller] fn handle_error_fatal( &self, - cause: impl Error + Send + Sync + 'static, + cause: impl Error + MaybeSend + MaybeSync + 'static, operation: &'static str, ) -> ! { panic!("Error in {operation}: {f}", f = self.format_error(&cause)); @@ -1467,7 +1467,7 @@ impl crate::Context for Context { buffer_data: &Self::BufferData, mode: MapMode, range: Range, - callback: Box) + Send + 'static>, + callback: crate::context::BufferMapCallback, ) { let operation = wgc::resource::BufferMapOperation { host: match mode { @@ -2279,7 +2279,7 @@ impl crate::Context for Context { &self, queue: &Self::QueueId, _queue_data: &Self::QueueData, - callback: Box, + callback: crate::context::SubmittedWorkDoneCallback, ) { let closure = wgc::device::queue::SubmittedWorkDoneClosure::from_rust(callback); @@ -3051,7 +3051,9 @@ pub struct BufferMappedRange { size: usize, } +#[cfg(not(target_arch = "wasm32"))] unsafe impl Send for BufferMappedRange {} +#[cfg(not(target_arch = "wasm32"))] unsafe impl Sync for BufferMappedRange {} impl crate::context::BufferMappedRange for BufferMappedRange { diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 239c663630..8ddd9eff24 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -19,14 +19,14 @@ use crate::{ UncapturedErrorHandler, }; -fn create_identified(value: T) -> (Identified, Sendable) { +fn create_identified(value: T) -> (Identified, T) { cfg_if::cfg_if! { if #[cfg(feature = "expose-ids")] { static NEXT_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1); let id = NEXT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - (Identified(core::num::NonZeroU64::new(id).unwrap(), PhantomData), Sendable(value)) + (Identified(core::num::NonZeroU64::new(id).unwrap(), PhantomData), value) } else { - (Identified(PhantomData), Sendable(value)) + (Identified(PhantomData), value) } } } @@ -63,22 +63,13 @@ impl From> for ObjectId { } } -#[derive(Clone, Debug)] -pub(crate) struct Sendable(T); -unsafe impl Send for Sendable {} -unsafe impl Sync for Sendable {} - #[derive(Clone, Debug)] pub(crate) struct Identified( #[cfg(feature = "expose-ids")] std::num::NonZeroU64, PhantomData, ); -unsafe impl Send for Identified {} -unsafe impl Sync for Identified {} pub(crate) struct Context(web_sys::Gpu); -unsafe impl Send for Context {} -unsafe impl Sync for Context {} impl fmt::Debug for Context { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -107,12 +98,12 @@ impl crate::Error { // This is safe on wasm32 *for now*, but similarly to the unsafe Send impls for the handle type // wrappers, the full story for threading on wasm32 is still unfolding. -pub(crate) struct MakeSendFuture { +pub(crate) struct MapFuture { future: F, map: M, } -impl T, T> Future for MakeSendFuture { +impl T, T> Future for MapFuture { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { @@ -128,14 +119,12 @@ impl T, T> Future for MakeSendFuture { } } -impl MakeSendFuture { +impl MapFuture { fn new(future: F, map: M) -> Self { Self { future, map } } } -unsafe impl Send for MakeSendFuture {} - fn map_texture_format(texture_format: wgt::TextureFormat) -> web_sys::GpuTextureFormat { use web_sys::GpuTextureFormat as tf; use wgt::TextureFormat; @@ -515,7 +504,7 @@ fn map_texture_view_dimension( fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> web_sys::GpuImageCopyBuffer { let buffer: &::BufferData = downcast_ref(view.buffer.data.as_ref()); - let mut mapped = web_sys::GpuImageCopyBuffer::new(&buffer.0); + let mut mapped = web_sys::GpuImageCopyBuffer::new(buffer); if let Some(bytes_per_row) = view.layout.bytes_per_row { mapped.bytes_per_row(bytes_per_row); } @@ -529,7 +518,7 @@ fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> web_sys::GpuImageCopyBu fn map_texture_copy_view(view: crate::ImageCopyTexture) -> web_sys::GpuImageCopyTexture { let texture: &::TextureData = downcast_ref(view.texture.data.as_ref()); - let mut mapped = web_sys::GpuImageCopyTexture::new(&texture.0); + let mut mapped = web_sys::GpuImageCopyTexture::new(texture); mapped.mip_level(view.mip_level); mapped.origin(&map_origin_3d(view.origin)); mapped @@ -540,7 +529,7 @@ fn map_tagged_texture_copy_view( ) -> web_sys::GpuImageCopyTextureTagged { let texture: &::TextureData = downcast_ref(view.texture.data.as_ref()); - let mut mapped = web_sys::GpuImageCopyTextureTagged::new(&texture.0); + let mut mapped = web_sys::GpuImageCopyTextureTagged::new(texture); mapped.mip_level(view.mip_level); mapped.origin(&map_origin_3d(view.origin)); mapped.aspect(map_texture_aspect(view.aspect)); @@ -663,10 +652,7 @@ type JsFutureResult = Result; fn future_request_adapter( result: JsFutureResult, -) -> Option<( - Identified, - Sendable, -)> { +) -> Option<(Identified, web_sys::GpuAdapter)> { match result.and_then(wasm_bindgen::JsCast::dyn_into) { Ok(adapter) => Some(create_identified(adapter)), Err(_) => None, @@ -678,16 +664,16 @@ fn future_request_device( ) -> Result< ( Identified, - Sendable, + web_sys::GpuDevice, Identified, - Sendable, + web_sys::GpuQueue, ), crate::RequestDeviceError, > { result .map(|js_value| { let (device_id, device_data) = create_identified(web_sys::GpuDevice::from(js_value)); - let (queue_id, queue_data) = create_identified(device_data.0.queue()); + let (queue_id, queue_data) = create_identified(device_data.queue()); (device_id, device_data, queue_id, queue_data) }) @@ -842,57 +828,57 @@ pub enum Canvas { impl crate::context::Context for Context { type AdapterId = Identified; - type AdapterData = Sendable; + type AdapterData = web_sys::GpuAdapter; type DeviceId = Identified; - type DeviceData = Sendable; + type DeviceData = web_sys::GpuDevice; type QueueId = Identified; - type QueueData = Sendable; + type QueueData = web_sys::GpuQueue; type ShaderModuleId = Identified; - type ShaderModuleData = Sendable; + type ShaderModuleData = web_sys::GpuShaderModule; type BindGroupLayoutId = Identified; - type BindGroupLayoutData = Sendable; + type BindGroupLayoutData = web_sys::GpuBindGroupLayout; type BindGroupId = Identified; - type BindGroupData = Sendable; + type BindGroupData = web_sys::GpuBindGroup; type TextureViewId = Identified; - type TextureViewData = Sendable; + type TextureViewData = web_sys::GpuTextureView; type SamplerId = Identified; - type SamplerData = Sendable; + type SamplerData = web_sys::GpuSampler; type BufferId = Identified; - type BufferData = Sendable; + type BufferData = web_sys::GpuBuffer; type TextureId = Identified; - type TextureData = Sendable; + type TextureData = web_sys::GpuTexture; type QuerySetId = Identified; - type QuerySetData = Sendable; + type QuerySetData = web_sys::GpuQuerySet; type PipelineLayoutId = Identified; - type PipelineLayoutData = Sendable; + type PipelineLayoutData = web_sys::GpuPipelineLayout; type RenderPipelineId = Identified; - type RenderPipelineData = Sendable; + type RenderPipelineData = web_sys::GpuRenderPipeline; type ComputePipelineId = Identified; - type ComputePipelineData = Sendable; + type ComputePipelineData = web_sys::GpuComputePipeline; type CommandEncoderId = Identified; - type CommandEncoderData = Sendable; + type CommandEncoderData = web_sys::GpuCommandEncoder; type ComputePassId = Identified; - type ComputePassData = Sendable; + type ComputePassData = web_sys::GpuComputePassEncoder; type RenderPassId = Identified; - type RenderPassData = Sendable; + type RenderPassData = web_sys::GpuRenderPassEncoder; type CommandBufferId = Identified; - type CommandBufferData = Sendable; + type CommandBufferData = web_sys::GpuCommandBuffer; type RenderBundleEncoderId = Identified; - type RenderBundleEncoderData = Sendable; + type RenderBundleEncoderData = web_sys::GpuRenderBundleEncoder; type RenderBundleId = Identified; - type RenderBundleData = Sendable; + type RenderBundleData = web_sys::GpuRenderBundle; type SurfaceId = Identified<(Canvas, web_sys::GpuCanvasContext)>; - type SurfaceData = Sendable<(Canvas, web_sys::GpuCanvasContext)>; + type SurfaceData = (Canvas, web_sys::GpuCanvasContext); type SurfaceOutputDetail = SurfaceOutputDetail; type SubmissionIndex = Unused; type SubmissionIndexData = (); - type RequestAdapterFuture = MakeSendFuture< + type RequestAdapterFuture = MapFuture< wasm_bindgen_futures::JsFuture, fn(JsFutureResult) -> Option<(Self::AdapterId, Self::AdapterData)>, >; - type RequestDeviceFuture = MakeSendFuture< + type RequestDeviceFuture = MapFuture< wasm_bindgen_futures::JsFuture, fn( JsFutureResult, @@ -907,7 +893,7 @@ impl crate::context::Context for Context { >, >; type PopErrorScopeFuture = - MakeSendFuture Option>; + MapFuture Option>; fn init(_instance_desc: wgt::InstanceDescriptor) -> Self { let global: Global = js_sys::global().unchecked_into(); @@ -964,7 +950,7 @@ impl crate::context::Context for Context { mapped_options.power_preference(mapped_power_preference); let adapter_promise = self.0.request_adapter_with_options(&mapped_options); - MakeSendFuture::new( + MapFuture::new( wasm_bindgen_futures::JsFuture::from(adapter_promise), future_request_adapter, ) @@ -1001,9 +987,9 @@ impl crate::context::Context for Context { mapped_desc.label(label); } - let device_promise = adapter_data.0.request_device_with_descriptor(&mapped_desc); + let device_promise = adapter_data.request_device_with_descriptor(&mapped_desc); - MakeSendFuture::new( + MapFuture::new( wasm_bindgen_futures::JsFuture::from(device_promise), future_request_device, ) @@ -1029,7 +1015,7 @@ impl crate::context::Context for Context { _adapter: &Self::AdapterId, adapter_data: &Self::AdapterData, ) -> wgt::Features { - map_wgt_features(adapter_data.0.features()) + map_wgt_features(adapter_data.features()) } fn adapter_limits( @@ -1037,7 +1023,7 @@ impl crate::context::Context for Context { _adapter: &Self::AdapterId, adapter_data: &Self::AdapterData, ) -> wgt::Limits { - let limits = adapter_data.0.limits(); + let limits = adapter_data.limits(); wgt::Limits { max_texture_dimension_1d: limits.max_texture_dimension_1d(), max_texture_dimension_2d: limits.max_texture_dimension_2d(), @@ -1143,7 +1129,7 @@ impl crate::context::Context for Context { device_data: &Self::DeviceData, config: &crate::SurfaceConfiguration, ) { - match surface_data.0 .0 { + match surface_data.0 { Canvas::Canvas(ref canvas) => { canvas.set_width(config.width); canvas.set_height(config.height); @@ -1167,7 +1153,7 @@ impl crate::context::Context for Context { _ => web_sys::GpuCanvasAlphaMode::Opaque, }; let mut mapped = - web_sys::GpuCanvasConfiguration::new(&device_data.0, map_texture_format(config.format)); + web_sys::GpuCanvasConfiguration::new(device_data, map_texture_format(config.format)); mapped.usage(config.usage.bits()); mapped.alpha_mode(alpha_mode); let mapped_view_formats = config @@ -1176,7 +1162,7 @@ impl crate::context::Context for Context { .map(|format| JsValue::from(map_texture_format(*format))) .collect::(); mapped.view_formats(&mapped_view_formats); - surface_data.0 .1.configure(&mapped); + surface_data.1.configure(&mapped); } fn surface_get_current_texture( @@ -1189,7 +1175,7 @@ impl crate::context::Context for Context { wgt::SurfaceStatus, Self::SurfaceOutputDetail, ) { - let (surface_id, surface_data) = create_identified(surface_data.0 .1.get_current_texture()); + let (surface_id, surface_data) = create_identified(surface_data.1.get_current_texture()); ( Some(surface_id), Some(surface_data), @@ -1215,7 +1201,7 @@ impl crate::context::Context for Context { _device: &Self::DeviceId, device_data: &Self::DeviceData, ) -> wgt::Features { - map_wgt_features(device_data.0.features()) + map_wgt_features(device_data.features()) } fn device_limits( @@ -1328,7 +1314,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { descriptor.label(label); } - create_identified(device_data.0.create_shader_module(&descriptor)) + create_identified(device_data.create_shader_module(&descriptor)) } unsafe fn device_create_shader_module_spirv( @@ -1436,7 +1422,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_bind_group_layout(&mapped_desc)) + create_identified(device_data.create_bind_group_layout(&mapped_desc)) } fn device_create_bind_group( @@ -1457,7 +1443,7 @@ impl crate::context::Context for Context { }) => { let buffer: &::BufferData = downcast_ref(buffer.data.as_ref()); - let mut mapped_buffer_binding = web_sys::GpuBufferBinding::new(&buffer.0); + let mut mapped_buffer_binding = web_sys::GpuBufferBinding::new(buffer); mapped_buffer_binding.offset(offset as f64); if let Some(s) = size { mapped_buffer_binding.size(s.get() as f64); @@ -1470,7 +1456,7 @@ impl crate::context::Context for Context { crate::BindingResource::Sampler(sampler) => { let sampler: &::SamplerData = downcast_ref(sampler.data.as_ref()); - JsValue::from(&sampler.0) + JsValue::from(sampler) } crate::BindingResource::SamplerArray(..) => { panic!("Web backend does not support arrays of samplers") @@ -1478,7 +1464,7 @@ impl crate::context::Context for Context { crate::BindingResource::TextureView(texture_view) => { let texture_view: &::TextureViewData = downcast_ref(texture_view.data.as_ref()); - JsValue::from(&texture_view.0) + JsValue::from(texture_view) } crate::BindingResource::TextureViewArray(..) => { panic!("Web backend does not support BINDING_INDEXING extension") @@ -1491,11 +1477,11 @@ impl crate::context::Context for Context { let bgl: &::BindGroupLayoutData = downcast_ref(desc.layout.data.as_ref()); - let mut mapped_desc = web_sys::GpuBindGroupDescriptor::new(&mapped_entries, &bgl.0); + let mut mapped_desc = web_sys::GpuBindGroupDescriptor::new(&mapped_entries, bgl); if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_bind_group(&mapped_desc)) + create_identified(device_data.create_bind_group(&mapped_desc)) } fn device_create_pipeline_layout( @@ -1510,14 +1496,14 @@ impl crate::context::Context for Context { .map(|bgl| { let bgl: &::BindGroupLayoutData = downcast_ref(bgl.data.as_ref()); - &bgl.0 + bgl }) .collect::(); let mut mapped_desc = web_sys::GpuPipelineLayoutDescriptor::new(&temp_layouts); if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_pipeline_layout(&mapped_desc)) + create_identified(device_data.create_pipeline_layout(&mapped_desc)) } fn device_create_render_pipeline( @@ -1528,8 +1514,7 @@ impl crate::context::Context for Context { ) -> (Self::RenderPipelineId, Self::RenderPipelineData) { let module: &::ShaderModuleData = downcast_ref(desc.vertex.module.data.as_ref()); - let mut mapped_vertex_state = - web_sys::GpuVertexState::new(desc.vertex.entry_point, &module.0); + let mut mapped_vertex_state = web_sys::GpuVertexState::new(desc.vertex.entry_point, module); let buffers = desc .vertex @@ -1565,7 +1550,7 @@ impl crate::context::Context for Context { Some(layout) => { let layout: &::PipelineLayoutData = downcast_ref(layout.data.as_ref()); - JsValue::from(&layout.0) + JsValue::from(layout) } None => auto_layout, }, @@ -1604,7 +1589,7 @@ impl crate::context::Context for Context { let module: &::ShaderModuleData = downcast_ref(frag.module.data.as_ref()); let mapped_fragment_desc = - web_sys::GpuFragmentState::new(frag.entry_point, &module.0, &targets); + web_sys::GpuFragmentState::new(frag.entry_point, module, &targets); mapped_desc.fragment(&mapped_fragment_desc); } @@ -1617,7 +1602,7 @@ impl crate::context::Context for Context { let mapped_primitive = map_primitive_state(&desc.primitive); mapped_desc.primitive(&mapped_primitive); - create_identified(device_data.0.create_render_pipeline(&mapped_desc)) + create_identified(device_data.create_render_pipeline(&mapped_desc)) } fn device_create_compute_pipeline( @@ -1629,14 +1614,14 @@ impl crate::context::Context for Context { let shader_module: &::ShaderModuleData = downcast_ref(desc.module.data.as_ref()); let mapped_compute_stage = - web_sys::GpuProgrammableStage::new(desc.entry_point, &shader_module.0); + web_sys::GpuProgrammableStage::new(desc.entry_point, shader_module); let auto_layout = wasm_bindgen::JsValue::from(web_sys::GpuAutoLayoutMode::Auto); let mut mapped_desc = web_sys::GpuComputePipelineDescriptor::new( &match desc.layout { Some(layout) => { let layout: &::PipelineLayoutData = downcast_ref(layout.data.as_ref()); - JsValue::from(&layout.0) + JsValue::from(layout) } None => auto_layout, }, @@ -1645,7 +1630,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_compute_pipeline(&mapped_desc)) + create_identified(device_data.create_compute_pipeline(&mapped_desc)) } fn device_create_buffer( @@ -1660,7 +1645,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_buffer(&mapped_desc)) + create_identified(device_data.create_buffer(&mapped_desc)) } fn device_create_texture( @@ -1686,7 +1671,7 @@ impl crate::context::Context for Context { .map(|format| JsValue::from(map_texture_format(*format))) .collect::(); mapped_desc.view_formats(&mapped_view_formats); - create_identified(device_data.0.create_texture(&mapped_desc)) + create_identified(device_data.create_texture(&mapped_desc)) } fn device_create_sampler( @@ -1712,7 +1697,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_sampler_with_descriptor(&mapped_desc)) + create_identified(device_data.create_sampler_with_descriptor(&mapped_desc)) } fn device_create_query_set( @@ -1730,7 +1715,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.0.create_query_set(&mapped_desc)) + create_identified(device_data.create_query_set(&mapped_desc)) } fn device_create_command_encoder( @@ -1743,11 +1728,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified( - device_data - .0 - .create_command_encoder_with_descriptor(&mapped_desc), - ) + create_identified(device_data.create_command_encoder_with_descriptor(&mapped_desc)) } fn device_create_render_bundle_encoder( @@ -1774,7 +1755,7 @@ impl crate::context::Context for Context { mapped_desc.stencil_read_only(ds.stencil_read_only); } mapped_desc.sample_count(desc.sample_count); - create_identified(device_data.0.create_render_bundle_encoder(&mapped_desc)) + create_identified(device_data.create_render_bundle_encoder(&mapped_desc)) } fn device_drop(&self, _device: &Self::DeviceId, _device_data: &Self::DeviceData) { @@ -1801,9 +1782,7 @@ impl crate::context::Context for Context { let error = crate::Error::from_js(event.error().value_of()); handler(error); }) as Box); - device_data - .0 - .set_onuncapturederror(Some(f.as_ref().unchecked_ref())); + device_data.set_onuncapturederror(Some(f.as_ref().unchecked_ref())); // TODO: This will leak the memory associated with the error handler by default. f.forget(); } @@ -1814,7 +1793,7 @@ impl crate::context::Context for Context { device_data: &Self::DeviceData, filter: crate::ErrorFilter, ) { - device_data.0.push_error_scope(match filter { + device_data.push_error_scope(match filter { crate::ErrorFilter::OutOfMemory => web_sys::GpuErrorFilter::OutOfMemory, crate::ErrorFilter::Validation => web_sys::GpuErrorFilter::Validation, }); @@ -1825,8 +1804,8 @@ impl crate::context::Context for Context { _device: &Self::DeviceId, device_data: &Self::DeviceData, ) -> Self::PopErrorScopeFuture { - let error_promise = device_data.0.pop_error_scope(); - MakeSendFuture::new( + let error_promise = device_data.pop_error_scope(); + MapFuture::new( wasm_bindgen_futures::JsFuture::from(error_promise), future_pop_error_scope, ) @@ -1838,9 +1817,9 @@ impl crate::context::Context for Context { buffer_data: &Self::BufferData, mode: crate::MapMode, range: Range, - callback: Box) + Send + 'static>, + callback: crate::context::BufferMapCallback, ) { - let map_promise = buffer_data.0.map_async_with_f64_and_f64( + let map_promise = buffer_data.map_async_with_f64_and_f64( map_map_mode(mode), range.start as f64, (range.end - range.start) as f64, @@ -1855,7 +1834,7 @@ impl crate::context::Context for Context { buffer_data: &Self::BufferData, sub_range: Range, ) -> Box { - let array_buffer = buffer_data.0.get_mapped_range_with_f64_and_f64( + let array_buffer = buffer_data.get_mapped_range_with_f64_and_f64( sub_range.start as f64, (sub_range.end - sub_range.start) as f64, ); @@ -1868,7 +1847,7 @@ impl crate::context::Context for Context { } fn buffer_unmap(&self, _buffer: &Self::BufferId, buffer_data: &Self::BufferData) { - buffer_data.0.unmap(); + buffer_data.unmap(); } fn texture_create_view( @@ -1896,7 +1875,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped.label(label); } - create_identified(texture_data.0.create_view_with_descriptor(&mapped)) + create_identified(texture_data.create_view_with_descriptor(&mapped)) } fn surface_drop(&self, _surface: &Self::SurfaceId, _surface_data: &Self::SurfaceData) { @@ -1908,7 +1887,7 @@ impl crate::context::Context for Context { } fn buffer_destroy(&self, _buffer: &Self::BufferId, buffer_data: &Self::BufferData) { - buffer_data.0.destroy(); + buffer_data.destroy(); } fn buffer_drop(&self, _buffer: &Self::BufferId, _buffer_data: &Self::BufferData) { @@ -1916,7 +1895,7 @@ impl crate::context::Context for Context { } fn texture_destroy(&self, _texture: &Self::TextureId, texture_data: &Self::TextureData) { - texture_data.0.destroy(); + texture_data.destroy(); } fn texture_drop(&self, _texture: &Self::TextureId, _texture_data: &Self::TextureData) { @@ -2017,7 +1996,7 @@ impl crate::context::Context for Context { pipeline_data: &Self::ComputePipelineData, index: u32, ) -> (Self::BindGroupLayoutId, Self::BindGroupLayoutData) { - create_identified(pipeline_data.0.get_bind_group_layout(index)) + create_identified(pipeline_data.get_bind_group_layout(index)) } fn render_pipeline_get_bind_group_layout( @@ -2026,7 +2005,7 @@ impl crate::context::Context for Context { pipeline_data: &Self::RenderPipelineData, index: u32, ) -> (Self::BindGroupLayoutId, Self::BindGroupLayoutData) { - create_identified(pipeline_data.0.get_bind_group_layout(index)) + create_identified(pipeline_data.get_bind_group_layout(index)) } fn command_encoder_copy_buffer_to_buffer( @@ -2041,15 +2020,13 @@ impl crate::context::Context for Context { destination_offset: wgt::BufferAddress, copy_size: wgt::BufferAddress, ) { - encoder_data - .0 - .copy_buffer_to_buffer_with_f64_and_f64_and_f64( - &source_data.0, - source_offset as f64, - &destination_data.0, - destination_offset as f64, - copy_size as f64, - ) + encoder_data.copy_buffer_to_buffer_with_f64_and_f64_and_f64( + source_data, + source_offset as f64, + destination_data, + destination_offset as f64, + copy_size as f64, + ) } fn command_encoder_copy_buffer_to_texture( @@ -2060,13 +2037,11 @@ impl crate::context::Context for Context { destination: crate::ImageCopyTexture, copy_size: wgt::Extent3d, ) { - encoder_data - .0 - .copy_buffer_to_texture_with_gpu_extent_3d_dict( - &map_buffer_copy_view(source), - &map_texture_copy_view(destination), - &map_extent_3d(copy_size), - ) + encoder_data.copy_buffer_to_texture_with_gpu_extent_3d_dict( + &map_buffer_copy_view(source), + &map_texture_copy_view(destination), + &map_extent_3d(copy_size), + ) } fn command_encoder_copy_texture_to_buffer( @@ -2077,13 +2052,11 @@ impl crate::context::Context for Context { destination: crate::ImageCopyBuffer, copy_size: wgt::Extent3d, ) { - encoder_data - .0 - .copy_texture_to_buffer_with_gpu_extent_3d_dict( - &map_texture_copy_view(source), - &map_buffer_copy_view(destination), - &map_extent_3d(copy_size), - ) + encoder_data.copy_texture_to_buffer_with_gpu_extent_3d_dict( + &map_texture_copy_view(source), + &map_buffer_copy_view(destination), + &map_extent_3d(copy_size), + ) } fn command_encoder_copy_texture_to_texture( @@ -2094,13 +2067,11 @@ impl crate::context::Context for Context { destination: crate::ImageCopyTexture, copy_size: wgt::Extent3d, ) { - encoder_data - .0 - .copy_texture_to_texture_with_gpu_extent_3d_dict( - &map_texture_copy_view(source), - &map_texture_copy_view(destination), - &map_extent_3d(copy_size), - ) + encoder_data.copy_texture_to_texture_with_gpu_extent_3d_dict( + &map_texture_copy_view(source), + &map_texture_copy_view(destination), + &map_extent_3d(copy_size), + ) } fn command_encoder_begin_compute_pass( @@ -2113,11 +2084,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified( - encoder_data - .0 - .begin_compute_pass_with_descriptor(&mapped_desc), - ) + create_identified(encoder_data.begin_compute_pass_with_descriptor(&mapped_desc)) } fn command_encoder_end_compute_pass( @@ -2127,7 +2094,7 @@ impl crate::context::Context for Context { _pass: &mut Self::ComputePassId, pass_data: &mut Self::ComputePassData, ) { - pass_data.0.end(); + pass_data.end(); } fn command_encoder_begin_render_pass( @@ -2156,7 +2123,7 @@ impl crate::context::Context for Context { let mut mapped_color_attachment = web_sys::GpuRenderPassColorAttachment::new( load_value, map_store_op(ca.ops.store), - &view.0, + view, ); if let Some(cv) = clear_value { mapped_color_attachment.clear_value(&cv); @@ -2164,7 +2131,7 @@ impl crate::context::Context for Context { if let Some(rt) = ca.resolve_target { let resolve_target_view: &::TextureViewData = downcast_ref(rt.data.as_ref()); - mapped_color_attachment.resolve_target(&resolve_target_view.0); + mapped_color_attachment.resolve_target(resolve_target_view); } mapped_color_attachment.store_op(map_store_op(ca.ops.store)); @@ -2184,7 +2151,7 @@ impl crate::context::Context for Context { let depth_stencil_attachment: &::TextureViewData = downcast_ref(dsa.view.data.as_ref()); let mut mapped_depth_stencil_attachment = - web_sys::GpuRenderPassDepthStencilAttachment::new(&depth_stencil_attachment.0); + web_sys::GpuRenderPassDepthStencilAttachment::new(depth_stencil_attachment); if let Some(ref ops) = dsa.depth_ops { let load_op = match ops.load { crate::LoadOp::Clear(v) => { @@ -2212,7 +2179,7 @@ impl crate::context::Context for Context { mapped_desc.depth_stencil_attachment(&mapped_depth_stencil_attachment); } - create_identified(encoder_data.0.begin_render_pass(&mapped_desc)) + create_identified(encoder_data.begin_render_pass(&mapped_desc)) } fn command_encoder_end_render_pass( @@ -2222,7 +2189,7 @@ impl crate::context::Context for Context { _pass: &mut Self::RenderPassId, pass_data: &mut Self::RenderPassData, ) { - pass_data.0.end(); + pass_data.end(); } fn command_encoder_finish( @@ -2230,13 +2197,13 @@ impl crate::context::Context for Context { _encoder: Self::CommandEncoderId, encoder_data: &mut Self::CommandEncoderData, ) -> (Self::CommandBufferId, Self::CommandBufferData) { - let label = encoder_data.0.label(); + let label = encoder_data.label(); create_identified(if label.is_empty() { - encoder_data.0.finish() + encoder_data.finish() } else { let mut mapped_desc = web_sys::GpuCommandBufferDescriptor::new(); mapped_desc.label(&label); - encoder_data.0.finish_with_descriptor(&mapped_desc) + encoder_data.finish_with_descriptor(&mapped_desc) }) } @@ -2260,14 +2227,10 @@ impl crate::context::Context for Context { ) { let buffer: &::BufferData = downcast_ref(buffer.data.as_ref()); match size { - Some(size) => encoder_data.0.clear_buffer_with_f64_and_f64( - &buffer.0, - offset as f64, - size.get() as f64, - ), - None => encoder_data - .0 - .clear_buffer_with_f64(&buffer.0, offset as f64), + Some(size) => { + encoder_data.clear_buffer_with_f64_and_f64(buffer, offset as f64, size.get() as f64) + } + None => encoder_data.clear_buffer_with_f64(buffer, offset as f64), } } @@ -2308,9 +2271,7 @@ impl crate::context::Context for Context { query_set_data: &Self::QuerySetData, query_index: u32, ) { - encoder_data - .0 - .write_timestamp(&query_set_data.0, query_index); + encoder_data.write_timestamp(query_set_data, query_index); } fn command_encoder_resolve_query_set( @@ -2325,11 +2286,11 @@ impl crate::context::Context for Context { destination_data: &Self::BufferData, destination_offset: wgt::BufferAddress, ) { - encoder_data.0.resolve_query_set_with_u32( - &query_set_data.0, + encoder_data.resolve_query_set_with_u32( + query_set_data, first_query, query_count, - &destination_data.0, + destination_data, destination_offset as u32, ); } @@ -2344,9 +2305,9 @@ impl crate::context::Context for Context { Some(label) => { let mut mapped_desc = web_sys::GpuRenderBundleDescriptor::new(); mapped_desc.label(label); - encoder_data.0.finish_with_descriptor(&mapped_desc) + encoder_data.finish_with_descriptor(&mapped_desc) } - None => encoder_data.0.finish(), + None => encoder_data.finish(), }) } @@ -2360,23 +2321,21 @@ impl crate::context::Context for Context { data: &[u8], ) { /* Skip the copy once gecko allows BufferSource instead of ArrayBuffer - queue_data.0.write_buffer_with_f64_and_u8_array_and_f64_and_f64( - &buffer_data.0, + queue_data.write_buffer_with_f64_and_u8_array_and_f64_and_f64( + buffer_data, offset as f64, data, 0f64, data.len() as f64, ); */ - queue_data - .0 - .write_buffer_with_f64_and_buffer_source_and_f64_and_f64( - &buffer_data.0, - offset as f64, - &js_sys::Uint8Array::from(data).buffer(), - 0f64, - data.len() as f64, - ); + queue_data.write_buffer_with_f64_and_buffer_source_and_f64_and_f64( + buffer_data, + offset as f64, + &js_sys::Uint8Array::from(data).buffer(), + 0f64, + data.len() as f64, + ); } fn queue_validate_write_buffer( @@ -2388,7 +2347,7 @@ impl crate::context::Context for Context { offset: wgt::BufferAddress, size: wgt::BufferSize, ) -> Option<()> { - let usage = wgt::BufferUsages::from_bits_truncate(buffer_data.0.usage()); + let usage = wgt::BufferUsages::from_bits_truncate(buffer_data.usage()); // TODO: actually send this down the error scope if !usage.contains(wgt::BufferUsages::COPY_DST) { log::error!("Destination buffer is missing the `COPY_DST` usage flag"); @@ -2409,8 +2368,8 @@ impl crate::context::Context for Context { ); return None; } - if write_size + offset > buffer_data.0.size() as u64 { - log::error!("copy of {}..{} would end up overrunning the bounds of the destination buffer of size {}", offset, offset + write_size, buffer_data.0.size()); + if write_size + offset > buffer_data.size() as u64 { + log::error!("copy of {}..{} would end up overrunning the bounds of the destination buffer of size {}", offset, offset + write_size, buffer_data.size()); return None; } Some(()) @@ -2470,21 +2429,19 @@ impl crate::context::Context for Context { mapped_data_layout.offset(data_layout.offset as f64); /* Skip the copy once gecko allows BufferSource instead of ArrayBuffer - queue_data.0.write_texture_with_u8_array_and_gpu_extent_3d_dict( + queue_data.write_texture_with_u8_array_and_gpu_extent_3d_dict( &map_texture_copy_view(texture), data, &mapped_data_layout, &map_extent_3d(size), ); */ - queue_data - .0 - .write_texture_with_buffer_source_and_gpu_extent_3d_dict( - &map_texture_copy_view(texture), - &js_sys::Uint8Array::from(data).buffer(), - &mapped_data_layout, - &map_extent_3d(size), - ); + queue_data.write_texture_with_buffer_source_and_gpu_extent_3d_dict( + &map_texture_copy_view(texture), + &js_sys::Uint8Array::from(data).buffer(), + &mapped_data_layout, + &map_extent_3d(size), + ); } fn queue_copy_external_image_to_texture( @@ -2495,13 +2452,11 @@ impl crate::context::Context for Context { dest: crate::ImageCopyTextureTagged, size: wgt::Extent3d, ) { - queue_data - .0 - .copy_external_image_to_texture_with_gpu_extent_3d_dict( - &map_external_texture_copy_view(source), - &map_tagged_texture_copy_view(dest), - &map_extent_3d(size), - ); + queue_data.copy_external_image_to_texture_with_gpu_extent_3d_dict( + &map_external_texture_copy_view(source), + &map_tagged_texture_copy_view(dest), + &map_extent_3d(size), + ); } fn queue_submit>( @@ -2511,10 +2466,10 @@ impl crate::context::Context for Context { command_buffers: I, ) -> (Self::SubmissionIndex, Self::SubmissionIndexData) { let temp_command_buffers = command_buffers - .map(|(_, data)| data.0) + .map(|(_, data)| data) .collect::(); - queue_data.0.submit(&temp_command_buffers); + queue_data.submit(&temp_command_buffers); (Unused, ()) } @@ -2531,7 +2486,7 @@ impl crate::context::Context for Context { &self, _queue: &Self::QueueId, _queue_data: &Self::QueueData, - _callback: Box, + _callback: crate::context::SubmittedWorkDoneCallback, ) { unimplemented!() } @@ -2546,7 +2501,7 @@ impl crate::context::Context for Context { _pipeline: &Self::ComputePipelineId, pipeline_data: &Self::ComputePipelineData, ) { - pass_data.0.set_pipeline(&pipeline_data.0) + pass_data.set_pipeline(pipeline_data) } fn compute_pass_set_bind_group( @@ -2558,15 +2513,13 @@ impl crate::context::Context for Context { bind_group_data: &Self::BindGroupData, offsets: &[wgt::DynamicOffset], ) { - pass_data - .0 - .set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( - index, - &bind_group_data.0, - offsets, - 0f64, - offsets.len() as u32, - ); + pass_data.set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( + index, + bind_group_data, + offsets, + 0f64, + offsets.len() as u32, + ); } fn compute_pass_set_push_constants( @@ -2646,9 +2599,7 @@ impl crate::context::Context for Context { y: u32, z: u32, ) { - pass_data - .0 - .dispatch_workgroups_with_workgroup_count_y_and_workgroup_count_z(x, y, z); + pass_data.dispatch_workgroups_with_workgroup_count_y_and_workgroup_count_z(x, y, z); } fn compute_pass_dispatch_workgroups_indirect( @@ -2660,8 +2611,7 @@ impl crate::context::Context for Context { indirect_offset: wgt::BufferAddress, ) { pass_data - .0 - .dispatch_workgroups_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); + .dispatch_workgroups_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); } fn render_bundle_encoder_set_pipeline( @@ -2671,7 +2621,7 @@ impl crate::context::Context for Context { _pipeline: &Self::RenderPipelineId, pipeline_data: &Self::RenderPipelineData, ) { - encoder_data.0.set_pipeline(&pipeline_data.0); + encoder_data.set_pipeline(pipeline_data); } fn render_bundle_encoder_set_bind_group( @@ -2683,15 +2633,13 @@ impl crate::context::Context for Context { bind_group_data: &Self::BindGroupData, offsets: &[wgt::DynamicOffset], ) { - encoder_data - .0 - .set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( - index, - &bind_group_data.0, - offsets, - 0f64, - offsets.len() as u32, - ); + encoder_data.set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( + index, + bind_group_data, + offsets, + 0f64, + offsets.len() as u32, + ); } fn render_bundle_encoder_set_index_buffer( @@ -2706,16 +2654,16 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - encoder_data.0.set_index_buffer_with_f64_and_f64( - &buffer_data.0, + encoder_data.set_index_buffer_with_f64_and_f64( + buffer_data, map_index_format(index_format), offset as f64, s.get() as f64, ); } None => { - encoder_data.0.set_index_buffer_with_f64( - &buffer_data.0, + encoder_data.set_index_buffer_with_f64( + buffer_data, map_index_format(index_format), offset as f64, ); @@ -2735,17 +2683,15 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - encoder_data.0.set_vertex_buffer_with_f64_and_f64( + encoder_data.set_vertex_buffer_with_f64_and_f64( slot, - &buffer_data.0, + buffer_data, offset as f64, s.get() as f64, ); } None => { - encoder_data - .0 - .set_vertex_buffer_with_f64(slot, &buffer_data.0, offset as f64); + encoder_data.set_vertex_buffer_with_f64(slot, buffer_data, offset as f64); } }; } @@ -2768,14 +2714,12 @@ impl crate::context::Context for Context { vertices: Range, instances: Range, ) { - encoder_data - .0 - .draw_with_instance_count_and_first_vertex_and_first_instance( - vertices.end - vertices.start, - instances.end - instances.start, - vertices.start, - instances.start, - ); + encoder_data.draw_with_instance_count_and_first_vertex_and_first_instance( + vertices.end - vertices.start, + instances.end - instances.start, + vertices.start, + instances.start, + ); } fn render_bundle_encoder_draw_indexed( @@ -2787,7 +2731,6 @@ impl crate::context::Context for Context { instances: Range, ) { encoder_data - .0 .draw_indexed_with_instance_count_and_first_index_and_base_vertex_and_first_instance( indices.end - indices.start, instances.end - instances.start, @@ -2805,9 +2748,7 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - encoder_data - .0 - .draw_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); + encoder_data.draw_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); } fn render_bundle_encoder_draw_indexed_indirect( @@ -2818,9 +2759,7 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - encoder_data - .0 - .draw_indexed_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); + encoder_data.draw_indexed_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); } fn render_bundle_encoder_multi_draw_indirect( @@ -2886,7 +2825,7 @@ impl crate::context::Context for Context { _pipeline: &Self::RenderPipelineId, pipeline_data: &Self::RenderPipelineData, ) { - pass_data.0.set_pipeline(&pipeline_data.0); + pass_data.set_pipeline(pipeline_data); } fn render_pass_set_bind_group( @@ -2898,15 +2837,13 @@ impl crate::context::Context for Context { bind_group_data: &Self::BindGroupData, offsets: &[wgt::DynamicOffset], ) { - pass_data - .0 - .set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( - index, - &bind_group_data.0, - offsets, - 0f64, - offsets.len() as u32, - ); + pass_data.set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( + index, + bind_group_data, + offsets, + 0f64, + offsets.len() as u32, + ); } fn render_pass_set_index_buffer( @@ -2921,16 +2858,16 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - pass_data.0.set_index_buffer_with_f64_and_f64( - &buffer_data.0, + pass_data.set_index_buffer_with_f64_and_f64( + buffer_data, map_index_format(index_format), offset as f64, s.get() as f64, ); } None => { - pass_data.0.set_index_buffer_with_f64( - &buffer_data.0, + pass_data.set_index_buffer_with_f64( + buffer_data, map_index_format(index_format), offset as f64, ); @@ -2950,17 +2887,15 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - pass_data.0.set_vertex_buffer_with_f64_and_f64( + pass_data.set_vertex_buffer_with_f64_and_f64( slot, - &buffer_data.0, + buffer_data, offset as f64, s.get() as f64, ); } None => { - pass_data - .0 - .set_vertex_buffer_with_f64(slot, &buffer_data.0, offset as f64); + pass_data.set_vertex_buffer_with_f64(slot, buffer_data, offset as f64); } }; } @@ -2983,14 +2918,12 @@ impl crate::context::Context for Context { vertices: Range, instances: Range, ) { - pass_data - .0 - .draw_with_instance_count_and_first_vertex_and_first_instance( - vertices.end - vertices.start, - instances.end - instances.start, - vertices.start, - instances.start, - ); + pass_data.draw_with_instance_count_and_first_vertex_and_first_instance( + vertices.end - vertices.start, + instances.end - instances.start, + vertices.start, + instances.start, + ); } fn render_pass_draw_indexed( @@ -3002,7 +2935,6 @@ impl crate::context::Context for Context { instances: Range, ) { pass_data - .0 .draw_indexed_with_instance_count_and_first_index_and_base_vertex_and_first_instance( indices.end - indices.start, instances.end - instances.start, @@ -3020,9 +2952,7 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - pass_data - .0 - .draw_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); + pass_data.draw_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); } fn render_pass_draw_indexed_indirect( @@ -3033,9 +2963,7 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - pass_data - .0 - .draw_indexed_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); + pass_data.draw_indexed_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); } fn render_pass_multi_draw_indirect( @@ -3100,9 +3028,7 @@ impl crate::context::Context for Context { pass_data: &mut Self::RenderPassData, color: wgt::Color, ) { - pass_data - .0 - .set_blend_constant_with_gpu_color_dict(&map_color(color)); + pass_data.set_blend_constant_with_gpu_color_dict(&map_color(color)); } fn render_pass_set_scissor_rect( @@ -3114,7 +3040,7 @@ impl crate::context::Context for Context { width: u32, height: u32, ) { - pass_data.0.set_scissor_rect(x, y, width, height); + pass_data.set_scissor_rect(x, y, width, height); } fn render_pass_set_viewport( @@ -3128,9 +3054,7 @@ impl crate::context::Context for Context { min_depth: f32, max_depth: f32, ) { - pass_data - .0 - .set_viewport(x, y, width, height, min_depth, max_depth); + pass_data.set_viewport(x, y, width, height, min_depth, max_depth); } fn render_pass_set_stencil_reference( @@ -3139,7 +3063,7 @@ impl crate::context::Context for Context { pass_data: &mut Self::RenderPassData, reference: u32, ) { - pass_data.0.set_stencil_reference(reference); + pass_data.set_stencil_reference(reference); } fn render_pass_insert_debug_marker( @@ -3210,9 +3134,9 @@ impl crate::context::Context for Context { >, ) { let mapped = render_bundles - .map(|(_, bundle_data)| &bundle_data.0) + .map(|(_, bundle_data)| bundle_data) .collect::(); - pass_data.0.execute_bundles(&mapped); + pass_data.execute_bundles(&mapped); } } diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index 6633e61b61..458252ba35 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -8,10 +8,10 @@ use wgt::{ }; use crate::{ - BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, BufferAsyncError, BufferDescriptor, - CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, DeviceDescriptor, - Error, ErrorFilter, ImageCopyBuffer, ImageCopyTexture, Maintain, MapMode, - PipelineLayoutDescriptor, QuerySetDescriptor, RenderBundleDescriptor, + AnySendSync, BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, BufferAsyncError, + BufferDescriptor, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, + DeviceDescriptor, Error, ErrorFilter, ImageCopyBuffer, ImageCopyTexture, Maintain, MapMode, + MaybeSend, MaybeSync, PipelineLayoutDescriptor, QuerySetDescriptor, RenderBundleDescriptor, RenderBundleEncoderDescriptor, RenderPassDescriptor, RenderPipelineDescriptor, RequestAdapterOptions, RequestDeviceError, SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, Texture, TextureDescriptor, TextureViewDescriptor, @@ -27,59 +27,59 @@ impl + From + 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 ContextData for T {} +pub trait ContextData: Debug + MaybeSend + MaybeSync + 'static {} +impl ContextData for T {} -pub trait Context: Debug + Send + Sized + Sync { - type AdapterId: ContextId + Send + Sync; +pub trait Context: Debug + MaybeSend + MaybeSync + Sized { + type AdapterId: ContextId + MaybeSend + MaybeSync; type AdapterData: ContextData; - type DeviceId: ContextId + Send + Sync; + type DeviceId: ContextId + MaybeSend + MaybeSync; type DeviceData: ContextData; - type QueueId: ContextId + Send + Sync; + type QueueId: ContextId + MaybeSend + MaybeSync; type QueueData: ContextData; - type ShaderModuleId: ContextId + Send + Sync; + type ShaderModuleId: ContextId + MaybeSend + MaybeSync; type ShaderModuleData: ContextData; - type BindGroupLayoutId: ContextId + Send + Sync; + type BindGroupLayoutId: ContextId + MaybeSend + MaybeSync; type BindGroupLayoutData: ContextData; - type BindGroupId: ContextId + Send + Sync; + type BindGroupId: ContextId + MaybeSend + MaybeSync; type BindGroupData: ContextData; - type TextureViewId: ContextId + Send + Sync; + type TextureViewId: ContextId + MaybeSend + MaybeSync; type TextureViewData: ContextData; - type SamplerId: ContextId + Send + Sync; + type SamplerId: ContextId + MaybeSend + MaybeSync; type SamplerData: ContextData; - type BufferId: ContextId + Send + Sync; + type BufferId: ContextId + MaybeSend + MaybeSync; type BufferData: ContextData; - type TextureId: ContextId + Send + Sync; + type TextureId: ContextId + MaybeSend + MaybeSync; type TextureData: ContextData; - type QuerySetId: ContextId + Send + Sync; + type QuerySetId: ContextId + MaybeSend + MaybeSync; type QuerySetData: ContextData; - type PipelineLayoutId: ContextId + Send + Sync; + type PipelineLayoutId: ContextId + MaybeSend + MaybeSync; type PipelineLayoutData: ContextData; - type RenderPipelineId: ContextId + Send + Sync; + type RenderPipelineId: ContextId + MaybeSend + MaybeSync; type RenderPipelineData: ContextData; - type ComputePipelineId: ContextId + Send + Sync; + type ComputePipelineId: ContextId + MaybeSend + MaybeSync; type ComputePipelineData: ContextData; - type CommandEncoderId: ContextId + Send + Sync; + type CommandEncoderId: ContextId + MaybeSend + MaybeSync; type CommandEncoderData: ContextData; type ComputePassId: ContextId; type ComputePassData: ContextData; type RenderPassId: ContextId; type RenderPassData: ContextData; - type CommandBufferId: ContextId + Send + Sync; + type CommandBufferId: ContextId + MaybeSend + MaybeSync; type CommandBufferData: ContextData; type RenderBundleEncoderId: ContextId; type RenderBundleEncoderData: ContextData; - type RenderBundleId: ContextId + Send + Sync; + type RenderBundleId: ContextId + MaybeSend + MaybeSync; type RenderBundleData: ContextData; - type SurfaceId: ContextId + Send + Sync; + type SurfaceId: ContextId + MaybeSend + MaybeSync; type SurfaceData: ContextData; - type SurfaceOutputDetail: Send + Sync + 'static; - type SubmissionIndex: ContextId + Clone + Copy + Send + Sync; + type SurfaceOutputDetail: MaybeSend + MaybeSync + 'static; + type SubmissionIndex: ContextId + Clone + Copy + MaybeSend + MaybeSync; type SubmissionIndexData: ContextData + Copy; type RequestAdapterFuture: Future> - + Send + + MaybeSend + 'static; type RequestDeviceFuture: Future< Output = Result< @@ -91,9 +91,9 @@ pub trait Context: Debug + Send + Sized + Sync { ), RequestDeviceError, >, - > + Send + > + MaybeSend + 'static; - type PopErrorScopeFuture: Future> + Send + 'static; + type PopErrorScopeFuture: Future> + MaybeSend + '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, - callback: Box) + 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, + callback: SubmittedWorkDoneCallback, ); fn device_start_capture(&self, device: &Self::DeviceId, device_data: &Self::DeviceData); @@ -1039,15 +1039,16 @@ impl ObjectId { } } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ObjectId: Send, Sync); -pub(crate) fn downcast_ref(data: &crate::Data) -> &T { +pub(crate) fn downcast_ref(data: &crate::Data) -> &T { strict_assert!(data.is::()); // Copied from std. unsafe { &*(data as *const dyn Any as *const T) } } -fn downcast_mut(data: &mut crate::Data) -> &mut T { +fn downcast_mut(data: &mut crate::Data) -> &mut T { strict_assert!(data.is::()); // Copied from std. unsafe { &mut *(data as *mut dyn Any as *mut T) } @@ -1079,8 +1080,37 @@ pub(crate) struct DeviceRequest { pub queue_data: Box, } +#[cfg(not(target_arch = "wasm32"))] +pub type BufferMapCallback = Box) + Send + 'static>; +#[cfg(target_arch = "wasm32")] +pub type BufferMapCallback = Box) + 'static>; + +#[cfg(not(target_arch = "wasm32"))] +pub(crate) type AdapterRequestDeviceFuture = + Box> + Send>; +#[cfg(target_arch = "wasm32")] +pub(crate) type AdapterRequestDeviceFuture = + Box>>; + +#[cfg(not(target_arch = "wasm32"))] +pub type InstanceRequestAdapterFuture = + Box)>> + Send>; +#[cfg(target_arch = "wasm32")] +pub type InstanceRequestAdapterFuture = + Box)>>>; + +#[cfg(not(target_arch = "wasm32"))] +pub type DevicePopErrorFuture = Box> + Send>; +#[cfg(target_arch = "wasm32")] +pub type DevicePopErrorFuture = Box>>; + +#[cfg(not(target_arch = "wasm32"))] +pub type SubmittedWorkDoneCallback = Box; +#[cfg(target_arch = "wasm32")] +pub type SubmittedWorkDoneCallback = Box; + /// 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 + MaybeSend + MaybeSync { fn as_any(&self) -> &dyn Any; fn instance_create_surface( @@ -1092,14 +1122,14 @@ pub(crate) trait DynContext: Debug + Send + Sync { fn instance_request_adapter( &self, options: &RequestAdapterOptions<'_>, - ) -> Pin)>> + Send>>; + ) -> Pin; fn adapter_request_device( &self, adapter: &ObjectId, adapter_data: &crate::Data, desc: &DeviceDescriptor, trace_dir: Option<&std::path::Path>, - ) -> Pin> + Send>>; + ) -> Pin; fn instance_poll_all_devices(&self, force_wait: bool) -> bool; fn adapter_is_surface_supported( @@ -1152,10 +1182,10 @@ pub(crate) trait DynContext: Debug + Send + Sync { Option, Option>, SurfaceStatus, - Box, + Box, ); - 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 AnySendSync); + fn surface_texture_discard(&self, texture: &ObjectId, detail: &dyn AnySendSync); fn device_features(&self, device: &ObjectId, device_data: &crate::Data) -> Features; fn device_limits(&self, device: &ObjectId, device_data: &crate::Data) -> Limits; @@ -1262,14 +1292,14 @@ pub(crate) trait DynContext: Debug + Send + Sync { &self, device: &ObjectId, device_data: &crate::Data, - ) -> Pin> + Send + 'static>>; + ) -> Pin; fn buffer_map_async( &self, buffer: &ObjectId, buffer_data: &crate::Data, mode: MapMode, range: Range, - callback: Box) + Send + 'static>, + callback: BufferMapCallback, ); fn buffer_get_mapped_range( &self, @@ -1511,7 +1541,7 @@ pub(crate) trait DynContext: Debug + Send + Sync { &self, queue: &ObjectId, queue_data: &crate::Data, - callback: Box, + callback: SubmittedWorkDoneCallback, ); fn device_start_capture(&self, device: &ObjectId, data: &crate::Data); @@ -1931,7 +1961,7 @@ where fn instance_request_adapter( &self, options: &RequestAdapterOptions<'_>, - ) -> Pin)>> + Send>> { + ) -> Pin { 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 +1975,7 @@ where adapter_data: &crate::Data, desc: &DeviceDescriptor, trace_dir: Option<&std::path::Path>, - ) -> Pin> + Send>> { + ) -> Pin { let adapter = ::from(*adapter); let adapter_data = downcast_ref(adapter_data); let future = Context::adapter_request_device(self, &adapter, adapter_data, desc, trace_dir); @@ -2064,13 +2094,13 @@ where Option, Option>, SurfaceStatus, - Box, + Box, ) { let surface = ::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; + let detail = Box::new(detail) as Box; ( texture.map(Into::into), texture_data.map(|b| Box::new(b) as _), @@ -2079,12 +2109,12 @@ where ) } - fn surface_present(&self, texture: &ObjectId, detail: &(dyn Any + Send + Sync)) { + fn surface_present(&self, texture: &ObjectId, detail: &dyn AnySendSync) { let texture = ::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 AnySendSync) { let texture = ::from(*texture); Context::surface_texture_discard(self, &texture, detail.downcast_ref().unwrap()) } @@ -2325,7 +2355,7 @@ where &self, device: &ObjectId, device_data: &crate::Data, - ) -> Pin> + Send + 'static>> { + ) -> Pin { let device = ::from(*device); let device_data = downcast_ref(device_data); Box::pin(Context::device_pop_error_scope(self, &device, device_data)) @@ -2337,7 +2367,7 @@ where buffer_data: &crate::Data, mode: MapMode, range: Range, - callback: Box) + Send + 'static>, + callback: BufferMapCallback, ) { let buffer = ::from(*buffer); let buffer_data = downcast_ref(buffer_data); @@ -2928,7 +2958,7 @@ where &self, queue: &ObjectId, queue_data: &crate::Data, - callback: Box, + callback: SubmittedWorkDoneCallback, ) { let queue = ::from(*queue); let queue_data = downcast_ref(queue_data); @@ -3861,7 +3891,7 @@ where } } -pub trait QueueWriteBuffer: Send + Sync { +pub trait QueueWriteBuffer: MaybeSend + MaybeSync { fn slice(&self) -> &[u8]; fn slice_mut(&mut self) -> &mut [u8]; diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index a9a45ffaa1..4a2ea84e04 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -66,8 +66,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 +78,10 @@ pub enum ErrorFilter { static_assertions::assert_impl_all!(ErrorFilter: Send, Sync); type C = dyn DynContext; +#[cfg(not(target_arch = "wasm32"))] type Data = dyn Any + Send + Sync; +#[cfg(target_arch = "wasm32")] +type Data = dyn Any; /// Context for all other wgpu objects. Instance of wgpu. /// @@ -94,6 +95,7 @@ type Data = dyn Any + Send + Sync; pub struct Instance { context: Arc, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Instance: Send, Sync); /// Handle to a physical graphics and/or compute device. @@ -110,6 +112,7 @@ pub struct Adapter { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Adapter: Send, Sync); impl Drop for Adapter { @@ -134,6 +137,7 @@ pub struct Device { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Device: Send, Sync); /// Identifier for a particular call to [`Queue::submit`]. Can be used @@ -144,6 +148,7 @@ static_assertions::assert_impl_all!(Device: Send, Sync); /// There is no analogue in the WebGPU specification. #[derive(Debug, Clone)] pub struct SubmissionIndex(ObjectId, Arc); +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync); /// The main purpose of this struct is to resolve mapped ranges (convert sizes @@ -220,6 +225,7 @@ pub struct Buffer { usage: BufferUsages, // Todo: missing map_state https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapstate } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Buffer: Send, Sync); /// Slice into a [`Buffer`]. @@ -236,6 +242,7 @@ pub struct BufferSlice<'a> { offset: BufferAddress, size: Option, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BufferSlice: Send, Sync); /// Handle to a texture on the GPU. @@ -251,6 +258,7 @@ pub struct Texture { owned: bool, descriptor: TextureDescriptor<'static>, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Texture: Send, Sync); /// Handle to a texture view. @@ -265,6 +273,7 @@ pub struct TextureView { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(TextureView: Send, Sync); /// Handle to a sampler. @@ -282,6 +291,7 @@ pub struct Sampler { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Sampler: Send, Sync); impl Drop for Sampler { @@ -322,6 +332,7 @@ pub struct Surface { // been created is is additionally wrapped in an option. config: Mutex>, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Surface: Send, Sync); impl Drop for Surface { @@ -349,6 +360,7 @@ pub struct BindGroupLayout { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BindGroupLayout: Send, Sync); impl Drop for BindGroupLayout { @@ -374,6 +386,7 @@ pub struct BindGroup { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BindGroup: Send, Sync); impl Drop for BindGroup { @@ -398,6 +411,7 @@ pub struct ShaderModule { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ShaderModule: Send, Sync); impl Drop for ShaderModule { @@ -490,6 +504,7 @@ pub struct PipelineLayout { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(PipelineLayout: Send, Sync); impl Drop for PipelineLayout { @@ -513,6 +528,7 @@ pub struct RenderPipeline { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RenderPipeline: Send, Sync); impl Drop for RenderPipeline { @@ -547,6 +563,7 @@ pub struct ComputePipeline { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ComputePipeline: Send, Sync); impl Drop for ComputePipeline { @@ -584,6 +601,7 @@ pub struct CommandBuffer { id: Option, data: Option>, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(CommandBuffer: Send, Sync); impl Drop for CommandBuffer { @@ -612,6 +630,7 @@ pub struct CommandEncoder { id: Option, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(CommandEncoder: Send, Sync); impl Drop for CommandEncoder { @@ -688,6 +707,7 @@ pub struct RenderBundle { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RenderBundle: Send, Sync); impl Drop for RenderBundle { @@ -709,6 +729,7 @@ pub struct QuerySet { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(QuerySet: Send, Sync); impl Drop for QuerySet { @@ -732,6 +753,7 @@ pub struct Queue { id: ObjectId, data: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Queue: Send, Sync); /// Resource that can be bound to a pipeline. @@ -777,6 +799,7 @@ pub enum BindingResource<'a> { /// [`BindGroupLayoutEntry::count`] set to Some. TextureViewArray(&'a [&'a TextureView]), } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BindingResource: Send, Sync); /// Describes the segment of a buffer to bind. @@ -808,6 +831,7 @@ pub struct BufferBinding<'a> { /// Size of the binding in bytes, or `None` for using the rest of the buffer. pub size: Option, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BufferBinding: Send, Sync); /// Operation to perform to the output attachment at the start of a render pass. @@ -869,6 +893,7 @@ pub struct RenderPassColorAttachment<'tex> { /// What operations will be performed on this color attachment. pub ops: Operations, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RenderPassColorAttachment: Send, Sync); /// Describes a depth/stencil attachment to a [`RenderPass`]. @@ -886,6 +911,7 @@ pub struct RenderPassDepthStencilAttachment<'tex> { /// What operations will be performed on the stencil part of the attachment. pub stencil_ops: Option>, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RenderPassDepthStencilAttachment: Send, Sync); // The underlying types are also exported so that documentation shows up for them @@ -900,6 +926,7 @@ 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(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RequestAdapterOptions: Send, Sync); /// Describes a [`Device`]. /// @@ -952,6 +979,7 @@ 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; +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Maintain: Send, Sync); /// Describes a [`TextureView`]. @@ -1007,6 +1035,7 @@ pub struct PipelineLayoutDescriptor<'a> { /// If this array is non-empty, the [`Features::PUSH_CONSTANTS`] must be enabled. pub push_constant_ranges: &'a [PushConstantRange], } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(PipelineLayoutDescriptor: Send, Sync); /// Describes a [`Sampler`]. @@ -1076,6 +1105,7 @@ pub struct BindGroupEntry<'a> { /// Resource to attach to the binding pub resource: BindingResource<'a>, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BindGroupEntry: Send, Sync); /// Describes a group of bindings and the resources to be bound. @@ -1093,6 +1123,7 @@ pub struct BindGroupDescriptor<'a> { /// The resources to bind to this bind group. pub entries: &'a [BindGroupEntry<'a>], } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(BindGroupDescriptor: Send, Sync); /// Describes the attachments of a render pass. @@ -1113,6 +1144,7 @@ pub struct RenderPassDescriptor<'tex, 'desc> { /// The depth and stencil attachment of the render pass, if any. pub depth_stencil_attachment: Option>, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RenderPassDescriptor: Send, Sync); /// Describes how the vertex buffer is interpreted. @@ -1148,6 +1180,7 @@ pub struct VertexState<'a> { /// The format of any vertex buffers used with this pipeline. pub buffers: &'a [VertexBufferLayout<'a>], } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(VertexState: Send, Sync); /// Describes the fragment processing in a render pipeline. @@ -1166,6 +1199,7 @@ pub struct FragmentState<'a> { /// The color state of the render targets. pub targets: &'a [Option], } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(FragmentState: Send, Sync); /// Describes a render (graphics) pipeline. @@ -1194,6 +1228,7 @@ pub struct RenderPipelineDescriptor<'a> { /// layers the attachments will have. pub multiview: Option, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(RenderPipelineDescriptor: Send, Sync); /// Describes the attachments of a compute pass. @@ -1227,6 +1262,7 @@ pub struct ComputePipelineDescriptor<'a> { /// and no return value in the shader. pub entry_point: &'a str, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ComputePipelineDescriptor: Send, Sync); pub use wgt::ImageCopyBuffer as ImageCopyBufferBase; @@ -1235,6 +1271,7 @@ 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(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ImageCopyBuffer: Send, Sync); pub use wgt::ImageCopyTexture as ImageCopyTextureBase; @@ -1243,6 +1280,7 @@ 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(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync); pub use wgt::ImageCopyTextureTagged as ImageCopyTextureTaggedBase; @@ -1252,6 +1290,7 @@ 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(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync); /// Describes a [`BindGroupLayout`]. @@ -1308,8 +1347,9 @@ pub struct SurfaceTexture { /// but should be recreated for maximum performance. pub suboptimal: bool, presented: bool, - detail: Box, + detail: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync); /// Result of an unsuccessful call to [`Surface::get_current_texture`]. @@ -1463,7 +1503,7 @@ impl Instance { pub fn request_adapter( &self, options: &RequestAdapterOptions, - ) -> impl Future> + Send { + ) -> impl Future> + MaybeSend { let context = Arc::clone(&self.context); let adapter = self.context.instance_request_adapter(options); async move { @@ -1743,7 +1783,7 @@ impl Adapter { &self, desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, - ) -> impl Future> + Send { + ) -> impl Future> + MaybeSend { let context = Arc::clone(&self.context); let device = DynContext::adapter_request_device( &*self.context, @@ -2257,7 +2297,7 @@ impl Device { } /// Pop an error scope. - pub fn pop_error_scope(&self) -> impl Future> + Send { + pub fn pop_error_scope(&self) -> impl Future> + MaybeSend { self.context .device_pop_error_scope(&self.id, self.data.as_ref()) } @@ -2562,7 +2602,7 @@ impl<'a> BufferSlice<'a> { pub fn map_async( &self, mode: MapMode, - callback: impl FnOnce(Result<(), BufferAsyncError>) + Send + 'static, + callback: impl FnOnce(Result<(), BufferAsyncError>) + MaybeSend + 'static, ) { let mut mc = self.buffer.map_context.lock(); assert_eq!( @@ -3970,6 +4010,7 @@ pub struct QueueWriteBufferView<'a> { offset: BufferAddress, inner: Box, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(QueueWriteBufferView: Send, Sync); impl Deref for QueueWriteBufferView<'_> { @@ -4609,16 +4650,25 @@ pub enum Error { /// Out of memory error OutOfMemory { /// Lower level source of the error. + #[cfg(not(target_arch = "wasm32"))] source: Box, + /// Lower level source of the error. + #[cfg(target_arch = "wasm32")] + source: Box, }, /// Validation error, signifying a bug in code or data Validation { /// Lower level source of the error. + #[cfg(not(target_arch = "wasm32"))] source: Box, + /// Lower level source of the error. + #[cfg(target_arch = "wasm32")] + source: Box, /// Description of the validation error. description: String, }, } +#[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(Error: Send); impl error::Error for Error { @@ -4638,3 +4688,51 @@ impl Display for Error { } } } + +use send_sync::*; + +mod send_sync { + use std::any::Any; + use std::fmt; + + #[cfg(not(target_arch = "wasm32"))] + pub trait MaybeSend: Send {} + #[cfg(not(target_arch = "wasm32"))] + impl MaybeSend for T {} + #[cfg(target_arch = "wasm32")] + pub trait MaybeSend {} + #[cfg(target_arch = "wasm32")] + impl MaybeSend for T {} + + #[cfg(not(target_arch = "wasm32"))] + pub trait MaybeSync: Sync {} + #[cfg(not(target_arch = "wasm32"))] + impl MaybeSync for T {} + #[cfg(target_arch = "wasm32")] + pub trait MaybeSync {} + #[cfg(target_arch = "wasm32")] + impl MaybeSync for T {} + + pub trait AnySendSync: Any + MaybeSend + MaybeSync { + fn upcast_any_ref(&self) -> &dyn Any; + } + impl AnySendSync for T { + #[inline] + fn upcast_any_ref(&self) -> &dyn Any { + self + } + } + + impl dyn AnySendSync + 'static { + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + self.upcast_any_ref().downcast_ref::() + } + } + + impl fmt::Debug for dyn AnySendSync { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Any").finish_non_exhaustive() + } + } +} From 241e1703342659dfa1cc836e7d7589e632318fe3 Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Wed, 19 Apr 2023 22:42:30 +0200 Subject: [PATCH 2/3] Address review --- wgpu-hal/src/lib.rs | 63 ++++++++++------------------- wgpu-types/src/lib.rs | 23 +++++++++++ wgpu/src/backend/direct.rs | 11 ++--- wgpu/src/context.rs | 82 +++++++++++++++++++------------------- wgpu/src/lib.rs | 43 +++++++------------- 5 files changed, 106 insertions(+), 116 deletions(-) diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index 0d0514faa8..910e46ca25 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -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; type CommandEncoder: CommandEncoder; - type CommandBuffer: MaybeSend + MaybeSync + fmt::Debug; + type CommandBuffer: WasmNotSend + WasmNotSync + fmt::Debug; - type Buffer: fmt::Debug + MaybeSend + MaybeSync + 'static; - type Texture: fmt::Debug + MaybeSend + MaybeSync + 'static; - type SurfaceTexture: fmt::Debug + MaybeSend + MaybeSync + Borrow; - type TextureView: fmt::Debug + MaybeSend + MaybeSync; - type Sampler: fmt::Debug + MaybeSend + MaybeSync; - type QuerySet: fmt::Debug + MaybeSend + MaybeSync; - type Fence: fmt::Debug + MaybeSend + MaybeSync; + type Buffer: fmt::Debug + WasmNotSend + WasmNotSync + 'static; + type Texture: fmt::Debug + WasmNotSend + WasmNotSync + 'static; + type SurfaceTexture: fmt::Debug + WasmNotSend + WasmNotSync + Borrow; + 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: MaybeSend + MaybeSync; - type BindGroup: fmt::Debug + MaybeSend + MaybeSync; - type PipelineLayout: MaybeSend + MaybeSync; - type ShaderModule: fmt::Debug + MaybeSend + MaybeSync; - type RenderPipeline: MaybeSend + MaybeSync; - type ComputePipeline: MaybeSend + MaybeSync; + 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: Sized + MaybeSend + MaybeSync { +pub trait Instance: Sized + WasmNotSend + WasmNotSync { unsafe fn init(desc: &InstanceDescriptor) -> Result; unsafe fn create_surface( &self, @@ -190,7 +191,7 @@ pub trait Instance: Sized + MaybeSend + MaybeSync { unsafe fn enumerate_adapters(&self) -> Vec>; } -pub trait Surface: MaybeSend + MaybeSync { +pub trait Surface: WasmNotSend + WasmNotSync { unsafe fn configure( &mut self, device: &A::Device, @@ -216,7 +217,7 @@ pub trait Surface: MaybeSend + MaybeSync { unsafe fn discard_texture(&mut self, texture: A::SurfaceTexture); } -pub trait Adapter: MaybeSend + MaybeSync { +pub trait Adapter: WasmNotSend + WasmNotSync { unsafe fn open( &self, features: wgt::Features, @@ -240,7 +241,7 @@ pub trait Adapter: MaybeSend + MaybeSync { unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp; } -pub trait Device: MaybeSend + MaybeSync { +pub trait Device: 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: MaybeSend + MaybeSync { unsafe fn stop_capture(&self); } -pub trait Queue: MaybeSend + MaybeSync { +pub trait Queue: WasmNotSend + WasmNotSync { /// Submits the command buffers for execution on GPU. /// /// Valid usage: @@ -360,7 +361,7 @@ pub trait Queue: MaybeSend + MaybeSync { /// 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: MaybeSend + MaybeSync + fmt::Debug { +pub trait CommandEncoder: 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. @@ -1309,28 +1310,6 @@ impl ValidationCanary { } } -use send_sync::*; - -mod send_sync { - #[cfg(not(target_arch = "wasm32"))] - pub trait MaybeSend: Send {} - #[cfg(not(target_arch = "wasm32"))] - impl MaybeSend for T {} - #[cfg(target_arch = "wasm32")] - pub trait MaybeSend {} - #[cfg(target_arch = "wasm32")] - impl MaybeSend for T {} - - #[cfg(not(target_arch = "wasm32"))] - pub trait MaybeSync: Sync {} - #[cfg(not(target_arch = "wasm32"))] - impl MaybeSync for T {} - #[cfg(target_arch = "wasm32")] - pub trait MaybeSync {} - #[cfg(target_arch = "wasm32")] - impl MaybeSync for T {} -} - #[test] fn test_default_limits() { let limits = wgt::Limits::default(); diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 5d56a74e31..ff977844e9 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -6312,3 +6312,26 @@ impl Default for InstanceDescriptor { } } } + +pub use send_sync::*; + +#[doc(hidden)] +mod send_sync { + #[cfg(not(target_arch = "wasm32"))] + pub trait WasmNotSend: Send {} + #[cfg(not(target_arch = "wasm32"))] + impl WasmNotSend for T {} + #[cfg(target_arch = "wasm32")] + pub trait WasmNotSend {} + #[cfg(target_arch = "wasm32")] + impl WasmNotSend for T {} + + #[cfg(not(target_arch = "wasm32"))] + pub trait WasmNotSync: Sync {} + #[cfg(not(target_arch = "wasm32"))] + impl WasmNotSync for T {} + #[cfg(target_arch = "wasm32")] + pub trait WasmNotSync {} + #[cfg(target_arch = "wasm32")] + impl WasmNotSync for T {} +} diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 5b7dd3cd3f..8fd5eb1fc8 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -2,8 +2,8 @@ use crate::{ context::{ObjectId, Unused}, AdapterInfo, BindGroupDescriptor, BindGroupLayoutDescriptor, BindingResource, BufferBinding, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, - DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode, MaybeSend, MaybeSync, - Operations, PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor, + DownlevelCapabilities, Features, Label, Limits, LoadOp, MapMode, Operations, + PipelineLayoutDescriptor, RenderBundleEncoderDescriptor, RenderPipelineDescriptor, SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, ShaderSource, SurfaceStatus, TextureDescriptor, TextureViewDescriptor, UncapturedErrorHandler, }; @@ -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, - cause: impl Error + MaybeSend + MaybeSync + '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, - cause: impl Error + MaybeSend + MaybeSync + '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 + MaybeSend + MaybeSync + 'static, + cause: impl Error + WasmNotSend + WasmNotSync + 'static, operation: &'static str, ) -> ! { panic!("Error in {operation}: {f}", f = self.format_error(&cause)); diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index 458252ba35..fbc85279cb 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -4,14 +4,14 @@ 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::{ - AnySendSync, BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, BufferAsyncError, + AnyWasmNotSendSync, BindGroupDescriptor, BindGroupLayoutDescriptor, Buffer, BufferAsyncError, BufferDescriptor, CommandEncoderDescriptor, ComputePassDescriptor, ComputePipelineDescriptor, DeviceDescriptor, Error, ErrorFilter, ImageCopyBuffer, ImageCopyTexture, Maintain, MapMode, - MaybeSend, MaybeSync, PipelineLayoutDescriptor, QuerySetDescriptor, RenderBundleDescriptor, + PipelineLayoutDescriptor, QuerySetDescriptor, RenderBundleDescriptor, RenderBundleEncoderDescriptor, RenderPassDescriptor, RenderPipelineDescriptor, RequestAdapterOptions, RequestDeviceError, SamplerDescriptor, ShaderModuleDescriptor, ShaderModuleDescriptorSpirV, Texture, TextureDescriptor, TextureViewDescriptor, @@ -27,59 +27,59 @@ impl + From + 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 + MaybeSend + MaybeSync + 'static {} -impl ContextData for T {} +pub trait ContextData: Debug + WasmNotSend + WasmNotSync + 'static {} +impl ContextData for T {} -pub trait Context: Debug + MaybeSend + MaybeSync + Sized { - type AdapterId: ContextId + MaybeSend + MaybeSync; +pub trait Context: Debug + WasmNotSend + WasmNotSync + Sized { + type AdapterId: ContextId + WasmNotSend + WasmNotSync; type AdapterData: ContextData; - type DeviceId: ContextId + MaybeSend + MaybeSync; + type DeviceId: ContextId + WasmNotSend + WasmNotSync; type DeviceData: ContextData; - type QueueId: ContextId + MaybeSend + MaybeSync; + type QueueId: ContextId + WasmNotSend + WasmNotSync; type QueueData: ContextData; - type ShaderModuleId: ContextId + MaybeSend + MaybeSync; + type ShaderModuleId: ContextId + WasmNotSend + WasmNotSync; type ShaderModuleData: ContextData; - type BindGroupLayoutId: ContextId + MaybeSend + MaybeSync; + type BindGroupLayoutId: ContextId + WasmNotSend + WasmNotSync; type BindGroupLayoutData: ContextData; - type BindGroupId: ContextId + MaybeSend + MaybeSync; + type BindGroupId: ContextId + WasmNotSend + WasmNotSync; type BindGroupData: ContextData; - type TextureViewId: ContextId + MaybeSend + MaybeSync; + type TextureViewId: ContextId + WasmNotSend + WasmNotSync; type TextureViewData: ContextData; - type SamplerId: ContextId + MaybeSend + MaybeSync; + type SamplerId: ContextId + WasmNotSend + WasmNotSync; type SamplerData: ContextData; - type BufferId: ContextId + MaybeSend + MaybeSync; + type BufferId: ContextId + WasmNotSend + WasmNotSync; type BufferData: ContextData; - type TextureId: ContextId + MaybeSend + MaybeSync; + type TextureId: ContextId + WasmNotSend + WasmNotSync; type TextureData: ContextData; - type QuerySetId: ContextId + MaybeSend + MaybeSync; + type QuerySetId: ContextId + WasmNotSend + WasmNotSync; type QuerySetData: ContextData; - type PipelineLayoutId: ContextId + MaybeSend + MaybeSync; + type PipelineLayoutId: ContextId + WasmNotSend + WasmNotSync; type PipelineLayoutData: ContextData; - type RenderPipelineId: ContextId + MaybeSend + MaybeSync; + type RenderPipelineId: ContextId + WasmNotSend + WasmNotSync; type RenderPipelineData: ContextData; - type ComputePipelineId: ContextId + MaybeSend + MaybeSync; + type ComputePipelineId: ContextId + WasmNotSend + WasmNotSync; type ComputePipelineData: ContextData; - type CommandEncoderId: ContextId + MaybeSend + MaybeSync; + type CommandEncoderId: ContextId + WasmNotSend + WasmNotSync; type CommandEncoderData: ContextData; type ComputePassId: ContextId; type ComputePassData: ContextData; type RenderPassId: ContextId; type RenderPassData: ContextData; - type CommandBufferId: ContextId + MaybeSend + MaybeSync; + type CommandBufferId: ContextId + WasmNotSend + WasmNotSync; type CommandBufferData: ContextData; type RenderBundleEncoderId: ContextId; type RenderBundleEncoderData: ContextData; - type RenderBundleId: ContextId + MaybeSend + MaybeSync; + type RenderBundleId: ContextId + WasmNotSend + WasmNotSync; type RenderBundleData: ContextData; - type SurfaceId: ContextId + MaybeSend + MaybeSync; + type SurfaceId: ContextId + WasmNotSend + WasmNotSync; type SurfaceData: ContextData; - type SurfaceOutputDetail: MaybeSend + MaybeSync + 'static; - type SubmissionIndex: ContextId + Clone + Copy + MaybeSend + MaybeSync; + type SurfaceOutputDetail: WasmNotSend + WasmNotSync + 'static; + type SubmissionIndex: ContextId + Clone + Copy + WasmNotSend + WasmNotSync; type SubmissionIndexData: ContextData + Copy; type RequestAdapterFuture: Future> - + MaybeSend + + WasmNotSend + 'static; type RequestDeviceFuture: Future< Output = Result< @@ -91,9 +91,9 @@ pub trait Context: Debug + MaybeSend + MaybeSync + Sized { ), RequestDeviceError, >, - > + MaybeSend + > + WasmNotSend + 'static; - type PopErrorScopeFuture: Future> + MaybeSend + 'static; + type PopErrorScopeFuture: Future> + WasmNotSend + 'static; fn init(instance_desc: wgt::InstanceDescriptor) -> Self; fn instance_create_surface( @@ -1042,13 +1042,15 @@ impl ObjectId { #[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(ObjectId: Send, Sync); -pub(crate) fn downcast_ref(data: &crate::Data) -> &T { +pub(crate) fn downcast_ref( + data: &crate::Data, +) -> &T { strict_assert!(data.is::()); // Copied from std. unsafe { &*(data as *const dyn Any as *const T) } } -fn downcast_mut(data: &mut crate::Data) -> &mut T { +fn downcast_mut(data: &mut crate::Data) -> &mut T { strict_assert!(data.is::()); // Copied from std. unsafe { &mut *(data as *mut dyn Any as *mut T) } @@ -1110,7 +1112,7 @@ pub type SubmittedWorkDoneCallback = Box; pub type SubmittedWorkDoneCallback = Box; /// An object safe variant of [`Context`] implemented by all types that implement [`Context`]. -pub(crate) trait DynContext: Debug + MaybeSend + MaybeSync { +pub(crate) trait DynContext: Debug + WasmNotSend + WasmNotSync { fn as_any(&self) -> &dyn Any; fn instance_create_surface( @@ -1182,10 +1184,10 @@ pub(crate) trait DynContext: Debug + MaybeSend + MaybeSync { Option, Option>, SurfaceStatus, - Box, + Box, ); - fn surface_present(&self, texture: &ObjectId, detail: &dyn AnySendSync); - fn surface_texture_discard(&self, texture: &ObjectId, detail: &dyn AnySendSync); + 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; @@ -2094,13 +2096,13 @@ where Option, Option>, SurfaceStatus, - Box, + Box, ) { let surface = ::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; + let detail = Box::new(detail) as Box; ( texture.map(Into::into), texture_data.map(|b| Box::new(b) as _), @@ -2109,12 +2111,12 @@ where ) } - fn surface_present(&self, texture: &ObjectId, detail: &dyn AnySendSync) { + fn surface_present(&self, texture: &ObjectId, detail: &dyn AnyWasmNotSendSync) { let texture = ::from(*texture); Context::surface_present(self, &texture, detail.downcast_ref().unwrap()) } - fn surface_texture_discard(&self, texture: &ObjectId, detail: &dyn AnySendSync) { + fn surface_texture_discard(&self, texture: &ObjectId, detail: &dyn AnyWasmNotSendSync) { let texture = ::from(*texture); Context::surface_texture_discard(self, &texture, detail.downcast_ref().unwrap()) } @@ -3891,7 +3893,7 @@ where } } -pub trait QueueWriteBuffer: MaybeSend + MaybeSync { +pub trait QueueWriteBuffer: WasmNotSend + WasmNotSync { fn slice(&self) -> &[u8]; fn slice_mut(&mut self) -> &mut [u8]; diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 4a2ea84e04..9080082094 100644 --- a/wgpu/src/lib.rs +++ b/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( @@ -1347,7 +1348,7 @@ pub struct SurfaceTexture { /// but should be recreated for maximum performance. pub suboptimal: bool, presented: bool, - detail: Box, + detail: Box, } #[cfg(not(target_arch = "wasm32"))] static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync); @@ -1503,7 +1504,7 @@ impl Instance { pub fn request_adapter( &self, options: &RequestAdapterOptions, - ) -> impl Future> + MaybeSend { + ) -> impl Future> + WasmNotSend { let context = Arc::clone(&self.context); let adapter = self.context.instance_request_adapter(options); async move { @@ -1783,7 +1784,7 @@ impl Adapter { &self, desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, - ) -> impl Future> + MaybeSend { + ) -> impl Future> + WasmNotSend { let context = Arc::clone(&self.context); let device = DynContext::adapter_request_device( &*self.context, @@ -2297,7 +2298,7 @@ impl Device { } /// Pop an error scope. - pub fn pop_error_scope(&self) -> impl Future> + MaybeSend { + pub fn pop_error_scope(&self) -> impl Future> + WasmNotSend { self.context .device_pop_error_scope(&self.id, self.data.as_ref()) } @@ -2602,7 +2603,7 @@ impl<'a> BufferSlice<'a> { pub fn map_async( &self, mode: MapMode, - callback: impl FnOnce(Result<(), BufferAsyncError>) + MaybeSend + 'static, + callback: impl FnOnce(Result<(), BufferAsyncError>) + WasmNotSend + 'static, ) { let mut mc = self.buffer.map_context.lock(); assert_eq!( @@ -4695,42 +4696,26 @@ mod send_sync { use std::any::Any; use std::fmt; - #[cfg(not(target_arch = "wasm32"))] - pub trait MaybeSend: Send {} - #[cfg(not(target_arch = "wasm32"))] - impl MaybeSend for T {} - #[cfg(target_arch = "wasm32")] - pub trait MaybeSend {} - #[cfg(target_arch = "wasm32")] - impl MaybeSend for T {} - - #[cfg(not(target_arch = "wasm32"))] - pub trait MaybeSync: Sync {} - #[cfg(not(target_arch = "wasm32"))] - impl MaybeSync for T {} - #[cfg(target_arch = "wasm32")] - pub trait MaybeSync {} - #[cfg(target_arch = "wasm32")] - impl MaybeSync for T {} - - pub trait AnySendSync: Any + MaybeSend + MaybeSync { + use wgt::{WasmNotSend, WasmNotSync}; + + pub trait AnyWasmNotSendSync: Any + WasmNotSend + WasmNotSync { fn upcast_any_ref(&self) -> &dyn Any; } - impl AnySendSync for T { + impl AnyWasmNotSendSync for T { #[inline] fn upcast_any_ref(&self) -> &dyn Any { self } } - impl dyn AnySendSync + 'static { + impl dyn AnyWasmNotSendSync + 'static { #[inline] pub fn downcast_ref(&self) -> Option<&T> { self.upcast_any_ref().downcast_ref::() } } - impl fmt::Debug for dyn AnySendSync { + impl fmt::Debug for dyn AnyWasmNotSendSync { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Any").finish_non_exhaustive() } From 38a00c457e38217d34f5e1bded5d6766134f319b Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Wed, 21 Jun 2023 16:09:12 +0200 Subject: [PATCH 3/3] Add opt-in crate feature --- .github/workflows/ci.yml | 1 + wgpu-core/Cargo.toml | 2 + wgpu-core/src/command/bundle.rs | 16 +- wgpu-core/src/device/queue.rs | 24 +- wgpu-core/src/error.rs | 16 +- wgpu-core/src/global.rs | 11 +- wgpu-core/src/resource.rs | 40 ++- wgpu-hal/Cargo.toml | 1 + wgpu-hal/src/gles/adapter.rs | 13 + wgpu-hal/src/gles/device.rs | 13 + wgpu-hal/src/gles/mod.rs | 81 ++++- wgpu-hal/src/gles/queue.rs | 13 + wgpu-hal/src/gles/web.rs | 22 ++ wgpu-types/Cargo.toml | 1 + wgpu-types/src/lib.rs | 77 ++++- wgpu/Cargo.toml | 2 + wgpu/src/backend/direct.rs | 16 +- wgpu/src/backend/web.rs | 526 +++++++++++++++++++------------- wgpu/src/context.rs | 88 +++++- wgpu/src/lib.rs | 376 ++++++++++++++++++++--- 20 files changed, 1045 insertions(+), 294 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50c3038615..079ac59038 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 diff --git a/wgpu-core/Cargo.toml b/wgpu-core/Cargo.toml index a2654d2a9f..00b58ce4f4 100644 --- a/wgpu-core/Cargo.toml +++ b/wgpu-core/Cargo.toml @@ -48,6 +48,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" diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 0b87cb6740..5c4ca122a8 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -746,9 +746,21 @@ pub struct RenderBundle { pub(crate) life_guard: LifeGuard, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] unsafe impl Send for RenderBundle {} -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] unsafe impl Sync for RenderBundle {} impl RenderBundle { diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index de7c16755a..6e0be3b297 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -37,7 +37,13 @@ pub struct SubmittedWorkDoneClosureC { pub user_data: *mut u8, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -46,9 +52,21 @@ pub struct SubmittedWorkDoneClosure { inner: SubmittedWorkDoneClosureInner, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] type SubmittedWorkDoneCallback = Box; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] type SubmittedWorkDoneCallback = Box; enum SubmittedWorkDoneClosureInner { diff --git a/wgpu-core/src/error.rs b/wgpu-core/src/error.rs index 1e38f67261..62ecebe9b9 100644 --- a/wgpu-core/src/error.rs +++ b/wgpu-core/src/error.rs @@ -162,9 +162,21 @@ pub fn format_pretty_any( #[derive(Debug)] pub struct ContextError { pub string: &'static str, - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] pub cause: Box, - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] pub cause: Box, pub label_key: &'static str, pub label: String, diff --git a/wgpu-core/src/global.rs b/wgpu-core/src/global.rs index 2ef19e945e..e3ed2be761 100644 --- a/wgpu-core/src/global.rs +++ b/wgpu-core/src/global.rs @@ -155,7 +155,16 @@ impl Drop for Global { } } -#[cfg(all(test, not(target_arch = "wasm32")))] +#[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) { fn test_internal(_: T) {} test_internal(global) diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 4f2c2f9ec1..fe881c2d06 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -79,9 +79,21 @@ pub(crate) enum BufferMapState { Idle, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] unsafe impl Send for BufferMapState {} -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] unsafe impl Sync for BufferMapState {} #[repr(C)] @@ -90,7 +102,13 @@ pub struct BufferMapCallbackC { pub user_data: *mut u8, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -99,9 +117,21 @@ pub struct BufferMapCallback { inner: Option, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] type BufferMapCallbackCallback = Box; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] type BufferMapCallbackCallback = Box; enum BufferMapCallbackInner { diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index 6baa39ce9a..319475e79d 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -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"] [[example]] name = "halmark" diff --git a/wgpu-hal/src/gles/adapter.rs b/wgpu-hal/src/gles/adapter.rs index 20bf8a8e28..d7e72619c5 100644 --- a/wgpu-hal/src/gles/adapter.rs +++ b/wgpu-hal/src/gles/adapter.rs @@ -936,6 +936,19 @@ impl super::AdapterShared { } } +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for super::Adapter {} +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for super::Adapter {} + #[cfg(test)] mod tests { use super::super::Adapter; diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 612483339e..ecd68b4b8d 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -1320,3 +1320,16 @@ impl crate::Device for super::Device { } } } + +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for super::Device {} +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for super::Device {} diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 0566de3cdc..5c53b3a281 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -246,6 +246,19 @@ pub struct Buffer { data: Option>>>, } +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for Buffer {} +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for Buffer {} + #[derive(Clone, Debug)] pub enum TextureInner { Renderbuffer { @@ -262,6 +275,19 @@ pub enum TextureInner { }, } +#[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) { match *self { @@ -450,6 +476,19 @@ struct UniformDesc { utype: u32, } +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for UniformDesc {} +#[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 /// sampler (in this layout) that the texture is used with. type SamplerBindMap = [Option; MAX_TEXTURE_SLOTS]; @@ -512,10 +551,36 @@ pub struct RenderPipeline { alpha_to_coverage_enabled: bool, } +#[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, } +#[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 { queries: Box<[glow::Query]>, @@ -528,9 +593,21 @@ pub struct Fence { pending: Vec<(crate::FenceValue, glow::Fence)>, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] unsafe impl Send for Fence {} -#[cfg(not(target_arch = "wasm32"))] +#[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 { diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index bfba315e5c..6eacfdd88a 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -1524,3 +1524,16 @@ impl crate::Queue for super::Queue { 1.0 } } + +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for super::Queue {} +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for super::Queue {} diff --git a/wgpu-hal/src/gles/web.rs b/wgpu-hal/src/gles/web.rs index 820d108f23..49bc5656de 100644 --- a/wgpu-hal/src/gles/web.rs +++ b/wgpu-hal/src/gles/web.rs @@ -106,6 +106,17 @@ impl Instance { } } +#[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 for Instance { unsafe fn init(_desc: &crate::InstanceDescriptor) -> Result { Ok(Instance { @@ -167,6 +178,17 @@ pub struct Surface { srgb_present_program: Option, } +#[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), diff --git a/wgpu-types/Cargo.toml b/wgpu-types/Cargo.toml index 8a4e7e0075..6b30c02ae5 100644 --- a/wgpu-types/Cargo.toml +++ b/wgpu-types/Cargo.toml @@ -25,6 +25,7 @@ targets = [ trace = ["serde"] replay = ["serde"] strict_asserts = [] +fragile-send-sync-non-atomic-wasm = [] [dependencies] bitflags = "2" diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index ff977844e9..a5e838653b 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5917,6 +5917,19 @@ impl std::ops::Deref for ExternalImageSource { } } +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for ExternalImageSource {} +#[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. /// /// Corresponds to [HTML Canvas `PredefinedColorSpace`]( @@ -6317,21 +6330,69 @@ pub use send_sync::*; #[doc(hidden)] mod send_sync { - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] pub trait WasmNotSend: Send {} - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] impl WasmNotSend for T {} - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] pub trait WasmNotSend {} - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] impl WasmNotSend for T {} - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] pub trait WasmNotSync: Sync {} - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] impl WasmNotSync for T {} - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] pub trait WasmNotSync {} - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] impl WasmNotSync for T {} } diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 1047e7bf47..2842281a19 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -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 diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index 8fd5eb1fc8..a5c9f30511 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -3052,9 +3052,21 @@ pub struct BufferMappedRange { size: usize, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] unsafe impl Send for BufferMappedRange {} -#[cfg(not(target_arch = "wasm32"))] +#[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 { diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index 8ddd9eff24..1dc5c712ab 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -19,14 +19,14 @@ use crate::{ UncapturedErrorHandler, }; -fn create_identified(value: T) -> (Identified, T) { +fn create_identified(value: T) -> (Identified, Sendable) { cfg_if::cfg_if! { if #[cfg(feature = "expose-ids")] { static NEXT_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1); let id = NEXT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed); - (Identified(core::num::NonZeroU64::new(id).unwrap(), PhantomData), value) + (Identified(core::num::NonZeroU64::new(id).unwrap(), PhantomData), Sendable(value)) } else { - (Identified(PhantomData), value) + (Identified(PhantomData), Sendable(value)) } } } @@ -63,13 +63,46 @@ impl From> for ObjectId { } } +#[derive(Clone, Debug)] +pub(crate) struct Sendable(T); +#[cfg(all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for Sendable {} +#[cfg(all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for Sendable {} + #[derive(Clone, Debug)] pub(crate) struct Identified( #[cfg(feature = "expose-ids")] std::num::NonZeroU64, PhantomData, ); +#[cfg(all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for Identified {} +#[cfg(all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for Identified {} 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -98,12 +131,12 @@ impl crate::Error { // This is safe on wasm32 *for now*, but similarly to the unsafe Send impls for the handle type // wrappers, the full story for threading on wasm32 is still unfolding. -pub(crate) struct MapFuture { +pub(crate) struct MakeSendFuture { future: F, map: M, } -impl T, T> Future for MapFuture { +impl T, T> Future for MakeSendFuture { type Output = T; fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll { @@ -119,12 +152,18 @@ impl T, T> Future for MapFuture { } } -impl MapFuture { +impl MakeSendFuture { fn new(future: F, map: M) -> Self { Self { future, map } } } +#[cfg(all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for MakeSendFuture {} + fn map_texture_format(texture_format: wgt::TextureFormat) -> web_sys::GpuTextureFormat { use web_sys::GpuTextureFormat as tf; use wgt::TextureFormat; @@ -504,7 +543,7 @@ fn map_texture_view_dimension( fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> web_sys::GpuImageCopyBuffer { let buffer: &::BufferData = downcast_ref(view.buffer.data.as_ref()); - let mut mapped = web_sys::GpuImageCopyBuffer::new(buffer); + let mut mapped = web_sys::GpuImageCopyBuffer::new(&buffer.0); if let Some(bytes_per_row) = view.layout.bytes_per_row { mapped.bytes_per_row(bytes_per_row); } @@ -518,7 +557,7 @@ fn map_buffer_copy_view(view: crate::ImageCopyBuffer) -> web_sys::GpuImageCopyBu fn map_texture_copy_view(view: crate::ImageCopyTexture) -> web_sys::GpuImageCopyTexture { let texture: &::TextureData = downcast_ref(view.texture.data.as_ref()); - let mut mapped = web_sys::GpuImageCopyTexture::new(texture); + let mut mapped = web_sys::GpuImageCopyTexture::new(&texture.0); mapped.mip_level(view.mip_level); mapped.origin(&map_origin_3d(view.origin)); mapped @@ -529,7 +568,7 @@ fn map_tagged_texture_copy_view( ) -> web_sys::GpuImageCopyTextureTagged { let texture: &::TextureData = downcast_ref(view.texture.data.as_ref()); - let mut mapped = web_sys::GpuImageCopyTextureTagged::new(texture); + let mut mapped = web_sys::GpuImageCopyTextureTagged::new(&texture.0); mapped.mip_level(view.mip_level); mapped.origin(&map_origin_3d(view.origin)); mapped.aspect(map_texture_aspect(view.aspect)); @@ -652,7 +691,10 @@ type JsFutureResult = Result; fn future_request_adapter( result: JsFutureResult, -) -> Option<(Identified, web_sys::GpuAdapter)> { +) -> Option<( + Identified, + Sendable, +)> { match result.and_then(wasm_bindgen::JsCast::dyn_into) { Ok(adapter) => Some(create_identified(adapter)), Err(_) => None, @@ -664,16 +706,16 @@ fn future_request_device( ) -> Result< ( Identified, - web_sys::GpuDevice, + Sendable, Identified, - web_sys::GpuQueue, + Sendable, ), crate::RequestDeviceError, > { result .map(|js_value| { let (device_id, device_data) = create_identified(web_sys::GpuDevice::from(js_value)); - let (queue_id, queue_data) = create_identified(device_data.queue()); + let (queue_id, queue_data) = create_identified(device_data.0.queue()); (device_id, device_data, queue_id, queue_data) }) @@ -828,57 +870,57 @@ pub enum Canvas { impl crate::context::Context for Context { type AdapterId = Identified; - type AdapterData = web_sys::GpuAdapter; + type AdapterData = Sendable; type DeviceId = Identified; - type DeviceData = web_sys::GpuDevice; + type DeviceData = Sendable; type QueueId = Identified; - type QueueData = web_sys::GpuQueue; + type QueueData = Sendable; type ShaderModuleId = Identified; - type ShaderModuleData = web_sys::GpuShaderModule; + type ShaderModuleData = Sendable; type BindGroupLayoutId = Identified; - type BindGroupLayoutData = web_sys::GpuBindGroupLayout; + type BindGroupLayoutData = Sendable; type BindGroupId = Identified; - type BindGroupData = web_sys::GpuBindGroup; + type BindGroupData = Sendable; type TextureViewId = Identified; - type TextureViewData = web_sys::GpuTextureView; + type TextureViewData = Sendable; type SamplerId = Identified; - type SamplerData = web_sys::GpuSampler; + type SamplerData = Sendable; type BufferId = Identified; - type BufferData = web_sys::GpuBuffer; + type BufferData = Sendable; type TextureId = Identified; - type TextureData = web_sys::GpuTexture; + type TextureData = Sendable; type QuerySetId = Identified; - type QuerySetData = web_sys::GpuQuerySet; + type QuerySetData = Sendable; type PipelineLayoutId = Identified; - type PipelineLayoutData = web_sys::GpuPipelineLayout; + type PipelineLayoutData = Sendable; type RenderPipelineId = Identified; - type RenderPipelineData = web_sys::GpuRenderPipeline; + type RenderPipelineData = Sendable; type ComputePipelineId = Identified; - type ComputePipelineData = web_sys::GpuComputePipeline; + type ComputePipelineData = Sendable; type CommandEncoderId = Identified; - type CommandEncoderData = web_sys::GpuCommandEncoder; + type CommandEncoderData = Sendable; type ComputePassId = Identified; - type ComputePassData = web_sys::GpuComputePassEncoder; + type ComputePassData = Sendable; type RenderPassId = Identified; - type RenderPassData = web_sys::GpuRenderPassEncoder; + type RenderPassData = Sendable; type CommandBufferId = Identified; - type CommandBufferData = web_sys::GpuCommandBuffer; + type CommandBufferData = Sendable; type RenderBundleEncoderId = Identified; - type RenderBundleEncoderData = web_sys::GpuRenderBundleEncoder; + type RenderBundleEncoderData = Sendable; type RenderBundleId = Identified; - type RenderBundleData = web_sys::GpuRenderBundle; + type RenderBundleData = Sendable; type SurfaceId = Identified<(Canvas, web_sys::GpuCanvasContext)>; - type SurfaceData = (Canvas, web_sys::GpuCanvasContext); + type SurfaceData = Sendable<(Canvas, web_sys::GpuCanvasContext)>; type SurfaceOutputDetail = SurfaceOutputDetail; type SubmissionIndex = Unused; type SubmissionIndexData = (); - type RequestAdapterFuture = MapFuture< + type RequestAdapterFuture = MakeSendFuture< wasm_bindgen_futures::JsFuture, fn(JsFutureResult) -> Option<(Self::AdapterId, Self::AdapterData)>, >; - type RequestDeviceFuture = MapFuture< + type RequestDeviceFuture = MakeSendFuture< wasm_bindgen_futures::JsFuture, fn( JsFutureResult, @@ -893,7 +935,7 @@ impl crate::context::Context for Context { >, >; type PopErrorScopeFuture = - MapFuture Option>; + MakeSendFuture Option>; fn init(_instance_desc: wgt::InstanceDescriptor) -> Self { let global: Global = js_sys::global().unchecked_into(); @@ -950,7 +992,7 @@ impl crate::context::Context for Context { mapped_options.power_preference(mapped_power_preference); let adapter_promise = self.0.request_adapter_with_options(&mapped_options); - MapFuture::new( + MakeSendFuture::new( wasm_bindgen_futures::JsFuture::from(adapter_promise), future_request_adapter, ) @@ -987,9 +1029,9 @@ impl crate::context::Context for Context { mapped_desc.label(label); } - let device_promise = adapter_data.request_device_with_descriptor(&mapped_desc); + let device_promise = adapter_data.0.request_device_with_descriptor(&mapped_desc); - MapFuture::new( + MakeSendFuture::new( wasm_bindgen_futures::JsFuture::from(device_promise), future_request_device, ) @@ -1015,7 +1057,7 @@ impl crate::context::Context for Context { _adapter: &Self::AdapterId, adapter_data: &Self::AdapterData, ) -> wgt::Features { - map_wgt_features(adapter_data.features()) + map_wgt_features(adapter_data.0.features()) } fn adapter_limits( @@ -1023,7 +1065,7 @@ impl crate::context::Context for Context { _adapter: &Self::AdapterId, adapter_data: &Self::AdapterData, ) -> wgt::Limits { - let limits = adapter_data.limits(); + let limits = adapter_data.0.limits(); wgt::Limits { max_texture_dimension_1d: limits.max_texture_dimension_1d(), max_texture_dimension_2d: limits.max_texture_dimension_2d(), @@ -1129,7 +1171,7 @@ impl crate::context::Context for Context { device_data: &Self::DeviceData, config: &crate::SurfaceConfiguration, ) { - match surface_data.0 { + match surface_data.0 .0 { Canvas::Canvas(ref canvas) => { canvas.set_width(config.width); canvas.set_height(config.height); @@ -1153,7 +1195,7 @@ impl crate::context::Context for Context { _ => web_sys::GpuCanvasAlphaMode::Opaque, }; let mut mapped = - web_sys::GpuCanvasConfiguration::new(device_data, map_texture_format(config.format)); + web_sys::GpuCanvasConfiguration::new(&device_data.0, map_texture_format(config.format)); mapped.usage(config.usage.bits()); mapped.alpha_mode(alpha_mode); let mapped_view_formats = config @@ -1162,7 +1204,7 @@ impl crate::context::Context for Context { .map(|format| JsValue::from(map_texture_format(*format))) .collect::(); mapped.view_formats(&mapped_view_formats); - surface_data.1.configure(&mapped); + surface_data.0 .1.configure(&mapped); } fn surface_get_current_texture( @@ -1175,7 +1217,7 @@ impl crate::context::Context for Context { wgt::SurfaceStatus, Self::SurfaceOutputDetail, ) { - let (surface_id, surface_data) = create_identified(surface_data.1.get_current_texture()); + let (surface_id, surface_data) = create_identified(surface_data.0 .1.get_current_texture()); ( Some(surface_id), Some(surface_data), @@ -1201,7 +1243,7 @@ impl crate::context::Context for Context { _device: &Self::DeviceId, device_data: &Self::DeviceData, ) -> wgt::Features { - map_wgt_features(device_data.features()) + map_wgt_features(device_data.0.features()) } fn device_limits( @@ -1314,7 +1356,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { descriptor.label(label); } - create_identified(device_data.create_shader_module(&descriptor)) + create_identified(device_data.0.create_shader_module(&descriptor)) } unsafe fn device_create_shader_module_spirv( @@ -1422,7 +1464,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_bind_group_layout(&mapped_desc)) + create_identified(device_data.0.create_bind_group_layout(&mapped_desc)) } fn device_create_bind_group( @@ -1443,7 +1485,7 @@ impl crate::context::Context for Context { }) => { let buffer: &::BufferData = downcast_ref(buffer.data.as_ref()); - let mut mapped_buffer_binding = web_sys::GpuBufferBinding::new(buffer); + let mut mapped_buffer_binding = web_sys::GpuBufferBinding::new(&buffer.0); mapped_buffer_binding.offset(offset as f64); if let Some(s) = size { mapped_buffer_binding.size(s.get() as f64); @@ -1456,7 +1498,7 @@ impl crate::context::Context for Context { crate::BindingResource::Sampler(sampler) => { let sampler: &::SamplerData = downcast_ref(sampler.data.as_ref()); - JsValue::from(sampler) + JsValue::from(&sampler.0) } crate::BindingResource::SamplerArray(..) => { panic!("Web backend does not support arrays of samplers") @@ -1464,7 +1506,7 @@ impl crate::context::Context for Context { crate::BindingResource::TextureView(texture_view) => { let texture_view: &::TextureViewData = downcast_ref(texture_view.data.as_ref()); - JsValue::from(texture_view) + JsValue::from(&texture_view.0) } crate::BindingResource::TextureViewArray(..) => { panic!("Web backend does not support BINDING_INDEXING extension") @@ -1477,11 +1519,11 @@ impl crate::context::Context for Context { let bgl: &::BindGroupLayoutData = downcast_ref(desc.layout.data.as_ref()); - let mut mapped_desc = web_sys::GpuBindGroupDescriptor::new(&mapped_entries, bgl); + let mut mapped_desc = web_sys::GpuBindGroupDescriptor::new(&mapped_entries, &bgl.0); if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_bind_group(&mapped_desc)) + create_identified(device_data.0.create_bind_group(&mapped_desc)) } fn device_create_pipeline_layout( @@ -1496,14 +1538,14 @@ impl crate::context::Context for Context { .map(|bgl| { let bgl: &::BindGroupLayoutData = downcast_ref(bgl.data.as_ref()); - bgl + &bgl.0 }) .collect::(); let mut mapped_desc = web_sys::GpuPipelineLayoutDescriptor::new(&temp_layouts); if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_pipeline_layout(&mapped_desc)) + create_identified(device_data.0.create_pipeline_layout(&mapped_desc)) } fn device_create_render_pipeline( @@ -1514,7 +1556,8 @@ impl crate::context::Context for Context { ) -> (Self::RenderPipelineId, Self::RenderPipelineData) { let module: &::ShaderModuleData = downcast_ref(desc.vertex.module.data.as_ref()); - let mut mapped_vertex_state = web_sys::GpuVertexState::new(desc.vertex.entry_point, module); + let mut mapped_vertex_state = + web_sys::GpuVertexState::new(desc.vertex.entry_point, &module.0); let buffers = desc .vertex @@ -1550,7 +1593,7 @@ impl crate::context::Context for Context { Some(layout) => { let layout: &::PipelineLayoutData = downcast_ref(layout.data.as_ref()); - JsValue::from(layout) + JsValue::from(&layout.0) } None => auto_layout, }, @@ -1589,7 +1632,7 @@ impl crate::context::Context for Context { let module: &::ShaderModuleData = downcast_ref(frag.module.data.as_ref()); let mapped_fragment_desc = - web_sys::GpuFragmentState::new(frag.entry_point, module, &targets); + web_sys::GpuFragmentState::new(frag.entry_point, &module.0, &targets); mapped_desc.fragment(&mapped_fragment_desc); } @@ -1602,7 +1645,7 @@ impl crate::context::Context for Context { let mapped_primitive = map_primitive_state(&desc.primitive); mapped_desc.primitive(&mapped_primitive); - create_identified(device_data.create_render_pipeline(&mapped_desc)) + create_identified(device_data.0.create_render_pipeline(&mapped_desc)) } fn device_create_compute_pipeline( @@ -1614,14 +1657,14 @@ impl crate::context::Context for Context { let shader_module: &::ShaderModuleData = downcast_ref(desc.module.data.as_ref()); let mapped_compute_stage = - web_sys::GpuProgrammableStage::new(desc.entry_point, shader_module); + web_sys::GpuProgrammableStage::new(desc.entry_point, &shader_module.0); let auto_layout = wasm_bindgen::JsValue::from(web_sys::GpuAutoLayoutMode::Auto); let mut mapped_desc = web_sys::GpuComputePipelineDescriptor::new( &match desc.layout { Some(layout) => { let layout: &::PipelineLayoutData = downcast_ref(layout.data.as_ref()); - JsValue::from(layout) + JsValue::from(&layout.0) } None => auto_layout, }, @@ -1630,7 +1673,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_compute_pipeline(&mapped_desc)) + create_identified(device_data.0.create_compute_pipeline(&mapped_desc)) } fn device_create_buffer( @@ -1645,7 +1688,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_buffer(&mapped_desc)) + create_identified(device_data.0.create_buffer(&mapped_desc)) } fn device_create_texture( @@ -1671,7 +1714,7 @@ impl crate::context::Context for Context { .map(|format| JsValue::from(map_texture_format(*format))) .collect::(); mapped_desc.view_formats(&mapped_view_formats); - create_identified(device_data.create_texture(&mapped_desc)) + create_identified(device_data.0.create_texture(&mapped_desc)) } fn device_create_sampler( @@ -1697,7 +1740,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_sampler_with_descriptor(&mapped_desc)) + create_identified(device_data.0.create_sampler_with_descriptor(&mapped_desc)) } fn device_create_query_set( @@ -1715,7 +1758,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_query_set(&mapped_desc)) + create_identified(device_data.0.create_query_set(&mapped_desc)) } fn device_create_command_encoder( @@ -1728,7 +1771,11 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(device_data.create_command_encoder_with_descriptor(&mapped_desc)) + create_identified( + device_data + .0 + .create_command_encoder_with_descriptor(&mapped_desc), + ) } fn device_create_render_bundle_encoder( @@ -1755,7 +1802,7 @@ impl crate::context::Context for Context { mapped_desc.stencil_read_only(ds.stencil_read_only); } mapped_desc.sample_count(desc.sample_count); - create_identified(device_data.create_render_bundle_encoder(&mapped_desc)) + create_identified(device_data.0.create_render_bundle_encoder(&mapped_desc)) } fn device_drop(&self, _device: &Self::DeviceId, _device_data: &Self::DeviceData) { @@ -1782,7 +1829,9 @@ impl crate::context::Context for Context { let error = crate::Error::from_js(event.error().value_of()); handler(error); }) as Box); - device_data.set_onuncapturederror(Some(f.as_ref().unchecked_ref())); + device_data + .0 + .set_onuncapturederror(Some(f.as_ref().unchecked_ref())); // TODO: This will leak the memory associated with the error handler by default. f.forget(); } @@ -1793,7 +1842,7 @@ impl crate::context::Context for Context { device_data: &Self::DeviceData, filter: crate::ErrorFilter, ) { - device_data.push_error_scope(match filter { + device_data.0.push_error_scope(match filter { crate::ErrorFilter::OutOfMemory => web_sys::GpuErrorFilter::OutOfMemory, crate::ErrorFilter::Validation => web_sys::GpuErrorFilter::Validation, }); @@ -1804,8 +1853,8 @@ impl crate::context::Context for Context { _device: &Self::DeviceId, device_data: &Self::DeviceData, ) -> Self::PopErrorScopeFuture { - let error_promise = device_data.pop_error_scope(); - MapFuture::new( + let error_promise = device_data.0.pop_error_scope(); + MakeSendFuture::new( wasm_bindgen_futures::JsFuture::from(error_promise), future_pop_error_scope, ) @@ -1819,7 +1868,7 @@ impl crate::context::Context for Context { range: Range, callback: crate::context::BufferMapCallback, ) { - let map_promise = buffer_data.map_async_with_f64_and_f64( + let map_promise = buffer_data.0.map_async_with_f64_and_f64( map_map_mode(mode), range.start as f64, (range.end - range.start) as f64, @@ -1834,7 +1883,7 @@ impl crate::context::Context for Context { buffer_data: &Self::BufferData, sub_range: Range, ) -> Box { - let array_buffer = buffer_data.get_mapped_range_with_f64_and_f64( + let array_buffer = buffer_data.0.get_mapped_range_with_f64_and_f64( sub_range.start as f64, (sub_range.end - sub_range.start) as f64, ); @@ -1847,7 +1896,7 @@ impl crate::context::Context for Context { } fn buffer_unmap(&self, _buffer: &Self::BufferId, buffer_data: &Self::BufferData) { - buffer_data.unmap(); + buffer_data.0.unmap(); } fn texture_create_view( @@ -1875,7 +1924,7 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped.label(label); } - create_identified(texture_data.create_view_with_descriptor(&mapped)) + create_identified(texture_data.0.create_view_with_descriptor(&mapped)) } fn surface_drop(&self, _surface: &Self::SurfaceId, _surface_data: &Self::SurfaceData) { @@ -1887,7 +1936,7 @@ impl crate::context::Context for Context { } fn buffer_destroy(&self, _buffer: &Self::BufferId, buffer_data: &Self::BufferData) { - buffer_data.destroy(); + buffer_data.0.destroy(); } fn buffer_drop(&self, _buffer: &Self::BufferId, _buffer_data: &Self::BufferData) { @@ -1895,7 +1944,7 @@ impl crate::context::Context for Context { } fn texture_destroy(&self, _texture: &Self::TextureId, texture_data: &Self::TextureData) { - texture_data.destroy(); + texture_data.0.destroy(); } fn texture_drop(&self, _texture: &Self::TextureId, _texture_data: &Self::TextureData) { @@ -1996,7 +2045,7 @@ impl crate::context::Context for Context { pipeline_data: &Self::ComputePipelineData, index: u32, ) -> (Self::BindGroupLayoutId, Self::BindGroupLayoutData) { - create_identified(pipeline_data.get_bind_group_layout(index)) + create_identified(pipeline_data.0.get_bind_group_layout(index)) } fn render_pipeline_get_bind_group_layout( @@ -2005,7 +2054,7 @@ impl crate::context::Context for Context { pipeline_data: &Self::RenderPipelineData, index: u32, ) -> (Self::BindGroupLayoutId, Self::BindGroupLayoutData) { - create_identified(pipeline_data.get_bind_group_layout(index)) + create_identified(pipeline_data.0.get_bind_group_layout(index)) } fn command_encoder_copy_buffer_to_buffer( @@ -2020,13 +2069,15 @@ impl crate::context::Context for Context { destination_offset: wgt::BufferAddress, copy_size: wgt::BufferAddress, ) { - encoder_data.copy_buffer_to_buffer_with_f64_and_f64_and_f64( - source_data, - source_offset as f64, - destination_data, - destination_offset as f64, - copy_size as f64, - ) + encoder_data + .0 + .copy_buffer_to_buffer_with_f64_and_f64_and_f64( + &source_data.0, + source_offset as f64, + &destination_data.0, + destination_offset as f64, + copy_size as f64, + ) } fn command_encoder_copy_buffer_to_texture( @@ -2037,11 +2088,13 @@ impl crate::context::Context for Context { destination: crate::ImageCopyTexture, copy_size: wgt::Extent3d, ) { - encoder_data.copy_buffer_to_texture_with_gpu_extent_3d_dict( - &map_buffer_copy_view(source), - &map_texture_copy_view(destination), - &map_extent_3d(copy_size), - ) + encoder_data + .0 + .copy_buffer_to_texture_with_gpu_extent_3d_dict( + &map_buffer_copy_view(source), + &map_texture_copy_view(destination), + &map_extent_3d(copy_size), + ) } fn command_encoder_copy_texture_to_buffer( @@ -2052,11 +2105,13 @@ impl crate::context::Context for Context { destination: crate::ImageCopyBuffer, copy_size: wgt::Extent3d, ) { - encoder_data.copy_texture_to_buffer_with_gpu_extent_3d_dict( - &map_texture_copy_view(source), - &map_buffer_copy_view(destination), - &map_extent_3d(copy_size), - ) + encoder_data + .0 + .copy_texture_to_buffer_with_gpu_extent_3d_dict( + &map_texture_copy_view(source), + &map_buffer_copy_view(destination), + &map_extent_3d(copy_size), + ) } fn command_encoder_copy_texture_to_texture( @@ -2067,11 +2122,13 @@ impl crate::context::Context for Context { destination: crate::ImageCopyTexture, copy_size: wgt::Extent3d, ) { - encoder_data.copy_texture_to_texture_with_gpu_extent_3d_dict( - &map_texture_copy_view(source), - &map_texture_copy_view(destination), - &map_extent_3d(copy_size), - ) + encoder_data + .0 + .copy_texture_to_texture_with_gpu_extent_3d_dict( + &map_texture_copy_view(source), + &map_texture_copy_view(destination), + &map_extent_3d(copy_size), + ) } fn command_encoder_begin_compute_pass( @@ -2084,7 +2141,11 @@ impl crate::context::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - create_identified(encoder_data.begin_compute_pass_with_descriptor(&mapped_desc)) + create_identified( + encoder_data + .0 + .begin_compute_pass_with_descriptor(&mapped_desc), + ) } fn command_encoder_end_compute_pass( @@ -2094,7 +2155,7 @@ impl crate::context::Context for Context { _pass: &mut Self::ComputePassId, pass_data: &mut Self::ComputePassData, ) { - pass_data.end(); + pass_data.0.end(); } fn command_encoder_begin_render_pass( @@ -2123,7 +2184,7 @@ impl crate::context::Context for Context { let mut mapped_color_attachment = web_sys::GpuRenderPassColorAttachment::new( load_value, map_store_op(ca.ops.store), - view, + &view.0, ); if let Some(cv) = clear_value { mapped_color_attachment.clear_value(&cv); @@ -2131,7 +2192,7 @@ impl crate::context::Context for Context { if let Some(rt) = ca.resolve_target { let resolve_target_view: &::TextureViewData = downcast_ref(rt.data.as_ref()); - mapped_color_attachment.resolve_target(resolve_target_view); + mapped_color_attachment.resolve_target(&resolve_target_view.0); } mapped_color_attachment.store_op(map_store_op(ca.ops.store)); @@ -2151,7 +2212,7 @@ impl crate::context::Context for Context { let depth_stencil_attachment: &::TextureViewData = downcast_ref(dsa.view.data.as_ref()); let mut mapped_depth_stencil_attachment = - web_sys::GpuRenderPassDepthStencilAttachment::new(depth_stencil_attachment); + web_sys::GpuRenderPassDepthStencilAttachment::new(&depth_stencil_attachment.0); if let Some(ref ops) = dsa.depth_ops { let load_op = match ops.load { crate::LoadOp::Clear(v) => { @@ -2179,7 +2240,7 @@ impl crate::context::Context for Context { mapped_desc.depth_stencil_attachment(&mapped_depth_stencil_attachment); } - create_identified(encoder_data.begin_render_pass(&mapped_desc)) + create_identified(encoder_data.0.begin_render_pass(&mapped_desc)) } fn command_encoder_end_render_pass( @@ -2189,7 +2250,7 @@ impl crate::context::Context for Context { _pass: &mut Self::RenderPassId, pass_data: &mut Self::RenderPassData, ) { - pass_data.end(); + pass_data.0.end(); } fn command_encoder_finish( @@ -2197,13 +2258,13 @@ impl crate::context::Context for Context { _encoder: Self::CommandEncoderId, encoder_data: &mut Self::CommandEncoderData, ) -> (Self::CommandBufferId, Self::CommandBufferData) { - let label = encoder_data.label(); + let label = encoder_data.0.label(); create_identified(if label.is_empty() { - encoder_data.finish() + encoder_data.0.finish() } else { let mut mapped_desc = web_sys::GpuCommandBufferDescriptor::new(); mapped_desc.label(&label); - encoder_data.finish_with_descriptor(&mapped_desc) + encoder_data.0.finish_with_descriptor(&mapped_desc) }) } @@ -2227,10 +2288,14 @@ impl crate::context::Context for Context { ) { let buffer: &::BufferData = downcast_ref(buffer.data.as_ref()); match size { - Some(size) => { - encoder_data.clear_buffer_with_f64_and_f64(buffer, offset as f64, size.get() as f64) - } - None => encoder_data.clear_buffer_with_f64(buffer, offset as f64), + Some(size) => encoder_data.0.clear_buffer_with_f64_and_f64( + &buffer.0, + offset as f64, + size.get() as f64, + ), + None => encoder_data + .0 + .clear_buffer_with_f64(&buffer.0, offset as f64), } } @@ -2271,7 +2336,9 @@ impl crate::context::Context for Context { query_set_data: &Self::QuerySetData, query_index: u32, ) { - encoder_data.write_timestamp(query_set_data, query_index); + encoder_data + .0 + .write_timestamp(&query_set_data.0, query_index); } fn command_encoder_resolve_query_set( @@ -2286,11 +2353,11 @@ impl crate::context::Context for Context { destination_data: &Self::BufferData, destination_offset: wgt::BufferAddress, ) { - encoder_data.resolve_query_set_with_u32( - query_set_data, + encoder_data.0.resolve_query_set_with_u32( + &query_set_data.0, first_query, query_count, - destination_data, + &destination_data.0, destination_offset as u32, ); } @@ -2305,9 +2372,9 @@ impl crate::context::Context for Context { Some(label) => { let mut mapped_desc = web_sys::GpuRenderBundleDescriptor::new(); mapped_desc.label(label); - encoder_data.finish_with_descriptor(&mapped_desc) + encoder_data.0.finish_with_descriptor(&mapped_desc) } - None => encoder_data.finish(), + None => encoder_data.0.finish(), }) } @@ -2321,21 +2388,23 @@ impl crate::context::Context for Context { data: &[u8], ) { /* Skip the copy once gecko allows BufferSource instead of ArrayBuffer - queue_data.write_buffer_with_f64_and_u8_array_and_f64_and_f64( - buffer_data, + queue_data.0.write_buffer_with_f64_and_u8_array_and_f64_and_f64( + &buffer_data.0, offset as f64, data, 0f64, data.len() as f64, ); */ - queue_data.write_buffer_with_f64_and_buffer_source_and_f64_and_f64( - buffer_data, - offset as f64, - &js_sys::Uint8Array::from(data).buffer(), - 0f64, - data.len() as f64, - ); + queue_data + .0 + .write_buffer_with_f64_and_buffer_source_and_f64_and_f64( + &buffer_data.0, + offset as f64, + &js_sys::Uint8Array::from(data).buffer(), + 0f64, + data.len() as f64, + ); } fn queue_validate_write_buffer( @@ -2347,7 +2416,7 @@ impl crate::context::Context for Context { offset: wgt::BufferAddress, size: wgt::BufferSize, ) -> Option<()> { - let usage = wgt::BufferUsages::from_bits_truncate(buffer_data.usage()); + let usage = wgt::BufferUsages::from_bits_truncate(buffer_data.0.usage()); // TODO: actually send this down the error scope if !usage.contains(wgt::BufferUsages::COPY_DST) { log::error!("Destination buffer is missing the `COPY_DST` usage flag"); @@ -2368,8 +2437,8 @@ impl crate::context::Context for Context { ); return None; } - if write_size + offset > buffer_data.size() as u64 { - log::error!("copy of {}..{} would end up overrunning the bounds of the destination buffer of size {}", offset, offset + write_size, buffer_data.size()); + if write_size + offset > buffer_data.0.size() as u64 { + log::error!("copy of {}..{} would end up overrunning the bounds of the destination buffer of size {}", offset, offset + write_size, buffer_data.0.size()); return None; } Some(()) @@ -2429,19 +2498,21 @@ impl crate::context::Context for Context { mapped_data_layout.offset(data_layout.offset as f64); /* Skip the copy once gecko allows BufferSource instead of ArrayBuffer - queue_data.write_texture_with_u8_array_and_gpu_extent_3d_dict( + queue_data.0.write_texture_with_u8_array_and_gpu_extent_3d_dict( &map_texture_copy_view(texture), data, &mapped_data_layout, &map_extent_3d(size), ); */ - queue_data.write_texture_with_buffer_source_and_gpu_extent_3d_dict( - &map_texture_copy_view(texture), - &js_sys::Uint8Array::from(data).buffer(), - &mapped_data_layout, - &map_extent_3d(size), - ); + queue_data + .0 + .write_texture_with_buffer_source_and_gpu_extent_3d_dict( + &map_texture_copy_view(texture), + &js_sys::Uint8Array::from(data).buffer(), + &mapped_data_layout, + &map_extent_3d(size), + ); } fn queue_copy_external_image_to_texture( @@ -2452,11 +2523,13 @@ impl crate::context::Context for Context { dest: crate::ImageCopyTextureTagged, size: wgt::Extent3d, ) { - queue_data.copy_external_image_to_texture_with_gpu_extent_3d_dict( - &map_external_texture_copy_view(source), - &map_tagged_texture_copy_view(dest), - &map_extent_3d(size), - ); + queue_data + .0 + .copy_external_image_to_texture_with_gpu_extent_3d_dict( + &map_external_texture_copy_view(source), + &map_tagged_texture_copy_view(dest), + &map_extent_3d(size), + ); } fn queue_submit>( @@ -2466,10 +2539,10 @@ impl crate::context::Context for Context { command_buffers: I, ) -> (Self::SubmissionIndex, Self::SubmissionIndexData) { let temp_command_buffers = command_buffers - .map(|(_, data)| data) + .map(|(_, data)| data.0) .collect::(); - queue_data.submit(&temp_command_buffers); + queue_data.0.submit(&temp_command_buffers); (Unused, ()) } @@ -2501,7 +2574,7 @@ impl crate::context::Context for Context { _pipeline: &Self::ComputePipelineId, pipeline_data: &Self::ComputePipelineData, ) { - pass_data.set_pipeline(pipeline_data) + pass_data.0.set_pipeline(&pipeline_data.0) } fn compute_pass_set_bind_group( @@ -2513,13 +2586,15 @@ impl crate::context::Context for Context { bind_group_data: &Self::BindGroupData, offsets: &[wgt::DynamicOffset], ) { - pass_data.set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( - index, - bind_group_data, - offsets, - 0f64, - offsets.len() as u32, - ); + pass_data + .0 + .set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( + index, + &bind_group_data.0, + offsets, + 0f64, + offsets.len() as u32, + ); } fn compute_pass_set_push_constants( @@ -2599,7 +2674,9 @@ impl crate::context::Context for Context { y: u32, z: u32, ) { - pass_data.dispatch_workgroups_with_workgroup_count_y_and_workgroup_count_z(x, y, z); + pass_data + .0 + .dispatch_workgroups_with_workgroup_count_y_and_workgroup_count_z(x, y, z); } fn compute_pass_dispatch_workgroups_indirect( @@ -2611,7 +2688,8 @@ impl crate::context::Context for Context { indirect_offset: wgt::BufferAddress, ) { pass_data - .dispatch_workgroups_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); + .0 + .dispatch_workgroups_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); } fn render_bundle_encoder_set_pipeline( @@ -2621,7 +2699,7 @@ impl crate::context::Context for Context { _pipeline: &Self::RenderPipelineId, pipeline_data: &Self::RenderPipelineData, ) { - encoder_data.set_pipeline(pipeline_data); + encoder_data.0.set_pipeline(&pipeline_data.0); } fn render_bundle_encoder_set_bind_group( @@ -2633,13 +2711,15 @@ impl crate::context::Context for Context { bind_group_data: &Self::BindGroupData, offsets: &[wgt::DynamicOffset], ) { - encoder_data.set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( - index, - bind_group_data, - offsets, - 0f64, - offsets.len() as u32, - ); + encoder_data + .0 + .set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( + index, + &bind_group_data.0, + offsets, + 0f64, + offsets.len() as u32, + ); } fn render_bundle_encoder_set_index_buffer( @@ -2654,16 +2734,16 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - encoder_data.set_index_buffer_with_f64_and_f64( - buffer_data, + encoder_data.0.set_index_buffer_with_f64_and_f64( + &buffer_data.0, map_index_format(index_format), offset as f64, s.get() as f64, ); } None => { - encoder_data.set_index_buffer_with_f64( - buffer_data, + encoder_data.0.set_index_buffer_with_f64( + &buffer_data.0, map_index_format(index_format), offset as f64, ); @@ -2683,15 +2763,17 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - encoder_data.set_vertex_buffer_with_f64_and_f64( + encoder_data.0.set_vertex_buffer_with_f64_and_f64( slot, - buffer_data, + &buffer_data.0, offset as f64, s.get() as f64, ); } None => { - encoder_data.set_vertex_buffer_with_f64(slot, buffer_data, offset as f64); + encoder_data + .0 + .set_vertex_buffer_with_f64(slot, &buffer_data.0, offset as f64); } }; } @@ -2714,12 +2796,14 @@ impl crate::context::Context for Context { vertices: Range, instances: Range, ) { - encoder_data.draw_with_instance_count_and_first_vertex_and_first_instance( - vertices.end - vertices.start, - instances.end - instances.start, - vertices.start, - instances.start, - ); + encoder_data + .0 + .draw_with_instance_count_and_first_vertex_and_first_instance( + vertices.end - vertices.start, + instances.end - instances.start, + vertices.start, + instances.start, + ); } fn render_bundle_encoder_draw_indexed( @@ -2731,6 +2815,7 @@ impl crate::context::Context for Context { instances: Range, ) { encoder_data + .0 .draw_indexed_with_instance_count_and_first_index_and_base_vertex_and_first_instance( indices.end - indices.start, instances.end - instances.start, @@ -2748,7 +2833,9 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - encoder_data.draw_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); + encoder_data + .0 + .draw_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); } fn render_bundle_encoder_draw_indexed_indirect( @@ -2759,7 +2846,9 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - encoder_data.draw_indexed_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); + encoder_data + .0 + .draw_indexed_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); } fn render_bundle_encoder_multi_draw_indirect( @@ -2825,7 +2914,7 @@ impl crate::context::Context for Context { _pipeline: &Self::RenderPipelineId, pipeline_data: &Self::RenderPipelineData, ) { - pass_data.set_pipeline(pipeline_data); + pass_data.0.set_pipeline(&pipeline_data.0); } fn render_pass_set_bind_group( @@ -2837,13 +2926,15 @@ impl crate::context::Context for Context { bind_group_data: &Self::BindGroupData, offsets: &[wgt::DynamicOffset], ) { - pass_data.set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( - index, - bind_group_data, - offsets, - 0f64, - offsets.len() as u32, - ); + pass_data + .0 + .set_bind_group_with_u32_array_and_f64_and_dynamic_offsets_data_length( + index, + &bind_group_data.0, + offsets, + 0f64, + offsets.len() as u32, + ); } fn render_pass_set_index_buffer( @@ -2858,16 +2949,16 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - pass_data.set_index_buffer_with_f64_and_f64( - buffer_data, + pass_data.0.set_index_buffer_with_f64_and_f64( + &buffer_data.0, map_index_format(index_format), offset as f64, s.get() as f64, ); } None => { - pass_data.set_index_buffer_with_f64( - buffer_data, + pass_data.0.set_index_buffer_with_f64( + &buffer_data.0, map_index_format(index_format), offset as f64, ); @@ -2887,15 +2978,17 @@ impl crate::context::Context for Context { ) { match size { Some(s) => { - pass_data.set_vertex_buffer_with_f64_and_f64( + pass_data.0.set_vertex_buffer_with_f64_and_f64( slot, - buffer_data, + &buffer_data.0, offset as f64, s.get() as f64, ); } None => { - pass_data.set_vertex_buffer_with_f64(slot, buffer_data, offset as f64); + pass_data + .0 + .set_vertex_buffer_with_f64(slot, &buffer_data.0, offset as f64); } }; } @@ -2918,12 +3011,14 @@ impl crate::context::Context for Context { vertices: Range, instances: Range, ) { - pass_data.draw_with_instance_count_and_first_vertex_and_first_instance( - vertices.end - vertices.start, - instances.end - instances.start, - vertices.start, - instances.start, - ); + pass_data + .0 + .draw_with_instance_count_and_first_vertex_and_first_instance( + vertices.end - vertices.start, + instances.end - instances.start, + vertices.start, + instances.start, + ); } fn render_pass_draw_indexed( @@ -2935,6 +3030,7 @@ impl crate::context::Context for Context { instances: Range, ) { pass_data + .0 .draw_indexed_with_instance_count_and_first_index_and_base_vertex_and_first_instance( indices.end - indices.start, instances.end - instances.start, @@ -2952,7 +3048,9 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - pass_data.draw_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); + pass_data + .0 + .draw_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); } fn render_pass_draw_indexed_indirect( @@ -2963,7 +3061,9 @@ impl crate::context::Context for Context { indirect_buffer_data: &Self::BufferData, indirect_offset: wgt::BufferAddress, ) { - pass_data.draw_indexed_indirect_with_f64(indirect_buffer_data, indirect_offset as f64); + pass_data + .0 + .draw_indexed_indirect_with_f64(&indirect_buffer_data.0, indirect_offset as f64); } fn render_pass_multi_draw_indirect( @@ -3028,7 +3128,9 @@ impl crate::context::Context for Context { pass_data: &mut Self::RenderPassData, color: wgt::Color, ) { - pass_data.set_blend_constant_with_gpu_color_dict(&map_color(color)); + pass_data + .0 + .set_blend_constant_with_gpu_color_dict(&map_color(color)); } fn render_pass_set_scissor_rect( @@ -3040,7 +3142,7 @@ impl crate::context::Context for Context { width: u32, height: u32, ) { - pass_data.set_scissor_rect(x, y, width, height); + pass_data.0.set_scissor_rect(x, y, width, height); } fn render_pass_set_viewport( @@ -3054,7 +3156,9 @@ impl crate::context::Context for Context { min_depth: f32, max_depth: f32, ) { - pass_data.set_viewport(x, y, width, height, min_depth, max_depth); + pass_data + .0 + .set_viewport(x, y, width, height, min_depth, max_depth); } fn render_pass_set_stencil_reference( @@ -3063,7 +3167,7 @@ impl crate::context::Context for Context { pass_data: &mut Self::RenderPassData, reference: u32, ) { - pass_data.set_stencil_reference(reference); + pass_data.0.set_stencil_reference(reference); } fn render_pass_insert_debug_marker( @@ -3134,9 +3238,9 @@ impl crate::context::Context for Context { >, ) { let mapped = render_bundles - .map(|(_, bundle_data)| bundle_data) + .map(|(_, bundle_data)| &bundle_data.0) .collect::(); - pass_data.execute_bundles(&mapped); + pass_data.0.execute_bundles(&mapped); } } diff --git a/wgpu/src/context.rs b/wgpu/src/context.rs index fbc85279cb..33e8b5a5e4 100644 --- a/wgpu/src/context.rs +++ b/wgpu/src/context.rs @@ -1039,7 +1039,13 @@ impl ObjectId { } } -#[cfg(not(target_arch = "wasm32"))] +#[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( @@ -1082,33 +1088,93 @@ pub(crate) struct DeviceRequest { pub queue_data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] pub type BufferMapCallback = Box) + Send + 'static>; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] pub type BufferMapCallback = Box) + 'static>; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] pub(crate) type AdapterRequestDeviceFuture = Box> + Send>; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] pub(crate) type AdapterRequestDeviceFuture = Box>>; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] pub type InstanceRequestAdapterFuture = Box)>> + Send>; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] pub type InstanceRequestAdapterFuture = Box)>>>; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] pub type DevicePopErrorFuture = Box> + Send>; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] pub type DevicePopErrorFuture = Box>>; -#[cfg(not(target_arch = "wasm32"))] +#[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +))] pub type SubmittedWorkDoneCallback = Box; -#[cfg(target_arch = "wasm32")] +#[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) +)))] pub type SubmittedWorkDoneCallback = Box; /// An object safe variant of [`Context`] implemented by all types that implement [`Context`]. diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 9080082094..2ab86419a1 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -79,9 +79,21 @@ pub enum ErrorFilter { static_assertions::assert_impl_all!(ErrorFilter: Send, Sync); type C = dyn DynContext; -#[cfg(not(target_arch = "wasm32"))] +#[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(target_arch = "wasm32")] +#[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. @@ -96,7 +108,13 @@ type Data = dyn Any; pub struct Instance { context: Arc, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -113,7 +131,13 @@ pub struct Adapter { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -138,7 +162,13 @@ pub struct Device { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 @@ -149,7 +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); -#[cfg(not(target_arch = "wasm32"))] +#[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 @@ -226,7 +262,13 @@ pub struct Buffer { usage: BufferUsages, // Todo: missing map_state https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapstate } -#[cfg(not(target_arch = "wasm32"))] +#[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`]. @@ -243,7 +285,13 @@ pub struct BufferSlice<'a> { offset: BufferAddress, size: Option, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -259,7 +307,13 @@ pub struct Texture { owned: bool, descriptor: TextureDescriptor<'static>, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -274,7 +328,13 @@ pub struct TextureView { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -292,7 +352,13 @@ pub struct Sampler { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -333,7 +399,13 @@ pub struct Surface { // been created is is additionally wrapped in an option. config: Mutex>, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -361,7 +433,13 @@ pub struct BindGroupLayout { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -387,7 +465,13 @@ pub struct BindGroup { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -412,7 +496,13 @@ pub struct ShaderModule { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -505,7 +595,13 @@ pub struct PipelineLayout { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -529,7 +625,13 @@ pub struct RenderPipeline { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -564,7 +666,13 @@ pub struct ComputePipeline { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -602,7 +710,13 @@ pub struct CommandBuffer { id: Option, data: Option>, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -631,7 +745,13 @@ pub struct CommandEncoder { id: Option, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -708,7 +828,13 @@ pub struct RenderBundle { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -730,7 +856,13 @@ pub struct QuerySet { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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 { @@ -754,7 +886,13 @@ pub struct Queue { id: ObjectId, data: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -800,7 +938,13 @@ pub enum BindingResource<'a> { /// [`BindGroupLayoutEntry::count`] set to Some. TextureViewArray(&'a [&'a TextureView]), } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -832,7 +976,13 @@ pub struct BufferBinding<'a> { /// Size of the binding in bytes, or `None` for using the rest of the buffer. pub size: Option, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -894,7 +1044,13 @@ pub struct RenderPassColorAttachment<'tex> { /// What operations will be performed on this color attachment. pub ops: Operations, } -#[cfg(not(target_arch = "wasm32"))] +#[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`]. @@ -912,7 +1068,13 @@ pub struct RenderPassDepthStencilAttachment<'tex> { /// What operations will be performed on the stencil part of the attachment. pub stencil_ops: Option>, } -#[cfg(not(target_arch = "wasm32"))] +#[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 @@ -927,7 +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(not(target_arch = "wasm32"))] +#[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`]. /// @@ -980,7 +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; -#[cfg(not(target_arch = "wasm32"))] +#[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`]. @@ -1036,7 +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(not(target_arch = "wasm32"))] +#[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`]. @@ -1106,7 +1286,13 @@ pub struct BindGroupEntry<'a> { /// Resource to attach to the binding pub resource: BindingResource<'a>, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -1124,7 +1310,13 @@ pub struct BindGroupDescriptor<'a> { /// The resources to bind to this bind group. pub entries: &'a [BindGroupEntry<'a>], } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -1145,7 +1337,13 @@ pub struct RenderPassDescriptor<'tex, 'desc> { /// The depth and stencil attachment of the render pass, if any. pub depth_stencil_attachment: Option>, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -1181,7 +1379,13 @@ pub struct VertexState<'a> { /// The format of any vertex buffers used with this pipeline. pub buffers: &'a [VertexBufferLayout<'a>], } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -1200,7 +1404,13 @@ pub struct FragmentState<'a> { /// The color state of the render targets. pub targets: &'a [Option], } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -1229,7 +1439,13 @@ pub struct RenderPipelineDescriptor<'a> { /// layers the attachments will have. pub multiview: Option, } -#[cfg(not(target_arch = "wasm32"))] +#[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. @@ -1263,7 +1479,13 @@ pub struct ComputePipelineDescriptor<'a> { /// and no return value in the shader. pub entry_point: &'a str, } -#[cfg(not(target_arch = "wasm32"))] +#[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; @@ -1272,7 +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(not(target_arch = "wasm32"))] +#[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; @@ -1281,7 +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(not(target_arch = "wasm32"))] +#[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; @@ -1291,7 +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(not(target_arch = "wasm32"))] +#[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`]. @@ -1350,7 +1590,13 @@ pub struct SurfaceTexture { presented: bool, detail: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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`]. @@ -4011,7 +4257,13 @@ pub struct QueueWriteBufferView<'a> { offset: BufferAddress, inner: Box, } -#[cfg(not(target_arch = "wasm32"))] +#[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<'_> { @@ -4651,25 +4903,55 @@ pub enum Error { /// Out of memory error OutOfMemory { /// Lower level source of the error. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] source: Box, /// Lower level source of the error. - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] source: Box, }, /// Validation error, signifying a bug in code or data Validation { /// Lower level source of the error. - #[cfg(not(target_arch = "wasm32"))] + #[cfg(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + ))] source: Box, /// Lower level source of the error. - #[cfg(target_arch = "wasm32")] + #[cfg(not(any( + not(target_arch = "wasm32"), + all( + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") + ) + )))] source: Box, /// Description of the validation error. description: String, }, } -#[cfg(not(target_arch = "wasm32"))] +#[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 {