From 68e8b7d4a8b44a838ba11fede7ca920d3f192289 Mon Sep 17 00:00:00 2001 From: teoxoy <28601907+teoxoy@users.noreply.github.com> Date: Fri, 6 Sep 2024 20:40:09 +0200 Subject: [PATCH] [wgpu-core] introduce `Fallible` and use it for `Buffer` (first step of invalidity internalization) --- tests/tests/resource_error.rs | 17 +++---- wgpu-core/src/binding_model.rs | 8 ++-- wgpu-core/src/command/bundle.rs | 29 ++++++----- wgpu-core/src/command/clear.rs | 13 ++--- wgpu-core/src/command/compute.rs | 12 ++--- wgpu-core/src/command/compute_command.rs | 4 +- wgpu-core/src/command/draw.rs | 2 - wgpu-core/src/command/query.rs | 12 ++--- wgpu-core/src/command/render.rs | 42 ++++------------ wgpu-core/src/command/render_command.rs | 23 +++++---- wgpu-core/src/command/transfer.rs | 28 ++++------- wgpu-core/src/device/global.rs | 61 ++++++++++-------------- wgpu-core/src/device/queue.rs | 25 ++++------ wgpu-core/src/device/resource.rs | 8 ++-- wgpu-core/src/hub.rs | 4 +- wgpu-core/src/resource.rs | 57 +++++++++++++++++++--- 16 files changed, 162 insertions(+), 183 deletions(-) diff --git a/tests/tests/resource_error.rs b/tests/tests/resource_error.rs index fc7e062f4..0c58f7a13 100644 --- a/tests/tests/resource_error.rs +++ b/tests/tests/resource_error.rs @@ -17,21 +17,16 @@ static BAD_BUFFER: GpuTestConfiguration = GpuTestConfiguration::new().run_sync(| Some("`map` usage can only be combined with the opposite `copy`"), ); - let error = match ctx.adapter_info.backend.to_str() { - "vulkan" | "vk" => "bufferid id(0,1,vk) is invalid", - "dx12" | "d3d12" => "bufferid id(0,1,d3d12) is invalid", - "metal" | "mtl" => "bufferid id(0,1,mtl) is invalid", - "opengl" | "gles" | "gl" => "bufferid id(0,1,gl) is invalid", - "webgpu" => "bufferid id(0,1,webgpu) is invalid", - b => b, - }; - fail( &ctx.device, || buffer.slice(..).map_async(wgpu::MapMode::Write, |_| {}), - Some(error), + Some("Buffer with '' label is invalid"), + ); + fail( + &ctx.device, + || buffer.unmap(), + Some("Buffer with '' label is invalid"), ); - fail(&ctx.device, || buffer.unmap(), Some(error)); valid(&ctx.device, || buffer.destroy()); valid(&ctx.device, || buffer.destroy()); }); diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index bd89fbb2b..0ec07092c 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -6,8 +6,8 @@ use crate::{ init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction}, pipeline::{ComputePipeline, RenderPipeline}, resource::{ - Buffer, DestroyedResourceError, Labeled, MissingBufferUsageError, MissingTextureUsageError, - ResourceErrorIdent, Sampler, TextureView, TrackingData, + Buffer, DestroyedResourceError, InvalidResourceError, Labeled, MissingBufferUsageError, + MissingTextureUsageError, ResourceErrorIdent, Sampler, TextureView, TrackingData, }, resource_log, snatch::{SnatchGuard, Snatchable}, @@ -81,8 +81,6 @@ pub enum CreateBindGroupError { Device(#[from] DeviceError), #[error("Bind group layout is invalid")] InvalidLayout, - #[error("BufferId {0:?} is invalid")] - InvalidBufferId(BufferId), #[error("TextureViewId {0:?} is invalid")] InvalidTextureViewId(TextureViewId), #[error("SamplerId {0:?} is invalid")] @@ -188,6 +186,8 @@ pub enum CreateBindGroupError { StorageReadNotSupported(wgt::TextureFormat), #[error(transparent)] ResourceUsageCompatibility(#[from] ResourceUsageCompatibilityError), + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } #[derive(Clone, Debug, Error)] diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index d63388204..1429300bc 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -92,7 +92,10 @@ use crate::{ id, init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction}, pipeline::{PipelineFlags, RenderPipeline, VertexStep}, - resource::{Buffer, DestroyedResourceError, Labeled, ParentDevice, TrackingData}, + resource::{ + Buffer, DestroyedResourceError, Fallible, InvalidResourceError, Labeled, ParentDevice, + TrackingData, + }, resource_log, snatch::SnatchGuard, track::RenderBundleScope, @@ -578,7 +581,7 @@ impl RenderBundleEncoder { fn set_bind_group( state: &mut State, - bind_group_guard: &crate::lock::RwLockReadGuard>>, + bind_group_guard: &crate::storage::Storage>, dynamic_offsets: &[u32], index: u32, num_dynamic_offsets: usize, @@ -630,7 +633,7 @@ fn set_bind_group( fn set_pipeline( state: &mut State, - pipeline_guard: &crate::lock::RwLockReadGuard>>, + pipeline_guard: &crate::storage::Storage>, context: &RenderPassContext, is_depth_read_only: bool, is_stencil_read_only: bool, @@ -673,15 +676,13 @@ fn set_pipeline( fn set_index_buffer( state: &mut State, - buffer_guard: &crate::lock::RwLockReadGuard>>, + buffer_guard: &crate::storage::Storage>, buffer_id: id::Id, index_format: wgt::IndexFormat, offset: u64, size: Option, ) -> Result<(), RenderBundleErrorInner> { - let buffer = buffer_guard - .get_owned(buffer_id) - .map_err(|_| RenderCommandError::InvalidBufferId(buffer_id))?; + let buffer = buffer_guard.strict_get(buffer_id).get()?; state .trackers @@ -708,7 +709,7 @@ fn set_index_buffer( fn set_vertex_buffer( state: &mut State, - buffer_guard: &crate::lock::RwLockReadGuard>>, + buffer_guard: &crate::storage::Storage>, slot: u32, buffer_id: id::Id, offset: u64, @@ -723,9 +724,7 @@ fn set_vertex_buffer( .into()); } - let buffer = buffer_guard - .get_owned(buffer_id) - .map_err(|_| RenderCommandError::InvalidBufferId(buffer_id))?; + let buffer = buffer_guard.strict_get(buffer_id).get()?; state .trackers @@ -852,7 +851,7 @@ fn draw_indexed( fn multi_draw_indirect( state: &mut State, dynamic_offsets: &[u32], - buffer_guard: &crate::lock::RwLockReadGuard>>, + buffer_guard: &crate::storage::Storage>, buffer_id: id::Id, offset: u64, indexed: bool, @@ -864,9 +863,7 @@ fn multi_draw_indirect( let pipeline = state.pipeline()?; let used_bind_groups = pipeline.used_bind_groups; - let buffer = buffer_guard - .get_owned(buffer_id) - .map_err(|_| RenderCommandError::InvalidBufferId(buffer_id))?; + let buffer = buffer_guard.strict_get(buffer_id).get()?; state .trackers @@ -1538,6 +1535,8 @@ pub(super) enum RenderBundleErrorInner { MissingDownlevelFlags(#[from] MissingDownlevelFlags), #[error(transparent)] Bind(#[from] BindError), + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } impl From for RenderBundleErrorInner diff --git a/wgpu-core/src/command/clear.rs b/wgpu-core/src/command/clear.rs index 7a16f6db3..0000a2be5 100644 --- a/wgpu-core/src/command/clear.rs +++ b/wgpu-core/src/command/clear.rs @@ -11,8 +11,8 @@ use crate::{ id::{BufferId, CommandEncoderId, TextureId}, init_tracker::{MemoryInitKind, TextureInitRange}, resource::{ - DestroyedResourceError, Labeled, MissingBufferUsageError, ParentDevice, ResourceErrorIdent, - Texture, TextureClearMode, + DestroyedResourceError, InvalidResourceError, Labeled, MissingBufferUsageError, + ParentDevice, ResourceErrorIdent, Texture, TextureClearMode, }, snatch::SnatchGuard, track::{TextureSelector, TextureTrackerSetSingle}, @@ -27,8 +27,6 @@ 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("BufferId {0:?} is invalid")] - InvalidBufferId(BufferId), #[error("TextureId {0:?} is invalid")] InvalidTextureId(TextureId), #[error(transparent)] @@ -75,6 +73,8 @@ whereas subesource range specified start {subresource_base_array_layer} and coun Device(#[from] DeviceError), #[error(transparent)] CommandEncoderError(#[from] CommandEncoderError), + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } impl Global { @@ -107,10 +107,7 @@ impl Global { list.push(TraceCommand::ClearBuffer { dst, offset, size }); } - let dst_buffer = hub - .buffers - .get(dst) - .map_err(|_| ClearError::InvalidBufferId(dst))?; + let dst_buffer = hub.buffers.strict_get(dst).get()?; dst_buffer.same_device_as(cmd_buf.as_ref())?; diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index a9f03ac65..cbcb5979a 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -17,8 +17,8 @@ use crate::{ init_tracker::{BufferInitTrackerAction, MemoryInitKind}, pipeline::ComputePipeline, resource::{ - self, Buffer, DestroyedResourceError, Labeled, MissingBufferUsageError, ParentDevice, - Trackable, + self, Buffer, DestroyedResourceError, InvalidResourceError, Labeled, + MissingBufferUsageError, ParentDevice, Trackable, }, snatch::SnatchGuard, track::{ResourceUsageCompatibilityError, Tracker, TrackerIndex, UsageScope}, @@ -148,8 +148,6 @@ pub enum ComputePassErrorInner { end_offset: u64, buffer_size: u64, }, - #[error("BufferId {0:?} is invalid")] - InvalidBufferId(id::BufferId), #[error(transparent)] ResourceUsageCompatibility(#[from] ResourceUsageCompatibilityError), #[error(transparent)] @@ -176,6 +174,8 @@ pub enum ComputePassErrorInner { MissingDownlevelFlags(#[from] MissingDownlevelFlags), #[error("The compute pass has already been ended and no further commands can be recorded")] PassEnded, + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } /// Error encountered when performing a compute pass. @@ -1096,8 +1096,8 @@ impl Global { let buffer = hub .buffers - .get(buffer_id) - .map_err(|_| ComputePassErrorInner::InvalidBufferId(buffer_id)) + .strict_get(buffer_id) + .get() .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 6596b8e6a..700398982 100644 --- a/wgpu-core/src/command/compute_command.rs +++ b/wgpu-core/src/command/compute_command.rs @@ -136,10 +136,10 @@ impl ComputeCommand { ComputeCommand::DispatchIndirect { buffer_id, offset } => { ArcComputeCommand::DispatchIndirect { - buffer: buffers_guard.get_owned(buffer_id).map_err(|_| { + buffer: buffers_guard.strict_get(buffer_id).get().map_err(|e| { ComputePassError { scope: PassErrorScope::Dispatch { indirect: true }, - inner: ComputePassErrorInner::InvalidBufferId(buffer_id), + inner: e.into(), } })?, offset, diff --git a/wgpu-core/src/command/draw.rs b/wgpu-core/src/command/draw.rs index e8578bba0..dc343f0af 100644 --- a/wgpu-core/src/command/draw.rs +++ b/wgpu-core/src/command/draw.rs @@ -68,8 +68,6 @@ pub enum DrawError { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum RenderCommandError { - #[error("BufferId {0:?} is invalid")] - InvalidBufferId(id::BufferId), #[error("BindGroupId {0:?} is invalid")] InvalidBindGroupId(id::BindGroupId), #[error("Render bundle {0:?} is invalid")] diff --git a/wgpu-core/src/command/query.rs b/wgpu-core/src/command/query.rs index 6d9fa8021..886201e27 100644 --- a/wgpu-core/src/command/query.rs +++ b/wgpu-core/src/command/query.rs @@ -7,7 +7,8 @@ use crate::{ id, init_tracker::MemoryInitKind, resource::{ - DestroyedResourceError, MissingBufferUsageError, ParentDevice, QuerySet, Trackable, + DestroyedResourceError, InvalidResourceError, MissingBufferUsageError, ParentDevice, + QuerySet, Trackable, }, track::{StatelessTracker, TrackerIndex}, FastHashMap, @@ -100,12 +101,12 @@ pub enum QueryError { Use(#[from] QueryUseError), #[error("Error encountered while trying to resolve a query")] Resolve(#[from] ResolveError), - #[error("BufferId {0:?} is invalid")] - InvalidBufferId(id::BufferId), #[error(transparent)] DestroyedResource(#[from] DestroyedResourceError), #[error("QuerySetId {0:?} is invalid or destroyed")] InvalidQuerySetId(id::QuerySetId), + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } /// Error encountered while trying to use queries @@ -412,10 +413,7 @@ impl Global { query_set.same_device_as(cmd_buf.as_ref())?; - let dst_buffer = hub - .buffers - .get(destination) - .map_err(|_| QueryError::InvalidBufferId(destination))?; + let dst_buffer = hub.buffers.strict_get(destination).get()?; dst_buffer.same_device_as(cmd_buf.as_ref())?; diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index 00892f074..4065b73be 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -4,6 +4,7 @@ use crate::command::{ }; use crate::init_tracker::BufferInitTrackerAction; use crate::pipeline::RenderPipeline; +use crate::resource::InvalidResourceError; use crate::snatch::SnatchGuard; use crate::{ api_log, @@ -582,8 +583,6 @@ pub enum RenderPassErrorInner { InvalidParentEncoder, #[error("The format of the depth-stencil attachment ({0:?}) is not a depth-stencil format")] InvalidDepthStencilAttachmentFormat(wgt::TextureFormat), - #[error("Buffer {0:?} is invalid or destroyed")] - InvalidBuffer(id::BufferId), #[error("Render pipeline {0:?} is invalid")] InvalidPipeline(id::RenderPipelineId), #[error("QuerySet {0:?} is invalid")] @@ -705,6 +704,8 @@ pub enum RenderPassErrorInner { DestroyedResource(#[from] DestroyedResourceError), #[error("The compute pass has already been ended and no further commands can be recorded")] PassEnded, + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } impl From for RenderPassErrorInner { @@ -2776,8 +2777,8 @@ impl Global { let hub = &self.hub; let buffer = hub .buffers - .get(buffer_id) - .map_err(|_| RenderPassErrorInner::InvalidBuffer(buffer_id)) + .strict_get(buffer_id) + .get() .map_pass_err(scope)?; Ok(buffer) @@ -3174,23 +3175,11 @@ impl Global { }; let base = pass.base_mut(scope)?; - // Don't use resolve_render_pass_buffer_id here, because we don't want to take the read-lock twice. - let hub = &self.hub; - let buffers = hub.buffers.read(); - let buffer = buffers - .get_owned(buffer_id) - .map_err(|_| RenderPassErrorInner::InvalidBuffer(buffer_id)) - .map_pass_err(scope)?; - let count_buffer = buffers - .get_owned(count_buffer_id) - .map_err(|_| RenderPassErrorInner::InvalidBuffer(count_buffer_id)) - .map_pass_err(scope)?; - base.commands .push(ArcRenderCommand::MultiDrawIndirectCount { - buffer, + buffer: self.resolve_render_pass_buffer_id(scope, buffer_id)?, offset, - count_buffer, + count_buffer: self.resolve_render_pass_buffer_id(scope, count_buffer_id)?, count_buffer_offset, max_count, indexed: false, @@ -3214,24 +3203,11 @@ impl Global { }; let base = pass.base_mut(scope)?; - // Don't use resolve_render_pass_buffer_id here, because we don't want to take the read-lock twice. - let hub = &self.hub; - let buffers = hub.buffers.read(); - let buffer = buffers - .get_owned(buffer_id) - .map_err(|_| RenderPassErrorInner::InvalidBuffer(buffer_id)) - .map_pass_err(scope)?; - - let count_buffer = buffers - .get_owned(count_buffer_id) - .map_err(|_| RenderPassErrorInner::InvalidBuffer(count_buffer_id)) - .map_pass_err(scope)?; - base.commands .push(ArcRenderCommand::MultiDrawIndirectCount { - buffer, + buffer: self.resolve_render_pass_buffer_id(scope, buffer_id)?, offset, - count_buffer, + count_buffer: self.resolve_render_pass_buffer_id(scope, count_buffer_id)?, count_buffer_offset, max_count, indexed: true, diff --git a/wgpu-core/src/command/render_command.rs b/wgpu-core/src/command/render_command.rs index 7b8a2f283..cbbae1a08 100644 --- a/wgpu-core/src/command/render_command.rs +++ b/wgpu-core/src/command/render_command.rs @@ -238,10 +238,10 @@ impl RenderCommand { offset, size, } => ArcRenderCommand::SetIndexBuffer { - buffer: buffers_guard.get_owned(buffer_id).map_err(|_| { + buffer: buffers_guard.strict_get(buffer_id).get().map_err(|e| { RenderPassError { scope: PassErrorScope::SetIndexBuffer, - inner: RenderCommandError::InvalidBufferId(buffer_id).into(), + inner: e.into(), } })?, index_format, @@ -256,10 +256,10 @@ impl RenderCommand { size, } => ArcRenderCommand::SetVertexBuffer { slot, - buffer: buffers_guard.get_owned(buffer_id).map_err(|_| { + buffer: buffers_guard.strict_get(buffer_id).get().map_err(|e| { RenderPassError { scope: PassErrorScope::SetVertexBuffer, - inner: RenderCommandError::InvalidBufferId(buffer_id).into(), + inner: e.into(), } })?, offset, @@ -318,7 +318,7 @@ impl RenderCommand { count, indexed, } => ArcRenderCommand::MultiDrawIndirect { - buffer: buffers_guard.get_owned(buffer_id).map_err(|_| { + buffer: buffers_guard.strict_get(buffer_id).get().map_err(|e| { RenderPassError { scope: PassErrorScope::Draw { kind: if count.is_some() { @@ -328,7 +328,7 @@ impl RenderCommand { }, indexed, }, - inner: RenderCommandError::InvalidBufferId(buffer_id).into(), + inner: e.into(), } })?, offset, @@ -349,18 +349,17 @@ impl RenderCommand { indexed, }; ArcRenderCommand::MultiDrawIndirectCount { - buffer: buffers_guard.get_owned(buffer_id).map_err(|_| { + buffer: buffers_guard.strict_get(buffer_id).get().map_err(|e| { RenderPassError { scope, - inner: RenderCommandError::InvalidBufferId(buffer_id).into(), + inner: e.into(), } })?, offset, - count_buffer: buffers_guard.get_owned(count_buffer_id).map_err( - |_| RenderPassError { + count_buffer: buffers_guard.strict_get(count_buffer_id).get().map_err( + |e| RenderPassError { scope, - inner: RenderCommandError::InvalidBufferId(count_buffer_id) - .into(), + inner: e.into(), }, )?, count_buffer_offset, diff --git a/wgpu-core/src/command/transfer.rs b/wgpu-core/src/command/transfer.rs index aeceb29af..463e62b51 100644 --- a/wgpu-core/src/command/transfer.rs +++ b/wgpu-core/src/command/transfer.rs @@ -12,8 +12,8 @@ use crate::{ TextureInitTrackerAction, }, resource::{ - DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError, ParentDevice, - Texture, TextureErrorDimension, + DestroyedResourceError, InvalidResourceError, MissingBufferUsageError, + MissingTextureUsageError, ParentDevice, Texture, TextureErrorDimension, }, snatch::SnatchGuard, track::{TextureSelector, Tracker}, @@ -41,8 +41,6 @@ pub enum CopySide { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum TransferError { - #[error("BufferId {0:?} is invalid")] - InvalidBufferId(BufferId), #[error("TextureId {0:?} is invalid")] InvalidTextureId(TextureId), #[error("Source and destination cannot be the same buffer")] @@ -150,6 +148,8 @@ pub enum CopyError { Transfer(#[from] TransferError), #[error(transparent)] DestroyedResource(#[from] DestroyedResourceError), + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } impl From for CopyError { @@ -570,10 +570,7 @@ impl Global { let snatch_guard = device.snatchable_lock.read(); - let src_buffer = hub - .buffers - .get(source) - .map_err(|_| TransferError::InvalidBufferId(source))?; + let src_buffer = hub.buffers.strict_get(source).get()?; src_buffer.same_device_as(cmd_buf.as_ref())?; @@ -589,10 +586,7 @@ impl Global { // expecting only a single barrier let src_barrier = src_pending.map(|pending| pending.into_hal(&src_buffer, &snatch_guard)); - let dst_buffer = hub - .buffers - .get(destination) - .map_err(|_| TransferError::InvalidBufferId(destination))?; + let dst_buffer = hub.buffers.strict_get(destination).get()?; dst_buffer.same_device_as(cmd_buf.as_ref())?; @@ -778,10 +772,7 @@ impl Global { &snatch_guard, )?; - let src_buffer = hub - .buffers - .get(source.buffer) - .map_err(|_| TransferError::InvalidBufferId(source.buffer))?; + let src_buffer = hub.buffers.strict_get(source.buffer).get()?; src_buffer.same_device_as(cmd_buf.as_ref())?; @@ -966,10 +957,7 @@ impl Global { .map(|pending| pending.into_hal(src_raw)) .collect::>(); - let dst_buffer = hub - .buffers - .get(destination.buffer) - .map_err(|_| TransferError::InvalidBufferId(destination.buffer))?; + let dst_buffer = hub.buffers.strict_get(destination.buffer).get()?; dst_buffer.same_device_as(cmd_buf.as_ref())?; diff --git a/wgpu-core/src/device/global.rs b/wgpu-core/src/device/global.rs index 910a7f9d1..0deebf200 100644 --- a/wgpu-core/src/device/global.rs +++ b/wgpu-core/src/device/global.rs @@ -19,9 +19,10 @@ use crate::{ present, resource::{ self, BufferAccessError, BufferAccessResult, BufferMapOperation, CreateBufferError, + Fallible, }, storage::Storage, - Label, + Label, LabelHelpers, }; use wgt::{BufferAddress, TextureFormat}; @@ -124,7 +125,7 @@ impl Global { } }; - let id = fid.assign(buffer); + let id = fid.assign(Fallible::Valid(buffer)); api_log!( "Device::create_buffer({:?}{}) -> {id:?}", @@ -139,7 +140,7 @@ impl Global { return (id, None); }; - let id = fid.assign_error(); + let id = fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string()))); (id, Some(error)) } @@ -171,11 +172,14 @@ impl Global { /// [`device_create_buffer`]: Global::device_create_buffer /// [`usage`]: https://www.w3.org/TR/webgpu/#dom-gputexturedescriptor-usage /// [`wgpu_types::BufferUsages`]: wgt::BufferUsages - pub fn create_buffer_error(&self, backend: wgt::Backend, id_in: Option) { - let hub = &self.hub; - let fid = hub.buffers.prepare(backend, id_in); - - fid.assign_error(); + pub fn create_buffer_error( + &self, + backend: wgt::Backend, + id_in: Option, + desc: &resource::BufferDescriptor, + ) { + let fid = self.hub.buffers.prepare(backend, id_in); + fid.assign(Fallible::Invalid(Arc::new(desc.label.to_string()))); } pub fn create_render_bundle_error( @@ -208,10 +212,7 @@ impl Global { ) -> BufferAccessResult { let hub = &self.hub; - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; + let buffer = hub.buffers.strict_get(buffer_id).get()?; let device = &buffer.device; @@ -258,10 +259,7 @@ impl Global { let hub = &self.hub; - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| resource::DestroyError::Invalid)?; + let buffer = hub.buffers.strict_get(buffer_id).get()?; #[cfg(feature = "trace")] if let Some(trace) = buffer.device.trace.lock().as_mut() { @@ -282,9 +280,9 @@ impl Global { let hub = &self.hub; - let buffer = match hub.buffers.unregister(buffer_id) { - Some(buffer) => buffer, - None => { + let buffer = match hub.buffers.strict_unregister(buffer_id).get() { + Ok(buffer) => buffer, + Err(_) => { return; } }; @@ -425,7 +423,7 @@ impl Global { let texture = hub .textures .get(texture_id) - .map_err(|_| resource::DestroyError::Invalid)?; + .map_err(|_| resource::DestroyError::InvalidTextureId(texture_id))?; #[cfg(feature = "trace")] if let Some(trace) = texture.device.trace.lock().as_mut() { @@ -733,22 +731,21 @@ impl Global { fn resolve_entry<'a>( e: &BindGroupEntry<'a>, - buffer_storage: &Storage>, + buffer_storage: &Storage>, sampler_storage: &Storage>, texture_view_storage: &Storage>, ) -> Result, binding_model::CreateBindGroupError> { let resolve_buffer = |bb: &BufferBinding| { buffer_storage - .get_owned(bb.buffer_id) + .strict_get(bb.buffer_id) + .get() .map(|buffer| ResolvedBufferBinding { buffer, offset: bb.offset, size: bb.size, }) - .map_err(|_| { - binding_model::CreateBindGroupError::InvalidBufferId(bb.buffer_id) - }) + .map_err(binding_model::CreateBindGroupError::from) }; let resolve_sampler = |id: &id::SamplerId| { sampler_storage @@ -2197,9 +2194,9 @@ impl Global { let hub = &self.hub; let op_and_err = 'error: { - let buffer = match hub.buffers.get(buffer_id) { + let buffer = match hub.buffers.strict_get(buffer_id).get() { Ok(buffer) => buffer, - Err(_) => break 'error Some((op, BufferAccessError::InvalidBufferId(buffer_id))), + Err(e) => break 'error Some((op, e.into())), }; buffer.map_async(offset, size, op).err() @@ -2230,10 +2227,7 @@ impl Global { let hub = &self.hub; - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; + let buffer = hub.buffers.strict_get(buffer_id).get()?; { let snatch_guard = buffer.device.snatchable_lock.read(); @@ -2306,10 +2300,7 @@ impl Global { let hub = &self.hub; - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?; + let buffer = hub.buffers.strict_get(buffer_id).get()?; let snatch_guard = buffer.device.snatchable_lock.read(); buffer.check_destroyed(&snatch_guard)?; diff --git a/wgpu-core/src/device/queue.rs b/wgpu-core/src/device/queue.rs index 9923b8bba..bde4003f9 100644 --- a/wgpu-core/src/device/queue.rs +++ b/wgpu-core/src/device/queue.rs @@ -16,8 +16,8 @@ use crate::{ lock::RwLockWriteGuard, resource::{ Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedResourceError, - DestroyedTexture, FlushedStagingBuffer, Labeled, ParentDevice, ResourceErrorIdent, - StagingBuffer, Texture, TextureInner, Trackable, + DestroyedTexture, FlushedStagingBuffer, InvalidResourceError, Labeled, ParentDevice, + ResourceErrorIdent, StagingBuffer, Texture, TextureInner, Trackable, }, resource_log, track::{self, Tracker, TrackerIndex}, @@ -332,6 +332,10 @@ pub enum QueueWriteError { MemoryInitFailure(#[from] ClearError), #[error(transparent)] DestroyedResource(#[from] DestroyedResourceError), + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), + #[error("StagingBufferId {0:?} is invalid")] + InvalidStagingBufferId(id::StagingBufferId), } #[derive(Clone, Debug, Error)] @@ -368,10 +372,7 @@ impl Global { let hub = &self.hub; - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| TransferError::InvalidBufferId(buffer_id))?; + let buffer = hub.buffers.strict_get(buffer_id).get()?; let queue = hub.queues.strict_get(queue_id); @@ -465,7 +466,7 @@ impl Global { .staging_buffers .unregister(staging_buffer_id) .and_then(Arc::into_inner) - .ok_or_else(|| QueueWriteError::Transfer(TransferError::InvalidBufferId(buffer_id)))?; + .ok_or_else(|| QueueWriteError::InvalidStagingBufferId(staging_buffer_id))?; let mut pending_writes = device.pending_writes.lock(); @@ -498,10 +499,7 @@ impl Global { profiling::scope!("Queue::validate_write_buffer"); let hub = &self.hub; - let buffer = hub - .buffers - .get(buffer_id) - .map_err(|_| TransferError::InvalidBufferId(buffer_id))?; + let buffer = hub.buffers.strict_get(buffer_id).get()?; self.queue_validate_write_buffer_impl(&buffer, buffer_offset, buffer_size)?; @@ -544,10 +542,7 @@ impl Global { ) -> Result<(), QueueWriteError> { let hub = &self.hub; - let dst = hub - .buffers - .get(buffer_id) - .map_err(|_| TransferError::InvalidBufferId(buffer_id))?; + let dst = hub.buffers.strict_get(buffer_id).get()?; let transition = { let mut trackers = device.trackers.lock(); diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 253f2ca94..e7fe69984 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -21,7 +21,7 @@ use crate::{ pipeline, pool::ResourcePool, resource::{ - self, Buffer, Labeled, ParentDevice, QuerySet, Sampler, StagingBuffer, Texture, + self, Buffer, Fallible, Labeled, ParentDevice, QuerySet, Sampler, StagingBuffer, Texture, TextureView, TextureViewNotRenderableReason, TrackingData, }, resource_log, @@ -694,11 +694,11 @@ impl Device { Ok(texture) } - pub fn create_buffer_from_hal( + pub(crate) fn create_buffer_from_hal( self: &Arc, hal_buffer: Box, desc: &resource::BufferDescriptor, - ) -> Arc { + ) -> Fallible { unsafe { self.raw().add_raw_buffer(&*hal_buffer) }; let buffer = Buffer { @@ -723,7 +723,7 @@ impl Device { .buffers .insert_single(&buffer, hal::BufferUses::empty()); - buffer + Fallible::Valid(buffer) } pub(crate) fn create_texture( diff --git a/wgpu-core/src/hub.rs b/wgpu-core/src/hub.rs index d14986c01..3fb2e7963 100644 --- a/wgpu-core/src/hub.rs +++ b/wgpu-core/src/hub.rs @@ -107,7 +107,7 @@ use crate::{ instance::{Adapter, Surface}, pipeline::{ComputePipeline, PipelineCache, RenderPipeline, ShaderModule}, registry::{Registry, RegistryReport}, - resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureView}, + resource::{Buffer, Fallible, QuerySet, Sampler, StagingBuffer, Texture, TextureView}, storage::{Element, Storage}, }; use std::{fmt::Debug, sync::Arc}; @@ -175,7 +175,7 @@ pub struct Hub { pub(crate) compute_pipelines: Registry>, pub(crate) pipeline_caches: Registry>, pub(crate) query_sets: Registry>, - pub(crate) buffers: Registry>, + pub(crate) buffers: Registry>, pub(crate) staging_buffers: Registry>, pub(crate) textures: Registry>, pub(crate) texture_views: Registry>, diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index ae4dcced7..8e61ad11e 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -305,7 +305,7 @@ impl BufferMapCallback { let status = match result { Ok(()) => BufferMapAsyncStatus::Success, Err(BufferAccessError::Device(_)) => BufferMapAsyncStatus::ContextLost, - Err(BufferAccessError::InvalidBufferId(_)) + Err(BufferAccessError::InvalidResource(_)) | Err(BufferAccessError::DestroyedResource(_)) => BufferMapAsyncStatus::Invalid, Err(BufferAccessError::AlreadyMapped) => BufferMapAsyncStatus::AlreadyMapped, Err(BufferAccessError::MapAlreadyPending) => { @@ -324,7 +324,9 @@ impl BufferMapCallback { | Err(BufferAccessError::NegativeRange { .. }) => { BufferMapAsyncStatus::InvalidRange } - Err(_) => BufferMapAsyncStatus::Error, + Err(BufferAccessError::Failed) + | Err(BufferAccessError::NotMapped) + | Err(BufferAccessError::MapAborted) => BufferMapAsyncStatus::Error, }; (inner.callback)(status, inner.user_data); @@ -347,8 +349,6 @@ pub enum BufferAccessError { Device(#[from] DeviceError), #[error("Buffer map failed")] Failed, - #[error("BufferId {0:?} is invalid")] - InvalidBufferId(BufferId), #[error(transparent)] DestroyedResource(#[from] DestroyedResourceError), #[error("Buffer is already mapped")] @@ -386,6 +386,8 @@ pub enum BufferAccessError { }, #[error("Buffer map aborted")] MapAborted, + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), } #[derive(Clone, Debug, Error)] @@ -410,6 +412,45 @@ pub struct MissingTextureUsageError { #[error("{0} has been destroyed")] pub struct DestroyedResourceError(pub ResourceErrorIdent); +#[derive(Clone, Debug, Error)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[error("{0} is invalid")] +pub struct InvalidResourceError(pub ResourceErrorIdent); + +pub(crate) enum Fallible { + Valid(Arc), + Invalid(Arc), +} + +impl Fallible { + pub fn get(self) -> Result, InvalidResourceError> { + match self { + Fallible::Valid(v) => Ok(v), + Fallible::Invalid(label) => Err(InvalidResourceError(ResourceErrorIdent { + r#type: Cow::Borrowed(T::TYPE), + label: (*label).clone(), + })), + } + } +} + +impl Clone for Fallible { + fn clone(&self) -> Self { + match self { + Self::Valid(v) => Self::Valid(v.clone()), + Self::Invalid(l) => Self::Invalid(l.clone()), + } + } +} + +impl ResourceType for Fallible { + const TYPE: &'static str = T::TYPE; +} + +impl crate::storage::StorageItem for Fallible { + type Marker = T::Marker; +} + pub type BufferAccessResult = Result<(), BufferAccessError>; #[derive(Debug)] @@ -1202,7 +1243,7 @@ impl Global { let hub = &self.hub; - if let Ok(buffer) = hub.buffers.get(id) { + if let Ok(buffer) = hub.buffers.strict_get(id).get() { let snatch_guard = buffer.device.snatchable_lock.read(); let hal_buffer = buffer .raw(&snatch_guard) @@ -1821,8 +1862,10 @@ impl QuerySet { #[derive(Clone, Debug, Error)] #[non_exhaustive] pub enum DestroyError { - #[error("Resource is invalid")] - Invalid, + #[error("TextureId {0:?} is invalid")] + InvalidTextureId(TextureId), #[error("Resource is already destroyed")] AlreadyDestroyed, + #[error(transparent)] + InvalidResource(#[from] InvalidResourceError), }