refactor(ext/webgpu): use concrete error type (#26198)

This commit is contained in:
Leo Kettmeir 2024-10-18 18:53:04 -07:00 committed by GitHub
parent 6c4ef11f04
commit 615e6b7cc2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 351 additions and 177 deletions

1
Cargo.lock generated
View File

@ -2197,6 +2197,7 @@ dependencies = [
"deno_core",
"raw-window-handle",
"serde",
"thiserror",
"tokio",
"wgpu-core",
"wgpu-types",

View File

@ -25,6 +25,7 @@ serde = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["full"] }
wgpu-types = { workspace = true, features = ["serde"] }
raw-window-handle = { workspace = true }
thiserror.workspace = true
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgpu-core]
workspace = true

View File

@ -1,7 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -13,9 +11,18 @@ use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
use super::error::DomExceptionOperationError;
use super::error::WebGpuResult;
#[derive(Debug, thiserror::Error)]
pub enum BufferError {
#[error(transparent)]
Resource(deno_core::error::AnyError),
#[error("usage is not valid")]
InvalidUsage,
#[error(transparent)]
Access(wgpu_core::resource::BufferAccessError),
}
pub(crate) struct WebGpuBuffer(
pub(crate) super::Instance,
pub(crate) wgpu_core::id::BufferId,
@ -46,18 +53,19 @@ pub fn op_webgpu_create_buffer(
#[number] size: u64,
usage: u32,
mapped_at_creation: bool,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, BufferError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(device_rid)?;
.get::<super::WebGpuDevice>(device_rid)
.map_err(BufferError::Resource)?;
let device = device_resource.1;
let descriptor = wgpu_core::resource::BufferDescriptor {
label: Some(label),
size,
usage: wgpu_types::BufferUsages::from_bits(usage)
.ok_or_else(|| type_error("usage is not valid"))?,
.ok_or(BufferError::InvalidUsage)?,
mapped_at_creation,
};
@ -77,18 +85,21 @@ pub async fn op_webgpu_buffer_get_map_async(
mode: u32,
#[number] offset: u64,
#[number] size: u64,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, BufferError> {
let device;
let done = Arc::new(Mutex::new(None));
{
let state_ = state.borrow();
let instance = state_.borrow::<super::Instance>();
let buffer_resource =
state_.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
let buffer_resource = state_
.resource_table
.get::<WebGpuBuffer>(buffer_rid)
.map_err(BufferError::Resource)?;
let buffer = buffer_resource.1;
let device_resource = state_
.resource_table
.get::<super::WebGpuDevice>(device_rid)?;
.get::<super::WebGpuDevice>(device_rid)
.map_err(BufferError::Resource)?;
device = device_resource.1;
let done_ = done.clone();
@ -120,9 +131,7 @@ pub async fn op_webgpu_buffer_get_map_async(
let result = done.lock().unwrap().take();
match result {
Some(Ok(())) => return Ok(WebGpuResult::empty()),
Some(Err(e)) => {
return Err(DomExceptionOperationError::new(&e.to_string()).into())
}
Some(Err(e)) => return Err(BufferError::Access(e)),
None => {
{
let state = state.borrow();
@ -143,9 +152,12 @@ pub fn op_webgpu_buffer_get_mapped_range(
#[number] offset: u64,
#[number] size: Option<u64>,
#[buffer] buf: &mut [u8],
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, BufferError> {
let instance = state.borrow::<super::Instance>();
let buffer_resource = state.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
let buffer_resource = state
.resource_table
.get::<WebGpuBuffer>(buffer_rid)
.map_err(BufferError::Resource)?;
let buffer = buffer_resource.1;
let (slice_pointer, range_size) =
@ -154,7 +166,7 @@ pub fn op_webgpu_buffer_get_mapped_range(
offset,
size
))
.map_err(|e| DomExceptionOperationError::new(&e.to_string()))?;
.map_err(BufferError::Access)?;
// SAFETY: guarantee to be safe from wgpu
let slice = unsafe {
@ -176,12 +188,16 @@ pub fn op_webgpu_buffer_unmap(
#[smi] buffer_rid: ResourceId,
#[smi] mapped_rid: ResourceId,
#[buffer] buf: Option<&[u8]>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, BufferError> {
let mapped_resource = state
.resource_table
.take::<WebGpuBufferMapped>(mapped_rid)?;
.take::<WebGpuBufferMapped>(mapped_rid)
.map_err(BufferError::Resource)?;
let instance = state.borrow::<super::Instance>();
let buffer_resource = state.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
let buffer_resource = state
.resource_table
.get::<WebGpuBuffer>(buffer_rid)
.map_err(BufferError::Resource)?;
let buffer = buffer_resource.1;
if let Some(buf) = buf {

View File

@ -1,7 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -13,6 +11,14 @@ use std::rc::Rc;
use super::error::WebGpuResult;
#[derive(Debug, thiserror::Error)]
pub enum BundleError {
#[error(transparent)]
Resource(deno_core::error::AnyError),
#[error("size must be larger than 0")]
InvalidSize,
}
struct WebGpuRenderBundleEncoder(
RefCell<wgpu_core::command::RenderBundleEncoder>,
);
@ -53,7 +59,7 @@ pub struct CreateRenderBundleEncoderArgs {
pub fn op_webgpu_create_render_bundle_encoder(
state: &mut OpState,
#[serde] args: CreateRenderBundleEncoderArgs,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(args.device_rid)?;
@ -100,7 +106,7 @@ pub fn op_webgpu_render_bundle_encoder_finish(
state: &mut OpState,
#[smi] render_bundle_encoder_rid: ResourceId,
#[string] label: Cow<str>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_bundle_encoder_resource =
state
.resource_table
@ -131,7 +137,7 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group(
#[buffer] dynamic_offsets_data: &[u32],
#[number] dynamic_offsets_data_start: usize,
#[number] dynamic_offsets_data_length: usize,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let bind_group_resource =
state
.resource_table
@ -171,7 +177,7 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group(
state: &mut OpState,
#[smi] render_bundle_encoder_rid: ResourceId,
#[string] group_label: &str,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_bundle_encoder_resource =
state
.resource_table
@ -195,7 +201,7 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group(
pub fn op_webgpu_render_bundle_encoder_pop_debug_group(
state: &mut OpState,
#[smi] render_bundle_encoder_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_bundle_encoder_resource =
state
.resource_table
@ -214,7 +220,7 @@ pub fn op_webgpu_render_bundle_encoder_insert_debug_marker(
state: &mut OpState,
#[smi] render_bundle_encoder_rid: ResourceId,
#[string] marker_label: &str,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_bundle_encoder_resource =
state
.resource_table
@ -239,7 +245,7 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline(
state: &mut OpState,
#[smi] render_bundle_encoder_rid: ResourceId,
#[smi] pipeline: ResourceId,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pipeline_resource =
state
.resource_table
@ -266,18 +272,17 @@ pub fn op_webgpu_render_bundle_encoder_set_index_buffer(
#[serde] index_format: wgpu_types::IndexFormat,
#[number] offset: u64,
#[number] size: u64,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, BundleError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(buffer)?;
let render_bundle_encoder_resource =
state
.resource_table
.get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
let size = Some(
std::num::NonZeroU64::new(size)
.ok_or_else(|| type_error("size must be larger than 0"))?,
);
.get::<super::buffer::WebGpuBuffer>(buffer)
.map_err(BundleError::Resource)?;
let render_bundle_encoder_resource = state
.resource_table
.get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)
.map_err(BundleError::Resource)?;
let size =
Some(std::num::NonZeroU64::new(size).ok_or(BundleError::InvalidSize)?);
render_bundle_encoder_resource
.0
@ -296,19 +301,17 @@ pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer(
#[smi] buffer: ResourceId,
#[number] offset: u64,
#[number] size: Option<u64>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, BundleError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(buffer)?;
let render_bundle_encoder_resource =
state
.resource_table
.get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
.get::<super::buffer::WebGpuBuffer>(buffer)
.map_err(BundleError::Resource)?;
let render_bundle_encoder_resource = state
.resource_table
.get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)
.map_err(BundleError::Resource)?;
let size = if let Some(size) = size {
Some(
std::num::NonZeroU64::new(size)
.ok_or_else(|| type_error("size must be larger than 0"))?,
)
Some(std::num::NonZeroU64::new(size).ok_or(BundleError::InvalidSize)?)
} else {
None
};
@ -333,7 +336,7 @@ pub fn op_webgpu_render_bundle_encoder_draw(
instance_count: u32,
first_vertex: u32,
first_instance: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_bundle_encoder_resource =
state
.resource_table
@ -360,7 +363,7 @@ pub fn op_webgpu_render_bundle_encoder_draw_indexed(
first_index: u32,
base_vertex: i32,
first_instance: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_bundle_encoder_resource =
state
.resource_table
@ -385,7 +388,7 @@ pub fn op_webgpu_render_bundle_encoder_draw_indirect(
#[smi] render_bundle_encoder_rid: ResourceId,
#[smi] indirect_buffer: ResourceId,
#[number] indirect_offset: u64,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;

View File

@ -1,7 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::ResourceId;
@ -16,6 +14,47 @@ use std::ptr::NonNull;
use crate::surface::WebGpuSurface;
#[derive(Debug, thiserror::Error)]
pub enum ByowError {
#[error("Cannot create surface outside of WebGPU context. Did you forget to call `navigator.gpu.requestAdapter()`?")]
WebGPUNotInitiated,
#[error("Invalid parameters")]
InvalidParameters,
#[error(transparent)]
CreateSurface(wgpu_core::instance::CreateSurfaceError),
#[cfg(target_os = "windows")]
#[error("Invalid system on Windows")]
InvalidSystem,
#[cfg(target_os = "macos")]
#[error("Invalid system on macOS")]
InvalidSystem,
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd"
))]
#[error("Invalid system on Linux/BSD")]
InvalidSystem,
#[cfg(any(
target_os = "windows",
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd"
))]
#[error("window is null")]
NullWindow,
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd"
))]
#[error("display is null")]
NullDisplay,
#[cfg(target_os = "macos")]
#[error("ns_view is null")]
NSViewDisplay,
}
#[op2(fast)]
#[smi]
pub fn op_webgpu_surface_create(
@ -23,10 +62,10 @@ pub fn op_webgpu_surface_create(
#[string] system: &str,
p1: *const c_void,
p2: *const c_void,
) -> Result<ResourceId, AnyError> {
let instance = state.try_borrow::<super::Instance>().ok_or_else(|| {
type_error("Cannot create surface outside of WebGPU context. Did you forget to call `navigator.gpu.requestAdapter()`?")
})?;
) -> Result<ResourceId, ByowError> {
let instance = state
.try_borrow::<super::Instance>()
.ok_or(ByowError::WebGPUNotInitiated)?;
// Security note:
//
// The `p1` and `p2` parameters are pointers to platform-specific window
@ -41,13 +80,15 @@ pub fn op_webgpu_surface_create(
//
// - Only FFI can export v8::External to user code.
if p1.is_null() {
return Err(type_error("Invalid parameters"));
return Err(ByowError::InvalidParameters);
}
let (win_handle, display_handle) = raw_window(system, p1, p2)?;
// SAFETY: see above comment
let surface = unsafe {
instance.instance_create_surface(display_handle, win_handle, None)?
instance
.instance_create_surface(display_handle, win_handle, None)
.map_err(ByowError::CreateSurface)?
};
let rid = state
@ -66,15 +107,14 @@ fn raw_window(
system: &str,
_ns_window: *const c_void,
ns_view: *const c_void,
) -> Result<RawHandles, AnyError> {
) -> Result<RawHandles, ByowError> {
if system != "cocoa" {
return Err(type_error("Invalid system on macOS"));
return Err(ByowError::InvalidSystem);
}
let win_handle = raw_window_handle::RawWindowHandle::AppKit(
raw_window_handle::AppKitWindowHandle::new(
NonNull::new(ns_view as *mut c_void)
.ok_or(type_error("ns_view is null"))?,
NonNull::new(ns_view as *mut c_void).ok_or(ByowError::NSViewDisplay)?,
),
);
@ -89,16 +129,16 @@ fn raw_window(
system: &str,
window: *const c_void,
hinstance: *const c_void,
) -> Result<RawHandles, AnyError> {
) -> Result<RawHandles, ByowError> {
use raw_window_handle::WindowsDisplayHandle;
if system != "win32" {
return Err(type_error("Invalid system on Windows"));
return Err(ByowError::InvalidSystem);
}
let win_handle = {
let mut handle = raw_window_handle::Win32WindowHandle::new(
std::num::NonZeroIsize::new(window as isize)
.ok_or(type_error("window is null"))?,
.ok_or(ByowError::NullWindow)?,
);
handle.hinstance = std::num::NonZeroIsize::new(hinstance as isize);
@ -115,7 +155,7 @@ fn raw_window(
system: &str,
window: *const c_void,
display: *const c_void,
) -> Result<RawHandles, AnyError> {
) -> Result<RawHandles, ByowError> {
let (win_handle, display_handle);
if system == "x11" {
win_handle = raw_window_handle::RawWindowHandle::Xlib(
@ -131,19 +171,17 @@ fn raw_window(
} else if system == "wayland" {
win_handle = raw_window_handle::RawWindowHandle::Wayland(
raw_window_handle::WaylandWindowHandle::new(
NonNull::new(window as *mut c_void)
.ok_or(type_error("window is null"))?,
NonNull::new(window as *mut c_void).ok_or(ByowError::NullWindow)?,
),
);
display_handle = raw_window_handle::RawDisplayHandle::Wayland(
raw_window_handle::WaylandDisplayHandle::new(
NonNull::new(display as *mut c_void)
.ok_or(type_error("display is null"))?,
NonNull::new(display as *mut c_void).ok_or(ByowError::NullDisplay)?,
),
);
} else {
return Err(type_error("Invalid system on Linux/BSD"));
return Err(ByowError::InvalidSystem);
}
Ok((win_handle, display_handle))
@ -160,6 +198,6 @@ fn raw_window(
_system: &str,
_window: *const c_void,
_display: *const c_void,
) -> Result<RawHandles, AnyError> {
Err(type_error("Unsupported platform"))
) -> Result<RawHandles, deno_core::error::AnyError> {
Err(deno_core::error::type_error("Unsupported platform"))
}

View File

@ -1,11 +1,9 @@
// 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 wgpu_core::binding_model::CreateBindGroupError;
use wgpu_core::binding_model::CreateBindGroupLayoutError;
use wgpu_core::binding_model::CreatePipelineLayoutError;
@ -286,29 +284,3 @@ impl From<ConfigureSurfaceError> for WebGpuError {
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::<DomExceptionOperationError>()
.map(|_| "DOMExceptionOperationError")
}

View File

@ -2,7 +2,6 @@
#![cfg(not(target_arch = "wasm32"))]
#![warn(unsafe_op_in_unsafe_fn)]
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -16,7 +15,6 @@ use std::rc::Rc;
pub use wgpu_core;
pub use wgpu_types;
use error::DomExceptionOperationError;
use error::WebGpuResult;
pub const UNSTABLE_FEATURE_NAME: &str = "webgpu";
@ -85,6 +83,18 @@ pub mod shader;
pub mod surface;
pub mod texture;
#[derive(Debug, thiserror::Error)]
pub enum InitError {
#[error(transparent)]
Resource(deno_core::error::AnyError),
#[error(transparent)]
InvalidAdapter(wgpu_core::instance::InvalidAdapter),
#[error(transparent)]
RequestDevice(wgpu_core::instance::RequestDeviceError),
#[error(transparent)]
InvalidDevice(wgpu_core::device::InvalidDevice),
}
pub type Instance = std::sync::Arc<wgpu_core::global::Global>;
struct WebGpuAdapter(Instance, wgpu_core::id::AdapterId);
@ -400,7 +410,7 @@ pub fn op_webgpu_request_adapter(
state: Rc<RefCell<OpState>>,
#[serde] power_preference: Option<wgpu_types::PowerPreference>,
force_fallback_adapter: bool,
) -> Result<GpuAdapterResOrErr, AnyError> {
) -> Result<GpuAdapterResOrErr, InitError> {
let mut state = state.borrow_mut();
let backends = std::env::var("DENO_WEBGPU_BACKEND").map_or_else(
@ -441,10 +451,11 @@ pub fn op_webgpu_request_adapter(
}
};
let adapter_features =
gfx_select!(adapter => instance.adapter_features(adapter))?;
gfx_select!(adapter => instance.adapter_features(adapter))
.map_err(InitError::InvalidAdapter)?;
let features = deserialize_features(&adapter_features);
let adapter_limits =
gfx_select!(adapter => instance.adapter_limits(adapter))?;
let adapter_limits = gfx_select!(adapter => instance.adapter_limits(adapter))
.map_err(InitError::InvalidAdapter)?;
let instance = instance.clone();
@ -663,10 +674,12 @@ pub fn op_webgpu_request_device(
#[string] label: String,
#[serde] required_features: GpuRequiredFeatures,
#[serde] required_limits: Option<wgpu_types::Limits>,
) -> Result<GpuDeviceRes, AnyError> {
) -> Result<GpuDeviceRes, InitError> {
let mut state = state.borrow_mut();
let adapter_resource =
state.resource_table.take::<WebGpuAdapter>(adapter_rid)?;
let adapter_resource = state
.resource_table
.take::<WebGpuAdapter>(adapter_rid)
.map_err(InitError::Resource)?;
let adapter = adapter_resource.1;
let instance = state.borrow::<Instance>();
@ -685,13 +698,14 @@ pub fn op_webgpu_request_device(
));
adapter_resource.close();
if let Some(err) = maybe_err {
return Err(DomExceptionOperationError::new(&err.to_string()).into());
return Err(InitError::RequestDevice(err));
}
let device_features =
gfx_select!(device => instance.device_features(device))?;
let device_features = gfx_select!(device => instance.device_features(device))
.map_err(InitError::InvalidDevice)?;
let features = deserialize_features(&device_features);
let limits = gfx_select!(device => instance.device_limits(device))?;
let limits = gfx_select!(device => instance.device_limits(device))
.map_err(InitError::InvalidDevice)?;
let instance = instance.clone();
let instance2 = instance.clone();
@ -722,14 +736,17 @@ pub struct GPUAdapterInfo {
pub fn op_webgpu_request_adapter_info(
state: Rc<RefCell<OpState>>,
#[smi] adapter_rid: ResourceId,
) -> Result<GPUAdapterInfo, AnyError> {
) -> Result<GPUAdapterInfo, InitError> {
let state = state.borrow_mut();
let adapter_resource =
state.resource_table.get::<WebGpuAdapter>(adapter_rid)?;
let adapter_resource = state
.resource_table
.get::<WebGpuAdapter>(adapter_rid)
.map_err(InitError::Resource)?;
let adapter = adapter_resource.1;
let instance = state.borrow::<Instance>();
let info = gfx_select!(adapter => instance.adapter_get_info(adapter))?;
let info = gfx_select!(adapter => instance.adapter_get_info(adapter))
.map_err(InitError::InvalidAdapter)?;
Ok(GPUAdapterInfo {
vendor: info.vendor.to_string(),
@ -770,9 +787,11 @@ impl From<GpuQueryType> for wgpu_types::QueryType {
pub fn op_webgpu_create_query_set(
state: &mut OpState,
#[serde] args: CreateQuerySetArgs,
) -> Result<WebGpuResult, AnyError> {
let device_resource =
state.resource_table.get::<WebGpuDevice>(args.device_rid)?;
) -> Result<WebGpuResult, InitError> {
let device_resource = state
.resource_table
.get::<WebGpuDevice>(args.device_rid)
.map_err(InitError::Resource)?;
let device = device_resource.1;
let instance = state.borrow::<Instance>();

View File

@ -1,7 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -12,6 +10,14 @@ use std::cell::RefCell;
use super::error::WebGpuResult;
#[derive(Debug, thiserror::Error)]
pub enum RenderPassError {
#[error(transparent)]
Resource(deno_core::error::AnyError),
#[error("size must be larger than 0")]
InvalidSize,
}
pub(crate) struct WebGpuRenderPass(
pub(crate) RefCell<wgpu_core::command::RenderPass>,
);
@ -38,7 +44,7 @@ pub struct RenderPassSetViewportArgs {
pub fn op_webgpu_render_pass_set_viewport(
state: &mut OpState,
#[serde] args: RenderPassSetViewportArgs,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(args.render_pass_rid)?;
@ -65,7 +71,7 @@ pub fn op_webgpu_render_pass_set_scissor_rect(
y: u32,
width: u32,
height: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -87,7 +93,7 @@ pub fn op_webgpu_render_pass_set_blend_constant(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
#[serde] color: wgpu_types::Color,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -106,7 +112,7 @@ pub fn op_webgpu_render_pass_set_stencil_reference(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
reference: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -125,7 +131,7 @@ pub fn op_webgpu_render_pass_begin_occlusion_query(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
query_index: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -143,7 +149,7 @@ pub fn op_webgpu_render_pass_begin_occlusion_query(
pub fn op_webgpu_render_pass_end_occlusion_query(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -161,7 +167,7 @@ pub fn op_webgpu_render_pass_execute_bundles(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
#[serde] bundles: Vec<u32>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let bundles = bundles
.iter()
.map(|rid| {
@ -171,7 +177,7 @@ pub fn op_webgpu_render_pass_execute_bundles(
.get::<super::bundle::WebGpuRenderBundle>(*rid)?;
Ok(render_bundle_resource.1)
})
.collect::<Result<Vec<_>, AnyError>>()?;
.collect::<Result<Vec<_>, deno_core::error::AnyError>>()?;
let render_pass_resource = state
.resource_table
@ -191,7 +197,7 @@ pub fn op_webgpu_render_pass_end(
state: &mut OpState,
#[smi] command_encoder_rid: ResourceId,
#[smi] render_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let command_encoder_resource = state
.resource_table
.get::<super::command_encoder::WebGpuCommandEncoder>(
@ -217,7 +223,7 @@ pub fn op_webgpu_render_pass_set_bind_group(
#[buffer] dynamic_offsets_data: &[u32],
#[number] dynamic_offsets_data_start: usize,
#[number] dynamic_offsets_data_length: usize,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let bind_group_resource =
state
.resource_table
@ -251,7 +257,7 @@ pub fn op_webgpu_render_pass_push_debug_group(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
#[string] group_label: &str,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -270,7 +276,7 @@ pub fn op_webgpu_render_pass_push_debug_group(
pub fn op_webgpu_render_pass_pop_debug_group(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -288,7 +294,7 @@ pub fn op_webgpu_render_pass_insert_debug_marker(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
#[string] marker_label: &str,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -308,7 +314,7 @@ pub fn op_webgpu_render_pass_set_pipeline(
state: &mut OpState,
#[smi] render_pass_rid: ResourceId,
pipeline: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pipeline_resource =
state
.resource_table
@ -334,19 +340,18 @@ pub fn op_webgpu_render_pass_set_index_buffer(
#[serde] index_format: wgpu_types::IndexFormat,
#[number] offset: u64,
#[number] size: Option<u64>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, RenderPassError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(buffer)?;
.get::<super::buffer::WebGpuBuffer>(buffer)
.map_err(RenderPassError::Resource)?;
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
.get::<WebGpuRenderPass>(render_pass_rid)
.map_err(RenderPassError::Resource)?;
let size = if let Some(size) = size {
Some(
std::num::NonZeroU64::new(size)
.ok_or_else(|| type_error("size must be larger than 0"))?,
)
Some(std::num::NonZeroU64::new(size).ok_or(RenderPassError::InvalidSize)?)
} else {
None
};
@ -370,19 +375,18 @@ pub fn op_webgpu_render_pass_set_vertex_buffer(
buffer: u32,
#[number] offset: u64,
#[number] size: Option<u64>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, RenderPassError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(buffer)?;
.get::<super::buffer::WebGpuBuffer>(buffer)
.map_err(RenderPassError::Resource)?;
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
.get::<WebGpuRenderPass>(render_pass_rid)
.map_err(RenderPassError::Resource)?;
let size = if let Some(size) = size {
Some(
std::num::NonZeroU64::new(size)
.ok_or_else(|| type_error("size must be larger than 0"))?,
)
Some(std::num::NonZeroU64::new(size).ok_or(RenderPassError::InvalidSize)?)
} else {
None
};
@ -407,7 +411,7 @@ pub fn op_webgpu_render_pass_draw(
instance_count: u32,
first_vertex: u32,
first_instance: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -433,7 +437,7 @@ pub fn op_webgpu_render_pass_draw_indexed(
first_index: u32,
base_vertex: i32,
first_instance: u32,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let render_pass_resource = state
.resource_table
.get::<WebGpuRenderPass>(render_pass_rid)?;
@ -457,7 +461,7 @@ pub fn op_webgpu_render_pass_draw_indirect(
#[smi] render_pass_rid: ResourceId,
indirect_buffer: u32,
#[number] indirect_offset: u64,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
@ -481,7 +485,7 @@ pub fn op_webgpu_render_pass_draw_indexed_indirect(
#[smi] render_pass_rid: ResourceId,
indirect_buffer: u32,
#[number] indirect_offset: u64,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let buffer_resource = state
.resource_table
.get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;

View File

@ -1,6 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -47,7 +46,7 @@ pub struct CreateSamplerArgs {
pub fn op_webgpu_create_sampler(
state: &mut OpState,
#[serde] args: CreateSamplerArgs,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table

View File

@ -1,6 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -31,7 +30,7 @@ pub fn op_webgpu_create_shader_module(
#[smi] device_rid: ResourceId,
#[string] label: Cow<str>,
#[string] code: Cow<str>,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table

View File

@ -1,7 +1,6 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use super::WebGpuResult;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -11,6 +10,16 @@ use std::borrow::Cow;
use std::rc::Rc;
use wgpu_types::SurfaceStatus;
#[derive(Debug, thiserror::Error)]
pub enum SurfaceError {
#[error(transparent)]
Resource(deno_core::error::AnyError),
#[error("Invalid Surface Status")]
InvalidStatus,
#[error(transparent)]
Surface(wgpu_core::present::SurfaceError),
}
pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId);
impl Resource for WebGpuSurface {
fn name(&self) -> Cow<str> {
@ -41,7 +50,7 @@ pub struct SurfaceConfigureArgs {
pub fn op_webgpu_surface_configure(
state: &mut OpState,
#[serde] args: SurfaceConfigureArgs,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
@ -75,18 +84,22 @@ pub fn op_webgpu_surface_get_current_texture(
state: &mut OpState,
#[smi] device_rid: ResourceId,
#[smi] surface_rid: ResourceId,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, SurfaceError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(device_rid)?;
.get::<super::WebGpuDevice>(device_rid)
.map_err(SurfaceError::Resource)?;
let device = device_resource.1;
let surface_resource =
state.resource_table.get::<WebGpuSurface>(surface_rid)?;
let surface_resource = state
.resource_table
.get::<WebGpuSurface>(surface_rid)
.map_err(SurfaceError::Resource)?;
let surface = surface_resource.1;
let output =
gfx_select!(device => instance.surface_get_current_texture(surface, None))?;
gfx_select!(device => instance.surface_get_current_texture(surface, None))
.map_err(SurfaceError::Surface)?;
match output.status {
SurfaceStatus::Good | SurfaceStatus::Suboptimal => {
@ -98,7 +111,7 @@ pub fn op_webgpu_surface_get_current_texture(
});
Ok(WebGpuResult::rid(rid))
}
_ => Err(AnyError::msg("Invalid Surface Status")),
_ => Err(SurfaceError::InvalidStatus),
}
}
@ -107,17 +120,21 @@ pub fn op_webgpu_surface_present(
state: &mut OpState,
#[smi] device_rid: ResourceId,
#[smi] surface_rid: ResourceId,
) -> Result<(), AnyError> {
) -> Result<(), SurfaceError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
.get::<super::WebGpuDevice>(device_rid)?;
.get::<super::WebGpuDevice>(device_rid)
.map_err(SurfaceError::Resource)?;
let device = device_resource.1;
let surface_resource =
state.resource_table.get::<WebGpuSurface>(surface_rid)?;
let surface_resource = state
.resource_table
.get::<WebGpuSurface>(surface_rid)
.map_err(SurfaceError::Resource)?;
let surface = surface_resource.1;
let _ = gfx_select!(device => instance.surface_present(surface))?;
let _ = gfx_select!(device => instance.surface_present(surface))
.map_err(SurfaceError::Surface)?;
Ok(())
}

View File

@ -1,6 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use deno_core::Resource;
@ -62,7 +61,7 @@ pub struct CreateTextureArgs {
pub fn op_webgpu_create_texture(
state: &mut OpState,
#[serde] args: CreateTextureArgs,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let instance = state.borrow::<super::Instance>();
let device_resource = state
.resource_table
@ -111,7 +110,7 @@ pub struct CreateTextureViewArgs {
pub fn op_webgpu_create_texture_view(
state: &mut OpState,
#[serde] args: CreateTextureViewArgs,
) -> Result<WebGpuResult, AnyError> {
) -> Result<WebGpuResult, deno_core::error::AnyError> {
let instance = state.borrow::<super::Instance>();
let texture_resource = state
.resource_table

View File

@ -189,6 +189,89 @@ pub fn get_nix_error_class(error: &nix::Error) -> &'static str {
}
}
fn get_webgpu_error_class(e: &deno_webgpu::InitError) -> &'static str {
match e {
deno_webgpu::InitError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
deno_webgpu::InitError::InvalidAdapter(_) => "Error",
deno_webgpu::InitError::RequestDevice(_) => "DOMExceptionOperationError",
deno_webgpu::InitError::InvalidDevice(_) => "Error",
}
}
fn get_webgpu_buffer_error_class(
e: &deno_webgpu::buffer::BufferError,
) -> &'static str {
match e {
deno_webgpu::buffer::BufferError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
deno_webgpu::buffer::BufferError::InvalidUsage => "TypeError",
deno_webgpu::buffer::BufferError::Access(_) => "DOMExceptionOperationError",
}
}
fn get_webgpu_bundle_error_class(
e: &deno_webgpu::bundle::BundleError,
) -> &'static str {
match e {
deno_webgpu::bundle::BundleError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
deno_webgpu::bundle::BundleError::InvalidSize => "TypeError",
}
}
fn get_webgpu_byow_error_class(
e: &deno_webgpu::byow::ByowError,
) -> &'static str {
match e {
deno_webgpu::byow::ByowError::WebGPUNotInitiated => "TypeError",
deno_webgpu::byow::ByowError::InvalidParameters => "TypeError",
deno_webgpu::byow::ByowError::CreateSurface(_) => "Error",
deno_webgpu::byow::ByowError::InvalidSystem => "TypeError",
#[cfg(any(
target_os = "windows",
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd"
))]
deno_webgpu::byow::ByowError::NullWindow => "TypeError",
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd"
))]
deno_webgpu::byow::ByowError::NullDisplay => "TypeError",
#[cfg(target_os = "macos")]
deno_webgpu::byow::ByowError::NSViewDisplay => "TypeError",
}
}
fn get_webgpu_render_pass_error_class(
e: &deno_webgpu::render_pass::RenderPassError,
) -> &'static str {
match e {
deno_webgpu::render_pass::RenderPassError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
deno_webgpu::render_pass::RenderPassError::InvalidSize => "TypeError",
}
}
fn get_webgpu_surface_error_class(
e: &deno_webgpu::surface::SurfaceError,
) -> &'static str {
match e {
deno_webgpu::surface::SurfaceError::Resource(e) => {
get_error_class_name(e).unwrap_or("Error")
}
deno_webgpu::surface::SurfaceError::Surface(_) => "Error",
deno_webgpu::surface::SurfaceError::InvalidStatus => "Error",
}
}
fn get_crypto_decrypt_error_class(e: &DecryptError) -> &'static str {
match e {
DecryptError::General(e) => get_crypto_shared_error_class(e),
@ -778,7 +861,6 @@ fn get_websocket_upgrade_error(error: &WebSocketUpgradeError) -> &'static str {
pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
deno_core::error::get_custom_error_class(e)
.or_else(|| deno_webgpu::error::get_error_class_name(e))
.or_else(|| e.downcast_ref::<NApiError>().map(get_napi_error_class))
.or_else(|| e.downcast_ref::<WebError>().map(get_web_error_class))
.or_else(|| {
@ -840,6 +922,30 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
e.downcast_ref::<BroadcastChannelError>()
.map(get_broadcast_channel_error)
})
.or_else(|| {
e.downcast_ref::<deno_webgpu::InitError>()
.map(get_webgpu_error_class)
})
.or_else(|| {
e.downcast_ref::<deno_webgpu::buffer::BufferError>()
.map(get_webgpu_buffer_error_class)
})
.or_else(|| {
e.downcast_ref::<deno_webgpu::bundle::BundleError>()
.map(get_webgpu_bundle_error_class)
})
.or_else(|| {
e.downcast_ref::<deno_webgpu::byow::ByowError>()
.map(get_webgpu_byow_error_class)
})
.or_else(|| {
e.downcast_ref::<deno_webgpu::render_pass::RenderPassError>()
.map(get_webgpu_render_pass_error_class)
})
.or_else(|| {
e.downcast_ref::<deno_webgpu::surface::SurfaceError>()
.map(get_webgpu_surface_error_class)
})
.or_else(|| {
e.downcast_ref::<DecryptError>()
.map(get_crypto_decrypt_error_class)