diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 79000c452..927358ea2 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -971,7 +971,7 @@ impl Device { array_layer_count: Some(1), }, }; - clear_views.push(Some( + clear_views.push(ManuallyDrop::new( unsafe { self.raw().create_texture_view(&raw_texture, &desc) } .map_err(DeviceError::from)?, )); diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index 38828f764..3521f0438 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -9,7 +9,7 @@ When this texture is presented, we remove it from the device tracker as well as extract it from the hub. !*/ -use std::{borrow::Borrow, sync::Arc}; +use std::{borrow::Borrow, mem::ManuallyDrop, sync::Arc}; #[cfg(feature = "trace")] use crate::device::trace::Action; @@ -215,7 +215,7 @@ impl Global { &texture_desc, format_features, resource::TextureClearMode::Surface { - clear_view: Some(clear_view), + clear_view: ManuallyDrop::new(clear_view), }, true, ); diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index d23290789..80ed66b31 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -972,11 +972,11 @@ pub enum TextureClearMode { BufferCopy, // View for clear via RenderPass for every subsurface (mip/layer/slice) RenderPass { - clear_views: SmallVec<[Option; 1]>, + clear_views: SmallVec<[ManuallyDrop; 1]>, is_color: bool, }, Surface { - clear_view: Option, + clear_view: ManuallyDrop, }, // Texture can't be cleared, attempting to do so will cause panic. // (either because it is impossible for the type of texture or it is being destroyed) @@ -1062,10 +1062,10 @@ impl Drop for Texture { TextureClearMode::Surface { ref mut clear_view, .. } => { - if let Some(view) = clear_view.take() { - unsafe { - self.device.raw().destroy_texture_view(view); - } + // SAFETY: We are in the Drop impl and we don't use clear_view anymore after this point. + let raw = unsafe { ManuallyDrop::take(clear_view) }; + unsafe { + self.device.raw().destroy_texture_view(raw); } } TextureClearMode::RenderPass { @@ -1073,10 +1073,10 @@ impl Drop for Texture { .. } => { clear_views.iter_mut().for_each(|clear_view| { - if let Some(view) = clear_view.take() { - unsafe { - self.device.raw().destroy_texture_view(view); - } + // SAFETY: We are in the Drop impl and we don't use clear_view anymore after this point. + let raw = unsafe { ManuallyDrop::take(clear_view) }; + unsafe { + self.device.raw().destroy_texture_view(raw); } }); } @@ -1129,7 +1129,7 @@ impl Texture { TextureClearMode::None => { panic!("Given texture can't be cleared") } - TextureClearMode::Surface { ref clear_view, .. } => clear_view.as_ref().unwrap(), + TextureClearMode::Surface { ref clear_view, .. } => clear_view, TextureClearMode::RenderPass { ref clear_views, .. } => { @@ -1140,7 +1140,7 @@ impl Texture { } else { mip_level * desc.size.depth_or_array_layers } + depth_or_layer; - clear_views[index as usize].as_ref().unwrap() + &clear_views[index as usize] } } }