From 9295844345c21326d2eea79c626a5c567443bc77 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Mon, 1 Apr 2024 21:23:08 +0200 Subject: [PATCH 01/12] chore: update deno --- Cargo.lock | 2 +- Cargo.toml | 2 +- cts_runner/src/main.rs | 2 +- deno_webgpu/00_init.js | 7 + deno_webgpu/01_webgpu.js | 523 ++++++++++++++++++++++++--------- deno_webgpu/02_surface.js | 182 +++++------- deno_webgpu/Cargo.toml | 9 +- deno_webgpu/LICENSE.md | 2 +- deno_webgpu/README.md | 4 +- deno_webgpu/binding.rs | 2 +- deno_webgpu/buffer.rs | 4 +- deno_webgpu/bundle.rs | 2 +- deno_webgpu/byow.rs | 122 ++++++++ deno_webgpu/command_encoder.rs | 2 +- deno_webgpu/compute_pass.rs | 2 +- deno_webgpu/error.rs | 5 +- deno_webgpu/lib.rs | 52 ++-- deno_webgpu/pipeline.rs | 2 +- deno_webgpu/queue.rs | 2 +- deno_webgpu/render_pass.rs | 2 +- deno_webgpu/sampler.rs | 2 +- deno_webgpu/shader.rs | 2 +- deno_webgpu/surface.rs | 17 +- deno_webgpu/texture.rs | 2 +- 24 files changed, 638 insertions(+), 315 deletions(-) create mode 100644 deno_webgpu/00_init.js create mode 100644 deno_webgpu/byow.rs diff --git a/Cargo.lock b/Cargo.lock index eb2e05042f..69b4d58d9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1077,7 +1077,7 @@ dependencies = [ [[package]] name = "deno_webgpu" -version = "0.85.0" +version = "0.110.0" dependencies = [ "deno_core", "raw-window-handle 0.6.0", diff --git a/Cargo.toml b/Cargo.toml index 7cb26434bf..52e8c5c176 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -170,7 +170,7 @@ deno_core = "0.272.0" deno_url = "0.143.0" deno_web = "0.174.0" deno_webidl = "0.143.0" -deno_webgpu = { version = "0.85.0", path = "./deno_webgpu" } +deno_webgpu = { version = "0.110.0", path = "./deno_webgpu" } tokio = "1.36.0" termcolor = "1.4.1" diff --git a/cts_runner/src/main.rs b/cts_runner/src/main.rs index 201fda80d7..d18791863d 100644 --- a/cts_runner/src/main.rs +++ b/cts_runner/src/main.rs @@ -40,7 +40,7 @@ mod native { Arc::new(BlobStore::default()), None, ), - deno_webgpu::deno_webgpu::init_ops_and_esm(true), + deno_webgpu::deno_webgpu::init_ops_and_esm(), cts_runner::init_ops_and_esm(), ], ..Default::default() diff --git a/deno_webgpu/00_init.js b/deno_webgpu/00_init.js new file mode 100644 index 0000000000..0f10847cef --- /dev/null +++ b/deno_webgpu/00_init.js @@ -0,0 +1,7 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +import { core } from "ext:core/mod.js"; + +const loadWebGPU = core.createLazyLoader("ext:deno_webgpu/01_webgpu.js"); + +export { loadWebGPU }; diff --git a/deno_webgpu/01_webgpu.js b/deno_webgpu/01_webgpu.js index 6aecb03231..6aa90bd4db 100644 --- a/deno_webgpu/01_webgpu.js +++ b/deno_webgpu/01_webgpu.js @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // @ts-check /// @@ -7,22 +7,101 @@ /// import { core, primordials } from "ext:core/mod.js"; -import * as ops from "ext:core/ops"; -import * as webidl from "ext:deno_webidl/00_webidl.js"; -import { EventTarget } from "ext:deno_web/02_event.js"; -import { DOMException } from "ext:deno_web/01_dom_exception.js"; -import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; +const { + isDataView, + isTypedArray, +} = core; +import { + op_webgpu_buffer_get_map_async, + op_webgpu_buffer_get_mapped_range, + op_webgpu_buffer_unmap, + op_webgpu_command_encoder_begin_compute_pass, + op_webgpu_command_encoder_begin_render_pass, + op_webgpu_command_encoder_clear_buffer, + op_webgpu_command_encoder_copy_buffer_to_buffer, + op_webgpu_command_encoder_copy_buffer_to_texture, + op_webgpu_command_encoder_copy_texture_to_buffer, + op_webgpu_command_encoder_copy_texture_to_texture, + op_webgpu_command_encoder_finish, + op_webgpu_command_encoder_insert_debug_marker, + op_webgpu_command_encoder_pop_debug_group, + op_webgpu_command_encoder_push_debug_group, + op_webgpu_command_encoder_resolve_query_set, + op_webgpu_command_encoder_write_timestamp, + op_webgpu_compute_pass_dispatch_workgroups, + op_webgpu_compute_pass_dispatch_workgroups_indirect, + op_webgpu_compute_pass_end, + op_webgpu_compute_pass_insert_debug_marker, + op_webgpu_compute_pass_pop_debug_group, + op_webgpu_compute_pass_push_debug_group, + op_webgpu_compute_pass_set_bind_group, + op_webgpu_compute_pass_set_pipeline, + op_webgpu_compute_pipeline_get_bind_group_layout, + op_webgpu_create_bind_group, + op_webgpu_create_bind_group_layout, + op_webgpu_create_buffer, + op_webgpu_create_command_encoder, + op_webgpu_create_compute_pipeline, + op_webgpu_create_pipeline_layout, + op_webgpu_create_query_set, + op_webgpu_create_render_bundle_encoder, + op_webgpu_create_render_pipeline, + op_webgpu_create_sampler, + op_webgpu_create_shader_module, + op_webgpu_create_texture, + op_webgpu_create_texture_view, + op_webgpu_queue_submit, + op_webgpu_render_bundle_encoder_draw, + op_webgpu_render_bundle_encoder_draw_indexed, + op_webgpu_render_bundle_encoder_draw_indirect, + op_webgpu_render_bundle_encoder_finish, + op_webgpu_render_bundle_encoder_insert_debug_marker, + op_webgpu_render_bundle_encoder_pop_debug_group, + op_webgpu_render_bundle_encoder_push_debug_group, + op_webgpu_render_bundle_encoder_set_bind_group, + op_webgpu_render_bundle_encoder_set_index_buffer, + op_webgpu_render_bundle_encoder_set_pipeline, + op_webgpu_render_bundle_encoder_set_vertex_buffer, + op_webgpu_render_pass_begin_occlusion_query, + op_webgpu_render_pass_draw, + op_webgpu_render_pass_draw_indexed, + op_webgpu_render_pass_draw_indexed_indirect, + op_webgpu_render_pass_draw_indirect, + op_webgpu_render_pass_end, + op_webgpu_render_pass_end_occlusion_query, + op_webgpu_render_pass_execute_bundles, + op_webgpu_render_pass_insert_debug_marker, + op_webgpu_render_pass_pop_debug_group, + op_webgpu_render_pass_push_debug_group, + op_webgpu_render_pass_set_bind_group, + op_webgpu_render_pass_set_blend_constant, + op_webgpu_render_pass_set_index_buffer, + op_webgpu_render_pass_set_pipeline, + op_webgpu_render_pass_set_scissor_rect, + op_webgpu_render_pass_set_stencil_reference, + op_webgpu_render_pass_set_vertex_buffer, + op_webgpu_render_pass_set_viewport, + op_webgpu_render_pipeline_get_bind_group_layout, + op_webgpu_request_adapter, + op_webgpu_request_adapter_info, + op_webgpu_request_device, + op_webgpu_write_buffer, + op_webgpu_write_texture, +} from "ext:core/ops"; const { ArrayBuffer, - ArrayBufferIsView, + ArrayBufferPrototypeGetByteLength, ArrayIsArray, ArrayPrototypeFilter, + ArrayPrototypeIncludes, ArrayPrototypeMap, ArrayPrototypePop, ArrayPrototypePush, + DataViewPrototypeGetBuffer, Error, MathMax, ObjectDefineProperty, + ObjectHasOwn, ObjectPrototypeIsPrototypeOf, Promise, PromisePrototypeCatch, @@ -31,17 +110,24 @@ const { PromiseResolve, SafeArrayIterator, SafePromiseAll, - Set, + SafeSet, + SafeWeakRef, SetPrototypeHas, Symbol, SymbolFor, SymbolIterator, TypeError, + TypedArrayPrototypeGetBuffer, + TypedArrayPrototypeGetSymbolToStringTag, Uint32Array, - Uint32ArrayPrototype, Uint8Array, } = primordials; +import * as webidl from "ext:deno_webidl/00_webidl.js"; +import { EventTarget } from "ext:deno_web/02_event.js"; +import { DOMException } from "ext:deno_web/01_dom_exception.js"; +import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; + const _rid = Symbol("[[rid]]"); const _size = Symbol("[[size]]"); const _usage = Symbol("[[usage]]"); @@ -238,6 +324,7 @@ class GPU { /** * @param {GPURequestAdapterOptions} options */ + // deno-lint-ignore require-await async requestAdapter(options = {}) { webidl.assertBranded(this, GPUPrototype); options = webidl.converters.GPURequestAdapterOptions( @@ -246,7 +333,7 @@ class GPU { "Argument 1", ); - const { err, ...data } = await ops.op_webgpu_request_adapter( + const { err, ...data } = op_webgpu_request_adapter( options.powerPreference, options.forceFallbackAdapter, ); @@ -258,6 +345,16 @@ class GPU { } } + getPreferredCanvasFormat() { + // Same as Gecko. + // + // https://github.com/mozilla/gecko-dev/blob/b75080bb8b11844d18cb5f9ac6e68a866ef8e243/dom/webgpu/Instance.h#L42-L47 + if (core.build.os == "android") { + return "rgba8unorm"; + } + return "bgra8unorm"; + } + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { return `${this.constructor.name} ${inspect({}, inspectOptions)}`; } @@ -303,7 +400,6 @@ class GPUAdapter { } /** @returns {boolean} */ get isFallbackAdapter() { - webidl.assertBranded(this, GPUAdapterPrototype); webidl.assertBranded(this, GPUAdapterPrototype); return this[_adapter].isFallbackAdapter; } @@ -316,6 +412,7 @@ class GPUAdapter { * @param {GPUDeviceDescriptor} descriptor * @returns {Promise} */ + // deno-lint-ignore require-await async requestDevice(descriptor = {}) { webidl.assertBranded(this, GPUAdapterPrototype); const prefix = "Failed to execute 'requestDevice' on 'GPUAdapter'"; @@ -336,7 +433,7 @@ class GPUAdapter { } } - const { rid, features, limits } = await ops.op_webgpu_request_device( + const { rid, features, limits } = op_webgpu_request_device( this[_adapter].rid, descriptor.label, requiredFeatures, @@ -360,7 +457,7 @@ class GPUAdapter { * @param {string[]} unmaskHints * @returns {Promise} */ - async requestAdapterInfo(unmaskHints = []) { + requestAdapterInfo(unmaskHints = []) { webidl.assertBranded(this, GPUAdapterPrototype); const prefix = "Failed to execute 'requestAdapterInfo' on 'GPUAdapter'"; unmaskHints = webidl.converters["sequence"]( @@ -374,18 +471,20 @@ class GPUAdapter { architecture, device, description, - } = await ops.op_webgpu_request_adapter_info(this[_adapter].rid); + } = op_webgpu_request_adapter_info(this[_adapter].rid); const adapterInfo = webidl.createBranded(GPUAdapterInfo); - adapterInfo[_vendor] = unmaskHints.includes("vendor") ? vendor : ""; - adapterInfo[_architecture] = unmaskHints.includes("architecture") - ? architecture + adapterInfo[_vendor] = ArrayPrototypeIncludes(unmaskHints, "vendor") + ? vendor : ""; - adapterInfo[_device] = unmaskHints.includes("device") ? device : ""; - adapterInfo[_description] = unmaskHints.includes("description") - ? description + adapterInfo[_architecture] = + ArrayPrototypeIncludes(unmaskHints, "architecture") ? architecture : ""; + adapterInfo[_device] = ArrayPrototypeIncludes(unmaskHints, "device") + ? device : ""; - return adapterInfo; + adapterInfo[_description] = + ArrayPrototypeIncludes(unmaskHints, "description") ? description : ""; + return PromiseResolve(adapterInfo); } [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { @@ -617,7 +716,10 @@ class GPUSupportedLimits { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUSupportedLimitsPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUSupportedLimitsPrototype, + this, + ), keys: [ "maxTextureDimension1D", "maxTextureDimension2D", @@ -658,7 +760,7 @@ const GPUSupportedLimitsPrototype = GPUSupportedLimits.prototype; function createGPUSupportedFeatures(features) { /** @type {GPUSupportedFeatures} */ const supportedFeatures = webidl.createBranded(GPUSupportedFeatures); - supportedFeatures[webidl.setlikeInner] = new Set(features); + supportedFeatures[webidl.setlikeInner] = new SafeSet(features); webidl.setlike( supportedFeatures, GPUSupportedFeaturesPrototype, @@ -676,8 +778,7 @@ class GPUSupportedFeatures { if (ObjectPrototypeIsPrototypeOf(GPUSupportedFeaturesPrototype, this)) { return `${this.constructor.name} ${ // deno-lint-ignore prefer-primordials - inspect([...this], inspectOptions) - }`; + inspect([...this], inspectOptions)}`; } else { return `${this.constructor.name} ${inspect({}, inspectOptions)}`; } @@ -721,7 +822,10 @@ class GPUDeviceLostInfo { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUDeviceLostInfoPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUDeviceLostInfoPrototype, + this, + ), keys: [ "reason", "message", @@ -786,7 +890,7 @@ class InnerGPUDevice { features; /** @type {GPUSupportedLimits} */ limits; - /** @type {WeakRef[]} */ + /** @type {SafeWeakRef[]} */ resources; /** @type {boolean} */ isLost; @@ -816,7 +920,7 @@ class InnerGPUDevice { /** @param {any} resource */ trackResource(resource) { - ArrayPrototypePush(this.resources, new WeakRef(resource)); + ArrayPrototypePush(this.resources, new SafeWeakRef(resource)); } /** @param {{ type: string, value: string | null } | undefined} err */ @@ -971,7 +1075,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_buffer( + const { rid, err } = op_webgpu_create_buffer( device.rid, descriptor.label, descriptor.size, @@ -1022,7 +1126,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_texture({ + const { rid, err } = op_webgpu_create_texture({ deviceRid: device.rid, ...descriptor, size: normalizeGPUExtent3D(descriptor.size), @@ -1051,7 +1155,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_sampler({ + const { rid, err } = op_webgpu_create_sampler({ deviceRid: device.rid, ...descriptor, }); @@ -1084,6 +1188,7 @@ class GPUDevice extends EventTarget { const entry = descriptor.entries[i]; let j = 0; + // deno-lint-ignore prefer-primordials if (entry.buffer) j++; if (entry.sampler) j++; if (entry.texture) j++; @@ -1094,7 +1199,7 @@ class GPUDevice extends EventTarget { } } - const { rid, err } = ops.op_webgpu_create_bind_group_layout( + const { rid, err } = op_webgpu_create_bind_group_layout( device.rid, descriptor.label, descriptor.entries, @@ -1137,7 +1242,7 @@ class GPUDevice extends EventTarget { return rid; }, ); - const { rid, err } = ops.op_webgpu_create_pipeline_layout( + const { rid, err } = op_webgpu_create_pipeline_layout( device.rid, descriptor.label, bindGroupLayouts, @@ -1204,7 +1309,9 @@ class GPUDevice extends EventTarget { resource: rid, }; } else { + // deno-lint-ignore prefer-primordials const rid = assertResource(resource.buffer, prefix, context); + // deno-lint-ignore prefer-primordials assertDeviceMatch(device, resource.buffer, { prefix, resourceContext: context, @@ -1220,7 +1327,7 @@ class GPUDevice extends EventTarget { } }); - const { rid, err } = ops.op_webgpu_create_bind_group( + const { rid, err } = op_webgpu_create_bind_group( device.rid, descriptor.label, layout, @@ -1250,7 +1357,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_shader_module( + const { rid, err } = op_webgpu_create_shader_module( device.rid, descriptor.label, descriptor.code, @@ -1301,7 +1408,7 @@ class GPUDevice extends EventTarget { selfContext: "this", }); - const { rid, err } = ops.op_webgpu_create_compute_pipeline( + const { rid, err } = op_webgpu_create_compute_pipeline( device.rid, descriptor.label, layout, @@ -1375,7 +1482,7 @@ class GPUDevice extends EventTarget { }; } - const { rid, err } = ops.op_webgpu_create_render_pipeline({ + const { rid, err } = op_webgpu_create_render_pipeline({ deviceRid: device.rid, label: descriptor.label, layout, @@ -1423,7 +1530,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_command_encoder( + const { rid, err } = op_webgpu_create_command_encoder( device.rid, descriptor.label, ); @@ -1453,7 +1560,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_render_bundle_encoder({ + const { rid, err } = op_webgpu_create_render_bundle_encoder({ deviceRid: device.rid, ...descriptor, }); @@ -1482,7 +1589,7 @@ class GPUDevice extends EventTarget { "Argument 1", ); const device = assertDevice(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_query_set({ + const { rid, err } = op_webgpu_create_query_set({ deviceRid: device.rid, ...descriptor, }); @@ -1619,7 +1726,7 @@ class GPUQueue { return rid; }, ); - const { err } = ops.op_webgpu_queue_submit(device.rid, commandBufferRids); + const { err } = op_webgpu_queue_submit(device.rid, commandBufferRids); for (let i = 0; i < commandBuffers.length; ++i) { commandBuffers[i][_rid] = undefined; } @@ -1664,13 +1771,23 @@ class GPUQueue { selfContext: "this", resourceContext: "Argument 1", }); - const { err } = ops.op_webgpu_write_buffer( + /** @type {ArrayBufferLike} */ + let abLike = data; + if (isTypedArray(data)) { + abLike = TypedArrayPrototypeGetBuffer( + /** @type {Uint8Array} */ (data), + ); + } else if (isDataView(data)) { + abLike = DataViewPrototypeGetBuffer(/** @type {DataView} */ (data)); + } + + const { err } = op_webgpu_write_buffer( device.rid, bufferRid, bufferOffset, dataOffset, size, - new Uint8Array(ArrayBufferIsView(data) ? data.buffer : data), + new Uint8Array(abLike), ); device.pushError(err); } @@ -1704,7 +1821,18 @@ class GPUQueue { selfContext: "this", resourceContext: "texture", }); - const { err } = ops.op_webgpu_write_texture( + + /** @type {ArrayBufferLike} */ + let abLike = data; + if (isTypedArray(data)) { + abLike = TypedArrayPrototypeGetBuffer( + /** @type {Uint8Array} */ (data), + ); + } else if (isDataView(data)) { + abLike = DataViewPrototypeGetBuffer(/** @type {DataView} */ (data)); + } + + const { err } = op_webgpu_write_texture( device.rid, { texture: textureRid, @@ -1716,7 +1844,7 @@ class GPUQueue { }, dataLayout, normalizeGPUExtent3D(size), - new Uint8Array(ArrayBufferIsView(data) ? data.buffer : data), + new Uint8Array(abLike), ); device.pushError(err); } @@ -1900,8 +2028,7 @@ class GPUBuffer { this[_mapMode] = mode; this[_state] = "pending"; const promise = PromisePrototypeThen( - core.opAsync( - "op_webgpu_buffer_get_map_async", + op_webgpu_buffer_get_map_async( bufferRid, device.rid, mode, @@ -1947,9 +2074,9 @@ class GPUBuffer { throw new DOMException(`${prefix}: invalid state.`, "OperationError"); } for (let i = 0; i < mappedRanges.length; ++i) { - const [buffer, _rid, start] = mappedRanges[i]; + const { 0: buffer, 1: _rid, 2: start } = mappedRanges[i]; // TODO(lucacasonato): is this logic correct? - const end = start + buffer.byteLength; + const end = start + ArrayBufferPrototypeGetByteLength(buffer); if ( (start >= offset && start < (offset + rangeSize)) || (end >= offset && end < (offset + rangeSize)) @@ -1962,7 +2089,7 @@ class GPUBuffer { } const buffer = new ArrayBuffer(rangeSize); - const { rid } = ops.op_webgpu_buffer_get_mapped_range( + const { rid } = op_webgpu_buffer_get_mapped_range( bufferRid, offset, size, @@ -2016,8 +2143,8 @@ class GPUBuffer { throw new DOMException(`${prefix}: invalid state.`, "OperationError"); } for (let i = 0; i < mappedRanges.length; ++i) { - const [buffer, mappedRid] = mappedRanges[i]; - const { err } = ops.op_webgpu_buffer_unmap( + const { 0: buffer, 1: mappedRid } = mappedRanges[i]; + const { err } = op_webgpu_buffer_unmap( bufferRid, mappedRid, ...new SafeArrayIterator(write ? [new Uint8Array(buffer)] : []), @@ -2135,7 +2262,7 @@ class GPUTexture { [_device]; /** @type {number | undefined} */ [_rid]; - /** @type {WeakRef[]} */ + /** @type {SafeWeakRef[]} */ [_views]; /** @type {number} */ @@ -2189,7 +2316,7 @@ class GPUTexture { ); const device = assertDevice(this, prefix, "this"); const textureRid = assertResource(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_create_texture_view({ + const { rid, err } = op_webgpu_create_texture_view({ textureRid, ...descriptor, }); @@ -2200,7 +2327,7 @@ class GPUTexture { this, rid, ); - ArrayPrototypePush(this[_views], new WeakRef(textureView)); + ArrayPrototypePush(this[_views], new SafeWeakRef(textureView)); return textureView; } @@ -2423,7 +2550,10 @@ class GPUBindGroupLayout { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUBindGroupLayoutPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUBindGroupLayoutPrototype, + this, + ), keys: [ "label", ], @@ -2471,7 +2601,10 @@ class GPUPipelineLayout { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUPipelineLayoutPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUPipelineLayoutPrototype, + this, + ), keys: [ "label", ], @@ -2483,7 +2616,6 @@ class GPUPipelineLayout { GPUObjectBaseMixin("GPUPipelineLayout", GPUPipelineLayout); const GPUPipelineLayoutPrototype = GPUPipelineLayout.prototype; - /** * @param {string | null} label * @param {InnerGPUDevice} device @@ -2643,8 +2775,8 @@ class GPUComputePipeline { index = webidl.converters["unsigned long"](index, prefix, "Argument 1"); const device = assertDevice(this, prefix, "this"); const computePipelineRid = assertResource(this, prefix, "this"); - const { rid, label, err } = ops - .op_webgpu_compute_pipeline_get_bind_group_layout( + const { rid, label, err } = + op_webgpu_compute_pipeline_get_bind_group_layout( computePipelineRid, index, ); @@ -2663,7 +2795,10 @@ class GPUComputePipeline { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUComputePipelinePrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUComputePipelinePrototype, + this, + ), keys: [ "label", ], @@ -2719,11 +2854,10 @@ class GPURenderPipeline { index = webidl.converters["unsigned long"](index, prefix, "Argument 1"); const device = assertDevice(this, prefix, "this"); const renderPipelineRid = assertResource(this, prefix, "this"); - const { rid, label, err } = ops - .op_webgpu_render_pipeline_get_bind_group_layout( - renderPipelineRid, - index, - ); + const { rid, label, err } = op_webgpu_render_pipeline_get_bind_group_layout( + renderPipelineRid, + index, + ); device.pushError(err); const bindGroupLayout = createGPUBindGroupLayout( @@ -2739,7 +2873,10 @@ class GPURenderPipeline { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPURenderPipelinePrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPURenderPipelinePrototype, + this, + ), keys: [ "label", ], @@ -2793,7 +2930,7 @@ class GPUCommandEncoder { [_device]; /** @type {number | undefined} */ [_rid]; - /** @type {WeakRef[]} */ + /** @type {SafeWeakRef[]} */ [_encoders]; [_cleanup]() { @@ -2843,7 +2980,7 @@ class GPUCommandEncoder { if (descriptor.depthStencilAttachment) { if ( descriptor.depthStencilAttachment.depthLoadOp === "clear" && - !("depthClearValue" in descriptor.depthStencilAttachment) + !(ObjectHasOwn(descriptor.depthStencilAttachment, "depthClearValue")) ) { throw webidl.makeException( TypeError, @@ -2903,7 +3040,11 @@ class GPUCommandEncoder { prefix, `resolve target texture view for ${context}`, ); - assertResource(colorAttachment.resolveTarget[_texture], prefix, `texture backing resolve target texture view for ${context}`); + assertResource( + colorAttachment.resolveTarget[_texture], + prefix, + `texture backing resolve target texture view for ${context}`, + ); assertDeviceMatch( device, colorAttachment.resolveTarget[_texture], @@ -2936,16 +3077,21 @@ class GPUCommandEncoder { let timestampWrites = null; if (descriptor.timestampWrites) { - const querySet = assertResource(descriptor.timestampWrites.querySet, prefix, "querySet"); + const querySet = assertResource( + descriptor.timestampWrites.querySet, + prefix, + "querySet", + ); timestampWrites = { querySet, - beginningOfPassWriteIndex: descriptor.timestampWrites.beginningOfPassWriteIndex, + beginningOfPassWriteIndex: + descriptor.timestampWrites.beginningOfPassWriteIndex, endOfPassWriteIndex: descriptor.timestampWrites.endOfPassWriteIndex, }; } - const { rid } = ops.op_webgpu_command_encoder_begin_render_pass( + const { rid } = op_webgpu_command_encoder_begin_render_pass( commandEncoderRid, descriptor.label, colorAttachments, @@ -2959,7 +3105,7 @@ class GPUCommandEncoder { this, rid, ); - ArrayPrototypePush(this[_encoders], new WeakRef(renderPassEncoder)); + ArrayPrototypePush(this[_encoders], new SafeWeakRef(renderPassEncoder)); return renderPassEncoder; } @@ -2981,16 +3127,21 @@ class GPUCommandEncoder { let timestampWrites = null; if (descriptor.timestampWrites) { - const querySet = assertResource(descriptor.timestampWrites.querySet, prefix, "querySet"); + const querySet = assertResource( + descriptor.timestampWrites.querySet, + prefix, + "querySet", + ); timestampWrites = { querySet, - beginningOfPassWriteIndex: descriptor.timestampWrites.beginningOfPassWriteIndex, + beginningOfPassWriteIndex: + descriptor.timestampWrites.beginningOfPassWriteIndex, endOfPassWriteIndex: descriptor.timestampWrites.endOfPassWriteIndex, }; } - const { rid } = ops.op_webgpu_command_encoder_begin_compute_pass( + const { rid } = op_webgpu_command_encoder_begin_compute_pass( commandEncoderRid, descriptor.label, timestampWrites, @@ -3001,7 +3152,7 @@ class GPUCommandEncoder { this, rid, ); - ArrayPrototypePush(this[_encoders], new WeakRef(computePassEncoder)); + ArrayPrototypePush(this[_encoders], new SafeWeakRef(computePassEncoder)); return computePassEncoder; } @@ -3055,7 +3206,7 @@ class GPUCommandEncoder { selfContext: "this", }); - const { err } = ops.op_webgpu_command_encoder_copy_buffer_to_buffer( + const { err } = op_webgpu_command_encoder_copy_buffer_to_buffer( commandEncoderRid, sourceRid, sourceOffset, @@ -3086,10 +3237,12 @@ class GPUCommandEncoder { const device = assertDevice(this, prefix, "this"); const commandEncoderRid = assertResource(this, prefix, "this"); const sourceBufferRid = assertResource( + // deno-lint-ignore prefer-primordials source.buffer, prefix, "source in Argument 1", ); + // deno-lint-ignore prefer-primordials assertDeviceMatch(device, source.buffer, { prefix, resourceContext: "source in Argument 1", @@ -3106,7 +3259,7 @@ class GPUCommandEncoder { selfContext: "this", }); - const { err } = ops.op_webgpu_command_encoder_copy_buffer_to_texture( + const { err } = op_webgpu_command_encoder_copy_buffer_to_texture( commandEncoderRid, { ...source, @@ -3159,16 +3312,18 @@ class GPUCommandEncoder { selfContext: "this", }); const destinationBufferRid = assertResource( + // deno-lint-ignore prefer-primordials destination.buffer, prefix, "buffer in Argument 2", ); + // deno-lint-ignore prefer-primordials assertDeviceMatch(device, destination.buffer, { prefix, resourceContext: "buffer in Argument 2", selfContext: "this", }); - const { err } = ops.op_webgpu_command_encoder_copy_texture_to_buffer( + const { err } = op_webgpu_command_encoder_copy_texture_to_buffer( commandEncoderRid, { texture: sourceTextureRid, @@ -3228,7 +3383,7 @@ class GPUCommandEncoder { resourceContext: "texture in Argument 2", selfContext: "this", }); - const { err } = ops.op_webgpu_command_encoder_copy_texture_to_texture( + const { err } = op_webgpu_command_encoder_copy_texture_to_texture( commandEncoderRid, { texture: sourceTextureRid, @@ -3264,7 +3419,7 @@ class GPUCommandEncoder { const device = assertDevice(this, prefix, "this"); const commandEncoderRid = assertResource(this, prefix, "this"); const bufferRid = assertResource(buffer, prefix, "Argument 1"); - const { err } = ops.op_webgpu_command_encoder_clear_buffer( + const { err } = op_webgpu_command_encoder_clear_buffer( commandEncoderRid, bufferRid, offset, @@ -3283,7 +3438,7 @@ class GPUCommandEncoder { groupLabel = webidl.converters.USVString(groupLabel, prefix, "Argument 1"); const device = assertDevice(this, prefix, "this"); const commandEncoderRid = assertResource(this, prefix, "this"); - const { err } = ops.op_webgpu_command_encoder_push_debug_group( + const { err } = op_webgpu_command_encoder_push_debug_group( commandEncoderRid, groupLabel, ); @@ -3295,7 +3450,7 @@ class GPUCommandEncoder { const prefix = "Failed to execute 'popDebugGroup' on 'GPUCommandEncoder'"; const device = assertDevice(this, prefix, "this"); const commandEncoderRid = assertResource(this, prefix, "this"); - const { err } = ops.op_webgpu_command_encoder_pop_debug_group( + const { err } = op_webgpu_command_encoder_pop_debug_group( commandEncoderRid, ); device.pushError(err); @@ -3316,7 +3471,7 @@ class GPUCommandEncoder { ); const device = assertDevice(this, prefix, "this"); const commandEncoderRid = assertResource(this, prefix, "this"); - const { err } = ops.op_webgpu_command_encoder_insert_debug_marker( + const { err } = op_webgpu_command_encoder_insert_debug_marker( commandEncoderRid, markerLabel, ); @@ -3341,7 +3496,7 @@ class GPUCommandEncoder { resourceContext: "Argument 1", selfContext: "this", }); - const { err } = ops.op_webgpu_command_encoder_write_timestamp( + const { err } = op_webgpu_command_encoder_write_timestamp( commandEncoderRid, querySetRid, queryIndex, @@ -3393,7 +3548,7 @@ class GPUCommandEncoder { resourceContext: "Argument 3", selfContext: "this", }); - const { err } = ops.op_webgpu_command_encoder_resolve_query_set( + const { err } = op_webgpu_command_encoder_resolve_query_set( commandEncoderRid, querySetRid, firstQuery, @@ -3418,7 +3573,7 @@ class GPUCommandEncoder { ); const device = assertDevice(this, prefix, "this"); const commandEncoderRid = assertResource(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_command_encoder_finish( + const { rid, err } = op_webgpu_command_encoder_finish( commandEncoderRid, descriptor.label, ); @@ -3439,7 +3594,10 @@ class GPUCommandEncoder { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUCommandEncoderPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUCommandEncoderPrototype, + this, + ), keys: [ "label", ], @@ -3506,7 +3664,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_set_viewport({ + op_webgpu_render_pass_set_viewport({ renderPassRid, x, y, @@ -3539,7 +3697,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_set_scissor_rect( + op_webgpu_render_pass_set_scissor_rect( renderPassRid, x, y, @@ -3560,7 +3718,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_set_blend_constant( + op_webgpu_render_pass_set_blend_constant( renderPassRid, normalizeGPUColor(color), ); @@ -3582,7 +3740,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_set_stencil_reference( + op_webgpu_render_pass_set_stencil_reference( renderPassRid, reference, ); @@ -3600,7 +3758,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_begin_occlusion_query( + op_webgpu_render_pass_begin_occlusion_query( renderPassRid, queryIndex, ); @@ -3613,7 +3771,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_end_occlusion_query(renderPassRid); + op_webgpu_render_pass_end_occlusion_query(renderPassRid); } /** @@ -3646,7 +3804,7 @@ class GPURenderPassEncoder { }); return rid; }); - ops.op_webgpu_render_pass_execute_bundles(renderPassRid, bundleRids); + op_webgpu_render_pass_execute_bundles(renderPassRid, bundleRids); } end() { @@ -3663,7 +3821,7 @@ class GPURenderPassEncoder { "encoder referenced by this", ); const renderPassRid = assertResource(this, prefix, "this"); - const { err } = ops.op_webgpu_render_pass_end( + const { err } = op_webgpu_render_pass_end( commandEncoderRid, renderPassRid, ); @@ -3695,16 +3853,14 @@ class GPURenderPassEncoder { selfContext: "this", }); if ( - !(ObjectPrototypeIsPrototypeOf( - Uint32ArrayPrototype, - dynamicOffsetsData, - )) + TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !== + "Uint32Array" ) { dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []); dynamicOffsetsDataStart = 0; dynamicOffsetsDataLength = dynamicOffsetsData.length; } - ops.op_webgpu_render_pass_set_bind_group( + op_webgpu_render_pass_set_bind_group( renderPassRid, index, bindGroupRid, @@ -3726,7 +3882,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_push_debug_group(renderPassRid, groupLabel); + op_webgpu_render_pass_push_debug_group(renderPassRid, groupLabel); } popDebugGroup() { @@ -3736,7 +3892,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_pop_debug_group(renderPassRid); + op_webgpu_render_pass_pop_debug_group(renderPassRid); } /** @@ -3755,7 +3911,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_insert_debug_marker(renderPassRid, markerLabel); + op_webgpu_render_pass_insert_debug_marker(renderPassRid, markerLabel); } /** @@ -3783,7 +3939,7 @@ class GPURenderPassEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_pass_set_pipeline(renderPassRid, pipelineRid); + op_webgpu_render_pass_set_pipeline(renderPassRid, pipelineRid); } /** @@ -3820,7 +3976,7 @@ class GPURenderPassEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_pass_set_index_buffer( + op_webgpu_render_pass_set_index_buffer( renderPassRid, bufferRid, indexFormat, @@ -3859,7 +4015,7 @@ class GPURenderPassEncoder { resourceContext: "Argument 2", selfContext: "this", }); - ops.op_webgpu_render_pass_set_vertex_buffer( + op_webgpu_render_pass_set_vertex_buffer( renderPassRid, slot, bufferRid, @@ -3901,7 +4057,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_draw( + op_webgpu_render_pass_draw( renderPassRid, vertexCount, instanceCount, @@ -3947,7 +4103,7 @@ class GPURenderPassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const renderPassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_pass_draw_indexed( + op_webgpu_render_pass_draw_indexed( renderPassRid, indexCount, instanceCount, @@ -3992,7 +4148,7 @@ class GPURenderPassEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_pass_draw_indirect( + op_webgpu_render_pass_draw_indirect( renderPassRid, indirectBufferRid, indirectOffset, @@ -4035,7 +4191,7 @@ class GPURenderPassEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_pass_draw_indexed_indirect( + op_webgpu_render_pass_draw_indexed_indirect( renderPassRid, indirectBufferRid, indirectOffset, @@ -4046,7 +4202,10 @@ class GPURenderPassEncoder { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPURenderPassEncoderPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPURenderPassEncoderPrototype, + this, + ), keys: [ "label", ], @@ -4118,7 +4277,7 @@ class GPUComputePassEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_compute_pass_set_pipeline(computePassRid, pipelineRid); + op_webgpu_compute_pass_set_pipeline(computePassRid, pipelineRid); } /** @@ -4153,7 +4312,7 @@ class GPUComputePassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const computePassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_compute_pass_dispatch_workgroups( + op_webgpu_compute_pass_dispatch_workgroups( computePassRid, workgroupCountX, workgroupCountY, @@ -4197,7 +4356,7 @@ class GPUComputePassEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_compute_pass_dispatch_workgroups_indirect( + op_webgpu_compute_pass_dispatch_workgroups_indirect( computePassRid, indirectBufferRid, indirectOffset, @@ -4218,7 +4377,7 @@ class GPUComputePassEncoder { "encoder referenced by this", ); const computePassRid = assertResource(this, prefix, "this"); - const { err } = ops.op_webgpu_compute_pass_end( + const { err } = op_webgpu_compute_pass_end( commandEncoderRid, computePassRid, ); @@ -4251,16 +4410,14 @@ class GPUComputePassEncoder { selfContext: "this", }); if ( - !(ObjectPrototypeIsPrototypeOf( - Uint32ArrayPrototype, - dynamicOffsetsData, - )) + TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !== + "Uint32Array" ) { dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []); dynamicOffsetsDataStart = 0; dynamicOffsetsDataLength = dynamicOffsetsData.length; } - ops.op_webgpu_compute_pass_set_bind_group( + op_webgpu_compute_pass_set_bind_group( computePassRid, index, bindGroupRid, @@ -4282,7 +4439,7 @@ class GPUComputePassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const computePassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_compute_pass_push_debug_group(computePassRid, groupLabel); + op_webgpu_compute_pass_push_debug_group(computePassRid, groupLabel); } popDebugGroup() { @@ -4292,7 +4449,7 @@ class GPUComputePassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const computePassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_compute_pass_pop_debug_group(computePassRid); + op_webgpu_compute_pass_pop_debug_group(computePassRid); } /** @@ -4311,7 +4468,7 @@ class GPUComputePassEncoder { assertDevice(this[_encoder], prefix, "encoder referenced by this"); assertResource(this[_encoder], prefix, "encoder referenced by this"); const computePassRid = assertResource(this, prefix, "this"); - ops.op_webgpu_compute_pass_insert_debug_marker( + op_webgpu_compute_pass_insert_debug_marker( computePassRid, markerLabel, ); @@ -4321,7 +4478,10 @@ class GPUComputePassEncoder { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPUComputePassEncoderPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPUComputePassEncoderPrototype, + this, + ), keys: [ "label", ], @@ -4430,7 +4590,7 @@ class GPURenderBundleEncoder { ); const device = assertDevice(this, prefix, "this"); const renderBundleEncoderRid = assertResource(this, prefix, "this"); - const { rid, err } = ops.op_webgpu_render_bundle_encoder_finish( + const { rid, err } = op_webgpu_render_bundle_encoder_finish( renderBundleEncoderRid, descriptor.label, ); @@ -4466,16 +4626,14 @@ class GPURenderBundleEncoder { selfContext: "this", }); if ( - !(ObjectPrototypeIsPrototypeOf( - Uint32ArrayPrototype, - dynamicOffsetsData, - )) + TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !== + "Uint32Array" ) { dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []); dynamicOffsetsDataStart = 0; dynamicOffsetsDataLength = dynamicOffsetsData.length; } - ops.op_webgpu_render_bundle_encoder_set_bind_group( + op_webgpu_render_bundle_encoder_set_bind_group( renderBundleEncoderRid, index, bindGroupRid, @@ -4496,7 +4654,7 @@ class GPURenderBundleEncoder { groupLabel = webidl.converters.USVString(groupLabel, prefix, "Argument 1"); assertDevice(this, prefix, "this"); const renderBundleEncoderRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_bundle_encoder_push_debug_group( + op_webgpu_render_bundle_encoder_push_debug_group( renderBundleEncoderRid, groupLabel, ); @@ -4508,7 +4666,7 @@ class GPURenderBundleEncoder { "Failed to execute 'popDebugGroup' on 'GPURenderBundleEncoder'"; assertDevice(this, prefix, "this"); const renderBundleEncoderRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_bundle_encoder_pop_debug_group( + op_webgpu_render_bundle_encoder_pop_debug_group( renderBundleEncoderRid, ); } @@ -4528,7 +4686,7 @@ class GPURenderBundleEncoder { ); assertDevice(this, prefix, "this"); const renderBundleEncoderRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_bundle_encoder_insert_debug_marker( + op_webgpu_render_bundle_encoder_insert_debug_marker( renderBundleEncoderRid, markerLabel, ); @@ -4555,7 +4713,7 @@ class GPURenderBundleEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_bundle_encoder_set_pipeline( + op_webgpu_render_bundle_encoder_set_pipeline( renderBundleEncoderRid, pipelineRid, ); @@ -4588,7 +4746,7 @@ class GPURenderBundleEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_bundle_encoder_set_index_buffer( + op_webgpu_render_bundle_encoder_set_index_buffer( renderBundleEncoderRid, bufferRid, indexFormat, @@ -4622,7 +4780,7 @@ class GPURenderBundleEncoder { resourceContext: "Argument 2", selfContext: "this", }); - ops.op_webgpu_render_bundle_encoder_set_vertex_buffer( + op_webgpu_render_bundle_encoder_set_vertex_buffer( renderBundleEncoderRid, slot, bufferRid, @@ -4663,7 +4821,7 @@ class GPURenderBundleEncoder { ); assertDevice(this, prefix, "this"); const renderBundleEncoderRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_bundle_encoder_draw( + op_webgpu_render_bundle_encoder_draw( renderBundleEncoderRid, vertexCount, instanceCount, @@ -4709,7 +4867,7 @@ class GPURenderBundleEncoder { ); assertDevice(this, prefix, "this"); const renderBundleEncoderRid = assertResource(this, prefix, "this"); - ops.op_webgpu_render_bundle_encoder_draw_indexed( + op_webgpu_render_bundle_encoder_draw_indexed( renderBundleEncoderRid, indexCount, instanceCount, @@ -4750,7 +4908,7 @@ class GPURenderBundleEncoder { resourceContext: "Argument 1", selfContext: "this", }); - ops.op_webgpu_render_bundle_encoder_draw_indirect( + op_webgpu_render_bundle_encoder_draw_indirect( renderBundleEncoderRid, indirectBufferRid, indirectOffset, @@ -4761,7 +4919,10 @@ class GPURenderBundleEncoder { return inspect( createFilteredInspectProxy({ object: this, - evaluate: ObjectPrototypeIsPrototypeOf(GPURenderBundleEncoderPrototype, this), + evaluate: ObjectPrototypeIsPrototypeOf( + GPURenderBundleEncoderPrototype, + this, + ), keys: [ "label", ], @@ -4870,12 +5031,12 @@ class GPUQuerySet { get type() { webidl.assertBranded(this, GPUQuerySetPrototype); - this[_type](); + return this[_type](); } get count() { webidl.assertBranded(this, GPUQuerySetPrototype); - this[_count](); + return this[_count](); } [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { @@ -6957,6 +7118,78 @@ webidl.converters["GPUSignedOffset32"] = (V, opts) => // TYPEDEF: GPUFlagsConstant webidl.converters["GPUFlagsConstant"] = webidl.converters["unsigned long"]; +// ENUM: GPUCanvasAlphaMode +webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter( + "GPUCanvasAlphaMode", + [ + "opaque", + "premultiplied", + ], +); + +// NON-SPEC: ENUM: GPUPresentMode +webidl.converters["GPUPresentMode"] = webidl.createEnumConverter( + "GPUPresentMode", + [ + "autoVsync", + "autoNoVsync", + "fifo", + "fifoRelaxed", + "immediate", + "mailbox", + ], +); + +// DICT: GPUCanvasConfiguration +const dictMembersGPUCanvasConfiguration = [ + { key: "device", converter: webidl.converters.GPUDevice, required: true }, + { + key: "format", + converter: webidl.converters.GPUTextureFormat, + required: true, + }, + { + key: "usage", + converter: webidl.converters["GPUTextureUsageFlags"], + defaultValue: GPUTextureUsage.RENDER_ATTACHMENT, + }, + { + key: "alphaMode", + converter: webidl.converters["GPUCanvasAlphaMode"], + defaultValue: "opaque", + }, + + // Extended from spec + { + key: "presentMode", + converter: webidl.converters["GPUPresentMode"], + }, + { + key: "width", + converter: webidl.converters["long"], + required: true, + }, + { + key: "height", + converter: webidl.converters["long"], + required: true, + }, + { + key: "viewFormats", + converter: webidl.createSequenceConverter( + webidl.converters["GPUTextureFormat"], + ), + get defaultValue() { + return []; + }, + }, +]; +webidl.converters["GPUCanvasConfiguration"] = webidl + .createDictionaryConverter( + "GPUCanvasConfiguration", + dictMembersGPUCanvasConfiguration, + ); + const gpu = webidl.createBranded(GPU); export { _device, diff --git a/deno_webgpu/02_surface.js b/deno_webgpu/02_surface.js index d16f5c245d..f35f745af4 100644 --- a/deno_webgpu/02_surface.js +++ b/deno_webgpu/02_surface.js @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // @ts-check /// @@ -6,27 +6,32 @@ /// /// -const core = globalThis.Deno.core; -const ops = core.ops; -import * as webidl from "ext:deno_webidl/00_webidl.js"; -const primordials = globalThis.__bootstrap.primordials; -const { Symbol } = primordials; +import { primordials } from "ext:core/mod.js"; import { - _device, - assertDevice, - createGPUTexture, - GPUTextureUsage, -} from "ext:deno_webgpu/01_webgpu.js"; + op_webgpu_surface_configure, + op_webgpu_surface_create, + op_webgpu_surface_get_current_texture, + op_webgpu_surface_present, +} from "ext:core/ops"; +const { + ObjectPrototypeIsPrototypeOf, + Symbol, + SymbolFor, + TypeError, +} = primordials; + +import * as webidl from "ext:deno_webidl/00_webidl.js"; +import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; +import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; const _surfaceRid = Symbol("[[surfaceRid]]"); const _configuration = Symbol("[[configuration]]"); const _canvas = Symbol("[[canvas]]"); const _currentTexture = Symbol("[[currentTexture]]"); +const _present = Symbol("[[present]]"); class GPUCanvasContext { /** @type {number} */ [_surfaceRid]; - /** @type {InnerGPUDevice} */ - [_device]; [_configuration]; [_canvas]; /** @type {GPUTexture | undefined} */ @@ -50,11 +55,15 @@ class GPUCanvasContext { context: "Argument 1", }); + const { _device, assertDevice } = loadWebGPU(); this[_device] = configuration.device[_device]; this[_configuration] = configuration; - const device = assertDevice(this, { prefix, context: "configuration.device" }); + const device = assertDevice(this, { + prefix, + context: "configuration.device", + }); - const { err } = ops.op_webgpu_surface_configure({ + const { err } = op_webgpu_surface_configure({ surfaceRid: this[_surfaceRid], deviceRid: device.rid, format: configuration.format, @@ -69,6 +78,8 @@ class GPUCanvasContext { } unconfigure() { + const { _device } = loadWebGPU(); + webidl.assertBranded(this, GPUCanvasContextPrototype); this[_configuration] = null; @@ -77,11 +88,13 @@ class GPUCanvasContext { getCurrentTexture() { webidl.assertBranded(this, GPUCanvasContextPrototype); - const prefix = "Failed to execute 'getCurrentTexture' on 'GPUCanvasContext'"; + const prefix = + "Failed to execute 'getCurrentTexture' on 'GPUCanvasContext'"; if (this[_configuration] === null) { throw new DOMException("context is not configured.", "InvalidStateError"); } + const { createGPUTexture, assertDevice } = loadWebGPU(); const device = assertDevice(this, { prefix, context: "this" }); @@ -89,7 +102,10 @@ class GPUCanvasContext { return this[_currentTexture]; } - const { rid } = ops.op_webgpu_surface_get_current_texture(device.rid, this[_surfaceRid]); + const { rid } = op_webgpu_surface_get_current_texture( + device.rid, + this[_surfaceRid], + ); const texture = createGPUTexture( { @@ -112,102 +128,66 @@ class GPUCanvasContext { return texture; } - // Extended from spec. Required to present the texture; browser don't need this. - present() { + // Required to present the texture; browser don't need this. + [_present]() { + const { assertDevice } = loadWebGPU(); + webidl.assertBranded(this, GPUCanvasContextPrototype); const prefix = "Failed to execute 'present' on 'GPUCanvasContext'"; - const device = assertDevice(this[_currentTexture], { prefix, context: "this" }); - ops.op_webgpu_surface_present(device.rid, this[_surfaceRid]); + const device = assertDevice(this[_currentTexture], { + prefix, + context: "this", + }); + op_webgpu_surface_present(device.rid, this[_surfaceRid]); this[_currentTexture].destroy(); this[_currentTexture] = undefined; } + + [SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) { + return inspect( + createFilteredInspectProxy({ + object: this, + evaluate: ObjectPrototypeIsPrototypeOf(GPUCanvasContextPrototype, this), + keys: [ + "canvas", + ], + }), + inspectOptions, + ); + } } const GPUCanvasContextPrototype = GPUCanvasContext.prototype; function createCanvasContext(options) { + // lazy load webgpu if needed const canvasContext = webidl.createBranded(GPUCanvasContext); canvasContext[_surfaceRid] = options.surfaceRid; canvasContext[_canvas] = options.canvas; return canvasContext; } -// Converters - -// ENUM: GPUCanvasAlphaMode -webidl.converters["GPUCanvasAlphaMode"] = webidl.createEnumConverter( - "GPUCanvasAlphaMode", - [ - "opaque", - "premultiplied", - ], -); - -// NON-SPEC: ENUM: GPUPresentMode -webidl.converters["GPUPresentMode"] = webidl.createEnumConverter( - "GPUPresentMode", - [ - "autoVsync", - "autoNoVsync", - "fifo", - "fifoRelaxed", - "immediate", - "mailbox", - ], -); - -// DICT: GPUCanvasConfiguration -const dictMembersGPUCanvasConfiguration = [ - { key: "device", converter: webidl.converters.GPUDevice, required: true }, - { - key: "format", - converter: webidl.converters.GPUTextureFormat, - required: true, - }, - { - key: "usage", - converter: webidl.converters["GPUTextureUsageFlags"], - defaultValue: GPUTextureUsage.RENDER_ATTACHMENT, - }, - { - key: "alphaMode", - converter: webidl.converters["GPUCanvasAlphaMode"], - defaultValue: "opaque", - }, - - // Extended from spec - { - key: "presentMode", - converter: webidl.converters["GPUPresentMode"], - }, - { - key: "width", - converter: webidl.converters["long"], - required: true, - }, - { - key: "height", - converter: webidl.converters["long"], - required: true, - }, - { - key: "viewFormats", - converter: webidl.createSequenceConverter( - webidl.converters["GPUTextureFormat"], - ), - get defaultValue() { - return []; - }, - }, -]; -webidl.converters["GPUCanvasConfiguration"] = webidl - .createDictionaryConverter( - "GPUCanvasConfiguration", - dictMembersGPUCanvasConfiguration, - ); - - -window.__bootstrap.webgpu = { - ...window.__bootstrap.webgpu, - GPUCanvasContext, - createCanvasContext, -}; +// External webgpu surfaces + +// TODO(@littledivy): This will extend `OffscreenCanvas` when we add it. +class UnsafeWindowSurface { + #ctx; + #surfaceRid; + + constructor(system, win, display) { + this.#surfaceRid = op_webgpu_surface_create(system, win, display); + } + + getContext(context) { + if (context !== "webgpu") { + throw new TypeError("Only 'webgpu' context is supported."); + } + this.#ctx = createCanvasContext({ surfaceRid: this.#surfaceRid }); + return this.#ctx; + } + + present() { + this.#ctx[_present](); + } +} + +export { GPUCanvasContext, UnsafeWindowSurface }; diff --git a/deno_webgpu/Cargo.toml b/deno_webgpu/Cargo.toml index 9f6d96a95b..ee9ca14d02 100644 --- a/deno_webgpu/Cargo.toml +++ b/deno_webgpu/Cargo.toml @@ -1,8 +1,8 @@ -# Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. [package] name = "deno_webgpu" -version = "0.85.0" +version = "0.110.0" authors = ["the Deno authors"] edition.workspace = true license = "MIT" @@ -13,9 +13,6 @@ description = "WebGPU implementation for Deno" [lib] path = "lib.rs" -[features] -surface = ["wgpu-core/raw-window-handle", "dep:raw-window-handle"] - # We make all dependencies conditional on not being wasm, # so the whole workspace can built as wasm. [target.'cfg(not(target_arch = "wasm32"))'.dependencies] @@ -23,7 +20,7 @@ deno_core.workspace = true serde = { workspace = true, features = ["derive"] } tokio = { workspace = true, features = ["full"] } wgpu-types = { workspace = true, features = ["serde"] } -raw-window-handle = { workspace = true, optional = true } +raw-window-handle = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgpu-core] workspace = true diff --git a/deno_webgpu/LICENSE.md b/deno_webgpu/LICENSE.md index aec557f3a0..56753af367 100644 --- a/deno_webgpu/LICENSE.md +++ b/deno_webgpu/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright 2018-2023 the Deno authors +Copyright 2018-2024 the Deno authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/deno_webgpu/README.md b/deno_webgpu/README.md index 1cf031cda2..c419bfc60e 100644 --- a/deno_webgpu/README.md +++ b/deno_webgpu/README.md @@ -2,8 +2,8 @@ This op crate implements the WebGPU API as defined in https://gpuweb.github.io/gpuweb/ in Deno. The implementation targets the spec -draft as of February 22, 2021. The spec is still very much in flux. This op -crate tries to stay up to date with the spec, but is constrained by the features +draft as of March 31, 2024. The spec is still very much in flux. This extension +tries to stay up to date with the spec, but is constrained by the features implemented in our GPU backend library [wgpu](https://github.com/gfx-rs/wgpu). The spec is still very bare bones, and is still missing many details. As the diff --git a/deno_webgpu/binding.rs b/deno_webgpu/binding.rs index c0b9b5836d..0655976d5f 100644 --- a/deno_webgpu/binding.rs +++ b/deno_webgpu/binding.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::op2; diff --git a/deno_webgpu/buffer.rs b/deno_webgpu/buffer.rs index 9a2ebb003b..5b7d208806 100644 --- a/deno_webgpu/buffer.rs +++ b/deno_webgpu/buffer.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::type_error; use deno_core::error::AnyError; @@ -163,6 +163,7 @@ pub fn op_webgpu_buffer_get_mapped_range( )) .map_err(|e| DomExceptionOperationError::new(&e.to_string()))?; + // SAFETY: guarantee to be safe from wgpu let slice = unsafe { std::slice::from_raw_parts_mut(slice_pointer, range_size as usize) }; buf.copy_from_slice(slice); @@ -189,6 +190,7 @@ pub fn op_webgpu_buffer_unmap( let buffer = buffer_resource.1; if let Some(buf) = buf { + // SAFETY: guarantee to be safe from wgpu let slice = unsafe { std::slice::from_raw_parts_mut(mapped_resource.0, mapped_resource.1) }; slice.copy_from_slice(buf); } diff --git a/deno_webgpu/bundle.rs b/deno_webgpu/bundle.rs index d503599313..dfe5ccf494 100644 --- a/deno_webgpu/bundle.rs +++ b/deno_webgpu/bundle.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::type_error; use deno_core::error::AnyError; diff --git a/deno_webgpu/byow.rs b/deno_webgpu/byow.rs new file mode 100644 index 0000000000..21982204c9 --- /dev/null +++ b/deno_webgpu/byow.rs @@ -0,0 +1,122 @@ +// 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; +use std::ffi::c_void; +use std::ptr::NonNull; + +use crate::surface::WebGpuSurface; + +#[op2(fast)] +#[smi] +pub fn op_webgpu_surface_create( + state: &mut OpState, + #[string] system: &str, + p1: *const c_void, + p2: *const c_void, +) -> Result { + let instance = state.borrow::(); + // Security note: + // + // The `p1` and `p2` parameters are pointers to platform-specific window + // handles. + // + // The code below works under the assumption that: + // + // - handles can only be created by the FFI interface which + // enforces --allow-ffi. + // + // - `*const c_void` deserizalizes null and v8::External. + // + // - Only FFI can export v8::External to user code. + if p1.is_null() { + return Err(type_error("Invalid parameters")); + } + + let (win_handle, display_handle) = raw_window(system, p1, p2)?; + let surface = unsafe { instance.instance_create_surface(display_handle, win_handle, None)? }; + + let rid = state + .resource_table + .add(WebGpuSurface(instance.clone(), surface)); + Ok(rid) +} + +type RawHandles = ( + raw_window_handle::RawWindowHandle, + raw_window_handle::RawDisplayHandle, +); + +#[cfg(target_os = "macos")] +fn raw_window( + system: &str, + _ns_window: *const c_void, + ns_view: *const c_void, +) -> Result { + if system != "cocoa" { + return Err(type_error("Invalid system on macOS")); + } + + let win_handle = { + let handle = raw_window_handle::AppKitWindowHandle::new( + NonNull::new(ns_view as *mut c_void).ok_or(type_error("ns_view is null"))?, + ); + + raw_window_handle::RawWindowHandle::AppKit(handle) + }; + let display_handle = + raw_window_handle::RawDisplayHandle::AppKit(raw_window_handle::AppKitDisplayHandle::new()); + Ok((win_handle, display_handle)) +} + +#[cfg(target_os = "windows")] +fn raw_window( + system: &str, + window: *const c_void, + hinstance: *const c_void, +) -> Result { + use raw_window_handle::WindowsDisplayHandle; + if system != "win32" { + return Err(type_error("Invalid system on Windows")); + } + + let win_handle = { + let mut handle = raw_window_handle::Win32WindowHandle::new(); + handle.hwnd = window as *mut c_void; + handle.hinstance = hinstance as *mut c_void; + + raw_window_handle::RawWindowHandle::Win32(handle) + }; + + let display_handle = raw_window_handle::RawDisplayHandle::Windows(WindowsDisplayHandle::new()); + Ok((win_handle, display_handle)) +} + +#[cfg(target_os = "linux")] +fn raw_window( + system: &str, + window: *const c_void, + display: *const c_void, +) -> Result { + if system != "x11" { + return Err(type_error("Invalid system on Linux")); + } + + let win_handle = { + let mut handle = raw_window_handle::XlibWindowHandle::new(window as *mut c_void as _); + + raw_window_handle::RawWindowHandle::Xlib(handle) + }; + + let display_handle = { + let mut handle = + raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void)); + + raw_window_handle::RawDisplayHandle::Xlib(handle) + }; + + Ok((win_handle, display_handle)) +} diff --git a/deno_webgpu/command_encoder.rs b/deno_webgpu/command_encoder.rs index 679ac3cabf..20dfe0db09 100644 --- a/deno_webgpu/command_encoder.rs +++ b/deno_webgpu/command_encoder.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::WebGpuQuerySet; use deno_core::error::AnyError; diff --git a/deno_webgpu/compute_pass.rs b/deno_webgpu/compute_pass.rs index e1c9e29193..65ac93d632 100644 --- a/deno_webgpu/compute_pass.rs +++ b/deno_webgpu/compute_pass.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::op2; diff --git a/deno_webgpu/error.rs b/deno_webgpu/error.rs index 6c509a80d3..e20485c285 100644 --- a/deno_webgpu/error.rs +++ b/deno_webgpu/error.rs @@ -1,4 +1,5 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + use deno_core::error::AnyError; use deno_core::ResourceId; use serde::Serialize; @@ -23,7 +24,6 @@ use wgpu_core::device::DeviceError; use wgpu_core::pipeline::CreateComputePipelineError; use wgpu_core::pipeline::CreateRenderPipelineError; use wgpu_core::pipeline::CreateShaderModuleError; -#[cfg(feature = "surface")] use wgpu_core::present::ConfigureSurfaceError; use wgpu_core::resource::BufferAccessError; use wgpu_core::resource::CreateBufferError; @@ -277,7 +277,6 @@ impl From for WebGpuError { } } -#[cfg(feature = "surface")] impl From for WebGpuError { fn from(err: ConfigureSurfaceError) -> Self { WebGpuError::Validation(fmt_err(&err)) diff --git a/deno_webgpu/lib.rs b/deno_webgpu/lib.rs index 40e76e0fa5..7afc5571b7 100644 --- a/deno_webgpu/lib.rs +++ b/deno_webgpu/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. #![cfg(not(target_arch = "wasm32"))] #![warn(unsafe_op_in_unsafe_fn)] @@ -19,6 +19,8 @@ pub use wgpu_types; use error::DomExceptionOperationError; use error::WebGpuResult; +pub const UNSTABLE_FEATURE_NAME: &str = "webgpu"; + #[macro_use] mod macros { macro_rules! gfx_select { @@ -71,6 +73,7 @@ mod macros { pub mod binding; pub mod buffer; pub mod bundle; +pub mod byow; pub mod command_encoder; pub mod compute_pass; pub mod error; @@ -79,23 +82,9 @@ pub mod queue; pub mod render_pass; pub mod sampler; pub mod shader; -#[cfg(feature = "surface")] pub mod surface; pub mod texture; -pub struct Unstable(pub bool); - -fn check_unstable(state: &OpState, api_name: &str) { - let unstable = state.borrow::(); - if !unstable.0 { - eprintln!( - "Unstable API '{}'. The --unstable flag must be provided.", - api_name - ); - std::process::exit(70); - } -} - pub type Instance = std::sync::Arc; struct WebGpuAdapter(Instance, wgpu_core::id::AdapterId); @@ -224,12 +213,15 @@ deno_core::extension!( queue::op_webgpu_write_texture, // shader shader::op_webgpu_create_shader_module, + // surface + surface::op_webgpu_surface_configure, + surface::op_webgpu_surface_get_current_texture, + surface::op_webgpu_surface_present, + // byow + //byow::op_webgpu_surface_create, ], - esm = ["01_webgpu.js"], - options = { unstable: bool }, - state = |state, options| { - state.put(Unstable(options.unstable)); - }, + esm = ["00_init.js", "02_surface.js"], + lazy_loaded_esm = ["01_webgpu.js"], ); fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { @@ -391,15 +383,21 @@ pub struct GpuAdapterDevice { is_software: bool, } -#[op2(async)] +#[op2] #[serde] -pub async fn op_webgpu_request_adapter( +pub fn op_webgpu_request_adapter( state: Rc>, #[serde] power_preference: Option, force_fallback_adapter: bool, ) -> Result { let mut state = state.borrow_mut(); - check_unstable(&state, "navigator.gpu.requestAdapter"); + + // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` + // once we phase out `check_or_exit_with_legacy_fallback` + state + .feature_checker + .check_or_exit_with_legacy_fallback(UNSTABLE_FEATURE_NAME, "navigator.gpu.requestAdapter"); + let backends = std::env::var("DENO_WEBGPU_BACKEND").map_or_else( |_| wgpu_types::Backends::all(), |s| wgpu_core::instance::parse_backends_from_comma_list(&s), @@ -649,9 +647,9 @@ impl From for wgpu_types::Features { } } -#[op2(async)] +#[op2] #[serde] -pub async fn op_webgpu_request_device( +pub fn op_webgpu_request_device( state: Rc>, #[smi] adapter_rid: ResourceId, #[string] label: String, @@ -705,9 +703,9 @@ pub struct GPUAdapterInfo { description: String, } -#[op2(async)] +#[op2] #[serde] -pub async fn op_webgpu_request_adapter_info( +pub fn op_webgpu_request_adapter_info( state: Rc>, #[smi] adapter_rid: ResourceId, ) -> Result { diff --git a/deno_webgpu/pipeline.rs b/deno_webgpu/pipeline.rs index dcd4151eb5..fd2c0710fe 100644 --- a/deno_webgpu/pipeline.rs +++ b/deno_webgpu/pipeline.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::op2; diff --git a/deno_webgpu/queue.rs b/deno_webgpu/queue.rs index 61b56c7586..e5e20cb011 100644 --- a/deno_webgpu/queue.rs +++ b/deno_webgpu/queue.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::command_encoder::WebGpuCommandBuffer; use deno_core::error::AnyError; diff --git a/deno_webgpu/render_pass.rs b/deno_webgpu/render_pass.rs index 47b98c91fd..11b2f22865 100644 --- a/deno_webgpu/render_pass.rs +++ b/deno_webgpu/render_pass.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::type_error; use deno_core::error::AnyError; diff --git a/deno_webgpu/sampler.rs b/deno_webgpu/sampler.rs index 0d65d727a1..822c4bda14 100644 --- a/deno_webgpu/sampler.rs +++ b/deno_webgpu/sampler.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::op2; diff --git a/deno_webgpu/shader.rs b/deno_webgpu/shader.rs index f4604a04a5..17cde43936 100644 --- a/deno_webgpu/shader.rs +++ b/deno_webgpu/shader.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::op2; diff --git a/deno_webgpu/surface.rs b/deno_webgpu/surface.rs index 4d8412999c..a8b984eefe 100644 --- a/deno_webgpu/surface.rs +++ b/deno_webgpu/surface.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use super::WebGpuResult; use deno_core::error::AnyError; @@ -11,21 +11,6 @@ use std::borrow::Cow; use std::rc::Rc; use wgpu_types::SurfaceStatus; -deno_core::extension!( - deno_webgpu_surface, - deps = [deno_webidl, deno_web, deno_webgpu], - ops = [ - op_webgpu_surface_configure, - op_webgpu_surface_get_current_texture, - op_webgpu_surface_present, - ], - esm = ["02_surface.js"], - options = { unstable: bool }, - state = |state, options| { - state.put(super::Unstable(options.unstable)); - }, -); - pub struct WebGpuSurface(pub crate::Instance, pub wgpu_core::id::SurfaceId); impl Resource for WebGpuSurface { fn name(&self) -> Cow { diff --git a/deno_webgpu/texture.rs b/deno_webgpu/texture.rs index a9be7b9914..2dc1a740a5 100644 --- a/deno_webgpu/texture.rs +++ b/deno_webgpu/texture.rs @@ -1,4 +1,4 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use deno_core::error::AnyError; use deno_core::op2; From 49df0875ca6228a6f77b829168e8db71fa97fd5f Mon Sep 17 00:00:00 2001 From: crowlkats Date: Mon, 1 Apr 2024 23:31:59 +0200 Subject: [PATCH 02/12] update spec --- deno_webgpu/01_webgpu.js | 37 ++++++++--------- deno_webgpu/binding.rs | 18 +------- deno_webgpu/pipeline.rs | 4 +- deno_webgpu/webgpu.idl | 88 +++++++++++++++++++++------------------- 4 files changed, 69 insertions(+), 78 deletions(-) diff --git a/deno_webgpu/01_webgpu.js b/deno_webgpu/01_webgpu.js index 6aa90bd4db..4121af107d 100644 --- a/deno_webgpu/01_webgpu.js +++ b/deno_webgpu/01_webgpu.js @@ -454,17 +454,10 @@ class GPUAdapter { } /** - * @param {string[]} unmaskHints * @returns {Promise} */ - requestAdapterInfo(unmaskHints = []) { + requestAdapterInfo() { webidl.assertBranded(this, GPUAdapterPrototype); - const prefix = "Failed to execute 'requestAdapterInfo' on 'GPUAdapter'"; - unmaskHints = webidl.converters["sequence"]( - unmaskHints, - prefix, - "Argument 1", - ); const { vendor, @@ -474,16 +467,10 @@ class GPUAdapter { } = op_webgpu_request_adapter_info(this[_adapter].rid); const adapterInfo = webidl.createBranded(GPUAdapterInfo); - adapterInfo[_vendor] = ArrayPrototypeIncludes(unmaskHints, "vendor") - ? vendor - : ""; - adapterInfo[_architecture] = - ArrayPrototypeIncludes(unmaskHints, "architecture") ? architecture : ""; - adapterInfo[_device] = ArrayPrototypeIncludes(unmaskHints, "device") - ? device - : ""; - adapterInfo[_description] = - ArrayPrototypeIncludes(unmaskHints, "description") ? description : ""; + adapterInfo[_vendor] = vendor; + adapterInfo[_architecture] = architecture; + adapterInfo[_device] = device; + adapterInfo[_description] = description; return PromiseResolve(adapterInfo); } @@ -687,6 +674,14 @@ class GPUSupportedLimits { webidl.assertBranded(this, GPUSupportedLimitsPrototype); return this[_limits].maxInterStageShaderComponents; } + get maxColorAttachments() { + webidl.assertBranded(this, GPUSupportedLimitsPrototype); + return this[_limits].maxColorAttachments; + } + get maxColorAttachmentBytesPerSample() { + webidl.assertBranded(this, GPUSupportedLimitsPrototype); + return this[_limits].maxColorAttachmentBytesPerSample; + } get maxComputeWorkgroupStorageSize() { webidl.assertBranded(this, GPUSupportedLimitsPrototype); return this[_limits].maxComputeWorkgroupStorageSize; @@ -743,6 +738,8 @@ class GPUSupportedLimits { "maxVertexAttributes", "maxVertexBufferArrayStride", "maxInterStageShaderComponents", + "maxColorAttachments", + "maxColorAttachmentBytesPerSample", "maxComputeWorkgroupStorageSize", "maxComputeInvocationsPerWorkgroup", "maxComputeWorkgroupSizeX", @@ -5354,6 +5351,7 @@ webidl.converters["GPUTextureFormat"] = webidl.createEnumConverter( "bgra8unorm", "bgra8unorm-srgb", "rgb9e5ufloat", + "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", "rg32uint", @@ -5769,6 +5767,8 @@ webidl.converters["GPUStorageTextureAccess"] = webidl.createEnumConverter( "GPUStorageTextureAccess", [ "write-only", + "read-only", + "read-write", ], ); @@ -6028,7 +6028,6 @@ const dictMembersGPUProgrammableStage = [ { key: "entryPoint", converter: webidl.converters["USVString"], - required: true, }, { key: "constants", diff --git a/deno_webgpu/binding.rs b/deno_webgpu/binding.rs index 0655976d5f..0efeb6716a 100644 --- a/deno_webgpu/binding.rs +++ b/deno_webgpu/binding.rs @@ -112,25 +112,11 @@ impl From for wgpu_types::TextureSampleType { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct GpuStorageTextureBindingLayout { - access: GpuStorageTextureAccess, + access: wgpu_types::StorageTextureAccess, format: wgpu_types::TextureFormat, view_dimension: wgpu_types::TextureViewDimension, } -#[derive(Deserialize)] -#[serde(rename_all = "kebab-case")] -enum GpuStorageTextureAccess { - WriteOnly, -} - -impl From for wgpu_types::StorageTextureAccess { - fn from(access: GpuStorageTextureAccess) -> Self { - match access { - GpuStorageTextureAccess::WriteOnly => wgpu_types::StorageTextureAccess::WriteOnly, - } - } -} - #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct GpuBindGroupLayoutEntry { @@ -165,7 +151,7 @@ impl From for wgpu_types::BindingType { }, GpuBindingType::StorageTexture(storage_texture) => { wgpu_types::BindingType::StorageTexture { - access: storage_texture.access.into(), + access: storage_texture.access, format: storage_texture.format, view_dimension: storage_texture.view_dimension, } diff --git a/deno_webgpu/pipeline.rs b/deno_webgpu/pipeline.rs index fd2c0710fe..ab7cf42e7b 100644 --- a/deno_webgpu/pipeline.rs +++ b/deno_webgpu/pipeline.rs @@ -74,7 +74,7 @@ pub enum GPUPipelineLayoutOrGPUAutoLayoutMode { #[serde(rename_all = "camelCase")] pub struct GpuProgrammableStage { module: ResourceId, - entry_point: String, + entry_point: Option, // constants: HashMap } @@ -110,7 +110,7 @@ pub fn op_webgpu_create_compute_pipeline( layout: pipeline_layout, stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: compute_shader_module_resource.1, - entry_point: Some(Cow::from(compute.entry_point)), + entry_point: compute.entry_point.map(Cow::from), // TODO(lucacasonato): support args.compute.constants }, }; diff --git a/deno_webgpu/webgpu.idl b/deno_webgpu/webgpu.idl index 46d587874f..870e0f40e9 100644 --- a/deno_webgpu/webgpu.idl +++ b/deno_webgpu/webgpu.idl @@ -6,7 +6,7 @@ dictionary GPUObjectDescriptorBase { USVString label = ""; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUSupportedLimits { readonly attribute unsigned long maxTextureDimension1D; readonly attribute unsigned long maxTextureDimension2D; @@ -30,6 +30,8 @@ interface GPUSupportedLimits { readonly attribute unsigned long maxVertexAttributes; readonly attribute unsigned long maxVertexBufferArrayStride; readonly attribute unsigned long maxInterStageShaderComponents; + readonly attribute unsigned long maxColorAttachments; + readonly attribute unsigned long maxColorAttachmentBytesPerSample; readonly attribute unsigned long maxComputeWorkgroupStorageSize; readonly attribute unsigned long maxComputeInvocationsPerWorkgroup; readonly attribute unsigned long maxComputeWorkgroupSizeX; @@ -38,12 +40,12 @@ interface GPUSupportedLimits { readonly attribute unsigned long maxComputeWorkgroupsPerDimension; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUSupportedFeatures { readonly setlike; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUAdapterInfo { readonly attribute DOMString vendor; readonly attribute DOMString architecture; @@ -57,9 +59,10 @@ interface mixin NavigatorGPU { Navigator includes NavigatorGPU; WorkerNavigator includes NavigatorGPU; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPU { Promise requestAdapter(optional GPURequestAdapterOptions options = {}); + GPUTextureFormat getPreferredCanvasFormat(); }; dictionary GPURequestAdapterOptions { @@ -72,14 +75,14 @@ enum GPUPowerPreference { "high-performance", }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUAdapter { [SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedLimits limits; readonly attribute boolean isFallbackAdapter; Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); - Promise requestAdapterInfo(optional sequence unmaskHints = []); + Promise requestAdapterInfo(); }; dictionary GPUDeviceDescriptor @@ -141,7 +144,7 @@ enum GPUFeatureName { "shader-early-depth-test", }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUDevice : EventTarget { [SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedLimits limits; @@ -171,7 +174,7 @@ interface GPUDevice : EventTarget { }; GPUDevice includes GPUObjectBase; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUBuffer { readonly attribute GPUSize64Out size; readonly attribute GPUFlagsConstant usage; @@ -200,7 +203,7 @@ dictionary GPUBufferDescriptor }; typedef [EnforceRange] unsigned long GPUBufferUsageFlags; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] namespace GPUBufferUsage { const GPUFlagsConstant MAP_READ = 0x0001; const GPUFlagsConstant MAP_WRITE = 0x0002; @@ -215,13 +218,13 @@ namespace GPUBufferUsage { }; typedef [EnforceRange] unsigned long GPUMapModeFlags; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] namespace GPUMapMode { const GPUFlagsConstant READ = 0x0001; const GPUFlagsConstant WRITE = 0x0002; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUTexture { GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {}); @@ -256,7 +259,7 @@ enum GPUTextureDimension { }; typedef [EnforceRange] unsigned long GPUTextureUsageFlags; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] namespace GPUTextureUsage { const GPUFlagsConstant COPY_SRC = 0x01; const GPUFlagsConstant COPY_DST = 0x02; @@ -265,7 +268,7 @@ namespace GPUTextureUsage { const GPUFlagsConstant RENDER_ATTACHMENT = 0x10; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUTextureView { }; GPUTextureView includes GPUObjectBase; @@ -328,6 +331,7 @@ enum GPUTextureFormat { "bgra8unorm-srgb", // Packed 32-bit formats "rgb9e5ufloat", + "rgb10a2uint", "rgb10a2unorm", "rg11b10ufloat", @@ -416,7 +420,7 @@ enum GPUTextureFormat { "astc-12x12-unorm-srgb", }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUSampler { }; GPUSampler includes GPUObjectBase; @@ -462,7 +466,7 @@ enum GPUCompareFunction { "always", }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUBindGroupLayout { }; GPUBindGroupLayout includes GPUObjectBase; @@ -483,7 +487,7 @@ dictionary GPUBindGroupLayoutEntry { }; typedef [EnforceRange] unsigned long GPUShaderStageFlags; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] namespace GPUShaderStage { const GPUFlagsConstant VERTEX = 0x1; const GPUFlagsConstant FRAGMENT = 0x2; @@ -528,6 +532,8 @@ dictionary GPUTextureBindingLayout { enum GPUStorageTextureAccess { "write-only", + "read-only", + "read-write", }; dictionary GPUStorageTextureBindingLayout { @@ -536,7 +542,7 @@ dictionary GPUStorageTextureBindingLayout { GPUTextureViewDimension viewDimension = "2d"; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUBindGroup { }; GPUBindGroup includes GPUObjectBase; @@ -560,7 +566,7 @@ dictionary GPUBufferBinding { GPUSize64 size; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUPipelineLayout { }; GPUPipelineLayout includes GPUObjectBase; @@ -570,7 +576,7 @@ dictionary GPUPipelineLayoutDescriptor required sequence bindGroupLayouts; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUShaderModule { }; GPUShaderModule includes GPUObjectBase; @@ -586,7 +592,7 @@ enum GPUCompilationMessageType { "info", }; -[Exposed=(Window, DedicatedWorker), Serializable, SecureContext] +[Exposed=(Window, Worker), Serializable, SecureContext] interface GPUCompilationMessage { readonly attribute DOMString message; readonly attribute GPUCompilationMessageType type; @@ -596,7 +602,7 @@ interface GPUCompilationMessage { readonly attribute unsigned long long length; }; -[Exposed=(Window, DedicatedWorker), Serializable, SecureContext] +[Exposed=(Window, Worker), Serializable, SecureContext] interface GPUCompilationInfo { readonly attribute FrozenArray messages; }; @@ -616,13 +622,13 @@ interface mixin GPUPipelineBase { dictionary GPUProgrammableStage { required GPUShaderModule module; - required USVString entryPoint; + USVString entryPoint; record constants; }; -typedef double GPUPipelineConstantValue; // May represent WGSL’s bool, f32, i32, u32, and f16 if enabled. +typedef double GPUPipelineConstantValue; // May represent WGSL's bool, f32, i32, u32, and f16 if enabled. -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUComputePipeline { }; GPUComputePipeline includes GPUObjectBase; @@ -633,7 +639,7 @@ dictionary GPUComputePipelineDescriptor required GPUProgrammableStage compute; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPURenderPipeline { }; GPURenderPipeline includes GPUObjectBase; @@ -701,7 +707,7 @@ dictionary GPUBlendState { }; typedef [EnforceRange] unsigned long GPUColorWriteFlags; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] namespace GPUColorWrite { const GPUFlagsConstant RED = 0x1; const GPUFlagsConstant GREEN = 0x2; @@ -854,7 +860,7 @@ dictionary GPUImageCopyTexture { GPUTextureAspect aspect = "all"; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUCommandBuffer { }; GPUCommandBuffer includes GPUObjectBase; @@ -866,7 +872,7 @@ dictionary GPUCommandBufferDescriptor interface mixin GPUCommandsMixin { }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUCommandEncoder { GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {}); @@ -933,7 +939,7 @@ interface mixin GPUDebugCommandsMixin { undefined insertDebugMarker(USVString markerLabel); }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUComputePassEncoder { undefined setPipeline(GPUComputePipeline pipeline); undefined dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1); @@ -957,7 +963,7 @@ dictionary GPUComputePassDescriptor GPUComputePassTimestampWrites timestampWrites; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPURenderPassEncoder { undefined setViewport(float x, float y, float width, float height, @@ -1052,7 +1058,7 @@ interface mixin GPURenderCommandsMixin { undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPURenderBundle { }; GPURenderBundle includes GPUObjectBase; @@ -1061,7 +1067,7 @@ dictionary GPURenderBundleDescriptor : GPUObjectDescriptorBase { }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPURenderBundleEncoder { GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {}); }; @@ -1077,7 +1083,7 @@ dictionary GPURenderBundleEncoderDescriptor boolean stencilReadOnly = false; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUQueue { undefined submit(sequence commandBuffers); @@ -1098,7 +1104,7 @@ interface GPUQueue { }; GPUQueue includes GPUObjectBase; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUQuerySet { undefined destroy(); @@ -1118,7 +1124,7 @@ enum GPUQueryType { "timestamp", }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUCanvasContext { readonly attribute (HTMLCanvasElement or OffscreenCanvas) canvas; @@ -1146,7 +1152,7 @@ enum GPUDeviceLostReason { "destroyed", }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUDeviceLostInfo { readonly attribute GPUDeviceLostReason reason; readonly attribute DOMString message; @@ -1156,18 +1162,18 @@ partial interface GPUDevice { readonly attribute Promise lost; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUError { readonly attribute DOMString message; }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUValidationError : GPUError { constructor(DOMString message); }; -[Exposed=(Window, DedicatedWorker), SecureContext] +[Exposed=(Window, Worker), SecureContext] interface GPUOutOfMemoryError : GPUError { constructor(DOMString message); @@ -1176,7 +1182,7 @@ interface GPUOutOfMemoryError enum GPUErrorFilter { "validation", "out-of-memory", - "internal" + "internal", }; partial interface GPUDevice { @@ -1185,7 +1191,7 @@ partial interface GPUDevice { }; partial interface GPUDevice { - [Exposed=(Window, DedicatedWorker)] + [Exposed=(Window, Worker)] attribute EventHandler onuncapturederror; }; From 7248056215d2517bdde9263c8edabc872425bf1a Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 04:21:47 +0200 Subject: [PATCH 03/12] more error handling --- deno_webgpu/01_webgpu.js | 298 +++++++++++++++++++++++++++++++++++++-- deno_webgpu/error.rs | 1 + deno_webgpu/webgpu.idl | 34 +++++ 3 files changed, 320 insertions(+), 13 deletions(-) diff --git a/deno_webgpu/01_webgpu.js b/deno_webgpu/01_webgpu.js index 4121af107d..c479fa1e24 100644 --- a/deno_webgpu/01_webgpu.js +++ b/deno_webgpu/01_webgpu.js @@ -93,7 +93,6 @@ const { ArrayBufferPrototypeGetByteLength, ArrayIsArray, ArrayPrototypeFilter, - ArrayPrototypeIncludes, ArrayPrototypeMap, ArrayPrototypePop, ArrayPrototypePush, @@ -314,6 +313,42 @@ class GPUOutOfMemoryError extends GPUError { } const GPUOutOfMemoryErrorPrototype = GPUOutOfMemoryError.prototype; +class GPUInternalError extends GPUError { + name = "GPUInternalError"; + constructor() { + super(illegalConstructorKey); + this[webidl.brand] = webidl.brand; + } +} +const GPUInternalErrorPrototype = GPUInternalError.prototype; + +class GPUUncapturedErrorEvent extends Event { + #error; + + constructor(type, gpuUncapturedErrorEventInitDict) { + super(type, gpuUncapturedErrorEventInitDict); + this[webidl.brand] = webidl.brand; + + const prefix = "Failed to construct 'GPUUncapturedErrorEvent'"; + webidl.requiredArguments(arguments.length, 2, prefix); + gpuUncapturedErrorEventInitDict = webidl.converters + .gpuUncapturedErrorEventInitDict( + gpuUncapturedErrorEventInitDict, + prefix, + "Argument 2", + ); + + this.#error = gpuUncapturedErrorEventInitDict.error; + } + + get error() { + webidl.assertBranded(this, GPUUncapturedErrorEventPrototype); + return this.#error; + } +} +const GPUUncapturedErrorEventPrototype = GPUUncapturedErrorEvent.prototype; +defineEventHandler(GPUUncapturedErrorEvent.prototype, "uncapturederror"); + class GPU { [webidl.brand] = webidl.brand; @@ -897,6 +932,8 @@ class InnerGPUDevice { resolveLost; /** @type {ErrorScope[]} */ errorScopeStack; + /** @type {GPUDevice} */ + device; /** * @param {InnerGPUDeviceOptions} options @@ -942,6 +979,8 @@ class InnerGPUDevice { ); case "out-of-memory": return PromiseReject(new GPUOutOfMemoryError()); + case "internal": + return PromiseReject(new GPUInternalError()); } } }); @@ -966,8 +1005,12 @@ class InnerGPUDevice { validationFilteredPromise, ); } else { - PromisePrototypeCatch(validationFilteredPromise, () => { - // TODO(lucacasonato): emit an UncapturedErrorEvent + PromisePrototypeCatch(validationFilteredPromise, (err) => { + this.device.dispatchEvent( + new GPUUncapturedErrorEvent("uncapturederror", { + error: err, + }), + ); }); } // prevent uncaptured promise rejections @@ -987,12 +1030,41 @@ class InnerGPUDevice { if (oomScope) { ArrayPrototypePush(oomScope.operations, oomFilteredPromise); } else { - PromisePrototypeCatch(oomFilteredPromise, () => { - // TODO(lucacasonato): emit an UncapturedErrorEvent + PromisePrototypeCatch(oomFilteredPromise, (err) => { + this.device.dispatchEvent( + new GPUUncapturedErrorEvent("uncapturederror", { + error: err, + }), + ); }); } // prevent uncaptured promise rejections PromisePrototypeCatch(oomFilteredPromise, (_err) => {}); + + const internalStack = ArrayPrototypeFilter( + this.errorScopeStack, + ({ filter }) => filter == "internal", + ); + const internalScope = internalStack[internalStack.length - 1]; + const internalFilteredPromise = PromisePrototypeCatch(operation, (err) => { + if (ObjectPrototypeIsPrototypeOf(GPUInternalErrorPrototype, err)) { + return PromiseReject(err); + } + return PromiseResolve(); + }); + if (internalScope) { + ArrayPrototypePush(internalScope.operations, internalFilteredPromise); + } else { + PromisePrototypeCatch(internalFilteredPromise, (err) => { + this.device.dispatchEvent( + new GPUUncapturedErrorEvent("uncapturederror", { + error: err, + }), + ); + }); + } + // prevent uncaptured promise rejections + PromisePrototypeCatch(internalFilteredPromise, (_err) => {}); } } @@ -1506,12 +1578,166 @@ class GPUDevice extends EventTarget { createComputePipelineAsync(descriptor) { // TODO(lucacasonato): this should be real async - return PromiseResolve(this.createComputePipeline(descriptor)); + + webidl.assertBranded(this, GPUDevicePrototype); + const prefix = + "Failed to execute 'createComputePipelineAsync' on 'GPUDevice'"; + webidl.requiredArguments(arguments.length, 1, prefix); + descriptor = webidl.converters.GPUComputePipelineDescriptor( + descriptor, + prefix, + "Argument 1", + ); + const device = assertDevice(this, prefix, "this"); + let layout = descriptor.layout; + if (typeof descriptor.layout !== "string") { + const context = "layout"; + layout = assertResource(descriptor.layout, prefix, context); + assertDeviceMatch(device, descriptor.layout, { + prefix, + resourceContext: context, + selfContext: "this", + }); + } + const module = assertResource( + descriptor.compute.module, + prefix, + "compute shader module", + ); + assertDeviceMatch(device, descriptor.compute.module, { + prefix, + resourceContext: "compute shader module", + selfContext: "this", + }); + + const { rid, err } = op_webgpu_create_compute_pipeline( + device.rid, + descriptor.label, + layout, + { + module, + entryPoint: descriptor.compute.entryPoint, + constants: descriptor.compute.constants, + }, + ); + device.pushError(err); + if (err) { + switch (err.type) { + case "validation": + return PromiseReject( + new GPUPipelineError(err.value ?? "validation error", { + reason: "validation", + }), + ); + case "internal": + return PromiseReject( + new GPUPipelineError("internal error", { + reason: "validation", + }), + ); + } + } + + const computePipeline = createGPUComputePipeline( + descriptor.label, + device, + rid, + ); + device.trackResource(computePipeline); + return PromiseResolve(computePipeline); } createRenderPipelineAsync(descriptor) { // TODO(lucacasonato): this should be real async - return PromiseResolve(this.createRenderPipeline(descriptor)); + + webidl.assertBranded(this, GPUDevicePrototype); + const prefix = + "Failed to execute 'createRenderPipelineAsync' on 'GPUDevice'"; + webidl.requiredArguments(arguments.length, 1, prefix); + descriptor = webidl.converters.GPURenderPipelineDescriptor( + descriptor, + prefix, + "Argument 1", + ); + const device = assertDevice(this, prefix, "this"); + let layout = descriptor.layout; + if (typeof descriptor.layout !== "string") { + const context = "layout"; + layout = assertResource(descriptor.layout, prefix, context); + assertDeviceMatch(device, descriptor.layout, { + prefix, + resourceContext: context, + selfContext: "this", + }); + } + const module = assertResource( + descriptor.vertex.module, + prefix, + "vertex shader module", + ); + assertDeviceMatch(device, descriptor.vertex.module, { + prefix, + resourceContext: "vertex shader module", + selfContext: "this", + }); + let fragment = undefined; + if (descriptor.fragment) { + const module = assertResource( + descriptor.fragment.module, + prefix, + "fragment shader module", + ); + assertDeviceMatch(device, descriptor.fragment.module, { + prefix, + resourceContext: "fragment shader module", + selfContext: "this", + }); + fragment = { + module, + entryPoint: descriptor.fragment.entryPoint, + targets: descriptor.fragment.targets, + }; + } + + const { rid, err } = op_webgpu_create_render_pipeline({ + deviceRid: device.rid, + label: descriptor.label, + layout, + vertex: { + module, + entryPoint: descriptor.vertex.entryPoint, + buffers: descriptor.vertex.buffers, + }, + primitive: descriptor.primitive, + depthStencil: descriptor.depthStencil, + multisample: descriptor.multisample, + fragment, + }); + device.pushError(err); + if (err) { + switch (err.type) { + case "validation": + return PromiseReject( + new GPUPipelineError(err.value ?? "validation error", { + reason: "validation", + }), + ); + case "internal": + return PromiseReject( + new GPUPipelineError("internal error", { + reason: "validation", + }), + ); + } + } + + const renderPipeline = createGPURenderPipeline( + descriptor.label, + device, + rid, + ); + device.trackResource(renderPipeline); + return renderPipeline; } /** @@ -1674,6 +1900,29 @@ class GPUDevice extends EventTarget { GPUObjectBaseMixin("GPUDevice", GPUDevice); const GPUDevicePrototype = GPUDevice.prototype; +class GPUPipelineError extends DOMException { + #reason; + + constructor(message = "", options = {}) { + const prefix = "Failed to construct 'GPUPipelineError'"; + message = webidl.converters.DOMString(message, prefix, "Argument 1"); + options = webidl.converters.GPUPipelineErrorInit( + options, + prefix, + "Argument 2", + ); + super(message, "GPUPipelineError"); + + this.#reason = options.reason; + } + + get reason() { + webidl.assertBranded(this, GPUPipelineErrorPrototype); + return this.#reason; + } +} +const GPUPipelineErrorPrototype = GPUPipelineError.prototype; + /** * @param {string | null} label * @param {InnerGPUDevice} device @@ -3083,7 +3332,7 @@ class GPUCommandEncoder { timestampWrites = { querySet, beginningOfPassWriteIndex: - descriptor.timestampWrites.beginningOfPassWriteIndex, + descriptor.timestampWrites.beginningOfPassWriteIndex, endOfPassWriteIndex: descriptor.timestampWrites.endOfPassWriteIndex, }; } @@ -3133,7 +3382,7 @@ class GPUCommandEncoder { timestampWrites = { querySet, beginningOfPassWriteIndex: - descriptor.timestampWrites.beginningOfPassWriteIndex, + descriptor.timestampWrites.beginningOfPassWriteIndex, endOfPassWriteIndex: descriptor.timestampWrites.endOfPassWriteIndex, }; } @@ -3851,7 +4100,7 @@ class GPURenderPassEncoder { }); if ( TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !== - "Uint32Array" + "Uint32Array" ) { dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []); dynamicOffsetsDataStart = 0; @@ -4408,7 +4657,7 @@ class GPUComputePassEncoder { }); if ( TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !== - "Uint32Array" + "Uint32Array" ) { dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []); dynamicOffsetsDataStart = 0; @@ -4624,7 +4873,7 @@ class GPURenderBundleEncoder { }); if ( TypedArrayPrototypeGetSymbolToStringTag(dynamicOffsetsData) !== - "Uint32Array" + "Uint32Array" ) { dynamicOffsetsData = new Uint32Array(dynamicOffsetsData ?? []); dynamicOffsetsDataStart = 0; @@ -5172,6 +5421,27 @@ webidl.converters["GPUFeatureName"] = webidl.createEnumConverter( ], ); +// DICTIONARY: GPUPipelineErrorInit +webidl.converters["GPUPipelineErrorInit"] = webidl.createDictionaryConverter( + "GPUPipelineErrorInit", + [ + { + key: "reason", + converter: webidl.converters.GPUPipelineErrorReason, + required: true, + }, + ], +); + +// ENUM: GPUPipelineErrorReason +webidl.converters["GPUPipelineErrorReason"] = webidl.createEnumConverter( + "GPUPipelineErrorReason", + [ + "validation", + "internal", + ], +); + // TYPEDEF: GPUSize32 webidl.converters["GPUSize32"] = (V, opts) => webidl.converters["unsigned long"](V, { ...opts, enforceRange: true }); @@ -7070,7 +7340,7 @@ webidl.converters["GPUErrorFilter"] = webidl.createEnumConverter( [ "out-of-memory", "validation", - "internal" + "internal", ], ); @@ -7210,6 +7480,7 @@ export { GPUDevice, GPUDeviceLostInfo, GPUError, + GPUInternalError, GPUMapMode, GPUOutOfMemoryError, GPUPipelineLayout, @@ -7227,5 +7498,6 @@ export { GPUTexture, GPUTextureUsage, GPUTextureView, + GPUUncapturedErrorEvent, GPUValidationError, }; diff --git a/deno_webgpu/error.rs b/deno_webgpu/error.rs index e20485c285..bb82008992 100644 --- a/deno_webgpu/error.rs +++ b/deno_webgpu/error.rs @@ -87,6 +87,7 @@ pub enum WebGpuError { Lost, OutOfMemory, Validation(String), + Internal, } impl From for WebGpuError { diff --git a/deno_webgpu/webgpu.idl b/deno_webgpu/webgpu.idl index 870e0f40e9..bd709d117e 100644 --- a/deno_webgpu/webgpu.idl +++ b/deno_webgpu/webgpu.idl @@ -607,6 +607,21 @@ interface GPUCompilationInfo { readonly attribute FrozenArray messages; }; +[Exposed=(Window, Worker), SecureContext, Serializable] +interface GPUPipelineError : DOMException { + constructor(optional DOMString message = "", GPUPipelineErrorInit options); + readonly attribute GPUPipelineErrorReason reason; +}; + +dictionary GPUPipelineErrorInit { + required GPUPipelineErrorReason reason; +}; + +enum GPUPipelineErrorReason { + "validation", + "internal", +}; + enum GPUAutoLayoutMode { "auto", }; @@ -1179,6 +1194,12 @@ interface GPUOutOfMemoryError constructor(DOMString message); }; +[Exposed=(Window, Worker), SecureContext] +interface GPUInternalError + : GPUError { + constructor(DOMString message); +}; + enum GPUErrorFilter { "validation", "out-of-memory", @@ -1190,6 +1211,19 @@ partial interface GPUDevice { Promise popErrorScope(); }; +[Exposed=(Window, Worker), SecureContext] +interface GPUUncapturedErrorEvent : Event { + constructor( + DOMString type, + GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict + ); + [SameObject] readonly attribute GPUError error; +}; + +dictionary GPUUncapturedErrorEventInit : EventInit { + required GPUError error; +}; + partial interface GPUDevice { [Exposed=(Window, Worker)] attribute EventHandler onuncapturederror; From d108a4abe2942a63ba7829f132400d058f3f2dd8 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 05:28:10 +0200 Subject: [PATCH 04/12] cleanup queue --- deno_webgpu/01_webgpu.js | 21 ++++++++++++++------- deno_webgpu/lib.rs | 12 +++++++++--- deno_webgpu/queue.rs | 26 +++++++++++++++++++------- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/deno_webgpu/01_webgpu.js b/deno_webgpu/01_webgpu.js index c479fa1e24..e96a21b937 100644 --- a/deno_webgpu/01_webgpu.js +++ b/deno_webgpu/01_webgpu.js @@ -468,7 +468,7 @@ class GPUAdapter { } } - const { rid, features, limits } = op_webgpu_request_device( + const { rid, queueRid, features, limits } = op_webgpu_request_device( this[_adapter].rid, descriptor.label, requiredFeatures, @@ -481,11 +481,13 @@ class GPUAdapter { features: createGPUSupportedFeatures(features), limits: createGPUSupportedLimits(limits), }); - return createGPUDevice( + const device = createGPUDevice( descriptor.label, inner, - createGPUQueue(descriptor.label, inner), + createGPUQueue(descriptor.label, inner, queueRid), ); + inner.device = device; + return device; } /** @@ -911,6 +913,7 @@ function GPUObjectBaseMixin(name, type) { * @property {number | undefined} rid * @property {GPUSupportedFeatures} features * @property {GPUSupportedLimits} limits + * @property {GPUDevice} device */ class InnerGPUDevice { @@ -1926,19 +1929,23 @@ const GPUPipelineErrorPrototype = GPUPipelineError.prototype; /** * @param {string | null} label * @param {InnerGPUDevice} device + * @param {number} rid * @returns {GPUQueue} */ -function createGPUQueue(label, device) { +function createGPUQueue(label, device, rid) { /** @type {GPUQueue} */ const queue = webidl.createBranded(GPUQueue); queue[_label] = label; queue[_device] = device; + queue[_rid] = rid; return queue; } class GPUQueue { /** @type {InnerGPUDevice} */ [_device]; + /** @type {number} */ + [_rid]; constructor() { webidl.illegalConstructor(); @@ -1972,7 +1979,7 @@ class GPUQueue { return rid; }, ); - const { err } = op_webgpu_queue_submit(device.rid, commandBufferRids); + const { err } = op_webgpu_queue_submit(this[_rid], commandBufferRids); for (let i = 0; i < commandBuffers.length; ++i) { commandBuffers[i][_rid] = undefined; } @@ -2028,7 +2035,7 @@ class GPUQueue { } const { err } = op_webgpu_write_buffer( - device.rid, + this[_rid], bufferRid, bufferOffset, dataOffset, @@ -2079,7 +2086,7 @@ class GPUQueue { } const { err } = op_webgpu_write_texture( - device.rid, + this[_rid], { texture: textureRid, mipLevel: destination.mipLevel, diff --git a/deno_webgpu/lib.rs b/deno_webgpu/lib.rs index 7afc5571b7..a8dd2bdf98 100644 --- a/deno_webgpu/lib.rs +++ b/deno_webgpu/lib.rs @@ -378,6 +378,7 @@ pub enum GpuAdapterDeviceOrErr { #[serde(rename_all = "camelCase")] pub struct GpuAdapterDevice { rid: ResourceId, + queue_rid: ResourceId, limits: wgpu_types::Limits, features: Vec<&'static str>, is_software: bool, @@ -667,7 +668,7 @@ pub fn op_webgpu_request_device( required_limits: required_limits.unwrap_or_default(), }; - let (device, _queue, maybe_err) = gfx_select!(adapter => instance.adapter_request_device( + let (device, queue, maybe_err) = gfx_select!(adapter => instance.adapter_request_device( adapter, &descriptor, std::env::var("DENO_WEBGPU_TRACE").ok().as_ref().map(std::path::Path::new), @@ -682,11 +683,16 @@ pub fn op_webgpu_request_device( let features = deserialize_features(&device_features); let limits = gfx_select!(device => instance.device_limits(device))?; - let instance = instance.clone(); - let rid = state.resource_table.add(WebGpuDevice(instance, device)); + let rid = state + .resource_table + .add(WebGpuDevice(instance.clone(), device)); + let queue_rid = state + .resource_table + .add(queue::WebGpuQueue(instance.clone(), queue)); Ok(GpuAdapterDevice { rid, + queue_rid, features, limits, // TODO(lucacasonato): report correctly from wgpu diff --git a/deno_webgpu/queue.rs b/deno_webgpu/queue.rs index e5e20cb011..d873df4bb7 100644 --- a/deno_webgpu/queue.rs +++ b/deno_webgpu/queue.rs @@ -1,16 +1,28 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. use crate::command_encoder::WebGpuCommandBuffer; +use crate::Instance; use deno_core::error::AnyError; use deno_core::op2; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; use serde::Deserialize; +use std::borrow::Cow; +use std::rc::Rc; use super::error::WebGpuResult; -type WebGpuQueue = super::WebGpuDevice; +pub struct WebGpuQueue(Instance, wgpu_core::id::QueueId); +impl Resource for WebGpuQueue { + fn name(&self) -> Cow { + "webGPUQueue".into() + } + + fn close(self: Rc) { + gfx_select!(self.1 => self.0.queue_drop(self.1)); + } +} #[op2] #[serde] @@ -19,7 +31,7 @@ pub fn op_webgpu_queue_submit( #[smi] queue_rid: ResourceId, #[serde] command_buffers: Vec, ) -> Result { - let instance = state.borrow::(); + let instance = state.borrow::(); let queue_resource = state.resource_table.get::(queue_rid)?; let queue = queue_resource.1; @@ -32,7 +44,7 @@ pub fn op_webgpu_queue_submit( }) .collect::, AnyError>>()?; - let maybe_err = gfx_select!(queue => instance.queue_submit(queue.transmute(), &ids)).err(); + let maybe_err = gfx_select!(queue => instance.queue_submit(queue, &ids)).err(); for rid in command_buffers { let resource = state.resource_table.take::(rid)?; @@ -71,7 +83,7 @@ pub fn op_webgpu_write_buffer( #[number] size: Option, #[buffer] buf: &[u8], ) -> Result { - let instance = state.borrow::(); + let instance = state.borrow::(); let buffer_resource = state .resource_table .get::(buffer)?; @@ -84,7 +96,7 @@ pub fn op_webgpu_write_buffer( None => &buf[data_offset..], }; let maybe_err = gfx_select!(queue => instance.queue_write_buffer( - queue.transmute(), + queue, buffer, buffer_offset, data @@ -104,7 +116,7 @@ pub fn op_webgpu_write_texture( #[serde] size: wgpu_types::Extent3d, #[buffer] buf: &[u8], ) -> Result { - let instance = state.borrow::(); + let instance = state.borrow::(); let texture_resource = state .resource_table .get::(destination.texture)?; @@ -120,7 +132,7 @@ pub fn op_webgpu_write_texture( let data_layout = data_layout.into(); gfx_ok!(queue => instance.queue_write_texture( - queue.transmute(), + queue, &destination, buf, &data_layout, From c593e05b8b9232ecc68ed1d9d956649dcd359892 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 05:31:25 +0200 Subject: [PATCH 05/12] fix --- deno_webgpu/queue.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno_webgpu/queue.rs b/deno_webgpu/queue.rs index d873df4bb7..2640134455 100644 --- a/deno_webgpu/queue.rs +++ b/deno_webgpu/queue.rs @@ -13,7 +13,7 @@ use std::rc::Rc; use super::error::WebGpuResult; -pub struct WebGpuQueue(Instance, wgpu_core::id::QueueId); +pub struct WebGpuQueue(pub Instance, pub wgpu_core::id::QueueId); impl Resource for WebGpuQueue { fn name(&self) -> Cow { "webGPUQueue".into() From d7c12e0dd442398e64526347b282c01cc85cea5c Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 06:08:49 +0200 Subject: [PATCH 06/12] fix byow Co-authored-by: Divy Srivastava --- deno_webgpu/Cargo.toml | 2 +- deno_webgpu/byow.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deno_webgpu/Cargo.toml b/deno_webgpu/Cargo.toml index ee9ca14d02..586eb90c85 100644 --- a/deno_webgpu/Cargo.toml +++ b/deno_webgpu/Cargo.toml @@ -24,7 +24,7 @@ raw-window-handle = { workspace = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgpu-core] workspace = true -features = ["trace", "replay", "serde", "strict_asserts", "wgsl", "gles"] +features = ["raw-window-handle", "trace", "replay", "serde", "strict_asserts", "wgsl", "gles"] # We want the wgpu-core Metal backend on macOS and iOS. [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgpu-core] diff --git a/deno_webgpu/byow.rs b/deno_webgpu/byow.rs index 21982204c9..8e186ceaa6 100644 --- a/deno_webgpu/byow.rs +++ b/deno_webgpu/byow.rs @@ -113,7 +113,7 @@ fn raw_window( let display_handle = { let mut handle = - raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void)); + raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void), 0); raw_window_handle::RawDisplayHandle::Xlib(handle) }; From ebf8f9fa6ce5cfdfdd46dbc66983b5d87f0a5f1a Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 06:16:10 +0200 Subject: [PATCH 07/12] fix --- deno_webgpu/lib.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/deno_webgpu/lib.rs b/deno_webgpu/lib.rs index a8dd2bdf98..8e7beb9fa9 100644 --- a/deno_webgpu/lib.rs +++ b/deno_webgpu/lib.rs @@ -369,14 +369,23 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { #[derive(Serialize)] #[serde(untagged)] -pub enum GpuAdapterDeviceOrErr { +pub enum GpuAdapterResOrErr { Error { err: String }, - Features(GpuAdapterDevice), + Features(GpuAdapterRes), } #[derive(Serialize)] #[serde(rename_all = "camelCase")] -pub struct GpuAdapterDevice { +pub struct GpuAdapterRes { + rid: ResourceId, + limits: wgpu_types::Limits, + features: Vec<&'static str>, + is_software: bool, +} + +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GpuDeviceRes { rid: ResourceId, queue_rid: ResourceId, limits: wgpu_types::Limits, @@ -390,7 +399,7 @@ pub fn op_webgpu_request_adapter( state: Rc>, #[serde] power_preference: Option, force_fallback_adapter: bool, -) -> Result { +) -> Result { let mut state = state.borrow_mut(); // TODO(bartlomieju): replace with `state.feature_checker.check_or_exit` @@ -431,7 +440,7 @@ pub fn op_webgpu_request_adapter( let adapter = match res { Ok(adapter) => adapter, Err(err) => { - return Ok(GpuAdapterDeviceOrErr::Error { + return Ok(GpuAdapterResOrErr::Error { err: err.to_string(), }) } @@ -444,7 +453,7 @@ pub fn op_webgpu_request_adapter( let rid = state.resource_table.add(WebGpuAdapter(instance, adapter)); - Ok(GpuAdapterDeviceOrErr::Features(GpuAdapterDevice { + Ok(GpuAdapterResOrErr::Features(GpuAdapterRes { rid, features, limits: adapter_limits, @@ -656,7 +665,7 @@ pub fn op_webgpu_request_device( #[string] label: String, #[serde] required_features: GpuRequiredFeatures, #[serde] required_limits: Option, -) -> Result { +) -> Result { let mut state = state.borrow_mut(); let adapter_resource = state.resource_table.get::(adapter_rid)?; let adapter = adapter_resource.1; @@ -690,7 +699,7 @@ pub fn op_webgpu_request_device( .resource_table .add(queue::WebGpuQueue(instance.clone(), queue)); - Ok(GpuAdapterDevice { + Ok(GpuDeviceRes { rid, queue_rid, features, From ed424854a5fa2f56d3fc43792a86e0fb839e3132 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 06:23:53 +0200 Subject: [PATCH 08/12] fix --- deno_webgpu/byow.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/deno_webgpu/byow.rs b/deno_webgpu/byow.rs index 8e186ceaa6..3042f46ee8 100644 --- a/deno_webgpu/byow.rs +++ b/deno_webgpu/byow.rs @@ -60,13 +60,11 @@ fn raw_window( return Err(type_error("Invalid system on macOS")); } - let win_handle = { - let handle = raw_window_handle::AppKitWindowHandle::new( + 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"))?, - ); + )); - raw_window_handle::RawWindowHandle::AppKit(handle) - }; let display_handle = raw_window_handle::RawDisplayHandle::AppKit(raw_window_handle::AppKitDisplayHandle::new()); Ok((win_handle, display_handle)) @@ -105,18 +103,13 @@ fn raw_window( return Err(type_error("Invalid system on Linux")); } - let win_handle = { - let mut handle = raw_window_handle::XlibWindowHandle::new(window as *mut c_void as _); + let win_handle = raw_window_handle::RawWindowHandle::Xlib( + raw_window_handle::XlibWindowHandle::new(window as *mut c_void as _), + ); - raw_window_handle::RawWindowHandle::Xlib(handle) - }; - - let display_handle = { - let mut handle = - raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void), 0); - - raw_window_handle::RawDisplayHandle::Xlib(handle) - }; + let display_handle = raw_window_handle::RawDisplayHandle::Xlib( + raw_window_handle::XlibDisplayHandle::new(NonNull::new(display as *mut c_void), 0), + ); Ok((win_handle, display_handle)) } From b79ec7266db793c807018106f4634837593f11d3 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 06:37:29 +0200 Subject: [PATCH 09/12] fix --- deno_webgpu/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deno_webgpu/lib.rs b/deno_webgpu/lib.rs index 8e7beb9fa9..6f4a60a62f 100644 --- a/deno_webgpu/lib.rs +++ b/deno_webgpu/lib.rs @@ -692,12 +692,12 @@ pub fn op_webgpu_request_device( let features = deserialize_features(&device_features); let limits = gfx_select!(device => instance.device_limits(device))?; - let rid = state - .resource_table - .add(WebGpuDevice(instance.clone(), device)); + let instance = instance.clone(); + let instance2 = instance.clone(); + let rid = state.resource_table.add(WebGpuDevice(instance, device)); let queue_rid = state .resource_table - .add(queue::WebGpuQueue(instance.clone(), queue)); + .add(queue::WebGpuQueue(instance2, queue)); Ok(GpuDeviceRes { rid, From 8ae6f43fe5ba07dba419bcb749551cb6390916f9 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 07:41:22 +0200 Subject: [PATCH 10/12] fixes --- cts_runner/src/bootstrap.js | 4 +++- deno_webgpu/01_webgpu.js | 6 +++++- deno_webgpu/lib.rs | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cts_runner/src/bootstrap.js b/cts_runner/src/bootstrap.js index b168843931..5d9c6f65da 100644 --- a/cts_runner/src/bootstrap.js +++ b/cts_runner/src/bootstrap.js @@ -26,8 +26,9 @@ import { Console } from "ext:deno_console/01_console.js"; import * as url from "ext:deno_url/00_url.js"; import { DOMException } from "ext:deno_web/01_dom_exception.js"; import * as performance from "ext:deno_web/15_performance.js"; -import * as webgpu from "ext:deno_webgpu/01_webgpu.js"; +import { loadWebGPU } from "ext:deno_webgpu/00_init.js"; import * as imageData from "ext:deno_web/16_image_data.js"; +const webgpu = loadWebGPU(); // imports needed to pass module evaluation import "ext:deno_url/01_urlpattern.js"; @@ -39,6 +40,7 @@ import "ext:deno_web/10_filereader.js"; import "ext:deno_web/12_location.js"; import "ext:deno_web/13_message_port.js"; import "ext:deno_web/14_compression.js"; +import "ext:deno_webgpu/02_surface.js"; let globalThis_; diff --git a/deno_webgpu/01_webgpu.js b/deno_webgpu/01_webgpu.js index e96a21b937..11d7a5a442 100644 --- a/deno_webgpu/01_webgpu.js +++ b/deno_webgpu/01_webgpu.js @@ -123,7 +123,11 @@ const { } = primordials; import * as webidl from "ext:deno_webidl/00_webidl.js"; -import { EventTarget } from "ext:deno_web/02_event.js"; +import { + Event, + EventTarget, + defineEventHandler, +} from "ext:deno_web/02_event.js"; import { DOMException } from "ext:deno_web/01_dom_exception.js"; import { createFilteredInspectProxy } from "ext:deno_console/01_console.js"; diff --git a/deno_webgpu/lib.rs b/deno_webgpu/lib.rs index 6f4a60a62f..453d4ea7e3 100644 --- a/deno_webgpu/lib.rs +++ b/deno_webgpu/lib.rs @@ -218,7 +218,7 @@ deno_core::extension!( surface::op_webgpu_surface_get_current_texture, surface::op_webgpu_surface_present, // byow - //byow::op_webgpu_surface_create, + byow::op_webgpu_surface_create, ], esm = ["00_init.js", "02_surface.js"], lazy_loaded_esm = ["01_webgpu.js"], From 01fa76387d303ee946cb81539dad7bb82d5e4277 Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 19:56:09 +0200 Subject: [PATCH 11/12] fix cts --- cts_runner/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cts_runner/src/main.rs b/cts_runner/src/main.rs index d18791863d..0ebecfb01c 100644 --- a/cts_runner/src/main.rs +++ b/cts_runner/src/main.rs @@ -29,6 +29,9 @@ mod native { .ok_or_else(|| anyhow!("missing specifier in first command line argument"))?; let specifier = resolve_url_or_path(&url, &env::current_dir()?)?; + let mut feature_checker: deno_core::FeatureChecker = Default::default(); + feature_checker.enable_feature(deno_webgpu::UNSTABLE_FEATURE_NAME); + let options = RuntimeOptions { module_loader: Some(Rc::new(deno_core::FsModuleLoader)), get_error_class_fn: Some(&get_error_class_name), @@ -43,6 +46,7 @@ mod native { deno_webgpu::deno_webgpu::init_ops_and_esm(), cts_runner::init_ops_and_esm(), ], + feature_checker: Some(Arc::new(feature_checker)), ..Default::default() }; let mut js_runtime = JsRuntime::new(options); From b34cd7bda1461557364412e7a394b09f6b6b35cb Mon Sep 17 00:00:00 2001 From: crowlkats Date: Tue, 2 Apr 2024 20:08:05 +0200 Subject: [PATCH 12/12] clean --- cts_runner/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cts_runner/src/main.rs b/cts_runner/src/main.rs index 0ebecfb01c..fe8c1cf818 100644 --- a/cts_runner/src/main.rs +++ b/cts_runner/src/main.rs @@ -29,7 +29,7 @@ mod native { .ok_or_else(|| anyhow!("missing specifier in first command line argument"))?; let specifier = resolve_url_or_path(&url, &env::current_dir()?)?; - let mut feature_checker: deno_core::FeatureChecker = Default::default(); + let mut feature_checker = deno_core::FeatureChecker::default(); feature_checker.enable_feature(deno_webgpu::UNSTABLE_FEATURE_NAME); let options = RuntimeOptions {