[wgpu-core] introduce Fallible and use it for Buffer (first step of invalidity internalization)

This commit is contained in:
teoxoy 2024-09-06 20:40:09 +02:00 committed by Teodor Tanasoaia
parent 3437589107
commit 68e8b7d4a8
16 changed files with 162 additions and 183 deletions

View File

@ -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());
});

View File

@ -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)]

View File

@ -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<crate::storage::Storage<Arc<BindGroup>>>,
bind_group_guard: &crate::storage::Storage<Arc<BindGroup>>,
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<crate::storage::Storage<Arc<RenderPipeline>>>,
pipeline_guard: &crate::storage::Storage<Arc<RenderPipeline>>,
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<crate::storage::Storage<Arc<Buffer>>>,
buffer_guard: &crate::storage::Storage<Fallible<Buffer>>,
buffer_id: id::Id<id::markers::Buffer>,
index_format: wgt::IndexFormat,
offset: u64,
size: Option<std::num::NonZeroU64>,
) -> 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<crate::storage::Storage<Arc<Buffer>>>,
buffer_guard: &crate::storage::Storage<Fallible<Buffer>>,
slot: u32,
buffer_id: id::Id<id::markers::Buffer>,
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<crate::storage::Storage<Arc<Buffer>>>,
buffer_guard: &crate::storage::Storage<Fallible<Buffer>>,
buffer_id: id::Id<id::markers::Buffer>,
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<T> From<T> for RenderBundleErrorInner

View File

@ -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())?;

View File

@ -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

View File

@ -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,

View File

@ -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")]

View File

@ -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())?;

View File

@ -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<MissingBufferUsageError> 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,

View File

@ -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,

View File

@ -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<DeviceError> 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::<Vec<_>>();
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())?;

View File

@ -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<id::BufferId>) {
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<id::BufferId>,
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<Arc<resource::Buffer>>,
buffer_storage: &Storage<Fallible<resource::Buffer>>,
sampler_storage: &Storage<Arc<resource::Sampler>>,
texture_view_storage: &Storage<Arc<resource::TextureView>>,
) -> Result<ResolvedBindGroupEntry<'a>, 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)?;

View File

@ -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();

View File

@ -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<Self>,
hal_buffer: Box<dyn hal::DynBuffer>,
desc: &resource::BufferDescriptor,
) -> Arc<Buffer> {
) -> Fallible<Buffer> {
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(

View File

@ -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<Arc<ComputePipeline>>,
pub(crate) pipeline_caches: Registry<Arc<PipelineCache>>,
pub(crate) query_sets: Registry<Arc<QuerySet>>,
pub(crate) buffers: Registry<Arc<Buffer>>,
pub(crate) buffers: Registry<Fallible<Buffer>>,
pub(crate) staging_buffers: Registry<Arc<StagingBuffer>>,
pub(crate) textures: Registry<Arc<Texture>>,
pub(crate) texture_views: Registry<Arc<TextureView>>,

View File

@ -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<T: ParentDevice> {
Valid(Arc<T>),
Invalid(Arc<String>),
}
impl<T: ParentDevice> Fallible<T> {
pub fn get(self) -> Result<Arc<T>, InvalidResourceError> {
match self {
Fallible::Valid(v) => Ok(v),
Fallible::Invalid(label) => Err(InvalidResourceError(ResourceErrorIdent {
r#type: Cow::Borrowed(T::TYPE),
label: (*label).clone(),
})),
}
}
}
impl<T: ParentDevice> Clone for Fallible<T> {
fn clone(&self) -> Self {
match self {
Self::Valid(v) => Self::Valid(v.clone()),
Self::Invalid(l) => Self::Invalid(l.clone()),
}
}
}
impl<T: ParentDevice> ResourceType for Fallible<T> {
const TYPE: &'static str = T::TYPE;
}
impl<T: ParentDevice + crate::storage::StorageItem> crate::storage::StorageItem for Fallible<T> {
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),
}