// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::ResourceId; use serde::Serialize; use std::convert::From; use std::error::Error; use std::fmt; use std::fmt::Write; use wgpu_core::binding_model::CreateBindGroupError; use wgpu_core::binding_model::CreateBindGroupLayoutError; use wgpu_core::binding_model::CreatePipelineLayoutError; use wgpu_core::binding_model::GetBindGroupLayoutError; use wgpu_core::command::ClearError; use wgpu_core::command::CommandEncoderError; use wgpu_core::command::ComputePassError; use wgpu_core::command::CopyError; use wgpu_core::command::CreateRenderBundleError; use wgpu_core::command::QueryError; use wgpu_core::command::RenderBundleError; use wgpu_core::command::RenderPassError; use wgpu_core::device::queue::QueueSubmitError; use wgpu_core::device::queue::QueueWriteError; use wgpu_core::device::DeviceError; use wgpu_core::pipeline::CreateComputePipelineError; use wgpu_core::pipeline::CreateRenderPipelineError; use wgpu_core::pipeline::CreateShaderModuleError; use wgpu_core::present::ConfigureSurfaceError; use wgpu_core::resource::BufferAccessError; use wgpu_core::resource::CreateBufferError; use wgpu_core::resource::CreateQuerySetError; use wgpu_core::resource::CreateSamplerError; use wgpu_core::resource::CreateTextureError; use wgpu_core::resource::CreateTextureViewError; fn fmt_err(err: &(dyn Error + 'static)) -> String { let mut output = err.to_string(); let mut level = 0; fn print_tree(output: &mut String, level: &mut usize, e: &(dyn Error + 'static)) { let mut print = |e: &(dyn Error + 'static)| { writeln!(output, "{}{}", " ".repeat(*level * 2), e).unwrap(); if let Some(e) = e.source() { *level += 1; print_tree(output, level, e); *level -= 1; } }; if let Some(multi) = e.downcast_ref::() { for e in multi.errors() { print(e); } } else { print(e); } } print_tree(&mut output, &mut level, err); output } #[derive(Serialize)] pub struct WebGpuResult { pub rid: Option, pub err: Option, } impl WebGpuResult { pub fn rid(rid: ResourceId) -> Self { Self { rid: Some(rid), err: None, } } pub fn rid_err>(rid: ResourceId, err: Option) -> Self { Self { rid: Some(rid), err: err.map(Into::into), } } pub fn maybe_err>(err: Option) -> Self { Self { rid: None, err: err.map(Into::into), } } pub fn empty() -> Self { Self { rid: None, err: None, } } } #[derive(Serialize)] #[serde(tag = "type", content = "value")] #[serde(rename_all = "kebab-case")] pub enum WebGpuError { Lost, OutOfMemory, Validation(String), Internal, } impl From for WebGpuError { fn from(err: CreateBufferError) -> Self { match err { CreateBufferError::Device(err) => err.into(), CreateBufferError::AccessError(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: DeviceError) -> Self { match err { DeviceError::Lost => WebGpuError::Lost, DeviceError::OutOfMemory => WebGpuError::OutOfMemory, _ => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: BufferAccessError) -> Self { match err { BufferAccessError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreateBindGroupLayoutError) -> Self { match err { CreateBindGroupLayoutError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreatePipelineLayoutError) -> Self { match err { CreatePipelineLayoutError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreateBindGroupError) -> Self { match err { CreateBindGroupError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: RenderBundleError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CreateRenderBundleError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CopyError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CommandEncoderError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: QueryError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: ComputePassError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CreateComputePipelineError) -> Self { match err { CreateComputePipelineError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: GetBindGroupLayoutError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CreateRenderPipelineError) -> Self { match err { CreateRenderPipelineError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: RenderPassError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CreateSamplerError) -> Self { match err { CreateSamplerError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreateShaderModuleError) -> Self { match err { CreateShaderModuleError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreateTextureError) -> Self { match err { CreateTextureError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreateTextureViewError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CreateQuerySetError) -> Self { match err { CreateQuerySetError::Device(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: QueueSubmitError) -> Self { match err { QueueSubmitError::Queue(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: QueueWriteError) -> Self { match err { QueueWriteError::Queue(err) => err.into(), err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: ClearError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: ConfigureSurfaceError) -> Self { WebGpuError::Validation(fmt_err(&err)) } } #[derive(Debug)] pub struct DomExceptionOperationError { pub msg: String, } impl DomExceptionOperationError { pub fn new(msg: &str) -> Self { DomExceptionOperationError { msg: msg.to_string(), } } } impl fmt::Display for DomExceptionOperationError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.pad(&self.msg) } } impl std::error::Error for DomExceptionOperationError {} pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { e.downcast_ref::() .map(|_| "DOMExceptionOperationError") }