consolidate destroyed texture/buffer errors and separate them from invalid ID errors

This commit is contained in:
teoxoy 2024-06-20 01:57:10 +02:00 committed by Teodor Tanasoaia
parent 97a038a768
commit a024afe182
17 changed files with 207 additions and 287 deletions

View File

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

View File

@ -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<A: HalApi> RenderBundle<A> {
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<A: HalApi> RenderBundle<A> {
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<A: HalApi> RenderBundle<A> {
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<A: HalApi> RenderBundle<A> {
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 { .. } => {

View File

@ -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<A: HalApi>(
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() {

View File

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

View File

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

View File

@ -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);
}
_ => {}

View File

@ -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<A: HalApi> BakedCommands<A> {
&mut self,
device_tracker: &mut Tracker<A>,
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<A: HalApi> BakedCommands<A> {
.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<A: HalApi> BakedCommands<A> {
device_tracker: &mut Tracker<A>,
device: &Device<A>,
snatch_guard: &SnatchGuard<'_>,
) -> Result<(), DestroyedTextureError> {
) -> Result<(), DestroyedResourceError> {
profiling::scope!("initialize_texture_memory");
let mut ranges: Vec<TextureInitRange> = Vec::new();
@ -324,8 +319,8 @@ impl<A: HalApi> BakedCommands<A> {
// 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.

View File

@ -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<A: HalApi> {
texture_memory_actions: CommandBufferTextureMemoryActions<A>,
}
pub(crate) struct DestroyedBufferError(pub ResourceErrorIdent);
pub(crate) struct DestroyedTextureError(pub ResourceErrorIdent);
/// The mutable state of a [`CommandBuffer`].
pub struct CommandBufferMutable<A: HalApi> {
/// The [`wgpu_hal::Api::CommandBuffer`]s we've built so far, and the encoder

View File

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

View File

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

View File

@ -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<DeviceError> 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(),

View File

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

View File

@ -323,9 +323,7 @@ fn map_buffer<A: HalApi>(
kind: HostMap,
snatch_guard: &SnatchGuard,
) -> Result<ptr::NonNull<u8>, 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)?

View File

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

View File

@ -1008,9 +1008,7 @@ impl<A: HalApi> Device<A> {
) -> Result<TextureView<A>, 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<A: HalApi> Device<A> {
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) => {

View File

@ -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<A: HalApi> Buffer<A> {
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<A: HalApi> Buffer<A> {
{
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<A: HalApi> Buffer<A> {
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<A: HalApi> Drop for Texture<A> {
}
impl<A: HalApi> Texture<A> {
pub(crate) fn try_inner<'a>(
&'a self,
guard: &'a SnatchGuard,
) -> Result<&'a TextureInner<A>, 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<A: HalApi> TextureView<A> {
#[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:?}`")]

View File

@ -270,7 +270,7 @@ impl PendingTransition<hal::BufferUses> {
buf: &'a resource::Buffer<A>,
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,