From 9b53e96e2d4955397dea9659f9891175a4ec5954 Mon Sep 17 00:00:00 2001 From: i509VCB Date: Thu, 15 Sep 2022 00:51:47 -0500 Subject: [PATCH] statically assert public wgpu types appropriately implement Send and Sync Although we still have some gaps and disagreements between Web and Native whether some types are Send + Sync and a few safety concerns, this pull request should help prevent accidentally making types no longer Send + Sync when the types should be and vice versa. --- CHANGELOG.md | 1 + Cargo.lock | 7 +++++ wgpu/Cargo.toml | 1 + wgpu/src/backend/web.rs | 28 ++++++++++--------- wgpu/src/lib.rs | 61 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3555702a5a..c6e32c31b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,7 @@ the same every time it is rendered, we now warn if it is missing. - Improve the validation and error reporting of buffer mappings by @nical in [#2848](https://github.com/gfx-rs/wgpu/pull/2848) - Fix compilation errors when using wgpu-core in isolation while targetting `wasm32-unknown-unknown` by @Seamooo in [#2922](https://github.com/gfx-rs/wgpu/pull/2922) - Fixed opening of RenderDoc library by @abuffseagull in [#2930](https://github.com/gfx-rs/wgpu/pull/2930) +- Fixed `CommandEncoder` not being `Send` and `Sync` on web by @i509VCB in [#3025](https://github.com/gfx-rs/wgpu/pull/3025) #### Metal - Add the missing `msg_send![view, retain]` call within `from_view` by @jinleili in [#2976](https://github.com/gfx-rs/wgpu/pull/2976) diff --git a/Cargo.lock b/Cargo.lock index 7b48ee4aad..cd9a41aa97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1919,6 +1919,12 @@ dependencies = [ "num-traits 0.2.15", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.10.0" @@ -2365,6 +2371,7 @@ dependencies = [ "raw-window-handle 0.5.0", "serde", "smallvec", + "static_assertions", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index e0040dfb16..1495c1f240 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -117,6 +117,7 @@ parking_lot = ">=0.11,<0.13" raw-window-handle = "0.5" serde = { version = "1", features = ["derive"], optional = true } smallvec = "1" +static_assertions = "1.1.0" [dev-dependencies] bitflags = "1" diff --git a/wgpu/src/backend/web.rs b/wgpu/src/backend/web.rs index f816125148..c68d37faab 100644 --- a/wgpu/src/backend/web.rs +++ b/wgpu/src/backend/web.rs @@ -993,7 +993,7 @@ impl crate::Context for Context { type PipelineLayoutId = Sendable; type RenderPipelineId = Sendable; type ComputePipelineId = Sendable; - type CommandEncoderId = web_sys::GpuCommandEncoder; + type CommandEncoderId = Sendable; type ComputePassId = ComputePass; type RenderPassId = RenderPass; type CommandBufferId = Sendable; @@ -1718,9 +1718,11 @@ impl crate::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - device - .0 - .create_command_encoder_with_descriptor(&mapped_desc) + Sendable( + device + .0 + .create_command_encoder_with_descriptor(&mapped_desc), + ) } fn device_create_render_bundle_encoder( @@ -1950,7 +1952,7 @@ impl crate::Context for Context { destination_offset: wgt::BufferAddress, copy_size: wgt::BufferAddress, ) { - encoder.copy_buffer_to_buffer_with_f64_and_f64_and_f64( + encoder.0.copy_buffer_to_buffer_with_f64_and_f64_and_f64( &source.0, source_offset as f64, &destination.0, @@ -1966,7 +1968,7 @@ impl crate::Context for Context { destination: crate::ImageCopyTexture, copy_size: wgt::Extent3d, ) { - encoder.copy_buffer_to_texture_with_gpu_extent_3d_dict( + encoder.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), @@ -1980,7 +1982,7 @@ impl crate::Context for Context { destination: crate::ImageCopyBuffer, copy_size: wgt::Extent3d, ) { - encoder.copy_texture_to_buffer_with_gpu_extent_3d_dict( + encoder.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), @@ -1994,7 +1996,7 @@ impl crate::Context for Context { destination: crate::ImageCopyTexture, copy_size: wgt::Extent3d, ) { - encoder.copy_texture_to_texture_with_gpu_extent_3d_dict( + encoder.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), @@ -2010,7 +2012,7 @@ impl crate::Context for Context { if let Some(label) = desc.label { mapped_desc.label(label); } - ComputePass(encoder.begin_compute_pass_with_descriptor(&mapped_desc)) + ComputePass(encoder.0.begin_compute_pass_with_descriptor(&mapped_desc)) } fn command_encoder_end_compute_pass( @@ -2105,7 +2107,7 @@ impl crate::Context for Context { mapped_desc.depth_stencil_attachment(&mapped_depth_stencil_attachment); } - RenderPass(encoder.begin_render_pass(&mapped_desc)) + RenderPass(encoder.0.begin_render_pass(&mapped_desc)) } fn command_encoder_end_render_pass( @@ -2117,13 +2119,13 @@ impl crate::Context for Context { } fn command_encoder_finish(&self, encoder: Self::CommandEncoderId) -> Self::CommandBufferId { - let label = encoder.label(); + let label = encoder.0.label(); Sendable(if label.is_empty() { - encoder.finish() + encoder.0.finish() } else { let mut mapped_desc = web_sys::GpuCommandBufferDescriptor::new(); mapped_desc.label(&label); - encoder.finish_with_descriptor(&mapped_desc) + encoder.0.finish_with_descriptor(&mapped_desc) }) } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 541fa3566e..eccce175dc 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -53,6 +53,7 @@ pub enum ErrorFilter { /// Catch only validation errors. Validation, } +static_assertions::assert_impl_all!(ErrorFilter: Send, Sync); trait ComputePassInner { fn set_pipeline(&mut self, pipeline: &Ctx::ComputePipelineId); @@ -546,6 +547,7 @@ trait Context: Debug + Send + Sized + Sync { pub struct Instance { context: Arc, } +static_assertions::assert_impl_all!(Instance: Send, Sync); /// Handle to a physical graphics and/or compute device. /// @@ -560,6 +562,7 @@ pub struct Adapter { context: Arc, id: ::AdapterId, } +static_assertions::assert_impl_all!(Adapter: Send, Sync); impl Drop for Adapter { fn drop(&mut self) { @@ -582,12 +585,14 @@ pub struct Device { context: Arc, id: ::DeviceId, } +static_assertions::assert_impl_all!(Device: Send, Sync); /// Identifier for a particular call to [`Queue::submit`]. Can be used /// as part of an argument to [`Device::poll`] to block for a particular /// submission to finish. #[derive(Debug, Copy, Clone)] pub struct SubmissionIndex(::SubmissionIndex); +static_assertions::assert_impl_all!(SubmissionIndex: Send, Sync); /// The main purpose of this struct is to resolve mapped ranges (convert sizes /// to end points), and to ensure that the sub-ranges don't intersect. @@ -662,6 +667,7 @@ pub struct Buffer { size: wgt::BufferAddress, usage: BufferUsages, } +static_assertions::assert_impl_all!(Buffer: Send, Sync); /// Slice into a [`Buffer`]. /// @@ -674,6 +680,7 @@ pub struct BufferSlice<'a> { offset: BufferAddress, size: Option, } +static_assertions::assert_impl_all!(BufferSlice: Send, Sync); /// Handle to a texture on the GPU. /// @@ -686,6 +693,7 @@ pub struct Texture { id: ::TextureId, owned: bool, } +static_assertions::assert_impl_all!(Texture: Send, Sync); /// Handle to a texture view. /// @@ -698,6 +706,7 @@ pub struct TextureView { context: Arc, id: ::TextureViewId, } +static_assertions::assert_impl_all!(TextureView: Send, Sync); /// Handle to a sampler. /// @@ -713,6 +722,7 @@ pub struct Sampler { context: Arc, id: ::SamplerId, } +static_assertions::assert_impl_all!(Sampler: Send, Sync); impl Drop for Sampler { fn drop(&mut self) { @@ -731,6 +741,7 @@ pub struct Surface { context: Arc, id: ::SurfaceId, } +static_assertions::assert_impl_all!(Surface: Send, Sync); impl Drop for Surface { fn drop(&mut self) { @@ -756,6 +767,7 @@ pub struct BindGroupLayout { context: Arc, id: ::BindGroupLayoutId, } +static_assertions::assert_impl_all!(BindGroupLayout: Send, Sync); impl Drop for BindGroupLayout { fn drop(&mut self) { @@ -778,6 +790,7 @@ pub struct BindGroup { context: Arc, id: ::BindGroupId, } +static_assertions::assert_impl_all!(BindGroup: Send, Sync); impl Drop for BindGroup { fn drop(&mut self) { @@ -800,6 +813,7 @@ pub struct ShaderModule { context: Arc, id: ::ShaderModuleId, } +static_assertions::assert_impl_all!(ShaderModule: Send, Sync); impl Drop for ShaderModule { fn drop(&mut self) { @@ -843,6 +857,7 @@ pub enum ShaderSource<'a> { #[cfg_attr(docsrs, doc(cfg(feature = "naga")))] Naga(naga::Module), } +static_assertions::assert_impl_all!(ShaderSource: Send, Sync); /// Descriptor for use with [`Device::create_shader_module`]. /// @@ -854,6 +869,7 @@ pub struct ShaderModuleDescriptor<'a> { /// Source code for the shader. pub source: ShaderSource<'a>, } +static_assertions::assert_impl_all!(ShaderModuleDescriptor: Send, Sync); /// Descriptor for a shader module given by SPIR-V binary. pub struct ShaderModuleDescriptorSpirV<'a> { @@ -862,6 +878,7 @@ pub struct ShaderModuleDescriptorSpirV<'a> { /// Binary SPIR-V data, in 4-byte words. pub source: Cow<'a, [u32]>, } +static_assertions::assert_impl_all!(ShaderModuleDescriptorSpirV: Send, Sync); /// Handle to a pipeline layout. /// @@ -874,6 +891,7 @@ pub struct PipelineLayout { context: Arc, id: ::PipelineLayoutId, } +static_assertions::assert_impl_all!(PipelineLayout: Send, Sync); impl Drop for PipelineLayout { fn drop(&mut self) { @@ -894,6 +912,7 @@ pub struct RenderPipeline { context: Arc, id: ::RenderPipelineId, } +static_assertions::assert_impl_all!(RenderPipeline: Send, Sync); impl Drop for RenderPipeline { fn drop(&mut self) { @@ -927,6 +946,7 @@ pub struct ComputePipeline { context: Arc, id: ::ComputePipelineId, } +static_assertions::assert_impl_all!(ComputePipeline: Send, Sync); impl Drop for ComputePipeline { fn drop(&mut self) { @@ -961,6 +981,7 @@ pub struct CommandBuffer { context: Arc, id: Option<::CommandBufferId>, } +static_assertions::assert_impl_all!(CommandBuffer: Send, Sync); impl Drop for CommandBuffer { fn drop(&mut self) { @@ -986,6 +1007,7 @@ pub struct CommandEncoder { context: Arc, id: Option<::CommandEncoderId>, } +static_assertions::assert_impl_all!(CommandEncoder: Send, Sync); impl Drop for CommandEncoder { fn drop(&mut self) { @@ -1041,6 +1063,7 @@ pub struct RenderBundleEncoder<'a> { /// command buffer. _p: PhantomData<*const u8>, } +static_assertions::assert_not_impl_any!(RenderBundleEncoder<'_>: Send, Sync); /// Pre-prepared reusable bundle of GPU operations. /// @@ -1056,6 +1079,7 @@ pub struct RenderBundle { context: Arc, id: ::RenderBundleId, } +static_assertions::assert_impl_all!(RenderBundle: Send, Sync); impl Drop for RenderBundle { fn drop(&mut self) { @@ -1074,6 +1098,7 @@ pub struct QuerySet { context: Arc, id: ::QuerySetId, } +static_assertions::assert_impl_all!(QuerySet: Send, Sync); impl Drop for QuerySet { fn drop(&mut self) { @@ -1095,6 +1120,7 @@ pub struct Queue { context: Arc, id: ::QueueId, } +static_assertions::assert_impl_all!(Queue: Send, Sync); /// Resource that can be bound to a pipeline. /// @@ -1139,6 +1165,7 @@ pub enum BindingResource<'a> { /// [`BindGroupLayoutEntry::count`] set to Some. TextureViewArray(&'a [&'a TextureView]), } +static_assertions::assert_impl_all!(BindingResource: Send, Sync); /// Describes the segment of a buffer to bind. /// @@ -1157,6 +1184,7 @@ pub struct BufferBinding<'a> { /// Size of the binding, or `None` for using the rest of the buffer. pub size: Option, } +static_assertions::assert_impl_all!(BufferBinding: Send, Sync); /// Operation to perform to the output attachment at the start of a renderpass. /// @@ -1214,6 +1242,7 @@ pub struct RenderPassColorAttachment<'tex> { /// What operations will be performed on this color attachment. pub ops: Operations, } +static_assertions::assert_impl_all!(RenderPassColorAttachment: Send, Sync); /// Describes a depth/stencil attachment to a [`RenderPass`]. /// @@ -1230,6 +1259,7 @@ pub struct RenderPassDepthStencilAttachment<'tex> { /// What operations will be performed on the stencil part of the attachment. pub stencil_ops: Option>, } +static_assertions::assert_impl_all!(RenderPassDepthStencilAttachment: Send, Sync); // The underlying types are also exported so that documentation shows up for them @@ -1243,6 +1273,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>; +static_assertions::assert_impl_all!(RequestAdapterOptions: Send, Sync); /// Describes a [`Device`]. /// /// For use with [`Adapter::request_device`]. @@ -1250,6 +1281,7 @@ pub type RequestAdapterOptions<'a> = RequestAdapterOptionsBase<&'a Surface>; /// Corresponds to [WebGPU `GPUDeviceDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gpudevicedescriptor). pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor>; +static_assertions::assert_impl_all!(DeviceDescriptor: Send, Sync); /// Describes a [`Buffer`]. /// /// For use with [`Device::create_buffer`]. @@ -1257,6 +1289,7 @@ pub type DeviceDescriptor<'a> = wgt::DeviceDescriptor>; /// Corresponds to [WebGPU `GPUBufferDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferdescriptor). pub type BufferDescriptor<'a> = wgt::BufferDescriptor>; +static_assertions::assert_impl_all!(BufferDescriptor: Send, Sync); /// Describes a [`CommandEncoder`]. /// /// For use with [`Device::create_command_encoder`]. @@ -1264,6 +1297,7 @@ pub type BufferDescriptor<'a> = wgt::BufferDescriptor>; /// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor). pub type CommandEncoderDescriptor<'a> = wgt::CommandEncoderDescriptor>; +static_assertions::assert_impl_all!(CommandEncoderDescriptor: Send, Sync); /// Describes a [`RenderBundle`]. /// /// For use with [`RenderBundleEncoder::finish`]. @@ -1271,6 +1305,7 @@ pub type CommandEncoderDescriptor<'a> = wgt::CommandEncoderDescriptor> /// Corresponds to [WebGPU `GPURenderBundleDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundledescriptor). pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor>; +static_assertions::assert_impl_all!(RenderBundleDescriptor: Send, Sync); /// Describes a [`Texture`]. /// /// For use with [`Device::create_texture`]. @@ -1278,6 +1313,7 @@ pub type RenderBundleDescriptor<'a> = wgt::RenderBundleDescriptor>; /// Corresponds to [WebGPU `GPUTextureDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor). pub type TextureDescriptor<'a> = wgt::TextureDescriptor>; +static_assertions::assert_impl_all!(TextureDescriptor: Send, Sync); /// Describes a [`QuerySet`]. /// /// For use with [`Device::create_query_set`]. @@ -1285,9 +1321,11 @@ pub type TextureDescriptor<'a> = wgt::TextureDescriptor>; /// Corresponds to [WebGPU `GPUQuerySetDescriptor`]( /// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor). pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor>; +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; +static_assertions::assert_impl_all!(Maintain: Send, Sync); /// Describes a [`TextureView`]. /// @@ -1319,6 +1357,7 @@ pub struct TextureViewDescriptor<'a> { /// If `None`, considered to include the rest of the array layers, but at least 1 in total. pub array_layer_count: Option, } +static_assertions::assert_impl_all!(TextureViewDescriptor: Send, Sync); /// Describes a [`PipelineLayout`]. /// @@ -1340,6 +1379,7 @@ pub struct PipelineLayoutDescriptor<'a> { /// If this array is non-empty, the [`Features::PUSH_CONSTANTS`] must be enabled. pub push_constant_ranges: &'a [PushConstantRange], } +static_assertions::assert_impl_all!(PipelineLayoutDescriptor: Send, Sync); /// Describes a [`Sampler`]. /// @@ -1374,6 +1414,7 @@ pub struct SamplerDescriptor<'a> { /// Border color to use when address_mode is [`AddressMode::ClampToBorder`] pub border_color: Option, } +static_assertions::assert_impl_all!(SamplerDescriptor: Send, Sync); impl Default for SamplerDescriptor<'_> { fn default() -> Self { @@ -1407,6 +1448,7 @@ pub struct BindGroupEntry<'a> { /// Resource to attach to the binding pub resource: BindingResource<'a>, } +static_assertions::assert_impl_all!(BindGroupEntry: Send, Sync); /// Describes a group of bindings and the resources to be bound. /// @@ -1423,6 +1465,7 @@ pub struct BindGroupDescriptor<'a> { /// The resources to bind to this bind group. pub entries: &'a [BindGroupEntry<'a>], } +static_assertions::assert_impl_all!(BindGroupDescriptor: Send, Sync); /// Describes the attachments of a render pass. /// @@ -1442,6 +1485,7 @@ pub struct RenderPassDescriptor<'tex, 'desc> { /// The depth and stencil attachment of the render pass, if any. pub depth_stencil_attachment: Option>, } +static_assertions::assert_impl_all!(RenderPassDescriptor: Send, Sync); /// Describes how the vertex buffer is interpreted. /// @@ -1458,6 +1502,7 @@ pub struct VertexBufferLayout<'a> { /// The list of attributes which comprise a single vertex. pub attributes: &'a [VertexAttribute], } +static_assertions::assert_impl_all!(VertexBufferLayout: Send, Sync); /// Describes the vertex processing in a render pipeline. /// @@ -1475,6 +1520,7 @@ pub struct VertexState<'a> { /// The format of any vertex buffers used with this pipeline. pub buffers: &'a [VertexBufferLayout<'a>], } +static_assertions::assert_impl_all!(VertexState: Send, Sync); /// Describes the fragment processing in a render pipeline. /// @@ -1492,6 +1538,7 @@ pub struct FragmentState<'a> { /// The color state of the render targets. pub targets: &'a [Option], } +static_assertions::assert_impl_all!(FragmentState: Send, Sync); /// Describes a render (graphics) pipeline. /// @@ -1519,6 +1566,7 @@ pub struct RenderPipelineDescriptor<'a> { /// layers the attachments will have. pub multiview: Option, } +static_assertions::assert_impl_all!(RenderPipelineDescriptor: Send, Sync); /// Describes the attachments of a compute pass. /// @@ -1531,6 +1579,7 @@ pub struct ComputePassDescriptor<'a> { /// Debug label of the compute pass. This will show up in graphics debuggers for easy identification. pub label: Label<'a>, } +static_assertions::assert_impl_all!(ComputePassDescriptor: Send, Sync); /// Describes a compute pipeline. /// @@ -1550,6 +1599,7 @@ pub struct ComputePipelineDescriptor<'a> { /// and no return value in the shader. pub entry_point: &'a str, } +static_assertions::assert_impl_all!(ComputePipelineDescriptor: Send, Sync); pub use wgt::ImageCopyBuffer as ImageCopyBufferBase; /// View of a buffer which can be used to copy to/from a texture. @@ -1557,6 +1607,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>; +static_assertions::assert_impl_all!(ImageCopyBuffer: Send, Sync); pub use wgt::ImageCopyTexture as ImageCopyTextureBase; /// View of a texture which can be used to copy to/from a buffer/texture. @@ -1564,6 +1615,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>; +static_assertions::assert_impl_all!(ImageCopyTexture: Send, Sync); /// Describes a [`BindGroupLayout`]. /// @@ -1579,6 +1631,7 @@ pub struct BindGroupLayoutDescriptor<'a> { /// Array of entries in this BindGroupLayout pub entries: &'a [BindGroupLayoutEntry], } +static_assertions::assert_impl_all!(BindGroupLayoutDescriptor: Send, Sync); /// Describes a [`RenderBundleEncoder`]. /// @@ -1602,6 +1655,7 @@ pub struct RenderBundleEncoderDescriptor<'a> { /// If this render bundle will rendering to multiple array layers in the attachments at the same time. pub multiview: Option, } +static_assertions::assert_impl_all!(RenderBundleEncoderDescriptor: Send, Sync); /// Surface texture that can be rendered to. /// Result of a successful call to [`Surface::get_current_texture`]. @@ -1615,6 +1669,7 @@ pub struct SurfaceTexture { presented: bool, detail: ::SurfaceOutputDetail, } +static_assertions::assert_impl_all!(SurfaceTexture: Send, Sync); /// Result of an unsuccessful call to [`Surface::get_current_texture`]. #[derive(Clone, PartialEq, Eq, Debug)] @@ -1628,6 +1683,7 @@ pub enum SurfaceError { /// There is no more memory left to allocate a new frame. OutOfMemory, } +static_assertions::assert_impl_all!(SurfaceError: Send, Sync); impl Display for SurfaceError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -2264,6 +2320,7 @@ impl Drop for Device { /// Requesting a device failed. #[derive(Clone, PartialEq, Eq, Debug)] pub struct RequestDeviceError; +static_assertions::assert_impl_all!(RequestDeviceError: Send, Sync); impl Display for RequestDeviceError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -2276,6 +2333,7 @@ impl error::Error for RequestDeviceError {} /// Error occurred when trying to async map a buffer. #[derive(Clone, PartialEq, Eq, Debug)] pub struct BufferAsyncError; +static_assertions::assert_impl_all!(BufferAsyncError: Send, Sync); impl Display for BufferAsyncError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -2293,6 +2351,7 @@ pub enum MapMode { /// Map only for writing Write, } +static_assertions::assert_impl_all!(MapMode: Send, Sync); fn range_to_offset_size>( bounds: S, @@ -3449,6 +3508,7 @@ pub struct QueueWriteBufferView<'a> { offset: BufferAddress, inner: QueueWriteBuffer, } +static_assertions::assert_impl_all!(QueueWriteBufferView: Send, Sync); impl<'a> std::ops::Deref for QueueWriteBufferView<'a> { type Target = [u8]; @@ -3677,6 +3737,7 @@ pub enum Error { description: String, }, } +static_assertions::assert_impl_all!(Error: Send); impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> {