Skip to content

Commit 073e53c

Browse files
WIP: idk if I need this
3 parents 853e129 + 2722999 + c5aa155 commit 073e53c

5 files changed

Lines changed: 108 additions & 53 deletions

File tree

deno_webgpu/01_webgpu.js

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import {
2222
GPUComputePipeline,
2323
GPUDevice,
2424
GPUDeviceLostInfo,
25+
GPUPipelineError,
26+
GPUPipelineErrorInit,
27+
GPUPipelineErrorReason,
2528
GPUPipelineLayout,
2629
GPUQuerySet,
2730
GPUQueue,
@@ -56,7 +59,6 @@ import {
5659
EventTargetPrototype,
5760
setEventTargetData,
5861
} from "ext:deno_web/02_event.js";
59-
import { DOMException } from "ext:deno_web/01_dom_exception.js";
6062
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
6163

6264
const privateCustomInspect = SymbolFor("Deno.privateCustomInspect");
@@ -124,28 +126,7 @@ class GPUInternalError extends GPUError {
124126
}
125127
core.registerErrorClass("GPUInternalError", GPUInternalError);
126128

127-
class GPUPipelineError extends DOMException {
128-
#reason;
129-
130-
constructor(message = "", options = { __proto__: null }) {
131-
const prefix = "Failed to construct 'GPUPipelineError'";
132-
message = webidl.converters.DOMString(message, prefix, "Argument 1");
133-
options = webidl.converters.GPUPipelineErrorInit(
134-
options,
135-
prefix,
136-
"Argument 2",
137-
);
138-
super(message, "GPUPipelineError");
139-
140-
this.#reason = options.reason;
141-
}
142-
143-
get reason() {
144-
webidl.assertBranded(this, GPUPipelineErrorPrototype);
145-
return this.#reason;
146-
}
147-
}
148-
const GPUPipelineErrorPrototype = GPUPipelineError.prototype;
129+
core.registerErrorClass("GPUPipelineError", GPUPipelineError);
149130

150131
class GPUUncapturedErrorEvent extends Event {
151132
#error;
@@ -840,25 +821,6 @@ ObjectDefineProperty(GPUQuerySetPrototype, privateCustomInspect, {
840821

841822
// Converters
842823

843-
webidl.converters["GPUPipelineErrorInit"] = webidl.createDictionaryConverter(
844-
"GPUPipelineErrorInit",
845-
[
846-
{
847-
key: "reason",
848-
converter: webidl.converters.GPUPipelineErrorReason,
849-
required: true,
850-
},
851-
],
852-
);
853-
854-
webidl.converters["GPUPipelineErrorReason"] = webidl.createEnumConverter(
855-
"GPUPipelineErrorReason",
856-
[
857-
"validation",
858-
"internal",
859-
],
860-
);
861-
862824
webidl.converters["GPUError"] = webidl.converters.any /* put union here! */;
863825

864826
const dictMembersGPUUncapturedErrorEventInit = [
@@ -918,6 +880,9 @@ export {
918880
GPUInternalError,
919881
GPUMapMode,
920882
GPUOutOfMemoryError,
883+
GPUPipelineError,
884+
GPUPipelineErrorInit,
885+
GPUPipelineErrorReason,
921886
GPUPipelineLayout,
922887
GPUQuerySet,
923888
GPUQueue,

deno_webgpu/device.rs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ use std::num::NonZeroU64;
66
use std::rc::Rc;
77

88
use deno_core::cppgc::{make_cppgc_object, SameObject};
9-
use deno_core::op2;
109
use deno_core::v8;
1110
use deno_core::webidl::WebIdlInterfaceConverter;
1211
use deno_core::GarbageCollected;
12+
use deno_core::{anyhow, op2};
1313
use deno_error::JsErrorBox;
1414
use wgpu_core::binding_model::BindingResource;
15-
use wgpu_core::pipeline::ProgrammableStageDescriptor;
15+
use wgpu_core::pipeline::{
16+
CreateRenderPipelineError, ProgrammableStageDescriptor,
17+
};
1618
use wgpu_types::BindingType;
1719

1820
use super::bind_group::GPUBindGroup;
@@ -29,7 +31,10 @@ use crate::adapter::GPUAdapterInfo;
2931
use crate::adapter::GPUSupportedFeatures;
3032
use crate::adapter::GPUSupportedLimits;
3133
use crate::command_encoder::GPUCommandEncoder;
32-
use crate::error::{GPUError, GPUGenericError};
34+
use crate::error::{
35+
GPUError, GPUGenericError, GPUPipelineError, GPUPipelineErrorInit,
36+
GPUPipelineErrorReason,
37+
};
3338
use crate::query_set::GPUQuerySet;
3439
use crate::render_bundle::GPURenderBundleEncoder;
3540
use crate::render_pipeline::GPURenderPipeline;
@@ -509,7 +514,9 @@ impl GPUDevice {
509514
&self,
510515
#[webidl] descriptor: super::render_pipeline::GPURenderPipelineDescriptor,
511516
) -> Result<GPURenderPipeline, JsErrorBox> {
512-
self.new_render_pipeline(descriptor)
517+
let (render_pipeline, err) = self.new_render_pipeline(descriptor)?;
518+
self.error_handler.push_error(err);
519+
Ok(render_pipeline)
513520
}
514521

515522
#[async_method]
@@ -529,7 +536,27 @@ impl GPUDevice {
529536
&self,
530537
#[webidl] descriptor: super::render_pipeline::GPURenderPipelineDescriptor,
531538
) -> Result<GPURenderPipeline, JsErrorBox> {
532-
self.new_render_pipeline(descriptor)
539+
let (render_pipeline, err) = self.new_render_pipeline(descriptor)?;
540+
if let Some(err) = err {
541+
use wgpu_types::error::ErrorType;
542+
use wgpu_types::error::WebGpuError as _;
543+
544+
let reason = match err.webgpu_error_type() {
545+
ErrorType::Internal => GPUPipelineErrorReason::Internal,
546+
ErrorType::Validation => GPUPipelineErrorReason::Validation,
547+
ErrorType::OutOfMemory | ErrorType::DeviceLost => {
548+
self.error_handler.push_error(Some(err));
549+
return Ok(render_pipeline);
550+
}
551+
};
552+
Err(JsErrorBox::from_err(GPUPipelineError::new(
553+
GPUPipelineErrorInit { reason },
554+
anyhow::Error::new(err),
555+
)))
556+
// NOTE: `render_pipeline` gets dropped.
557+
} else {
558+
Ok(render_pipeline)
559+
}
533560
}
534561

535562
fn create_command_encoder<'a>(
@@ -773,7 +800,8 @@ impl GPUDevice {
773800
fn new_render_pipeline(
774801
&self,
775802
descriptor: super::render_pipeline::GPURenderPipelineDescriptor,
776-
) -> Result<GPURenderPipeline, JsErrorBox> {
803+
) -> Result<(GPURenderPipeline, Option<CreateRenderPipelineError>), JsErrorBox>
804+
{
777805
let vertex = wgpu_core::pipeline::VertexState {
778806
stage: ProgrammableStageDescriptor {
779807
module: descriptor.vertex.module.id,
@@ -934,14 +962,14 @@ impl GPUDevice {
934962
None,
935963
);
936964

937-
self.error_handler.push_error(err);
938-
939-
Ok(GPURenderPipeline {
965+
let render_pipeline = GPURenderPipeline {
940966
instance: self.instance.clone(),
941967
error_handler: self.error_handler.clone(),
942968
id,
943969
label: descriptor.label,
944-
})
970+
};
971+
972+
Ok((render_pipeline, err))
945973
}
946974
}
947975

deno_webgpu/error.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ use std::fmt::Formatter;
55
use std::sync::Mutex;
66
use std::sync::OnceLock;
77

8+
use deno_core::anyhow;
89
use deno_core::cppgc::make_cppgc_object;
910
use deno_core::v8;
1011

12+
use deno_core::op2;
13+
use deno_core::webidl::WebIdlInterfaceConverter;
14+
use deno_core::GarbageCollected;
1115
use deno_core::JsRuntime;
1216
use deno_core::V8TaskSpawner;
17+
use deno_core::WebIDL;
1318
use wgpu_core::binding_model::CreateBindGroupError;
1419
use wgpu_core::binding_model::CreateBindGroupLayoutError;
1520
use wgpu_core::binding_model::CreatePipelineLayoutError;
@@ -379,3 +384,59 @@ pub enum GPUGenericError {
379384
#[error("Illegal constructor")]
380385
InvalidConstructor,
381386
}
387+
388+
#[derive(Debug, thiserror::Error, deno_error::JsError)]
389+
#[property("code" = 0)]
390+
#[property("message" = self.to_string())]
391+
#[property("name" = self.get_name().to_str().unwrap())]
392+
// TODO: Could we just return the type directly?
393+
#[property("reason" = self.reason.as_str().to_string())]
394+
// TODO: use `DOMException`
395+
#[class(generic)]
396+
#[error("{reason:?} error: {}", fmt_err(self.inner.as_ref()))]
397+
pub struct GPUPipelineError {
398+
pub reason: GPUPipelineErrorReason,
399+
pub(crate) inner: anyhow::Error,
400+
}
401+
402+
#[derive(WebIDL)]
403+
#[webidl(dictionary)]
404+
pub struct GPUPipelineErrorInit {
405+
pub reason: GPUPipelineErrorReason,
406+
}
407+
408+
#[derive(WebIDL, Clone, Copy, Debug)]
409+
#[webidl(enum)]
410+
pub enum GPUPipelineErrorReason {
411+
Validation,
412+
Internal,
413+
}
414+
415+
impl GPUPipelineError {
416+
pub fn new(options: GPUPipelineErrorInit, inner: anyhow::Error) -> Self {
417+
let GPUPipelineErrorInit { reason } = options;
418+
Self { inner, reason }
419+
}
420+
}
421+
422+
#[op2]
423+
impl GPUPipelineError {
424+
#[constructor]
425+
#[cppgc]
426+
fn constructor(
427+
#[webidl(default = "")] message: String,
428+
#[webidl] options: GPUPipelineErrorInit,
429+
) -> GPUPipelineError {
430+
GPUPipelineError::new(options, anyhow::Error::msg(message))
431+
}
432+
}
433+
434+
impl WebIdlInterfaceConverter for GPUPipelineError {
435+
const NAME: &'static str = "GPUPipelineError";
436+
}
437+
438+
impl GarbageCollected for GPUPipelineError {
439+
fn get_name(&self) -> &'static std::ffi::CStr {
440+
c"GPUPipelineError"
441+
}
442+
}

deno_webgpu/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ deno_core::extension!(
8484
compute_pipeline::GPUComputePipeline,
8585
device::GPUDevice,
8686
device::GPUDeviceLostInfo,
87+
error::GPUPipelineError,
8788
pipeline_layout::GPUPipelineLayout,
8889
query_set::GPUQuerySet,
8990
queue::GPUQueue,

wgpu-core/src/device/resource.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ impl Device {
567567
buffer: params_buffer,
568568
usage: hal::StateTransition {
569569
from: wgt::BufferUses::MAP_WRITE,
570-
to: wgt::BufferUses::COPY_SRC,
570+
to: wgt::BufferUses::COPY_DST,
571571
},
572572
}]);
573573
pending_writes.command_encoder.copy_buffer_to_buffer(

0 commit comments

Comments
 (0)