chore: backport deno changes (#5686)

This commit is contained in:
Leo Kettmeir 2024-05-11 02:29:09 -07:00 committed by GitHub
parent 2f4522714c
commit d0a5e48aa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 128 additions and 42 deletions

2
Cargo.lock generated
View File

@ -1079,7 +1079,7 @@ dependencies = [
[[package]] [[package]]
name = "deno_webgpu" name = "deno_webgpu"
version = "0.110.0" version = "0.118.0"
dependencies = [ dependencies = [
"deno_core", "deno_core",
"raw-window-handle 0.6.1", "raw-window-handle 0.6.1",

View File

@ -170,7 +170,7 @@ deno_core = "0.272.0"
deno_url = "0.143.0" deno_url = "0.143.0"
deno_web = "0.174.0" deno_web = "0.174.0"
deno_webidl = "0.143.0" deno_webidl = "0.143.0"
deno_webgpu = { version = "0.110.0", path = "./deno_webgpu" } deno_webgpu = { version = "0.118.0", path = "./deno_webgpu" }
tokio = "1.37.0" tokio = "1.37.0"
termcolor = "1.4.1" termcolor = "1.4.1"

View File

@ -121,9 +121,10 @@ const {
import * as webidl from "ext:deno_webidl/00_webidl.js"; import * as webidl from "ext:deno_webidl/00_webidl.js";
import { import {
defineEventHandler,
Event, Event,
EventTarget, EventTarget,
defineEventHandler, setEventTargetData,
} from "ext:deno_web/02_event.js"; } from "ext:deno_web/02_event.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js"; import { DOMException } from "ext:deno_web/01_dom_exception.js";
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
@ -299,7 +300,6 @@ class GPUValidationError extends GPUError {
this[_message] = message; this[_message] = message;
} }
} }
const GPUValidationErrorPrototype = GPUValidationError.prototype;
class GPUOutOfMemoryError extends GPUError { class GPUOutOfMemoryError extends GPUError {
name = "GPUOutOfMemoryError"; name = "GPUOutOfMemoryError";
@ -312,7 +312,6 @@ class GPUOutOfMemoryError extends GPUError {
this[_message] = message; this[_message] = message;
} }
} }
const GPUOutOfMemoryErrorPrototype = GPUOutOfMemoryError.prototype;
class GPUInternalError extends GPUError { class GPUInternalError extends GPUError {
name = "GPUInternalError"; name = "GPUInternalError";
@ -321,7 +320,6 @@ class GPUInternalError extends GPUError {
this[webidl.brand] = webidl.brand; this[webidl.brand] = webidl.brand;
} }
} }
const GPUInternalErrorPrototype = GPUInternalError.prototype;
class GPUUncapturedErrorEvent extends Event { class GPUUncapturedErrorEvent extends Event {
#error; #error;
@ -333,7 +331,7 @@ class GPUUncapturedErrorEvent extends Event {
const prefix = "Failed to construct 'GPUUncapturedErrorEvent'"; const prefix = "Failed to construct 'GPUUncapturedErrorEvent'";
webidl.requiredArguments(arguments.length, 2, prefix); webidl.requiredArguments(arguments.length, 2, prefix);
gpuUncapturedErrorEventInitDict = webidl.converters gpuUncapturedErrorEventInitDict = webidl.converters
.gpuUncapturedErrorEventInitDict( .GPUUncapturedErrorEventInit(
gpuUncapturedErrorEventInitDict, gpuUncapturedErrorEventInitDict,
prefix, prefix,
"Argument 2", "Argument 2",
@ -348,7 +346,6 @@ class GPUUncapturedErrorEvent extends Event {
} }
} }
const GPUUncapturedErrorEventPrototype = GPUUncapturedErrorEvent.prototype; const GPUUncapturedErrorEventPrototype = GPUUncapturedErrorEvent.prototype;
defineEventHandler(GPUUncapturedErrorEvent.prototype, "uncapturederror");
class GPU { class GPU {
[webidl.brand] = webidl.brand; [webidl.brand] = webidl.brand;
@ -420,9 +417,12 @@ function createGPUAdapter(inner) {
return adapter; return adapter;
} }
const _invalid = Symbol("[[invalid]]");
class GPUAdapter { class GPUAdapter {
/** @type {InnerGPUAdapter} */ /** @type {InnerGPUAdapter} */
[_adapter]; [_adapter];
/** @type {bool} */
[_invalid];
/** @returns {GPUSupportedFeatures} */ /** @returns {GPUSupportedFeatures} */
get features() { get features() {
@ -469,6 +469,12 @@ class GPUAdapter {
} }
} }
if (this[_invalid]) {
throw new TypeError(
"The adapter cannot be reused, as it has been invalidated by a device creation",
);
}
const { rid, queueRid, features, limits } = op_webgpu_request_device( const { rid, queueRid, features, limits } = op_webgpu_request_device(
this[_adapter].rid, this[_adapter].rid,
descriptor.label, descriptor.label,
@ -476,16 +482,20 @@ class GPUAdapter {
descriptor.requiredLimits, descriptor.requiredLimits,
); );
this[_invalid] = true;
const inner = new InnerGPUDevice({ const inner = new InnerGPUDevice({
rid, rid,
adapter: this, adapter: this,
features: createGPUSupportedFeatures(features), features: createGPUSupportedFeatures(features),
limits: createGPUSupportedLimits(limits), limits: createGPUSupportedLimits(limits),
}); });
const queue = createGPUQueue(descriptor.label, inner, queueRid);
inner.trackResource(queue);
const device = createGPUDevice( const device = createGPUDevice(
descriptor.label, descriptor.label,
inner, inner,
createGPUQueue(descriptor.label, inner, queueRid), queue,
); );
inner.device = device; inner.device = device;
return device; return device;
@ -497,6 +507,12 @@ class GPUAdapter {
requestAdapterInfo() { requestAdapterInfo() {
webidl.assertBranded(this, GPUAdapterPrototype); webidl.assertBranded(this, GPUAdapterPrototype);
if (this[_invalid]) {
throw new TypeError(
"The adapter cannot be reused, as it has been invalidated by a device creation",
);
}
const { const {
vendor, vendor,
architecture, architecture,
@ -977,7 +993,9 @@ class InnerGPUDevice {
); );
return; return;
case "validation": case "validation":
constructedError = new GPUValidationError(error.value ?? "validation error"); constructedError = new GPUValidationError(
error.value ?? "validation error",
);
break; break;
case "out-of-memory": case "out-of-memory":
constructedError = new GPUOutOfMemoryError(); constructedError = new GPUOutOfMemoryError();
@ -996,11 +1014,13 @@ class InnerGPUDevice {
({ filter }) => filter === error.type, ({ filter }) => filter === error.type,
); );
if (scope) { if (scope) {
scope.errors.push(constructedError); ArrayPrototypePush(scope.errors, constructedError);
} else { } else {
this.device.dispatchEvent(new GPUUncapturedErrorEvent("uncapturederror", { this.device.dispatchEvent(
new GPUUncapturedErrorEvent("uncapturederror", {
error: constructedError, error: constructedError,
})); }),
);
} }
} }
} }
@ -1017,6 +1037,7 @@ function createGPUDevice(label, inner, queue) {
device[_label] = label; device[_label] = label;
device[_device] = inner; device[_device] = inner;
device[_queue] = queue; device[_queue] = queue;
setEventTargetData(device);
return device; return device;
} }
@ -1132,10 +1153,11 @@ class GPUDevice extends EventTarget {
"Argument 1", "Argument 1",
); );
const device = assertDevice(this, prefix, "this"); const device = assertDevice(this, prefix, "this");
// assign normalized size to descriptor due to createGPUTexture needs it
descriptor.size = normalizeGPUExtent3D(descriptor.size);
const { rid, err } = op_webgpu_create_texture({ const { rid, err } = op_webgpu_create_texture({
deviceRid: device.rid, deviceRid: device.rid,
...descriptor, ...descriptor,
size: normalizeGPUExtent3D(descriptor.size),
}); });
device.pushError(err); device.pushError(err);
@ -1307,7 +1329,6 @@ class GPUDevice extends EventTarget {
} else { } else {
// deno-lint-ignore prefer-primordials // deno-lint-ignore prefer-primordials
const rid = assertResource(resource.buffer, prefix, context); const rid = assertResource(resource.buffer, prefix, context);
// deno-lint-ignore prefer-primordials
return { return {
binding: entry.binding, binding: entry.binding,
kind: "GPUBufferBinding", kind: "GPUBufferBinding",
@ -1816,6 +1837,7 @@ class GPUDevice extends EventTarget {
} }
GPUObjectBaseMixin("GPUDevice", GPUDevice); GPUObjectBaseMixin("GPUDevice", GPUDevice);
const GPUDevicePrototype = GPUDevice.prototype; const GPUDevicePrototype = GPUDevice.prototype;
defineEventHandler(GPUDevice.prototype, "uncapturederror");
class GPUPipelineError extends DOMException { class GPUPipelineError extends DOMException {
#reason; #reason;
@ -1861,6 +1883,15 @@ class GPUQueue {
/** @type {number} */ /** @type {number} */
[_rid]; [_rid];
[_cleanup]() {
const rid = this[_rid];
if (rid !== undefined) {
core.close(rid);
/** @type {number | undefined} */
this[_rid] = undefined;
}
}
constructor() { constructor() {
webidl.illegalConstructor(); webidl.illegalConstructor();
} }
@ -5488,6 +5519,16 @@ webidl.converters["GPUExtent3D"] = (V, opts) => {
if (typeof V === "object") { if (typeof V === "object") {
const method = V[SymbolIterator]; const method = V[SymbolIterator];
if (method !== undefined) { if (method !== undefined) {
// validate length of GPUExtent3D
const min = 1;
const max = 3;
if (V.length < min || V.length > max) {
throw webidl.makeException(
TypeError,
`A sequence of number used as a GPUExtent3D must have between ${min} and ${max} elements.`,
opts,
);
}
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts); return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
} }
return webidl.converters["GPUExtent3DDict"](V, opts); return webidl.converters["GPUExtent3DDict"](V, opts);
@ -6823,6 +6864,15 @@ webidl.converters["GPUOrigin3D"] = (V, opts) => {
if (typeof V === "object") { if (typeof V === "object") {
const method = V[SymbolIterator]; const method = V[SymbolIterator];
if (method !== undefined) { if (method !== undefined) {
// validate length of GPUOrigin3D
const length = 3;
if (V.length > length) {
throw webidl.makeException(
TypeError,
`A sequence of number used as a GPUOrigin3D must have at most ${length} elements.`,
opts,
);
}
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts); return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
} }
return webidl.converters["GPUOrigin3DDict"](V, opts); return webidl.converters["GPUOrigin3DDict"](V, opts);
@ -6891,6 +6941,15 @@ webidl.converters["GPUOrigin2D"] = (V, opts) => {
if (typeof V === "object") { if (typeof V === "object") {
const method = V[SymbolIterator]; const method = V[SymbolIterator];
if (method !== undefined) { if (method !== undefined) {
// validate length of GPUOrigin2D
const length = 2;
if (V.length > length) {
throw webidl.makeException(
TypeError,
`A sequence of number used as a GPUOrigin2D must have at most ${length} elements.`,
opts,
);
}
return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts); return webidl.converters["sequence<GPUIntegerCoordinate>"](V, opts);
} }
return webidl.converters["GPUOrigin2DDict"](V, opts); return webidl.converters["GPUOrigin2DDict"](V, opts);
@ -6976,6 +7035,15 @@ webidl.converters["GPUColor"] = (V, opts) => {
if (typeof V === "object") { if (typeof V === "object") {
const method = V[SymbolIterator]; const method = V[SymbolIterator];
if (method !== undefined) { if (method !== undefined) {
// validate length of GPUColor
const length = 4;
if (V.length !== length) {
throw webidl.makeException(
TypeError,
`A sequence of number used as a GPUColor must have exactly ${length} elements.`,
opts,
);
}
return webidl.converters["sequence<double>"](V, opts); return webidl.converters["sequence<double>"](V, opts);
} }
return webidl.converters["GPUColorDict"](V, opts); return webidl.converters["GPUColorDict"](V, opts);

View File

@ -2,7 +2,7 @@
[package] [package]
name = "deno_webgpu" name = "deno_webgpu"
version = "0.110.0" version = "0.118.0"
authors = ["the Deno authors"] authors = ["the Deno authors"]
edition.workspace = true edition.workspace = true
license = "MIT" license = "MIT"

View File

@ -6,6 +6,7 @@ use deno_core::op2;
use deno_core::OpState; use deno_core::OpState;
use deno_core::ResourceId; use deno_core::ResourceId;
use std::ffi::c_void; use std::ffi::c_void;
#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::ptr::NonNull; use std::ptr::NonNull;
use crate::surface::WebGpuSurface; use crate::surface::WebGpuSurface;
@ -37,6 +38,7 @@ pub fn op_webgpu_surface_create(
} }
let (win_handle, display_handle) = raw_window(system, p1, p2)?; 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)? }; let surface = unsafe { instance.instance_create_surface(display_handle, win_handle, None)? };
let rid = state let rid = state
@ -82,9 +84,10 @@ fn raw_window(
} }
let win_handle = { let win_handle = {
let mut handle = raw_window_handle::Win32WindowHandle::new(); let mut handle = raw_window_handle::Win32WindowHandle::new(
handle.hwnd = window as *mut c_void; std::num::NonZeroIsize::new(window as isize).ok_or(type_error("window is null"))?,
handle.hinstance = hinstance as *mut c_void; );
handle.hinstance = std::num::NonZeroIsize::new(hinstance as isize);
raw_window_handle::RawWindowHandle::Win32(handle) raw_window_handle::RawWindowHandle::Win32(handle)
}; };
@ -99,17 +102,30 @@ fn raw_window(
window: *const c_void, window: *const c_void,
display: *const c_void, display: *const c_void,
) -> Result<RawHandles, AnyError> { ) -> Result<RawHandles, AnyError> {
if system != "x11" { let (win_handle, display_handle);
return Err(type_error("Invalid system on Linux")); if system == "x11" {
} win_handle = raw_window_handle::RawWindowHandle::Xlib(
let win_handle = raw_window_handle::RawWindowHandle::Xlib(
raw_window_handle::XlibWindowHandle::new(window as *mut c_void as _), raw_window_handle::XlibWindowHandle::new(window as *mut c_void as _),
); );
let display_handle = raw_window_handle::RawDisplayHandle::Xlib( display_handle = raw_window_handle::RawDisplayHandle::Xlib(
raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void), 0), raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void), 0),
); );
} 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"))?,
),
);
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"))?,
),
);
} else {
return Err(type_error("Invalid system on Linux"));
}
Ok((win_handle, display_handle)) Ok((win_handle, display_handle))
} }

View File

@ -667,7 +667,7 @@ pub fn op_webgpu_request_device(
#[serde] required_limits: Option<wgpu_types::Limits>, #[serde] required_limits: Option<wgpu_types::Limits>,
) -> Result<GpuDeviceRes, AnyError> { ) -> Result<GpuDeviceRes, AnyError> {
let mut state = state.borrow_mut(); let mut state = state.borrow_mut();
let adapter_resource = state.resource_table.get::<WebGpuAdapter>(adapter_rid)?; let adapter_resource = state.resource_table.take::<WebGpuAdapter>(adapter_rid)?;
let adapter = adapter_resource.1; let adapter = adapter_resource.1;
let instance = state.borrow::<Instance>(); let instance = state.borrow::<Instance>();
@ -684,6 +684,7 @@ pub fn op_webgpu_request_device(
None, None,
None None
)); ));
adapter_resource.close();
if let Some(err) = maybe_err { if let Some(err) = maybe_err {
return Err(DomExceptionOperationError::new(&err.to_string()).into()); return Err(DomExceptionOperationError::new(&err.to_string()).into());
} }
@ -724,12 +725,13 @@ pub fn op_webgpu_request_adapter_info(
state: Rc<RefCell<OpState>>, state: Rc<RefCell<OpState>>,
#[smi] adapter_rid: ResourceId, #[smi] adapter_rid: ResourceId,
) -> Result<GPUAdapterInfo, AnyError> { ) -> Result<GPUAdapterInfo, AnyError> {
let state = state.borrow_mut(); let mut state = state.borrow_mut();
let adapter_resource = state.resource_table.get::<WebGpuAdapter>(adapter_rid)?; let adapter_resource = state.resource_table.take::<WebGpuAdapter>(adapter_rid)?;
let adapter = adapter_resource.1; let adapter = adapter_resource.1;
let instance = state.borrow::<Instance>(); 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))?;
adapter_resource.close();
Ok(GPUAdapterInfo { Ok(GPUAdapterInfo {
vendor: info.vendor.to_string(), vendor: info.vendor.to_string(),

View File

@ -76,7 +76,7 @@ pub enum GPUPipelineLayoutOrGPUAutoLayoutMode {
pub struct GpuProgrammableStage { pub struct GpuProgrammableStage {
module: ResourceId, module: ResourceId,
entry_point: Option<String>, entry_point: Option<String>,
constants: HashMap<String, f64>, constants: Option<HashMap<String, f64>>,
} }
#[op2] #[op2]
@ -112,7 +112,7 @@ pub fn op_webgpu_create_compute_pipeline(
stage: wgpu_core::pipeline::ProgrammableStageDescriptor { stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: compute_shader_module_resource.1, module: compute_shader_module_resource.1,
entry_point: compute.entry_point.map(Cow::from), entry_point: compute.entry_point.map(Cow::from),
constants: Cow::Owned(compute.constants), constants: Cow::Owned(compute.constants.unwrap_or_default()),
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },
}; };
@ -280,8 +280,8 @@ impl<'a> From<GpuVertexBufferLayout> for wgpu_core::pipeline::VertexBufferLayout
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
struct GpuVertexState { struct GpuVertexState {
module: ResourceId, module: ResourceId,
entry_point: String, entry_point: Option<String>,
constants: HashMap<String, f64>, constants: Option<HashMap<String, f64>>,
buffers: Vec<Option<GpuVertexBufferLayout>>, buffers: Vec<Option<GpuVertexBufferLayout>>,
} }
@ -308,8 +308,8 @@ impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
struct GpuFragmentState { struct GpuFragmentState {
targets: Vec<Option<wgpu_types::ColorTargetState>>, targets: Vec<Option<wgpu_types::ColorTargetState>>,
module: u32, module: u32,
entry_point: String, entry_point: Option<String>,
constants: HashMap<String, f64>, constants: Option<HashMap<String, f64>>,
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -358,8 +358,8 @@ pub fn op_webgpu_create_render_pipeline(
Some(wgpu_core::pipeline::FragmentState { Some(wgpu_core::pipeline::FragmentState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor { stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: fragment_shader_module_resource.1, module: fragment_shader_module_resource.1,
entry_point: Some(Cow::from(fragment.entry_point)), entry_point: fragment.entry_point.map(Cow::from),
constants: Cow::Owned(fragment.constants), constants: Cow::Owned(fragment.constants.unwrap_or_default()),
// Required to be true for WebGPU // Required to be true for WebGPU
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },
@ -383,8 +383,8 @@ pub fn op_webgpu_create_render_pipeline(
vertex: wgpu_core::pipeline::VertexState { vertex: wgpu_core::pipeline::VertexState {
stage: wgpu_core::pipeline::ProgrammableStageDescriptor { stage: wgpu_core::pipeline::ProgrammableStageDescriptor {
module: vertex_shader_module_resource.1, module: vertex_shader_module_resource.1,
entry_point: Some(Cow::Owned(args.vertex.entry_point)), entry_point: args.vertex.entry_point.map(Cow::Owned),
constants: Cow::Owned(args.vertex.constants), constants: Cow::Owned(args.vertex.constants.unwrap_or_default()),
// Required to be true for WebGPU // Required to be true for WebGPU
zero_initialize_workgroup_memory: true, zero_initialize_workgroup_memory: true,
}, },