feat(core): impl WebGpuError for API errors

This commit is contained in:
Erich Gubler 2024-11-14 14:50:01 -05:00
parent c8752e5118
commit 964c5bbf4c
24 changed files with 1017 additions and 16 deletions

View File

@ -58,7 +58,7 @@ Bottom level categories:
- Add extra acceleration structure vertex formats. By @Vecvec in [#7580](https://github.com/gfx-rs/wgpu/pull/7580).
- Add acceleration structure limits. By @Vecvec in [#7845](https://github.com/gfx-rs/wgpu/pull/7845).
- Add support for clip-distances feature for Vulkan and GL backends. By @dzamkov in [#7730](https://github.com/gfx-rs/wgpu/pull/7730)
- Added `wgpu_types::error::{ErrorType, WebGpuError}` for classification of errors according to WebGPU's [`GPUError`]'s classification scheme. This allows users of `wgpu-core` to offload error classification onto the WGPU ecosystem, rather than having to do it themselves without sufficient information. By @ErichDonGubler in [#6547](https://github.com/gfx-rs/wgpu/pull/6547).
- Added `wgpu_types::error::{ErrorType, WebGpuError}` for classification of errors according to WebGPU's [`GPUError`]'s classification scheme, and implement `WebGpuError` for existing errors. This allows users of `wgpu-core` to offload error classification onto the WGPU ecosystem, rather than having to do it themselves without sufficient information. By @ErichDonGubler in [#6547](https://github.com/gfx-rs/wgpu/pull/6547).
[`GPUError`]: https://www.w3.org/TR/webgpu/#gpuerror

View File

@ -15,6 +15,8 @@ use serde::Deserialize;
#[cfg(feature = "serde")]
use serde::Serialize;
use wgt::error::{ErrorType, WebGpuError};
use crate::{
device::{
bgl, Device, DeviceError, MissingDownlevelFlags, MissingFeatures, SHADER_STAGE_COUNT,
@ -76,6 +78,22 @@ pub enum CreateBindGroupLayoutError {
InvalidVisibility(wgt::ShaderStages),
}
impl WebGpuError for CreateBindGroupLayoutError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::Device(e) => e.webgpu_error_type(),
Self::ConflictBinding(_)
| Self::Entry { .. }
| Self::TooManyBindings(_)
| Self::InvalidBindingIndex { .. }
| Self::InvalidVisibility(_)
| Self::ContainsBothBindingArrayAndDynamicOffsetArray
| Self::ContainsBothBindingArrayAndUniformBuffer => ErrorType::Validation,
}
}
}
//TODO: refactor this to move out `enum BindingError`.
#[derive(Clone, Debug, Error)]
@ -210,6 +228,48 @@ pub enum CreateBindGroupError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for CreateBindGroupError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::DestroyedResource(e) => e,
Self::MissingBufferUsage(e) => e,
Self::MissingTextureUsage(e) => e,
Self::ResourceUsageCompatibility(e) => e,
Self::InvalidResource(e) => e,
Self::BindingArrayPartialLengthMismatch { .. }
| Self::BindingArrayLengthMismatch { .. }
| Self::BindingArrayZeroLength
| Self::BindingRangeTooLarge { .. }
| Self::BindingSizeTooSmall { .. }
| Self::BindingsNumMismatch { .. }
| Self::BindingZeroSize(_)
| Self::DuplicateBinding(_)
| Self::MissingBindingDeclaration(_)
| Self::SingleBindingExpected
| Self::UnalignedBufferOffset(_, _, _)
| Self::BufferRangeTooLarge { .. }
| Self::WrongBindingType { .. }
| Self::InvalidTextureMultisample { .. }
| Self::InvalidTextureSampleType { .. }
| Self::InvalidTextureDimension { .. }
| Self::InvalidStorageTextureFormat { .. }
| Self::InvalidStorageTextureMipLevelCount { .. }
| Self::WrongSamplerComparison { .. }
| Self::WrongSamplerFiltering { .. }
| Self::DepthStencilAspect
| Self::StorageReadNotSupported(_)
| Self::StorageWriteNotSupported(_)
| Self::StorageReadWriteNotSupported(_)
| Self::StorageAtomicNotSupported(_)
| Self::MissingTLASVertexReturn { .. }
| Self::InvalidExternalTextureMipLevelCount { .. }
| Self::InvalidExternalTextureFormat { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
pub enum BindingZone {
#[error("Stage {0:?}")]
@ -227,6 +287,12 @@ pub struct BindingTypeMaxCountError {
pub count: u32,
}
impl WebGpuError for BindingTypeMaxCountError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug)]
pub enum BindingTypeMaxCountErrorKind {
DynamicUniformBuffers,
@ -691,6 +757,22 @@ pub enum CreatePipelineLayoutError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for CreatePipelineLayoutError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingFeatures(e) => e,
Self::InvalidResource(e) => e,
Self::TooManyBindings(e) => e,
Self::MisalignedPushConstantRange { .. }
| Self::MoreThanOnePushConstantRangePerStage { .. }
| Self::PushConstantRangeTooLarge { .. }
| Self::TooManyGroups { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum PushConstantUploadError {
@ -722,6 +804,12 @@ pub enum PushConstantUploadError {
Unaligned(u32),
}
impl WebGpuError for PushConstantUploadError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
/// Describes a pipeline layout.
///
/// A `PipelineLayoutDescriptor` can be used to create a pipeline layout.
@ -964,6 +1052,12 @@ pub enum BindError {
},
}
impl WebGpuError for BindError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Debug)]
pub struct BindGroupDynamicBindingData {
/// The index of the binding.
@ -1125,6 +1219,15 @@ pub enum GetBindGroupLayoutError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for GetBindGroupLayoutError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::InvalidGroupIndex(_) => ErrorType::Validation,
Self::InvalidResource(e) => e.webgpu_error_type(),
}
}
}
#[derive(Clone, Debug, Error, Eq, PartialEq)]
#[error("Buffer is bound with size {bound_size} where the shader expects {shader_size} in group[{group_index}] compact index {compact_index}")]
pub struct LateMinBufferBindingSizeMismatch {

View File

@ -93,6 +93,8 @@ use core::{
use arrayvec::ArrayVec;
use thiserror::Error;
use wgt::error::{ErrorType, WebGpuError};
use crate::{
binding_model::{BindError, BindGroup, PipelineLayout},
command::{
@ -847,6 +849,15 @@ pub enum CreateRenderBundleError {
InvalidSampleCount(u32),
}
impl WebGpuError for CreateRenderBundleError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::ColorAttachment(e) => e.webgpu_error_type(),
Self::InvalidSampleCount(_) => ErrorType::Validation,
}
}
}
/// Error type returned from `RenderBundleEncoder::new` if the sample count is invalid.
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
@ -1515,6 +1526,21 @@ pub struct RenderBundleError {
inner: RenderBundleErrorInner,
}
impl WebGpuError for RenderBundleError {
fn webgpu_error_type(&self) -> ErrorType {
let Self { scope: _, inner } = self;
let e: &dyn WebGpuError = match inner {
RenderBundleErrorInner::Device(e) => e,
RenderBundleErrorInner::RenderCommand(e) => e,
RenderBundleErrorInner::Draw(e) => e,
RenderBundleErrorInner::MissingDownlevelFlags(e) => e,
RenderBundleErrorInner::Bind(e) => e,
RenderBundleErrorInner::InvalidResource(e) => e,
};
e.webgpu_error_type()
}
}
impl RenderBundleError {
pub fn from_device_error(e: DeviceError) -> Self {
Self {

View File

@ -21,8 +21,9 @@ use crate::{
use thiserror::Error;
use wgt::{
math::align_to, BufferAddress, BufferUsages, ImageSubresourceRange, TextureAspect,
TextureSelector,
error::{ErrorType, WebGpuError},
math::align_to,
BufferAddress, BufferUsages, ImageSubresourceRange, TextureAspect, TextureSelector,
};
/// Error encountered while attempting a clear.
@ -79,6 +80,28 @@ whereas subesource range specified start {subresource_base_array_layer} and coun
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for ClearError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::DestroyedResource(e) => e,
Self::MissingBufferUsage(e) => e,
Self::Device(e) => e,
Self::EncoderState(e) => e,
Self::InvalidResource(e) => e,
Self::NoValidTextureClearMode(..)
| Self::MissingClearTextureFeature
| Self::UnalignedFillSize(..)
| Self::UnalignedBufferOffset(..)
| Self::OffsetPlusSizeExceeds64BitBounds { .. }
| Self::BufferOverrun { .. }
| Self::MissingTextureAspect { .. }
| Self::InvalidTextureLevelRange { .. }
| Self::InvalidTextureLayerRange { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
impl Global {
pub fn command_encoder_clear_buffer(
&self,

View File

@ -1,5 +1,8 @@
use thiserror::Error;
use wgt::{BufferAddress, DynamicOffset};
use wgt::{
error::{ErrorType, WebGpuError},
BufferAddress, DynamicOffset,
};
use alloc::{borrow::Cow, boxed::Box, sync::Arc, vec::Vec};
use core::{fmt, str};
@ -125,6 +128,12 @@ pub enum DispatchError {
BindingSizeTooSmall(#[from] LateMinBufferBindingSizeMismatch),
}
impl WebGpuError for DispatchError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
/// Error encountered when performing a compute pass.
#[derive(Clone, Debug, Error)]
pub enum ComputePassErrorInner {
@ -209,6 +218,39 @@ where
}
}
impl WebGpuError for ComputePassError {
fn webgpu_error_type(&self) -> ErrorType {
let Self { scope: _, inner } = self;
let e: &dyn WebGpuError = match inner {
ComputePassErrorInner::Device(e) => e,
ComputePassErrorInner::EncoderState(e) => e,
ComputePassErrorInner::DestroyedResource(e) => e,
ComputePassErrorInner::ResourceUsageCompatibility(e) => e,
ComputePassErrorInner::MissingBufferUsage(e) => e,
ComputePassErrorInner::Dispatch(e) => e,
ComputePassErrorInner::Bind(e) => e,
ComputePassErrorInner::PushConstants(e) => e,
ComputePassErrorInner::QueryUse(e) => e,
ComputePassErrorInner::MissingFeatures(e) => e,
ComputePassErrorInner::MissingDownlevelFlags(e) => e,
ComputePassErrorInner::InvalidResource(e) => e,
ComputePassErrorInner::TimestampWrites(e) => e,
ComputePassErrorInner::InvalidValuesOffset(e) => e,
ComputePassErrorInner::InvalidPopDebugGroup(e) => e,
ComputePassErrorInner::InvalidParentEncoder
| ComputePassErrorInner::BindGroupIndexOutOfRange { .. }
| ComputePassErrorInner::UnalignedIndirectBufferOffset(_)
| ComputePassErrorInner::IndirectBufferOverrun { .. }
| ComputePassErrorInner::PushConstantOffsetAlignment
| ComputePassErrorInner::PushConstantSizeAlignment
| ComputePassErrorInner::PushConstantOutOfMemory
| ComputePassErrorInner::PassEnded => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
struct State<'scope, 'snatch_guard, 'cmd_buf, 'raw_encoder> {
pipeline: Option<Arc<ComputePipeline>>,

View File

@ -2,6 +2,8 @@ use alloc::boxed::Box;
use thiserror::Error;
use wgt::error::{ErrorType, WebGpuError};
use super::bind::BinderError;
use crate::command::pass;
use crate::{
@ -56,6 +58,12 @@ pub enum DrawError {
BindingSizeTooSmall(#[from] LateMinBufferBindingSizeMismatch),
}
impl WebGpuError for DrawError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
/// Error encountered when encoding a render command.
/// This is the shared error set between render bundles and passes.
#[derive(Clone, Debug, Error)]
@ -93,6 +101,30 @@ pub enum RenderCommandError {
Unimplemented(&'static str),
}
impl WebGpuError for RenderCommandError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::IncompatiblePipelineTargets(e) => e,
Self::ResourceUsageCompatibility(e) => e,
Self::DestroyedResource(e) => e,
Self::MissingBufferUsage(e) => e,
Self::MissingTextureUsage(e) => e,
Self::PushConstants(e) => e,
Self::BindGroupIndexOutOfRange { .. }
| Self::VertexBufferIndexOutOfRange { .. }
| Self::IncompatibleDepthAccess(..)
| Self::IncompatibleStencilAccess(..)
| Self::InvalidViewportRectSize { .. }
| Self::InvalidViewportRectPosition { .. }
| Self::InvalidViewportDepth(..)
| Self::InvalidScissorRect(..)
| Self::Unimplemented(..) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Rect<T> {

View File

@ -47,6 +47,8 @@ use crate::track::{DeviceTracker, ResourceUsageCompatibilityError, Tracker, Usag
use crate::{api_log, global::Global, id, resource_log, Label};
use crate::{hal_label, LabelHelpers};
use wgt::error::{ErrorType, WebGpuError};
use thiserror::Error;
#[cfg(feature = "trace")]
@ -1000,6 +1002,18 @@ pub enum EncoderStateError {
Submitted,
}
impl WebGpuError for EncoderStateError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
EncoderStateError::Invalid
| EncoderStateError::Ended
| EncoderStateError::Locked
| EncoderStateError::Unlocked
| EncoderStateError::Submitted => ErrorType::Validation,
}
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CommandEncoderError {
@ -1050,6 +1064,27 @@ impl CommandEncoderError {
}
}
impl WebGpuError for CommandEncoderError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::MissingFeatures(e) => e,
Self::State(e) => e,
Self::DestroyedResource(e) => e,
Self::Transfer(e) => e,
Self::Clear(e) => e,
Self::Query(e) => e,
Self::BuildAccelerationStructure(e) => e,
Self::TransitionResources(e) => e,
Self::ResourceUsage(e) => e,
Self::ComputePass(e) => e,
Self::RenderPass(e) => e,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum TimestampWritesError {
@ -1061,6 +1096,14 @@ pub enum TimestampWritesError {
IndicesMissing,
}
impl WebGpuError for TimestampWritesError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::IndicesEqual { .. } | Self::IndicesMissing => ErrorType::Validation,
}
}
}
impl Global {
pub fn command_encoder_finish(
&self,
@ -1426,3 +1469,10 @@ pub struct PassStateError {
#[source]
pub(super) inner: EncoderStateError,
}
impl WebGpuError for PassStateError {
fn webgpu_error_type(&self) -> ErrorType {
let Self { scope: _, inner } = self;
inner.webgpu_error_type()
}
}

View File

@ -16,6 +16,7 @@ use alloc::sync::Arc;
use alloc::vec::Vec;
use core::str;
use thiserror::Error;
use wgt::error::{ErrorType, WebGpuError};
use wgt::DynamicOffset;
#[derive(Clone, Debug, Error)]
@ -35,10 +36,22 @@ pub struct MissingPipeline;
#[error("Setting `values_offset` to be `None` is only for internal use in render bundles")]
pub struct InvalidValuesOffset;
impl WebGpuError for InvalidValuesOffset {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[error("Cannot pop debug group, because number of pushed debug groups is zero")]
pub struct InvalidPopDebugGroup;
impl WebGpuError for InvalidPopDebugGroup {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
pub(crate) struct BaseState<'scope, 'snatch_guard, 'cmd_buf, 'raw_encoder> {
pub(crate) device: &'cmd_buf Arc<Device>,

View File

@ -17,7 +17,10 @@ use crate::{
FastHashMap,
};
use thiserror::Error;
use wgt::BufferAddress;
use wgt::{
error::{ErrorType, WebGpuError},
BufferAddress,
};
#[derive(Debug)]
pub(crate) struct QueryResetMap {
@ -109,6 +112,21 @@ pub enum QueryError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for QueryError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::EncoderState(e) => e,
Self::Use(e) => e,
Self::Resolve(e) => e,
Self::InvalidResource(e) => e,
Self::Device(e) => e,
Self::MissingFeature(e) => e,
Self::DestroyedResource(e) => e,
};
e.webgpu_error_type()
}
}
/// Error encountered while trying to use queries
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
@ -136,6 +154,19 @@ pub enum QueryUseError {
},
}
impl WebGpuError for QueryUseError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::Device(e) => e.webgpu_error_type(),
Self::OutOfBounds { .. }
| Self::UsedTwiceInsideRenderpass { .. }
| Self::AlreadyStarted { .. }
| Self::AlreadyStopped
| Self::IncompatibleType { .. } => ErrorType::Validation,
}
}
}
/// Error encountered while trying to resolve a query.
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
@ -161,6 +192,17 @@ pub enum ResolveError {
},
}
impl WebGpuError for ResolveError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::MissingBufferUsage(e) => e.webgpu_error_type(),
Self::BufferOffsetAlignment
| Self::QueryOverrun { .. }
| Self::BufferOverrun { .. } => ErrorType::Validation,
}
}
}
impl QuerySet {
pub(crate) fn validate_query(
self: &Arc<Self>,

View File

@ -4,6 +4,7 @@ use core::{fmt, num::NonZeroU32, ops::Range, str};
use arrayvec::ArrayVec;
use thiserror::Error;
use wgt::{
error::{ErrorType, WebGpuError},
BufferAddress, BufferSize, BufferUsages, Color, DynamicOffset, IndexFormat, ShaderStages,
TextureSelector, TextureUsages, TextureViewDimension, VertexStepMode,
};
@ -620,6 +621,12 @@ pub enum ColorAttachmentError {
},
}
impl WebGpuError for ColorAttachmentError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum AttachmentError {
@ -639,6 +646,12 @@ pub enum AttachmentError {
ClearValueOutOfRange(f32),
}
impl WebGpuError for AttachmentError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
/// Error encountered when performing a render pass.
#[derive(Clone, Debug, Error)]
pub enum RenderPassErrorInner {
@ -816,6 +829,54 @@ impl<E: Into<RenderPassErrorInner>> MapPassErr<RenderPassError> for E {
}
}
impl WebGpuError for RenderPassError {
fn webgpu_error_type(&self) -> ErrorType {
let Self { scope: _, inner } = self;
let e: &dyn WebGpuError = match inner {
RenderPassErrorInner::Device(e) => e,
RenderPassErrorInner::ColorAttachment(e) => e,
RenderPassErrorInner::EncoderState(e) => e,
RenderPassErrorInner::MissingFeatures(e) => e,
RenderPassErrorInner::MissingDownlevelFlags(e) => e,
RenderPassErrorInner::RenderCommand(e) => e,
RenderPassErrorInner::Draw(e) => e,
RenderPassErrorInner::Bind(e) => e,
RenderPassErrorInner::QueryUse(e) => e,
RenderPassErrorInner::DestroyedResource(e) => e,
RenderPassErrorInner::InvalidResource(e) => e,
RenderPassErrorInner::IncompatibleBundleTargets(e) => e,
RenderPassErrorInner::InvalidAttachment(e) => e,
RenderPassErrorInner::TimestampWrites(e) => e,
RenderPassErrorInner::InvalidValuesOffset(e) => e,
RenderPassErrorInner::InvalidPopDebugGroup(e) => e,
RenderPassErrorInner::InvalidParentEncoder
| RenderPassErrorInner::UnsupportedResolveTargetFormat { .. }
| RenderPassErrorInner::MissingAttachments
| RenderPassErrorInner::TextureViewIsNotRenderable { .. }
| RenderPassErrorInner::AttachmentsDimensionMismatch { .. }
| RenderPassErrorInner::AttachmentSampleCountMismatch { .. }
| RenderPassErrorInner::InvalidResolveSampleCounts { .. }
| RenderPassErrorInner::MismatchedResolveTextureFormat { .. }
| RenderPassErrorInner::InvalidDepthOps
| RenderPassErrorInner::InvalidStencilOps
| RenderPassErrorInner::UnalignedIndirectBufferOffset(..)
| RenderPassErrorInner::IndirectBufferOverrun { .. }
| RenderPassErrorInner::IndirectCountBufferOverrun { .. }
| RenderPassErrorInner::ResourceUsageCompatibility(..)
| RenderPassErrorInner::IncompatibleBundleReadOnlyDepthStencil { .. }
| RenderPassErrorInner::PushConstantOffsetAlignment
| RenderPassErrorInner::PushConstantSizeAlignment
| RenderPassErrorInner::PushConstantOutOfMemory
| RenderPassErrorInner::MultiViewMismatch
| RenderPassErrorInner::MultiViewDimensionMismatch
| RenderPassErrorInner::MissingOcclusionQuerySet
| RenderPassErrorInner::PassEnded => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
struct RenderAttachment {
texture: Arc<Texture>,
selector: TextureSelector,

View File

@ -2,7 +2,10 @@ use alloc::{sync::Arc, vec::Vec};
use arrayvec::ArrayVec;
use thiserror::Error;
use wgt::{BufferAddress, BufferUsages, Extent3d, TextureSelector, TextureUsages};
use wgt::{
error::{ErrorType, WebGpuError},
BufferAddress, BufferUsages, Extent3d, TextureSelector, TextureUsages,
};
#[cfg(feature = "trace")]
use crate::device::trace::Command as TraceCommand;
@ -138,6 +141,46 @@ pub enum TransferError {
InvalidMipLevel { requested: u32, count: u32 },
}
impl WebGpuError for TransferError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::MissingBufferUsage(e) => e,
Self::MissingTextureUsage(e) => e,
Self::MemoryInitFailure(e) => e,
Self::BufferOverrun { .. }
| Self::TextureOverrun { .. }
| Self::InvalidTextureAspect { .. }
| Self::InvalidTextureMipLevel { .. }
| Self::InvalidDimensionExternal
| Self::UnalignedBufferOffset(..)
| Self::UnalignedCopySize(..)
| Self::UnalignedCopyWidth
| Self::UnalignedCopyHeight
| Self::UnalignedCopyOriginX
| Self::UnalignedCopyOriginY
| Self::UnalignedBytesPerRow
| Self::UnspecifiedBytesPerRow
| Self::UnspecifiedRowsPerImage
| Self::InvalidBytesPerRow
| Self::InvalidRowsPerImage
| Self::CopySrcMissingAspects
| Self::CopyDstMissingAspects
| Self::CopyAspectNotOne
| Self::CopyFromForbiddenTextureFormat { .. }
| Self::CopyToForbiddenTextureFormat { .. }
| Self::ExternalCopyToForbiddenTextureFormat(..)
| Self::TextureFormatsNotCopyCompatible { .. }
| Self::MissingDownlevelFlags(..)
| Self::InvalidSampleCount { .. }
| Self::SampleCountNotEqual { .. }
| Self::InvalidMipLevel { .. }
| Self::SameSourceDestinationBuffer => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
pub(crate) fn extract_texture_selector<T>(
copy_texture: &wgt::TexelCopyTextureInfo<T>,
copy_size: &Extent3d,

View File

@ -1,4 +1,5 @@
use thiserror::Error;
use wgt::error::{ErrorType, WebGpuError};
use crate::{
command::{CommandBuffer, CommandEncoderError, EncoderStateError},
@ -86,3 +87,15 @@ pub enum TransitionResourcesError {
#[error(transparent)]
ResourceUsage(#[from] ResourceUsageCompatibilityError),
}
impl WebGpuError for TransitionResourcesError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::EncoderState(e) => e,
Self::InvalidResource(e) => e,
Self::ResourceUsage(e) => e,
};
e.webgpu_error_type()
}
}

View File

@ -17,7 +17,10 @@ use crate::{
use arrayvec::ArrayVec;
use smallvec::SmallVec;
use thiserror::Error;
use wgt::{BufferAddress, DeviceLostReason, TextureFormat};
use wgt::{
error::{ErrorType, WebGpuError},
BufferAddress, DeviceLostReason, TextureFormat,
};
pub(crate) mod bgl;
pub mod global;
@ -102,6 +105,12 @@ pub enum RenderPassCompatibilityError {
},
}
impl WebGpuError for RenderPassCompatibilityError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
impl RenderPassContext {
// Assumes the renderpass only contains one subpass
pub(crate) fn check_compatible<T: Labeled>(
@ -313,6 +322,12 @@ impl fmt::Display for DeviceMismatch {
impl core::error::Error for DeviceMismatch {}
impl WebGpuError for DeviceMismatch {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
@ -329,6 +344,20 @@ pub enum DeviceError {
DeviceMismatch(#[from] Box<DeviceMismatch>),
}
impl WebGpuError for DeviceError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
DeviceError::DeviceMismatch(e) => e.webgpu_error_type(),
Self::Invalid(_) => ErrorType::Validation,
Self::ResourceCreationFailed => ErrorType::OutOfMemory,
Self::Lost => ErrorType::DeviceLost {
reason: DeviceLostReason::Unknown,
},
Self::OutOfMemory => ErrorType::OutOfMemory,
}
}
}
impl DeviceError {
/// Only use this function in contexts where there is no `Device`.
///
@ -347,12 +376,24 @@ impl DeviceError {
#[error("Features {0:?} are required but not enabled on the device")]
pub struct MissingFeatures(pub wgt::Features);
impl WebGpuError for MissingFeatures {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[error(
"Downlevel flags {0:?} are required but not supported on the device.\n{DOWNLEVEL_ERROR_MESSAGE}",
)]
pub struct MissingDownlevelFlags(pub wgt::DownlevelFlags);
impl WebGpuError for MissingDownlevelFlags {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ImplicitPipelineContext {

View File

@ -8,7 +8,10 @@ use core::{
};
use smallvec::SmallVec;
use thiserror::Error;
use wgt::AccelerationStructureFlags;
use wgt::{
error::{ErrorType, WebGpuError},
AccelerationStructureFlags,
};
use super::{life::LifetimeTracker, Device};
use crate::device::resource::CommandIndices;
@ -455,6 +458,19 @@ pub enum QueueWriteError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for QueueWriteError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Queue(e) => e,
Self::Transfer(e) => e,
Self::MemoryInitFailure(e) => e,
Self::DestroyedResource(e) => e,
Self::InvalidResource(e) => e,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum QueueSubmitError {
@ -474,6 +490,22 @@ pub enum QueueSubmitError {
ValidateAsActionsError(#[from] crate::ray_tracing::ValidateAsActionsError),
}
impl WebGpuError for QueueSubmitError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Queue(e) => e,
Self::Unmap(e) => e,
Self::CommandEncoder(e) => e,
Self::ValidateAsActionsError(e) => e,
Self::InvalidResource(e) => e,
Self::DestroyedResource(_) | Self::BufferStillMapped(_) => {
return ErrorType::Validation
}
};
e.webgpu_error_type()
}
}
//TODO: move out common parts of write_xxx.
impl Queue {

View File

@ -9,6 +9,7 @@ use alloc::{
use hashbrown::HashMap;
use thiserror::Error;
use wgt::error::{ErrorType, WebGpuError};
use crate::{
api_log, api_log_debug,
@ -37,6 +38,12 @@ pub struct FailedLimit {
allowed: u64,
}
impl WebGpuError for FailedLimit {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
fn check_limits(requested: &wgt::Limits, allowed: &wgt::Limits) -> Vec<FailedLimit> {
let mut failed = Vec::new();
@ -861,6 +868,18 @@ pub enum RequestDeviceError {
UnsupportedFeature(wgt::Features),
}
impl WebGpuError for RequestDeviceError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::LimitsExceeded(e) => e,
Self::TimestampNormalizerInitFailed(e) => e,
Self::UnsupportedFeature(_) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CreateSurfaceError {

View File

@ -10,6 +10,7 @@ use core::{marker::PhantomData, mem::ManuallyDrop, num::NonZeroU32};
use arrayvec::ArrayVec;
use naga::error::ShaderError;
use thiserror::Error;
use wgt::error::{ErrorType, WebGpuError};
pub use crate::pipeline_cache::PipelineCacheValidationError;
use crate::{
@ -131,6 +132,26 @@ pub enum CreateShaderModuleError {
},
}
impl WebGpuError for CreateShaderModuleError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingFeatures(e) => e,
Self::Generation => return ErrorType::Internal,
Self::Validation(..) | Self::InvalidGroupIndex { .. } => return ErrorType::Validation,
#[cfg(feature = "wgsl")]
Self::Parsing(..) => return ErrorType::Validation,
#[cfg(feature = "glsl")]
Self::ParsingGlsl(..) => return ErrorType::Validation,
#[cfg(feature = "spirv")]
Self::ParsingSpirV(..) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
/// Describes a programmable pipeline stage.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -181,6 +202,19 @@ pub enum ImplicitLayoutError {
Pipeline(#[from] CreatePipelineLayoutError),
}
impl WebGpuError for ImplicitLayoutError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::MissingImplicitPipelineIds | Self::MissingIds(_) | Self::ReflectionError(_) => {
return ErrorType::Validation
}
Self::BindGroup(e) => e,
Self::Pipeline(e) => e,
};
e.webgpu_error_type()
}
}
/// Describes a compute pipeline.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -222,6 +256,21 @@ pub enum CreateComputePipelineError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for CreateComputePipelineError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::MissingDownlevelFlags(e) => e,
Self::Implicit(e) => e,
Self::Stage(e) => e,
Self::Internal(_) => return ErrorType::Internal,
Self::PipelineConstants(_) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Debug)]
pub struct ComputePipeline {
pub(crate) raw: ManuallyDrop<Box<dyn hal::DynComputePipeline>>,
@ -268,6 +317,17 @@ pub enum CreatePipelineCacheError {
MissingFeatures(#[from] MissingFeatures),
}
impl WebGpuError for CreatePipelineCacheError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::Validation(e) => e,
Self::MissingFeatures(e) => e,
};
e.webgpu_error_type()
}
}
#[derive(Debug)]
pub struct PipelineCache {
pub(crate) raw: ManuallyDrop<Box<dyn hal::DynPipelineCache>>,
@ -500,6 +560,42 @@ pub enum CreateRenderPipelineError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for CreateRenderPipelineError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::MissingFeatures(e) => e,
Self::MissingDownlevelFlags(e) => e,
Self::Internal { .. } => return ErrorType::Internal,
Self::ColorAttachment(_)
| Self::Implicit(_)
| Self::ColorState(_, _)
| Self::DepthStencilState(_)
| Self::InvalidSampleCount(_)
| Self::TooManyVertexBuffers { .. }
| Self::TooManyVertexAttributes { .. }
| Self::VertexStrideTooLarge { .. }
| Self::UnalignedVertexStride { .. }
| Self::InvalidVertexAttributeOffset { .. }
| Self::ShaderLocationClash(_)
| Self::StripIndexFormatForNonStripTopology { .. }
| Self::ConservativeRasterizationNonFillPolygonMode
| Self::Stage { .. }
| Self::UnalignedShader { .. }
| Self::BlendFactorOnUnsupportedTarget { .. }
| Self::PipelineExpectsShaderToUseDualSourceBlending
| Self::ShaderExpectsPipelineToUseDualSourceBlending
| Self::NoTargetSpecified
| Self::PipelineConstants { .. }
| Self::VertexAttributeStrideTooLarge { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
bitflags::bitflags! {
#[repr(transparent)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]

View File

@ -1,5 +1,8 @@
use thiserror::Error;
use wgt::AdapterInfo;
use wgt::{
error::{ErrorType, WebGpuError},
AdapterInfo,
};
pub const HEADER_LENGTH: usize = size_of::<PipelineCacheHeader>();
@ -37,6 +40,12 @@ impl PipelineCacheValidationError {
}
}
impl WebGpuError for PipelineCacheValidationError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
/// Validate the data in a pipeline cache
pub fn validate_pipeline_cache<'d>(
cache_data: &'d [u8],

View File

@ -24,7 +24,10 @@ use crate::{
};
use thiserror::Error;
use wgt::SurfaceStatus as Status;
use wgt::{
error::{ErrorType, WebGpuError},
SurfaceStatus as Status,
};
const FRAME_TIMEOUT_MS: u32 = 1000;
@ -50,6 +53,19 @@ pub enum SurfaceError {
TextureDestroyed,
}
impl WebGpuError for SurfaceError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::Invalid
| Self::NotConfigured
| Self::AlreadyAcquired
| Self::TextureDestroyed => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum ConfigureSurfaceError {
@ -107,6 +123,27 @@ impl From<WaitIdleError> for ConfigureSurfaceError {
}
}
impl WebGpuError for ConfigureSurfaceError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingDownlevelFlags(e) => e,
Self::InvalidSurface
| Self::InvalidViewFormat(..)
| Self::PreviousOutputExists
| Self::GpuWaitTimeout
| Self::ZeroArea
| Self::TooLarge { .. }
| Self::UnsupportedQueueFamily
| Self::UnsupportedFormat { .. }
| Self::UnsupportedPresentMode { .. }
| Self::UnsupportedAlphaMode { .. }
| Self::UnsupportedUsage { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
pub type ResolvedSurfaceOutput = SurfaceOutput<Arc<resource::Texture>>;
#[repr(C)]

View File

@ -11,7 +11,10 @@
use alloc::{boxed::Box, sync::Arc, vec::Vec};
use thiserror::Error;
use wgt::{AccelerationStructureGeometryFlags, BufferAddress, IndexFormat, VertexFormat};
use wgt::{
error::{ErrorType, WebGpuError},
AccelerationStructureGeometryFlags, BufferAddress, IndexFormat, VertexFormat,
};
use crate::{
command::EncoderStateError,
@ -43,6 +46,20 @@ pub enum CreateBlasError {
TooManyPrimitives(u32, u32),
}
impl WebGpuError for CreateBlasError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingFeatures(e) => e,
Self::MissingIndexData
| Self::InvalidVertexFormat(..)
| Self::TooManyGeometries(..)
| Self::TooManyPrimitives(..) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
pub enum CreateTlasError {
#[error(transparent)]
@ -55,6 +72,17 @@ pub enum CreateTlasError {
TooManyInstances(u32, u32),
}
impl WebGpuError for CreateTlasError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingFeatures(e) => e,
Self::DisallowedFlag(..) | Self::TooManyInstances(..) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
/// Error encountered while attempting to do a copy on a command encoder.
#[derive(Clone, Debug, Error)]
pub enum BuildAccelerationStructureError {
@ -153,6 +181,41 @@ pub enum BuildAccelerationStructureError {
TlasDependentMissingVertexReturn(ResourceErrorIdent, ResourceErrorIdent),
}
impl WebGpuError for BuildAccelerationStructureError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::EncoderState(e) => e,
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::DestroyedResource(e) => e,
Self::MissingBufferUsage(e) => e,
Self::MissingFeatures(e) => e,
Self::InsufficientBufferSize(..)
| Self::UnalignedIndexBufferOffset(..)
| Self::UnalignedTransformBufferOffset(..)
| Self::InvalidIndexCount(..)
| Self::MissingAssociatedData(..)
| Self::IncompatibleBlasBuildSizes(..)
| Self::IncompatibleBlasFlags(..)
| Self::IncompatibleBlasVertexCount(..)
| Self::DifferentBlasVertexFormats(..)
| Self::VertexStrideTooSmall(..)
| Self::VertexStrideUnaligned(..)
| Self::BlasIndexCountProvidedMismatch(..)
| Self::IncompatibleBlasIndexCount(..)
| Self::DifferentBlasIndexFormats(..)
| Self::CompactedBlas(..)
| Self::MissingIndexBuffer(..)
| Self::TlasInvalidCustomIndex(..)
| Self::TlasInstanceCountExceeded(..)
| Self::TransformMissing(..)
| Self::UseTransformMissing(..)
| Self::TlasDependentMissingVertexReturn(..) => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
pub enum ValidateAsActionsError {
#[error(transparent)]
@ -168,6 +231,18 @@ pub enum ValidateAsActionsError {
BlasNewerThenTlas(ResourceErrorIdent, ResourceErrorIdent),
}
impl WebGpuError for ValidateAsActionsError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::DestroyedResource(e) => e,
Self::UsedUnbuiltTlas(..) | Self::UsedUnbuiltBlas(..) | Self::BlasNewerThenTlas(..) => {
return ErrorType::Validation
}
};
e.webgpu_error_type()
}
}
#[derive(Debug)]
pub struct BlasTriangleGeometry<'a> {
pub size: &'a wgt::BlasTriangleGeometrySizeDescriptor,
@ -288,6 +363,20 @@ pub enum BlasPrepareCompactError {
CompactionUnsupported,
}
impl WebGpuError for BlasPrepareCompactError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::CompactionPreparingAlready
| Self::DoubleCompaction
| Self::NotBuilt
| Self::CompactionUnsupported => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
pub enum CompactBlasError {
#[error(transparent)]
@ -309,4 +398,18 @@ pub enum CompactBlasError {
BlasNotReady,
}
impl WebGpuError for CompactBlasError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Encoder(e) => e,
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::DestroyedResource(e) => e,
Self::MissingFeatures(e) => e,
Self::BlasNotReady => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
pub type BlasCompactReadyPendingClosure = (Option<BlasCompactCallback>, BlasPrepareCompactResult);

View File

@ -9,7 +9,10 @@ use core::{
};
use smallvec::SmallVec;
use thiserror::Error;
use wgt::TextureSelector;
use wgt::{
error::{ErrorType, WebGpuError},
TextureSelector,
};
#[cfg(feature = "trace")]
use crate::device::trace;
@ -284,6 +287,30 @@ pub enum BufferAccessError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for BufferAccessError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::InvalidResource(e) => e,
Self::DestroyedResource(e) => e,
Self::Failed
| Self::AlreadyMapped
| Self::MapAlreadyPending
| Self::MissingBufferUsage(_)
| Self::NotMapped
| Self::UnalignedRange
| Self::UnalignedOffset { .. }
| Self::UnalignedRangeSize { .. }
| Self::OutOfBoundsUnderrun { .. }
| Self::OutOfBoundsOverrun { .. }
| Self::NegativeRange { .. }
| Self::MapAborted => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[error("Usage flags {actual:?} of {res} do not contain required usage flags {expected:?}")]
@ -293,6 +320,12 @@ pub struct MissingBufferUsageError {
pub(crate) expected: wgt::BufferUsages,
}
impl WebGpuError for MissingBufferUsageError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[error("Usage flags {actual:?} of {res} do not contain required usage flags {expected:?}")]
pub struct MissingTextureUsageError {
@ -301,16 +334,34 @@ pub struct MissingTextureUsageError {
pub(crate) expected: wgt::TextureUsages,
}
impl WebGpuError for MissingTextureUsageError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[error("{0} has been destroyed")]
pub struct DestroyedResourceError(pub ResourceErrorIdent);
impl WebGpuError for DestroyedResourceError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[error("{0} is invalid")]
pub struct InvalidResourceError(pub ResourceErrorIdent);
impl WebGpuError for InvalidResourceError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
pub enum Fallible<T: ParentDevice> {
Valid(Arc<T>),
Invalid(Arc<String>),
@ -785,6 +836,23 @@ crate::impl_parent_device!(Buffer);
crate::impl_storage_item!(Buffer);
crate::impl_trackable!(Buffer);
impl WebGpuError for CreateBufferError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::AccessError(e) => e,
Self::MissingDownlevelFlags(e) => e,
Self::IndirectValidationBindGroup(e) => e,
Self::UnalignedSize
| Self::InvalidUsage(_)
| Self::UsageMismatch(_)
| Self::MaxBufferSize { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
/// A buffer that has been marked as destroyed and is staged for actual deletion soon.
#[derive(Debug)]
pub struct DestroyedBuffer {
@ -1559,6 +1627,12 @@ pub enum TextureDimensionError {
MultisampledDepthOrArrayLayer(u32),
}
impl WebGpuError for TextureDimensionError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CreateTextureError {
@ -1613,6 +1687,31 @@ impl Borrow<TextureSelector> for Texture {
}
}
impl WebGpuError for CreateTextureError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::CreateTextureView(e) => e,
Self::InvalidDimension(e) => e,
Self::MissingFeatures(_, e) => e,
Self::MissingDownlevelFlags(e) => e,
Self::InvalidUsage(_)
| Self::InvalidDepthDimension(_, _)
| Self::InvalidCompressedDimension(_, _)
| Self::InvalidMipLevelCount { .. }
| Self::InvalidFormatUsages(_, _, _)
| Self::InvalidViewFormat(_, _)
| Self::InvalidDimensionUsages(_, _)
| Self::InvalidMultisampledStorageBinding
| Self::InvalidMultisampledFormat(_)
| Self::InvalidSampleCount(..)
| Self::MultisampledNotRenderAttachment => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
/// Describes a [`TextureView`].
#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -1795,6 +1894,33 @@ pub enum CreateTextureViewError {
MissingFeatures(#[from] MissingFeatures),
}
impl WebGpuError for CreateTextureViewError {
fn webgpu_error_type(&self) -> ErrorType {
match self {
Self::Device(e) => e.webgpu_error_type(),
Self::InvalidTextureViewDimension { .. }
| Self::InvalidResource(_)
| Self::InvalidMultisampledTextureViewDimension(_)
| Self::InvalidCubemapTextureDepth { .. }
| Self::InvalidCubemapArrayTextureDepth { .. }
| Self::InvalidCubeTextureViewSize
| Self::ZeroMipLevelCount
| Self::ZeroArrayLayerCount
| Self::TooManyMipLevels { .. }
| Self::TooManyArrayLayers { .. }
| Self::InvalidArrayLayerCount { .. }
| Self::InvalidAspect { .. }
| Self::FormatReinterpretation { .. }
| Self::DestroyedResource(_)
| Self::TextureViewFormatNotRenderable(_)
| Self::TextureViewFormatNotStorage(_)
| Self::InvalidTextureViewUsage { .. }
| Self::MissingFeatures(_) => ErrorType::Validation,
}
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum TextureViewDestroyError {}
@ -1911,6 +2037,21 @@ crate::impl_parent_device!(Sampler);
crate::impl_storage_item!(Sampler);
crate::impl_trackable!(Sampler);
impl WebGpuError for CreateSamplerError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingFeatures(e) => e,
Self::InvalidLodMinClamp(_)
| Self::InvalidLodMaxClamp { .. }
| Self::InvalidAnisotropy(_)
| Self::InvalidFilterModeWithAnisotropy { .. } => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CreateQuerySetError {
@ -1924,6 +2065,18 @@ pub enum CreateQuerySetError {
MissingFeatures(#[from] MissingFeatures),
}
impl WebGpuError for CreateQuerySetError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Device(e) => e,
Self::MissingFeatures(e) => e,
Self::TooManyQueries { .. } | Self::ZeroCount => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
#[derive(Debug)]

View File

@ -125,7 +125,10 @@ pub(crate) use texture::{
DeviceTextureTracker, TextureTracker, TextureTrackerSetSingle, TextureUsageScope,
TextureViewBindGroupState,
};
use wgt::strict_assert_ne;
use wgt::{
error::{ErrorType, WebGpuError},
strict_assert_ne,
};
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@ -358,6 +361,12 @@ pub enum ResourceUsageCompatibilityError {
},
}
impl WebGpuError for ResourceUsageCompatibilityError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
impl ResourceUsageCompatibilityError {
fn from_buffer(
buffer: &resource::Buffer,

View File

@ -8,7 +8,10 @@ use core::fmt;
use arrayvec::ArrayVec;
use hashbrown::hash_map::Entry;
use thiserror::Error;
use wgt::{BindGroupLayoutEntry, BindingType};
use wgt::{
error::{ErrorType, WebGpuError},
BindGroupLayoutEntry, BindingType,
};
use crate::{device::bgl, resource::InvalidResourceError, FastHashMap, FastHashSet};
@ -221,6 +224,12 @@ pub enum BindingError {
BadStorageFormat(wgt::TextureFormat),
}
impl WebGpuError for BindingError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum FilteringError {
@ -230,6 +239,12 @@ pub enum FilteringError {
Float,
}
impl WebGpuError for FilteringError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum InputError {
@ -243,6 +258,12 @@ pub enum InputError {
SamplingMismatch(Option<naga::Sampling>),
}
impl WebGpuError for InputError {
fn webgpu_error_type(&self) -> ErrorType {
ErrorType::Validation
}
}
/// Errors produced when validating a programmable stage of a pipeline.
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
@ -290,6 +311,31 @@ pub enum StageError {
InvalidResource(#[from] InvalidResourceError),
}
impl WebGpuError for StageError {
fn webgpu_error_type(&self) -> ErrorType {
let e: &dyn WebGpuError = match self {
Self::Binding(_, e) => e,
Self::InvalidResource(e) => e,
Self::Filtering {
texture: _,
sampler: _,
error,
} => error,
Self::Input {
location: _,
var: _,
error,
} => error,
Self::InvalidWorkgroupSize { .. }
| Self::TooManyVaryings { .. }
| Self::MissingEntryPoint(..)
| Self::NoEntryPointFound
| Self::MultipleEntryPointsFound => return ErrorType::Validation,
};
e.webgpu_error_type()
}
}
pub fn map_storage_format_to_naga(format: wgt::TextureFormat) -> Option<naga::StorageFormat> {
use naga::StorageFormat as Sf;
use wgt::TextureFormat as Tf;

View File

@ -449,6 +449,12 @@ impl fmt::Display for RequestAdapterError {
}
}
impl error::WebGpuError for RequestAdapterError {
fn webgpu_error_type(&self) -> error::ErrorType {
error::ErrorType::Validation
}
}
/// Represents the sets of limits an adapter/device supports.
///
/// We provide three different defaults.
@ -7743,9 +7749,10 @@ mod send_sync {
impl<T> WasmNotSync for T {}
}
/// Reason for "lose the device".
/// Corresponds to a [`GPUDeviceLostReason`]; usually seen by implementers of WebGPU with
/// [`error::ErrorType::DeviceLost::reason`].
///
/// Corresponds to [WebGPU `GPUDeviceLostReason`](https://gpuweb.github.io/gpuweb/#enumdef-gpudevicelostreason).
/// [`GPUDeviceLostReason`]: https://www.w3.org/TR/webgpu/#enumdef-gpudevicelostreason
#[repr(u8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]

View File

@ -361,6 +361,7 @@ impl ContextWgpuCore {
source: source_error,
};
}
ErrorType::DeviceLost { reason: _ } => return,
};
sink.handle_error(error);
}