use ManuallyDrop for remaining resources

This commit is contained in:
teoxoy 2024-08-07 14:24:52 +02:00 committed by Teodor Tanasoaia
parent b0cc0d2ebc
commit c1bc0864c5
5 changed files with 101 additions and 93 deletions

View File

@ -26,6 +26,7 @@ use serde::Serialize;
use std::{
borrow::Cow,
mem::ManuallyDrop,
ops::Range,
sync::{Arc, Weak},
};
@ -498,7 +499,7 @@ impl<A: HalApi> std::fmt::Display for ExclusivePipeline<A> {
/// Bind group layout.
#[derive(Debug)]
pub struct BindGroupLayout<A: HalApi> {
pub(crate) raw: Option<A::BindGroupLayout>,
pub(crate) raw: ManuallyDrop<A::BindGroupLayout>,
pub(crate) device: Arc<Device<A>>,
pub(crate) entries: bgl::EntryMap,
/// It is very important that we know if the bind group comes from the BGL pool.
@ -517,15 +518,15 @@ pub struct BindGroupLayout<A: HalApi> {
impl<A: HalApi> Drop for BindGroupLayout<A> {
fn drop(&mut self) {
resource_log!("Destroy raw {}", self.error_ident());
if matches!(self.origin, bgl::Origin::Pool) {
self.device.bgl_pool.remove(&self.entries);
}
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_bind_group_layout(raw);
}
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_bind_group_layout(raw);
}
}
}
@ -537,7 +538,7 @@ crate::impl_storage_item!(BindGroupLayout);
impl<A: HalApi> BindGroupLayout<A> {
pub(crate) fn raw(&self) -> &A::BindGroupLayout {
self.raw.as_ref().unwrap()
&self.raw
}
}
@ -651,7 +652,7 @@ pub struct ResolvedPipelineLayoutDescriptor<'a, A: HalApi> {
#[derive(Debug)]
pub struct PipelineLayout<A: HalApi> {
pub(crate) raw: Option<A::PipelineLayout>,
pub(crate) raw: ManuallyDrop<A::PipelineLayout>,
pub(crate) device: Arc<Device<A>>,
/// The `label` from the descriptor used to create the resource.
pub(crate) label: String,
@ -661,19 +662,19 @@ pub struct PipelineLayout<A: HalApi> {
impl<A: HalApi> Drop for PipelineLayout<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_pipeline_layout(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_pipeline_layout(raw);
}
}
}
impl<A: HalApi> PipelineLayout<A> {
pub(crate) fn raw(&self) -> &A::PipelineLayout {
self.raw.as_ref().unwrap()
&self.raw
}
pub(crate) fn get_binding_maps(&self) -> ArrayVec<&bgl::EntryMap, { hal::MAX_BIND_GROUPS }> {

View File

@ -2191,23 +2191,21 @@ impl Global {
if !cache.device.is_valid() {
return None;
}
if let Some(raw_cache) = cache.raw.as_ref() {
let mut vec = unsafe { cache.device.raw().pipeline_cache_get_data(raw_cache) }?;
let validation_key = cache.device.raw().pipeline_cache_validation_key()?;
let mut vec = unsafe { cache.device.raw().pipeline_cache_get_data(cache.raw()) }?;
let validation_key = cache.device.raw().pipeline_cache_validation_key()?;
let mut header_contents = [0; pipeline_cache::HEADER_LENGTH];
pipeline_cache::add_cache_header(
&mut header_contents,
&vec,
&cache.device.adapter.raw.info,
validation_key,
);
let mut header_contents = [0; pipeline_cache::HEADER_LENGTH];
pipeline_cache::add_cache_header(
&mut header_contents,
&vec,
&cache.device.adapter.raw.info,
validation_key,
);
let deleted = vec.splice(..0, header_contents).collect::<Vec<_>>();
debug_assert!(deleted.is_empty());
let deleted = vec.splice(..0, header_contents).collect::<Vec<_>>();
debug_assert!(deleted.is_empty());
return Some(vec);
}
return Some(vec);
}
None
}

View File

@ -80,7 +80,7 @@ use super::{
/// When locking pending_writes please check that trackers is not locked
/// trackers should be locked only when needed for the shortest time possible
pub struct Device<A: HalApi> {
raw: Option<A::Device>,
raw: ManuallyDrop<A::Device>,
pub(crate) adapter: Arc<Adapter<A>>,
pub(crate) queue: OnceCell<Weak<Queue<A>>>,
queue_to_drop: OnceCell<A::Queue>,
@ -169,7 +169,8 @@ impl<A: HalApi> std::fmt::Debug for Device<A> {
impl<A: HalApi> Drop for Device<A> {
fn drop(&mut self) {
resource_log!("Drop {}", self.error_ident());
let raw = self.raw.take().unwrap();
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
// SAFETY: We are in the Drop impl and we don't use self.pending_writes anymore after this point.
let pending_writes = unsafe { ManuallyDrop::take(&mut self.pending_writes.lock()) };
pending_writes.dispose(&raw);
@ -193,7 +194,7 @@ pub enum CreateDeviceError {
impl<A: HalApi> Device<A> {
pub(crate) fn raw(&self) -> &A::Device {
self.raw.as_ref().unwrap()
&self.raw
}
pub(crate) fn require_features(&self, feature: wgt::Features) -> Result<(), MissingFeatures> {
if self.features.contains(feature) {
@ -271,7 +272,7 @@ impl<A: HalApi> Device<A> {
let downlevel = adapter.raw.capabilities.downlevel.clone();
Ok(Self {
raw: Some(raw_device),
raw: ManuallyDrop::new(raw_device),
adapter: adapter.clone(),
queue: OnceCell::new(),
queue_to_drop: OnceCell::new(),
@ -1418,7 +1419,7 @@ impl<A: HalApi> Device<A> {
};
let sampler = Sampler {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
device: self.clone(),
label: desc.label.to_string(),
tracking_data: TrackingData::new(self.tracker_indices.samplers.clone()),
@ -1550,7 +1551,7 @@ impl<A: HalApi> Device<A> {
};
let module = pipeline::ShaderModule {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
device: self.clone(),
interface: Some(interface),
label: desc.label.to_string(),
@ -1591,7 +1592,7 @@ impl<A: HalApi> Device<A> {
};
let module = pipeline::ShaderModule {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
device: self.clone(),
interface: None,
label: desc.label.to_string(),
@ -1861,7 +1862,7 @@ impl<A: HalApi> Device<A> {
.map_err(binding_model::CreateBindGroupLayoutError::TooManyBindings)?;
let bgl = BindGroupLayout {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
device: self.clone(),
entries: entry_map,
origin,
@ -2576,7 +2577,7 @@ impl<A: HalApi> Device<A> {
drop(raw_bind_group_layouts);
let layout = binding_model::PipelineLayout {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
device: self.clone(),
label: desc.label.to_string(),
bind_group_layouts,
@ -2718,7 +2719,7 @@ impl<A: HalApi> Device<A> {
constants: desc.stage.constants.as_ref(),
zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
},
cache: cache.as_ref().and_then(|it| it.raw.as_ref()),
cache: cache.as_ref().map(|it| it.raw()),
};
let raw =
@ -2742,7 +2743,7 @@ impl<A: HalApi> Device<A> {
)?;
let pipeline = pipeline::ComputePipeline {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
layout: pipeline_layout,
device: self.clone(),
_shader_module: shader_module,
@ -3299,7 +3300,7 @@ impl<A: HalApi> Device<A> {
fragment_stage,
color_targets,
multiview: desc.multiview,
cache: cache.as_ref().and_then(|it| it.raw.as_ref()),
cache: cache.as_ref().map(|it| it.raw()),
};
let raw =
unsafe { self.raw().create_render_pipeline(&pipeline_desc) }.map_err(
@ -3363,7 +3364,7 @@ impl<A: HalApi> Device<A> {
};
let pipeline = pipeline::RenderPipeline {
raw: Some(raw),
raw: ManuallyDrop::new(raw),
layout: pipeline_layout,
device: self.clone(),
pass_context,
@ -3434,7 +3435,7 @@ impl<A: HalApi> Device<A> {
device: self.clone(),
label: desc.label.to_string(),
// This would be none in the error condition, which we don't implement yet
raw: Some(raw),
raw: ManuallyDrop::new(raw),
};
let cache = Arc::new(cache);
@ -3535,8 +3536,10 @@ impl<A: HalApi> Device<A> {
let hal_desc = desc.map_label(|label| label.to_hal(self.instance_flags));
let raw = unsafe { self.raw().create_query_set(&hal_desc).unwrap() };
let query_set = QuerySet {
raw: Some(unsafe { self.raw().create_query_set(&hal_desc).unwrap() }),
raw: ManuallyDrop::new(raw),
device: self.clone(),
label: desc.label.to_string(),
tracking_data: TrackingData::new(self.tracker_indices.query_sets.clone()),

View File

@ -10,7 +10,7 @@ use crate::{
};
use arrayvec::ArrayVec;
use naga::error::ShaderError;
use std::{borrow::Cow, marker::PhantomData, num::NonZeroU32, sync::Arc};
use std::{borrow::Cow, marker::PhantomData, mem::ManuallyDrop, num::NonZeroU32, sync::Arc};
use thiserror::Error;
/// Information about buffer bindings, which
@ -47,7 +47,7 @@ pub struct ShaderModuleDescriptor<'a> {
#[derive(Debug)]
pub struct ShaderModule<A: HalApi> {
pub(crate) raw: Option<A::ShaderModule>,
pub(crate) raw: ManuallyDrop<A::ShaderModule>,
pub(crate) device: Arc<Device<A>>,
pub(crate) interface: Option<validation::Interface>,
/// The `label` from the descriptor used to create the resource.
@ -56,12 +56,12 @@ pub struct ShaderModule<A: HalApi> {
impl<A: HalApi> Drop for ShaderModule<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_shader_module(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_shader_module(raw);
}
}
}
@ -73,7 +73,7 @@ crate::impl_storage_item!(ShaderModule);
impl<A: HalApi> ShaderModule<A> {
pub(crate) fn raw(&self) -> &A::ShaderModule {
self.raw.as_ref().unwrap()
&self.raw
}
pub(crate) fn finalize_entry_point_name(
@ -242,7 +242,7 @@ pub enum CreateComputePipelineError {
#[derive(Debug)]
pub struct ComputePipeline<A: HalApi> {
pub(crate) raw: Option<A::ComputePipeline>,
pub(crate) raw: ManuallyDrop<A::ComputePipeline>,
pub(crate) layout: Arc<PipelineLayout<A>>,
pub(crate) device: Arc<Device<A>>,
pub(crate) _shader_module: Arc<ShaderModule<A>>,
@ -254,12 +254,12 @@ pub struct ComputePipeline<A: HalApi> {
impl<A: HalApi> Drop for ComputePipeline<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_compute_pipeline(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_compute_pipeline(raw);
}
}
}
@ -272,7 +272,7 @@ crate::impl_trackable!(ComputePipeline);
impl<A: HalApi> ComputePipeline<A> {
pub(crate) fn raw(&self) -> &A::ComputePipeline {
self.raw.as_ref().unwrap()
&self.raw
}
}
@ -301,7 +301,7 @@ impl From<hal::PipelineCacheError> for CreatePipelineCacheError {
#[derive(Debug)]
pub struct PipelineCache<A: HalApi> {
pub(crate) raw: Option<A::PipelineCache>,
pub(crate) raw: ManuallyDrop<A::PipelineCache>,
pub(crate) device: Arc<Device<A>>,
/// The `label` from the descriptor used to create the resource.
pub(crate) label: String,
@ -309,12 +309,12 @@ pub struct PipelineCache<A: HalApi> {
impl<A: HalApi> Drop for PipelineCache<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_pipeline_cache(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_pipeline_cache(raw);
}
}
}
@ -324,6 +324,12 @@ crate::impl_labeled!(PipelineCache);
crate::impl_parent_device!(PipelineCache);
crate::impl_storage_item!(PipelineCache);
impl<A: HalApi> PipelineCache<A> {
pub(crate) fn raw(&self) -> &A::PipelineCache {
&self.raw
}
}
/// Describes how the vertex buffer is interpreted.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -586,7 +592,7 @@ impl Default for VertexStep {
#[derive(Debug)]
pub struct RenderPipeline<A: HalApi> {
pub(crate) raw: Option<A::RenderPipeline>,
pub(crate) raw: ManuallyDrop<A::RenderPipeline>,
pub(crate) device: Arc<Device<A>>,
pub(crate) layout: Arc<PipelineLayout<A>>,
pub(crate) _shader_modules:
@ -603,12 +609,12 @@ pub struct RenderPipeline<A: HalApi> {
impl<A: HalApi> Drop for RenderPipeline<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_render_pipeline(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_render_pipeline(raw);
}
}
}
@ -621,6 +627,6 @@ crate::impl_trackable!(RenderPipeline);
impl<A: HalApi> RenderPipeline<A> {
pub(crate) fn raw(&self) -> &A::RenderPipeline {
self.raw.as_ref().unwrap()
&self.raw
}
}

View File

@ -1697,7 +1697,7 @@ pub struct SamplerDescriptor<'a> {
#[derive(Debug)]
pub struct Sampler<A: HalApi> {
pub(crate) raw: Option<A::Sampler>,
pub(crate) raw: ManuallyDrop<A::Sampler>,
pub(crate) device: Arc<Device<A>>,
/// The `label` from the descriptor used to create the resource.
pub(crate) label: String,
@ -1710,19 +1710,19 @@ pub struct Sampler<A: HalApi> {
impl<A: HalApi> Drop for Sampler<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_sampler(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_sampler(raw);
}
}
}
impl<A: HalApi> Sampler<A> {
pub(crate) fn raw(&self) -> &A::Sampler {
self.raw.as_ref().unwrap()
&self.raw
}
}
@ -1793,7 +1793,7 @@ pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
#[derive(Debug)]
pub struct QuerySet<A: HalApi> {
pub(crate) raw: Option<A::QuerySet>,
pub(crate) raw: ManuallyDrop<A::QuerySet>,
pub(crate) device: Arc<Device<A>>,
/// The `label` from the descriptor used to create the resource.
pub(crate) label: String,
@ -1803,12 +1803,12 @@ pub struct QuerySet<A: HalApi> {
impl<A: HalApi> Drop for QuerySet<A> {
fn drop(&mut self) {
if let Some(raw) = self.raw.take() {
resource_log!("Destroy raw {}", self.error_ident());
unsafe {
use hal::Device;
self.device.raw().destroy_query_set(raw);
}
resource_log!("Destroy raw {}", self.error_ident());
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
unsafe {
use hal::Device;
self.device.raw().destroy_query_set(raw);
}
}
}
@ -1821,7 +1821,7 @@ crate::impl_trackable!(QuerySet);
impl<A: HalApi> QuerySet<A> {
pub(crate) fn raw(&self) -> &A::QuerySet {
self.raw.as_ref().unwrap()
&self.raw
}
}