From a024afe1825bc2327d63651ae5a316ce95ac2a30 Mon Sep 17 00:00:00 2001 From: teoxoy <28601907+teoxoy@users.noreply.github.com> Date: Thu, 20 Jun 2024 01:57:10 +0200 Subject: [PATCH] consolidate destroyed texture/buffer errors and separate them from invalid ID errors --- wgpu-core/src/binding_model.rs | 13 ++-- wgpu-core/src/command/bundle.rs | 36 +++------ wgpu-core/src/command/clear.rs | 24 +++--- wgpu-core/src/command/compute.rs | 25 ++----- wgpu-core/src/command/compute_command.rs | 2 +- wgpu-core/src/command/draw.rs | 11 +-- wgpu-core/src/command/memory_init.rs | 19 ++--- wgpu-core/src/command/mod.rs | 5 +- wgpu-core/src/command/query.rs | 21 +++--- wgpu-core/src/command/render.rs | 42 ++++------- wgpu-core/src/command/transfer.rs | 95 ++++++++---------------- wgpu-core/src/device/global.rs | 34 ++++----- wgpu-core/src/device/mod.rs | 4 +- wgpu-core/src/device/queue.rs | 71 ++++++------------ wgpu-core/src/device/resource.rs | 11 +-- wgpu-core/src/resource.rs | 79 +++++++++++++++----- wgpu-core/src/track/mod.rs | 2 +- 17 files changed, 207 insertions(+), 287 deletions(-) diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index dd0fe723db..c4a4884df8 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -9,8 +9,8 @@ use crate::{ id::{BindGroupLayoutId, BufferId, SamplerId, TextureViewId}, init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction}, resource::{ - MissingBufferUsageError, MissingTextureUsageError, ParentDevice, Resource, ResourceInfo, - ResourceType, + DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError, ParentDevice, + Resource, ResourceInfo, ResourceType, }, resource_log, snatch::{SnatchGuard, Snatchable}, @@ -78,12 +78,14 @@ pub enum CreateBindGroupError { Device(#[from] DeviceError), #[error("Bind group layout is invalid")] InvalidLayout, - #[error("Buffer {0:?} is invalid or destroyed")] - InvalidBuffer(BufferId), + #[error("BufferId {0:?} is invalid")] + InvalidBufferId(BufferId), #[error("Texture view {0:?} is invalid")] InvalidTextureView(TextureViewId), #[error("Sampler {0:?} is invalid")] InvalidSampler(SamplerId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error( "Binding count declared with at most {expected} items, but {actual} items were provided" )] @@ -198,9 +200,6 @@ impl PrettyError for CreateBindGroupError { Self::BindingSizeTooSmall { buffer, .. } => { fmt.buffer_label(&buffer); } - Self::InvalidBuffer(id) => { - fmt.buffer_label(&id); - } Self::InvalidTextureView(id) => { fmt.texture_view_label(&id); } diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index ecca9b3a9a..9e4e52fe83 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -97,7 +97,9 @@ use crate::{ id, init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction}, pipeline::{PipelineFlags, RenderPipeline, VertexStep}, - resource::{Buffer, ParentDevice, Resource, ResourceInfo, ResourceType}, + resource::{ + Buffer, DestroyedResourceError, ParentDevice, Resource, ResourceInfo, ResourceType, + }, resource_log, snatch::SnatchGuard, track::RenderBundleScope, @@ -825,8 +827,8 @@ pub enum CreateRenderBundleError { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum ExecutionError { - #[error("Buffer {0:?} is destroyed")] - DestroyedBuffer(id::BufferId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error("BindGroup {0:?} is invalid")] InvalidBindGroup(id::BindGroupId), #[error("Using {0} in a render bundle is not implemented")] @@ -835,15 +837,9 @@ pub enum ExecutionError { impl PrettyError for ExecutionError { fn fmt_pretty(&self, fmt: &mut ErrorFormatter) { fmt.error(self); - match *self { - Self::DestroyedBuffer(id) => { - fmt.buffer_label(&id); - } - Self::InvalidBindGroup(id) => { - fmt.bind_group_label(&id); - } - Self::Unimplemented(_reason) => {} - }; + if let Self::InvalidBindGroup(id) = *self { + fmt.bind_group_label(&id); + } } } @@ -939,9 +935,7 @@ impl RenderBundle { offset, size, } => { - let buffer: &A::Buffer = buffer - .raw(snatch_guard) - .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?; + let buffer: &A::Buffer = buffer.try_raw(snatch_guard)?; let bb = hal::BufferBinding { buffer, offset: *offset, @@ -955,9 +949,7 @@ impl RenderBundle { offset, size, } => { - let buffer = buffer - .raw(snatch_guard) - .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?; + let buffer = buffer.try_raw(snatch_guard)?; let bb = hal::BufferBinding { buffer, offset: *offset, @@ -1042,9 +1034,7 @@ impl RenderBundle { count: None, indexed: false, } => { - let buffer = buffer - .raw(snatch_guard) - .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?; + let buffer = buffer.try_raw(snatch_guard)?; unsafe { raw.draw_indirect(buffer, *offset, 1) }; } Cmd::MultiDrawIndirect { @@ -1053,9 +1043,7 @@ impl RenderBundle { count: None, indexed: true, } => { - let buffer = buffer - .raw(snatch_guard) - .ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?; + let buffer = buffer.try_raw(snatch_guard)?; unsafe { raw.draw_indexed_indirect(buffer, *offset, 1) }; } Cmd::MultiDrawIndirect { .. } | Cmd::MultiDrawIndirectCount { .. } => { diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 578346d987..f9d3249cca 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -11,7 +11,10 @@ use crate::{ hal_api::HalApi, id::{BufferId, CommandEncoderId, TextureId}, init_tracker::{MemoryInitKind, TextureInitRange}, - resource::{ParentDevice, Resource, ResourceErrorIdent, Texture, TextureClearMode}, + resource::{ + DestroyedResourceError, ParentDevice, Resource, ResourceErrorIdent, Texture, + TextureClearMode, + }, snatch::SnatchGuard, track::{TextureSelector, TextureTracker}, }; @@ -26,12 +29,12 @@ use wgt::{math::align_to, BufferAddress, BufferUsages, ImageSubresourceRange, Te pub enum ClearError { #[error("To use clear_texture the CLEAR_TEXTURE feature needs to be enabled")] MissingClearTextureFeature, - #[error("Buffer {0:?} is invalid or destroyed")] - InvalidBuffer(BufferId), + #[error("BufferId {0:?} is invalid")] + InvalidBufferId(BufferId), #[error("TextureId {0:?} is invalid")] InvalidTextureId(TextureId), - #[error("{0} has been destroyed")] - Destroyed(ResourceErrorIdent), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error("{0} can not be cleared")] NoValidTextureClearMode(ResourceErrorIdent), #[error("Buffer clear size {0:?} is not a multiple of `COPY_BUFFER_ALIGNMENT`")] @@ -101,7 +104,7 @@ impl Global { let dst_buffer = hub .buffers .get(dst) - .map_err(|_| ClearError::InvalidBuffer(dst))?; + .map_err(|_| ClearError::InvalidBufferId(dst))?; dst_buffer.same_device_as(cmd_buf.as_ref())?; @@ -111,10 +114,7 @@ impl Global { .set_single(&dst_buffer, hal::BufferUses::COPY_DST); let snatch_guard = dst_buffer.device.snatchable_lock.read(); - let dst_raw = dst_buffer - .raw - .get(&snatch_guard) - .ok_or(ClearError::InvalidBuffer(dst))?; + let dst_raw = dst_buffer.try_raw(&snatch_guard)?; if !dst_buffer.usage.contains(BufferUsages::COPY_DST) { return Err(ClearError::MissingCopyDstUsageFlag(Some(dst), None)); } @@ -264,9 +264,7 @@ pub(crate) fn clear_texture( zero_buffer: &A::Buffer, snatch_guard: &SnatchGuard<'_>, ) -> Result<(), ClearError> { - let dst_raw = dst_texture - .raw(snatch_guard) - .ok_or_else(|| ClearError::Destroyed(dst_texture.error_ident()))?; + let dst_raw = dst_texture.try_raw(snatch_guard)?; // Issue the right barrier. let clear_usage = match *dst_texture.clear_mode.read() { diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 7ecf9b35d3..b0d46a4c05 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -15,7 +15,7 @@ use crate::{ hal_api::HalApi, hal_label, id, init_tracker::MemoryInitKind, - resource::{self, MissingBufferUsageError, ParentDevice, Resource}, + resource::{self, DestroyedResourceError, MissingBufferUsageError, ParentDevice, Resource}, snatch::SnatchGuard, track::{Tracker, TrackerIndex, UsageConflict, UsageScope}, Label, @@ -166,16 +166,16 @@ pub enum ComputePassErrorInner { InvalidPipeline(id::ComputePipelineId), #[error("QuerySet {0:?} is invalid")] InvalidQuerySet(id::QuerySetId), - #[error("Indirect buffer {0:?} is invalid or destroyed")] - InvalidIndirectBuffer(id::BufferId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error("Indirect buffer uses bytes {offset}..{end_offset} which overruns indirect buffer of size {buffer_size}")] IndirectBufferOverrun { offset: u64, end_offset: u64, buffer_size: u64, }, - #[error("Buffer {0:?} is invalid or destroyed")] - InvalidBuffer(id::BufferId), + #[error("BufferId {0:?} is invalid")] + InvalidBufferId(id::BufferId), #[error(transparent)] ResourceUsageConflict(#[from] UsageConflict), #[error(transparent)] @@ -211,9 +211,6 @@ impl PrettyError for ComputePassErrorInner { Self::InvalidPipeline(id) => { fmt.compute_pipeline_label(&id); } - Self::InvalidIndirectBuffer(id) => { - fmt.buffer_label(&id); - } Self::Dispatch(DispatchError::IncompatibleBindGroup { ref diff, .. }) => { for d in diff { fmt.note(&d); @@ -773,7 +770,6 @@ impl Global { } } ArcComputeCommand::DispatchIndirect { buffer, offset } => { - let buffer_id = buffer.as_info().id(); let scope = PassErrorScope::Dispatch { indirect: true, pipeline: state.pipeline, @@ -806,11 +802,7 @@ impl Global { .map_pass_err(scope); } - let buf_raw = buffer - .raw - .get(&snatch_guard) - .ok_or(ComputePassErrorInner::InvalidIndirectBuffer(buffer_id)) - .map_pass_err(scope)?; + let buf_raw = buffer.try_raw(&snatch_guard).map_pass_err(scope)?; let stride = 3 * 4; // 3 integers, x/y/z group size @@ -1092,9 +1084,8 @@ impl Global { let buffer = hub .buffers - .read() - .get_owned(buffer_id) - .map_err(|_| ComputePassErrorInner::InvalidBuffer(buffer_id)) + .get(buffer_id) + .map_err(|_| ComputePassErrorInner::InvalidBufferId(buffer_id)) .map_pass_err(scope)?; base.commands diff --git a/wgpu-core/src/command/compute_command.rs b/wgpu-core/src/command/compute_command.rs index 49fdbbec24..1ef6e77bc5 100644 --- a/wgpu-core/src/command/compute_command.rs +++ b/wgpu-core/src/command/compute_command.rs @@ -132,7 +132,7 @@ impl ComputeCommand { indirect: true, pipeline: None, // TODO: not used right now, but once we do the resolve during recording we can use this again. }, - inner: ComputePassErrorInner::InvalidBuffer(buffer_id), + inner: ComputePassErrorInner::InvalidBufferId(buffer_id), } })?, offset, diff --git a/wgpu-core/src/command/draw.rs b/wgpu-core/src/command/draw.rs index af1cad6423..df4db03390 100644 --- a/wgpu-core/src/command/draw.rs +++ b/wgpu-core/src/command/draw.rs @@ -7,7 +7,9 @@ use crate::{ hal_api::HalApi, id, pipeline::RenderPipeline, - resource::{Buffer, MissingBufferUsageError, MissingTextureUsageError, QuerySet}, + resource::{ + Buffer, DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError, QuerySet, + }, track::UsageConflict, }; use wgt::{BufferAddress, BufferSize, Color, VertexStepMode}; @@ -90,8 +92,8 @@ pub enum RenderCommandError { IncompatiblePipelineRods, #[error(transparent)] UsageConflict(#[from] UsageConflict), - #[error("Buffer {0:?} is destroyed")] - DestroyedBuffer(id::BufferId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error(transparent)] MissingBufferUsage(#[from] MissingBufferUsageError), #[error(transparent)] @@ -120,8 +122,7 @@ impl crate::error::PrettyError for RenderCommandError { Self::UsageConflict(UsageConflict::TextureInvalid { id }) => { fmt.texture_label(&id); } - Self::UsageConflict(UsageConflict::BufferInvalid { id }) - | Self::DestroyedBuffer(id) => { + Self::UsageConflict(UsageConflict::BufferInvalid { id }) => { fmt.buffer_label(&id); } _ => {} diff --git a/wgpu-core/src/command/memory_init.rs b/wgpu-core/src/command/memory_init.rs index fed789e6e8..fcf4e5d66d 100644 --- a/wgpu-core/src/command/memory_init.rs +++ b/wgpu-core/src/command/memory_init.rs @@ -6,15 +6,13 @@ use crate::{ device::Device, hal_api::HalApi, init_tracker::*, - resource::{Resource, Texture}, + resource::{DestroyedResourceError, Resource, Texture}, snatch::SnatchGuard, track::{TextureTracker, Tracker}, FastHashMap, }; -use super::{ - clear::clear_texture, BakedCommands, ClearError, DestroyedBufferError, DestroyedTextureError, -}; +use super::{clear::clear_texture, BakedCommands, ClearError}; /// Surface that was discarded by `StoreOp::Discard` of a preceding renderpass. /// Any read access to this surface needs to be preceded by a texture initialization. @@ -171,7 +169,7 @@ impl BakedCommands { &mut self, device_tracker: &mut Tracker, snatch_guard: &SnatchGuard<'_>, - ) -> Result<(), DestroyedBufferError> { + ) -> Result<(), DestroyedResourceError> { profiling::scope!("initialize_buffer_memory"); // Gather init ranges for each buffer so we can collapse them. @@ -231,10 +229,7 @@ impl BakedCommands { .buffers .set_single(&buffer, hal::BufferUses::COPY_DST); - let raw_buf = buffer - .raw - .get(snatch_guard) - .ok_or(DestroyedBufferError(buffer.error_ident()))?; + let raw_buf = buffer.try_raw(snatch_guard)?; unsafe { self.encoder.transition_buffers( @@ -277,7 +272,7 @@ impl BakedCommands { device_tracker: &mut Tracker, device: &Device, snatch_guard: &SnatchGuard<'_>, - ) -> Result<(), DestroyedTextureError> { + ) -> Result<(), DestroyedResourceError> { profiling::scope!("initialize_texture_memory"); let mut ranges: Vec = Vec::new(); @@ -324,8 +319,8 @@ impl BakedCommands { // A Texture can be destroyed between the command recording // and now, this is out of our control so we have to handle // it gracefully. - if let Err(ClearError::Destroyed(ident)) = clear_result { - return Err(DestroyedTextureError(ident)); + if let Err(ClearError::DestroyedResource(e)) = clear_result { + return Err(e); } // Other errors are unexpected. diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 1481023b7d..997da708f6 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -29,7 +29,7 @@ use crate::lock::{rank, Mutex}; use crate::snatch::SnatchGuard; use crate::init_tracker::BufferInitTrackerAction; -use crate::resource::{ParentDevice, Resource, ResourceErrorIdent, ResourceInfo, ResourceType}; +use crate::resource::{ParentDevice, Resource, ResourceInfo, ResourceType}; use crate::track::{Tracker, UsageScope}; use crate::{api_log, global::Global, hal_api::HalApi, id, resource_log, Label}; @@ -243,9 +243,6 @@ pub(crate) struct BakedCommands { texture_memory_actions: CommandBufferTextureMemoryActions, } -pub(crate) struct DestroyedBufferError(pub ResourceErrorIdent); -pub(crate) struct DestroyedTextureError(pub ResourceErrorIdent); - /// The mutable state of a [`CommandBuffer`]. pub struct CommandBufferMutable { /// The [`wgpu_hal::Api::CommandBuffer`]s we've built so far, and the encoder diff --git a/wgpu-core/src/command/query.rs b/wgpu-core/src/command/query.rs index bb82eb721c..cd543585a1 100644 --- a/wgpu-core/src/command/query.rs +++ b/wgpu-core/src/command/query.rs @@ -9,7 +9,7 @@ use crate::{ hal_api::HalApi, id::{self, Id}, init_tracker::MemoryInitKind, - resource::{ParentDevice, QuerySet}, + resource::{DestroyedResourceError, ParentDevice, QuerySet}, storage::Storage, Epoch, FastHashMap, Index, }; @@ -113,8 +113,10 @@ pub enum QueryError { Use(#[from] QueryUseError), #[error("Error encountered while trying to resolve a query")] Resolve(#[from] ResolveError), - #[error("Buffer {0:?} is invalid or destroyed")] - InvalidBuffer(id::BufferId), + #[error("BufferId {0:?} is invalid")] + InvalidBufferId(id::BufferId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error("QuerySet {0:?} is invalid or destroyed")] InvalidQuerySet(id::QuerySetId), } @@ -122,11 +124,8 @@ pub enum QueryError { impl crate::error::PrettyError for QueryError { fn fmt_pretty(&self, fmt: &mut crate::error::ErrorFormatter) { fmt.error(self); - match *self { - Self::InvalidBuffer(id) => fmt.buffer_label(&id), - Self::InvalidQuerySet(id) => fmt.query_set_label(&id), - - _ => {} + if let Self::InvalidQuerySet(id) = *self { + fmt.query_set_label(&id) } } } @@ -409,7 +408,7 @@ impl Global { let dst_buffer = hub .buffers .get(destination) - .map_err(|_| QueryError::InvalidBuffer(destination))?; + .map_err(|_| QueryError::InvalidBufferId(destination))?; dst_buffer.same_device_as(cmd_buf.as_ref())?; @@ -465,9 +464,7 @@ impl Global { MemoryInitKind::ImplicitlyInitialized, )); - let raw_dst_buffer = dst_buffer - .raw(&snatch_guard) - .ok_or(QueryError::InvalidBuffer(destination))?; + let raw_dst_buffer = dst_buffer.try_raw(&snatch_guard)?; unsafe { raw_encoder.transition_buffers(dst_barrier.into_iter()); diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index f061ab9664..1ee58ed991 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -26,8 +26,8 @@ use crate::{ init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction}, pipeline::{self, PipelineFlags}, resource::{ - MissingBufferUsageError, MissingTextureUsageError, ParentDevice, QuerySet, Texture, - TextureView, TextureViewNotRenderableReason, + DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError, ParentDevice, + QuerySet, Texture, TextureView, TextureViewNotRenderableReason, }, storage::Storage, track::{TextureSelector, Tracker, UsageConflict, UsageScope}, @@ -666,6 +666,8 @@ pub enum RenderPassErrorInner { InvalidQuerySet(id::QuerySetId), #[error("missing occlusion query set")] MissingOcclusionQuerySet, + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), } impl PrettyError for RenderPassErrorInner { @@ -1678,11 +1680,7 @@ impl Global { buffer .check_usage(BufferUsages::INDEX) .map_pass_err(scope)?; - let buf_raw = buffer - .raw - .get(&snatch_guard) - .ok_or(RenderCommandError::DestroyedBuffer(buffer_id)) - .map_pass_err(scope)?; + let buf_raw = buffer.try_raw(&snatch_guard).map_pass_err(scope)?; let end = match size { Some(s) => offset + s.get(), @@ -1741,11 +1739,7 @@ impl Global { buffer .check_usage(BufferUsages::VERTEX) .map_pass_err(scope)?; - let buf_raw = buffer - .raw - .get(&snatch_guard) - .ok_or(RenderCommandError::DestroyedBuffer(buffer_id)) - .map_pass_err(scope)?; + let buf_raw = buffer.try_raw(&snatch_guard).map_pass_err(scope)?; let empty_slots = (1 + slot as usize).saturating_sub(state.vertex.inputs.len()); @@ -2039,11 +2033,8 @@ impl Global { indirect_buffer .check_usage(BufferUsages::INDIRECT) .map_pass_err(scope)?; - let indirect_raw = indirect_buffer - .raw - .get(&snatch_guard) - .ok_or(RenderCommandError::DestroyedBuffer(buffer_id)) - .map_pass_err(scope)?; + let indirect_raw = + indirect_buffer.try_raw(&snatch_guard).map_pass_err(scope)?; let actual_count = count.map_or(1, |c| c.get()); @@ -2112,11 +2103,8 @@ impl Global { indirect_buffer .check_usage(BufferUsages::INDIRECT) .map_pass_err(scope)?; - let indirect_raw = indirect_buffer - .raw - .get(&snatch_guard) - .ok_or(RenderCommandError::DestroyedBuffer(buffer_id)) - .map_pass_err(scope)?; + let indirect_raw = + indirect_buffer.try_raw(&snatch_guard).map_pass_err(scope)?; let count_buffer = info .usage_scope @@ -2130,11 +2118,7 @@ impl Global { count_buffer .check_usage(BufferUsages::INDIRECT) .map_pass_err(scope)?; - let count_raw = count_buffer - .raw - .get(&snatch_guard) - .ok_or(RenderCommandError::DestroyedBuffer(count_buffer_id)) - .map_pass_err(scope)?; + let count_raw = count_buffer.try_raw(&snatch_guard).map_pass_err(scope)?; let end_offset = offset + stride * max_count as u64; if end_offset > indirect_buffer.size { @@ -2373,8 +2357,8 @@ impl Global { unsafe { bundle.execute(raw, &snatch_guard) } .map_err(|e| match e { - ExecutionError::DestroyedBuffer(id) => { - RenderCommandError::DestroyedBuffer(id) + ExecutionError::DestroyedResource(e) => { + RenderCommandError::DestroyedResource(e) } ExecutionError::InvalidBindGroup(id) => { RenderCommandError::InvalidBindGroup(id) diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index bde24f5e8e..64e5e13499 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -13,7 +13,7 @@ use crate::{ has_copy_partial_init_tracker_coverage, MemoryInitKind, TextureInitRange, TextureInitTrackerAction, }, - resource::{ParentDevice, Texture, TextureErrorDimension}, + resource::{DestroyedResourceError, ParentDevice, Texture, TextureErrorDimension}, snatch::SnatchGuard, track::{TextureSelector, Tracker}, }; @@ -41,10 +41,10 @@ pub enum CopySide { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum TransferError { - #[error("Buffer {0:?} is invalid or destroyed")] - InvalidBuffer(BufferId), - #[error("Texture {0:?} is invalid or destroyed")] - InvalidTexture(TextureId), + #[error("BufferId {0:?} is invalid")] + InvalidBufferId(BufferId), + #[error("TextureId {0:?} is invalid")] + InvalidTextureId(TextureId), #[error("Source and destination cannot be the same buffer")] SameSourceDestinationBuffer, #[error("Source buffer/texture is missing the `COPY_SRC` usage flag")] @@ -143,33 +143,14 @@ pub enum TransferError { impl PrettyError for TransferError { fn fmt_pretty(&self, fmt: &mut ErrorFormatter) { fmt.error(self); - match *self { - Self::InvalidBuffer(id) => { - fmt.buffer_label(&id); + if let Self::MissingCopyDstUsageFlag(buf_opt, tex_opt) = *self { + if let Some(buf) = buf_opt { + fmt.buffer_label_with_key(&buf, "destination"); } - Self::InvalidTexture(id) => { - fmt.texture_label(&id); + if let Some(tex) = tex_opt { + fmt.texture_label_with_key(&tex, "destination"); } - // Self::MissingCopySrcUsageFlag(buf_opt, tex_opt) => { - // if let Some(buf) = buf_opt { - // let name = crate::gfx_select!(buf => global.buffer_label(buf)); - // ret.push_str(&format_label_line("source", &name)); - // } - // if let Some(tex) = tex_opt { - // let name = crate::gfx_select!(tex => global.texture_label(tex)); - // ret.push_str(&format_label_line("source", &name)); - // } - // } - Self::MissingCopyDstUsageFlag(buf_opt, tex_opt) => { - if let Some(buf) = buf_opt { - fmt.buffer_label_with_key(&buf, "destination"); - } - if let Some(tex) = tex_opt { - fmt.texture_label_with_key(&tex, "destination"); - } - } - _ => {} - }; + } } } /// Error encountered while attempting to do a copy on a command encoder. @@ -180,6 +161,8 @@ pub enum CopyError { Encoder(#[from] CommandEncoderError), #[error("Copy error")] Transfer(#[from] TransferError), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), } impl From for CopyError { @@ -595,7 +578,7 @@ impl Global { let src_buffer = hub .buffers .get(source) - .map_err(|_| TransferError::InvalidBuffer(source))?; + .map_err(|_| TransferError::InvalidBufferId(source))?; src_buffer.same_device_as(cmd_buf.as_ref())?; @@ -604,10 +587,7 @@ impl Global { .buffers .set_single(&src_buffer, hal::BufferUses::COPY_SRC); - let src_raw = src_buffer - .raw - .get(&snatch_guard) - .ok_or(TransferError::InvalidBuffer(source))?; + let src_raw = src_buffer.try_raw(&snatch_guard)?; if !src_buffer.usage.contains(BufferUsages::COPY_SRC) { return Err(TransferError::MissingCopySrcUsageFlag.into()); } @@ -617,7 +597,7 @@ impl Global { let dst_buffer = hub .buffers .get(destination) - .map_err(|_| TransferError::InvalidBuffer(destination))?; + .map_err(|_| TransferError::InvalidBufferId(destination))?; dst_buffer.same_device_as(cmd_buf.as_ref())?; @@ -626,10 +606,7 @@ impl Global { .buffers .set_single(&dst_buffer, hal::BufferUses::COPY_DST); - let dst_raw = dst_buffer - .raw - .get(&snatch_guard) - .ok_or(TransferError::InvalidBuffer(destination))?; + let dst_raw = dst_buffer.try_raw(&snatch_guard)?; if !dst_buffer.usage.contains(BufferUsages::COPY_DST) { return Err(TransferError::MissingCopyDstUsageFlag(Some(destination), None).into()); } @@ -765,7 +742,7 @@ impl Global { let dst_texture = hub .textures .get(destination.texture) - .map_err(|_| TransferError::InvalidTexture(destination.texture))?; + .map_err(|_| TransferError::InvalidTextureId(destination.texture))?; dst_texture.same_device_as(cmd_buf.as_ref())?; @@ -797,7 +774,7 @@ impl Global { let src_buffer = hub .buffers .get(source.buffer) - .map_err(|_| TransferError::InvalidBuffer(source.buffer))?; + .map_err(|_| TransferError::InvalidBufferId(source.buffer))?; src_buffer.same_device_as(cmd_buf.as_ref())?; @@ -805,10 +782,7 @@ impl Global { .buffers .set_single(&src_buffer, hal::BufferUses::COPY_SRC); - let src_raw = src_buffer - .raw - .get(&snatch_guard) - .ok_or(TransferError::InvalidBuffer(source.buffer))?; + let src_raw = src_buffer.try_raw(&snatch_guard)?; if !src_buffer.usage.contains(BufferUsages::COPY_SRC) { return Err(TransferError::MissingCopySrcUsageFlag.into()); } @@ -818,9 +792,7 @@ impl Global { tracker .textures .set_single(&dst_texture, dst_range, hal::TextureUses::COPY_DST); - let dst_raw = dst_texture - .raw(&snatch_guard) - .ok_or(TransferError::InvalidTexture(destination.texture))?; + let dst_raw = dst_texture.try_raw(&snatch_guard)?; if !dst_texture.desc.usage.contains(TextureUsages::COPY_DST) { return Err( TransferError::MissingCopyDstUsageFlag(None, Some(destination.texture)).into(), @@ -927,7 +899,7 @@ impl Global { let src_texture = hub .textures .get(source.texture) - .map_err(|_| TransferError::InvalidTexture(source.texture))?; + .map_err(|_| TransferError::InvalidTextureId(source.texture))?; src_texture.same_device_as(cmd_buf.as_ref())?; @@ -956,9 +928,7 @@ impl Global { tracker .textures .set_single(&src_texture, src_range, hal::TextureUses::COPY_SRC); - let src_raw = src_texture - .raw(&snatch_guard) - .ok_or(TransferError::InvalidTexture(source.texture))?; + let src_raw = src_texture.try_raw(&snatch_guard)?; if !src_texture.desc.usage.contains(TextureUsages::COPY_SRC) { return Err(TransferError::MissingCopySrcUsageFlag.into()); } @@ -980,7 +950,7 @@ impl Global { let dst_buffer = hub .buffers .get(destination.buffer) - .map_err(|_| TransferError::InvalidBuffer(destination.buffer))?; + .map_err(|_| TransferError::InvalidBufferId(destination.buffer))?; dst_buffer.same_device_as(cmd_buf.as_ref())?; @@ -988,10 +958,7 @@ impl Global { .buffers .set_single(&dst_buffer, hal::BufferUses::COPY_DST); - let dst_raw = dst_buffer - .raw - .get(&snatch_guard) - .ok_or(TransferError::InvalidBuffer(destination.buffer))?; + let dst_raw = dst_buffer.try_raw(&snatch_guard)?; if !dst_buffer.usage.contains(BufferUsages::COPY_DST) { return Err( TransferError::MissingCopyDstUsageFlag(Some(destination.buffer), None).into(), @@ -1103,11 +1070,11 @@ impl Global { let src_texture = hub .textures .get(source.texture) - .map_err(|_| TransferError::InvalidTexture(source.texture))?; + .map_err(|_| TransferError::InvalidTextureId(source.texture))?; let dst_texture = hub .textures .get(destination.texture) - .map_err(|_| TransferError::InvalidTexture(source.texture))?; + .map_err(|_| TransferError::InvalidTextureId(source.texture))?; src_texture.same_device_as(cmd_buf.as_ref())?; dst_texture.same_device_as(cmd_buf.as_ref())?; @@ -1174,9 +1141,7 @@ impl Global { src_range, hal::TextureUses::COPY_SRC, ); - let src_raw = src_texture - .raw(&snatch_guard) - .ok_or(TransferError::InvalidTexture(source.texture))?; + let src_raw = src_texture.try_raw(&snatch_guard)?; if !src_texture.desc.usage.contains(TextureUsages::COPY_SRC) { return Err(TransferError::MissingCopySrcUsageFlag.into()); } @@ -1192,9 +1157,7 @@ impl Global { dst_range, hal::TextureUses::COPY_DST, ); - let dst_raw = dst_texture - .raw(&snatch_guard) - .ok_or(TransferError::InvalidTexture(destination.texture))?; + let dst_raw = dst_texture.try_raw(&snatch_guard)?; if !dst_texture.desc.usage.contains(TextureUsages::COPY_DST) { return Err( TransferError::MissingCopyDstUsageFlag(None, Some(destination.texture)).into(), diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 3fa7786029..77e1587906 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -387,7 +387,7 @@ impl Global { let buffer = hub .buffers .get(buffer_id) - .map_err(|_| BufferAccessError::Invalid)?; + .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; buffer.check_usage(wgt::BufferUsages::MAP_WRITE)?; //assert!(buffer isn't used by the GPU); @@ -402,9 +402,7 @@ impl Global { }); } - let raw_buf = buffer - .raw(&snatch_guard) - .ok_or(BufferAccessError::Destroyed)?; + let raw_buf = buffer.try_raw(&snatch_guard)?; unsafe { let mapping = device .raw() @@ -448,13 +446,11 @@ impl Global { let buffer = hub .buffers .get(buffer_id) - .map_err(|_| BufferAccessError::Invalid)?; + .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; buffer.check_usage(wgt::BufferUsages::MAP_READ)?; //assert!(buffer isn't used by the GPU); - let raw_buf = buffer - .raw(&snatch_guard) - .ok_or(BufferAccessError::Destroyed)?; + let raw_buf = buffer.try_raw(&snatch_guard)?; unsafe { let mapping = device .raw() @@ -789,13 +785,15 @@ impl Global { let error = 'error: { let texture = match hub.textures.get(texture_id) { Ok(texture) => texture, - Err(_) => break 'error resource::CreateTextureViewError::InvalidTexture, + Err(_) => { + break 'error resource::CreateTextureViewError::InvalidTextureId(texture_id) + } }; let device = &texture.device; { let snatch_guard = device.snatchable_lock.read(); - if texture.is_destroyed(&snatch_guard) { - break 'error resource::CreateTextureViewError::InvalidTexture; + if let Err(e) = texture.check_destroyed(&snatch_guard) { + break 'error e.into(); } } #[cfg(feature = "trace")] @@ -2432,7 +2430,7 @@ impl Global { let op_and_err = 'error: { let buffer = match hub.buffers.get(buffer_id) { Ok(buffer) => buffer, - Err(_) => break 'error Some((op, BufferAccessError::Invalid)), + Err(_) => break 'error Some((op, BufferAccessError::InvalidBufferId(buffer_id))), }; buffer.map_async(offset, size, op).err() @@ -2466,13 +2464,11 @@ impl Global { let buffer = hub .buffers .get(buffer_id) - .map_err(|_| BufferAccessError::Invalid)?; + .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; { let snatch_guard = buffer.device.snatchable_lock.read(); - if buffer.is_destroyed(&snatch_guard) { - return Err(BufferAccessError::Destroyed); - } + buffer.check_destroyed(&snatch_guard)?; } let range_size = if let Some(size) = size { @@ -2535,12 +2531,10 @@ impl Global { let buffer = hub .buffers .get(buffer_id) - .map_err(|_| BufferAccessError::Invalid)?; + .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; let snatch_guard = buffer.device.snatchable_lock.read(); - if buffer.is_destroyed(&snatch_guard) { - return Err(BufferAccessError::Destroyed); - } + buffer.check_destroyed(&snatch_guard)?; drop(snatch_guard); buffer.device.check_is_valid()?; diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index b8c4992182..2bb3890f3d 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -323,9 +323,7 @@ fn map_buffer( kind: HostMap, snatch_guard: &SnatchGuard, ) -> Result, BufferAccessError> { - let raw_buffer = buffer - .raw(snatch_guard) - .ok_or(BufferAccessError::Destroyed)?; + let raw_buffer = buffer.try_raw(snatch_guard)?; let mapping = unsafe { raw.map_buffer(raw_buffer, offset..offset + size) .map_err(DeviceError::from)? diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 9ca2bd1f0b..6ac5a9f018 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -16,9 +16,9 @@ use crate::{ init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange}, lock::{rank, Mutex, RwLockWriteGuard}, resource::{ - Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, ParentDevice, - Resource, ResourceErrorIdent, ResourceInfo, ResourceType, StagingBuffer, Texture, - TextureInner, + Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedResourceError, + DestroyedTexture, ParentDevice, Resource, ResourceInfo, ResourceType, StagingBuffer, + Texture, TextureInner, }, resource_log, track, FastHashMap, SubmissionIndex, }; @@ -365,6 +365,8 @@ pub enum QueueWriteError { Transfer(#[from] TransferError), #[error(transparent)] MemoryInitFailure(#[from] ClearError), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), } #[derive(Clone, Debug, Error)] @@ -372,10 +374,8 @@ pub enum QueueWriteError { pub enum QueueSubmitError { #[error(transparent)] Queue(#[from] DeviceError), - #[error("{0} has been destroyed")] - DestroyedBuffer(ResourceErrorIdent), - #[error("{0} has been destroyed")] - DestroyedTexture(ResourceErrorIdent), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error(transparent)] Unmap(#[from] BufferAccessError), #[error("Buffer {0:?} is still mapped")] @@ -406,7 +406,7 @@ impl Global { let buffer = hub .buffers .get(buffer_id) - .map_err(|_| TransferError::InvalidBuffer(buffer_id))?; + .map_err(|_| TransferError::InvalidBufferId(buffer_id))?; let queue = hub .queues @@ -513,7 +513,7 @@ impl Global { let staging_buffer = hub.staging_buffers.unregister(staging_buffer_id); if staging_buffer.is_none() { - return Err(QueueWriteError::Transfer(TransferError::InvalidBuffer( + return Err(QueueWriteError::Transfer(TransferError::InvalidBufferId( buffer_id, ))); } @@ -556,7 +556,7 @@ impl Global { let buffer = hub .buffers .get(buffer_id) - .map_err(|_| TransferError::InvalidBuffer(buffer_id))?; + .map_err(|_| TransferError::InvalidBufferId(buffer_id))?; self.queue_validate_write_buffer_impl(&buffer, buffer_id, buffer_offset, buffer_size)?; @@ -608,7 +608,7 @@ impl Global { let dst = hub .buffers .get(buffer_id) - .map_err(|_| TransferError::InvalidBuffer(buffer_id))?; + .map_err(|_| TransferError::InvalidBufferId(buffer_id))?; let transition = { let mut trackers = device.trackers.lock(); @@ -616,10 +616,7 @@ impl Global { }; let snatch_guard = device.snatchable_lock.read(); - let dst_raw = dst - .raw - .get(&snatch_guard) - .ok_or(TransferError::InvalidBuffer(buffer_id))?; + let dst_raw = dst.try_raw(&snatch_guard)?; dst.same_device_as(queue.as_ref())?; @@ -702,7 +699,7 @@ impl Global { let dst = hub .textures .get(destination.texture) - .map_err(|_| TransferError::InvalidTexture(destination.texture))?; + .map_err(|_| TransferError::InvalidTextureId(destination.texture))?; dst.same_device_as(queue.as_ref())?; @@ -830,9 +827,7 @@ impl Global { dst.info .use_at(device.active_submission_index.load(Ordering::Relaxed) + 1); - let dst_raw = dst - .raw(&snatch_guard) - .ok_or(TransferError::InvalidTexture(destination.texture))?; + let dst_raw = dst.try_raw(&snatch_guard)?; let bytes_per_row = data_layout .bytes_per_row @@ -1093,9 +1088,7 @@ impl Global { .use_at(device.active_submission_index.load(Ordering::Relaxed) + 1); let snatch_guard = device.snatchable_lock.read(); - let dst_raw = dst - .raw(&snatch_guard) - .ok_or(TransferError::InvalidTexture(destination.texture))?; + let dst_raw = dst.try_raw(&snatch_guard)?; let regions = hal::TextureCopy { src_base: hal::TextureCopyBase { @@ -1219,11 +1212,7 @@ impl Global { { profiling::scope!("buffers"); for buffer in cmd_buf_trackers.buffers.used_resources() { - if buffer.raw.get(&snatch_guard).is_none() { - return Err(QueueSubmitError::DestroyedBuffer( - buffer.error_ident(), - )); - } + buffer.check_destroyed(&snatch_guard)?; buffer.info.use_at(submit_index); match *buffer.map_state.lock() { @@ -1239,14 +1228,9 @@ impl Global { { profiling::scope!("textures"); for texture in cmd_buf_trackers.textures.used_resources() { - let should_extend = match texture.inner.get(&snatch_guard) { - None => { - return Err(QueueSubmitError::DestroyedTexture( - texture.error_ident(), - )); - } - Some(TextureInner::Native { .. }) => false, - Some(TextureInner::Surface { ref raw, .. }) => { + let should_extend = match texture.try_inner(&snatch_guard)? { + TextureInner::Native { .. } => false, + TextureInner::Surface { ref raw, .. } => { if raw.is_some() { // Compare the Arcs by pointer as Textures don't implement Eq. submit_surface_textures_owned @@ -1350,12 +1334,8 @@ impl Global { //Note: locking the trackers has to be done after the storages let mut trackers = device.trackers.lock(); - baked - .initialize_buffer_memory(&mut *trackers, &snatch_guard) - .map_err(|err| QueueSubmitError::DestroyedBuffer(err.0))?; - baked - .initialize_texture_memory(&mut *trackers, device, &snatch_guard) - .map_err(|err| QueueSubmitError::DestroyedTexture(err.0))?; + baked.initialize_buffer_memory(&mut *trackers, &snatch_guard)?; + baked.initialize_texture_memory(&mut *trackers, device, &snatch_guard)?; //Note: stateless trackers are not merged: // device already knows these resources exist. CommandBuffer::insert_barriers_from_tracker( @@ -1422,12 +1402,9 @@ impl Global { { used_surface_textures.set_size(hub.textures.read().len()); for texture in pending_writes.dst_textures.values() { - match texture.inner.get(&snatch_guard) { - None => { - return Err(QueueSubmitError::DestroyedTexture(texture.error_ident())); - } - Some(TextureInner::Native { .. }) => {} - Some(TextureInner::Surface { ref raw, .. }) => { + match texture.try_inner(&snatch_guard)? { + TextureInner::Native { .. } => {} + TextureInner::Surface { ref raw, .. } => { if raw.is_some() { // Compare the Arcs by pointer as Textures don't implement Eq submit_surface_textures_owned diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index cb27ed9d4d..f915ceb975 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -1008,9 +1008,7 @@ impl Device { ) -> Result, resource::CreateTextureViewError> { let snatch_guard = texture.device.snatchable_lock.read(); - let texture_raw = texture - .raw(&snatch_guard) - .ok_or(resource::CreateTextureViewError::InvalidTexture)?; + let texture_raw = texture.try_raw(&snatch_guard)?; // resolve TextureViewDescriptor defaults // https://gpuweb.github.io/gpuweb/#abstract-opdef-resolving-gputextureviewdescriptor-defaults @@ -1925,17 +1923,14 @@ impl Device { let buffer = storage .get(bb.buffer_id) - .map_err(|_| Error::InvalidBuffer(bb.buffer_id))?; + .map_err(|_| Error::InvalidBufferId(bb.buffer_id))?; used.buffers.add_single(buffer, internal_use); buffer.same_device(self)?; buffer.check_usage(pub_usage)?; - let raw_buffer = buffer - .raw - .get(snatch_guard) - .ok_or(Error::InvalidBuffer(bb.buffer_id))?; + let raw_buffer = buffer.try_raw(snatch_guard)?; let (bind_size, bind_end) = match bb.size { Some(size) => { diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index f5f4ee4a64..a495933f2f 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -340,9 +340,8 @@ impl BufferMapCallback { let status = match result { Ok(()) => BufferMapAsyncStatus::Success, Err(BufferAccessError::Device(_)) => BufferMapAsyncStatus::ContextLost, - Err(BufferAccessError::Invalid) | Err(BufferAccessError::Destroyed) => { - BufferMapAsyncStatus::Invalid - } + Err(BufferAccessError::InvalidBufferId(_)) + | Err(BufferAccessError::DestroyedResource(_)) => BufferMapAsyncStatus::Invalid, Err(BufferAccessError::AlreadyMapped) => BufferMapAsyncStatus::AlreadyMapped, Err(BufferAccessError::MapAlreadyPending) => { BufferMapAsyncStatus::MapAlreadyPending @@ -382,10 +381,10 @@ pub enum BufferAccessError { Device(#[from] DeviceError), #[error("Buffer map failed")] Failed, - #[error("Buffer is invalid")] - Invalid, - #[error("Buffer is destroyed")] - Destroyed, + #[error("BufferId {0:?} is invalid")] + InvalidBufferId(BufferId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error("Buffer is already mapped")] AlreadyMapped, #[error("Buffer map is pending")] @@ -439,6 +438,10 @@ pub struct MissingTextureUsageError { pub(crate) expected: wgt::TextureUsages, } +#[derive(Clone, Debug, Error)] +#[error("{0} has been destroyed")] +pub struct DestroyedResourceError(pub ResourceErrorIdent); + pub type BufferAccessResult = Result<(), BufferAccessError>; #[derive(Debug)] @@ -487,8 +490,23 @@ impl Buffer { self.raw.get(guard) } - pub(crate) fn is_destroyed(&self, guard: &SnatchGuard) -> bool { - self.raw.get(guard).is_none() + pub(crate) fn try_raw<'a>( + &'a self, + guard: &'a SnatchGuard, + ) -> Result<&A::Buffer, DestroyedResourceError> { + self.raw + .get(guard) + .ok_or_else(|| DestroyedResourceError(self.error_ident())) + } + + pub(crate) fn check_destroyed<'a>( + &'a self, + guard: &'a SnatchGuard, + ) -> Result<(), DestroyedResourceError> { + self.raw + .get(guard) + .map(|_| ()) + .ok_or_else(|| DestroyedResourceError(self.error_ident())) } /// Checks that the given buffer usage contains the required buffer usage, @@ -571,8 +589,8 @@ impl Buffer { { let snatch_guard = device.snatchable_lock.read(); - if self.is_destroyed(&snatch_guard) { - return Err((op, BufferAccessError::Destroyed)); + if let Err(e) = self.check_destroyed(&snatch_guard) { + return Err((op, e.into())); } } @@ -623,9 +641,7 @@ impl Buffer { let device = &self.device; let snatch_guard = device.snatchable_lock.read(); - let raw_buf = self - .raw(&snatch_guard) - .ok_or(BufferAccessError::Destroyed)?; + let raw_buf = self.try_raw(&snatch_guard)?; let buffer_id = self.info.id(); log::debug!("Buffer {:?} map state -> Idle", buffer_id); match mem::replace(&mut *self.map_state.lock(), BufferMapState::Idle) { @@ -1039,12 +1055,37 @@ impl Drop for Texture { } impl Texture { + pub(crate) fn try_inner<'a>( + &'a self, + guard: &'a SnatchGuard, + ) -> Result<&'a TextureInner, DestroyedResourceError> { + self.inner + .get(guard) + .ok_or_else(|| DestroyedResourceError(self.error_ident())) + } + pub(crate) fn raw<'a>(&'a self, snatch_guard: &'a SnatchGuard) -> Option<&'a A::Texture> { self.inner.get(snatch_guard)?.raw() } - pub(crate) fn is_destroyed(&self, guard: &SnatchGuard) -> bool { - self.inner.get(guard).is_none() + pub(crate) fn try_raw<'a>( + &'a self, + guard: &'a SnatchGuard, + ) -> Result<&'a A::Texture, DestroyedResourceError> { + self.inner + .get(guard) + .and_then(|t| t.raw()) + .ok_or_else(|| DestroyedResourceError(self.error_ident())) + } + + pub(crate) fn check_destroyed<'a>( + &'a self, + guard: &'a SnatchGuard, + ) -> Result<(), DestroyedResourceError> { + self.inner + .get(guard) + .map(|_| ()) + .ok_or_else(|| DestroyedResourceError(self.error_ident())) } pub(crate) fn inner_mut<'a>( @@ -1563,8 +1604,10 @@ impl TextureView { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum CreateTextureViewError { - #[error("Parent texture is invalid or destroyed")] - InvalidTexture, + #[error("TextureId {0:?} is invalid")] + InvalidTextureId(TextureId), + #[error(transparent)] + DestroyedResource(#[from] DestroyedResourceError), #[error("Not enough memory left to create texture view")] OutOfMemory, #[error("Invalid texture view dimension `{view:?}` with texture of dimension `{texture:?}`")] diff --git a/wgpu-core/src/track/mod.rs b/wgpu-core/src/track/mod.rs index 1e4f4ca7ef..391b91367d 100644 --- a/wgpu-core/src/track/mod.rs +++ b/wgpu-core/src/track/mod.rs @@ -270,7 +270,7 @@ impl PendingTransition { buf: &'a resource::Buffer, snatch_guard: &'a SnatchGuard<'a>, ) -> hal::BufferBarrier<'a, A> { - let buffer = buf.raw.get(snatch_guard).expect("Buffer is destroyed"); + let buffer = buf.raw(snatch_guard).expect("Buffer is destroyed"); hal::BufferBarrier { buffer, usage: self.usage,