From dd6febe309839a8ac0e73d7b50d67dfc117f7f5b Mon Sep 17 00:00:00 2001 From: Leo Kettmeir Date: Tue, 24 May 2022 09:01:19 +0200 Subject: [PATCH] Update deno (#2691) * update deno crates & align to IDL * revert GPUAutoLayoutMode * revert GPUAutoLayoutMode --- cts_runner/Cargo.toml | 12 +- cts_runner/src/main.rs | 2 +- deno_webgpu/Cargo.toml | 6 +- deno_webgpu/{ => src}/01_webgpu.js | 152 +++++++++++++++++++++----- deno_webgpu/{ => src}/02_idl_types.js | 16 ++- deno_webgpu/src/lib.rs | 34 +++++- deno_webgpu/src/sampler.rs | 2 +- deno_webgpu/webgpu.idl | 127 +++++++++++---------- 8 files changed, 250 insertions(+), 101 deletions(-) rename deno_webgpu/{ => src}/01_webgpu.js (97%) rename deno_webgpu/{ => src}/02_idl_types.js (99%) diff --git a/cts_runner/Cargo.toml b/cts_runner/Cargo.toml index a6aa10a89..5487a6476 100644 --- a/cts_runner/Cargo.toml +++ b/cts_runner/Cargo.toml @@ -11,11 +11,11 @@ publish = false resolver = "2" [dependencies] -deno_console = "0.43.0" -deno_core = "0.125.0" -deno_url = "0.43.0" -deno_web = "0.74.0" -deno_webidl = "0.43.0" +deno_console = "0.53.0" +deno_core = "0.135.0" +deno_url = "0.53.0" +deno_web = "0.84.0" +deno_webidl = "0.53.0" deno_webgpu = { path = "../deno_webgpu" } -tokio = { version = "1.15.0", features = ["full"] } +tokio = { version = "1.17.0", features = ["full"] } termcolor = "1.1.2" diff --git a/cts_runner/src/main.rs b/cts_runner/src/main.rs index 6c5e998d8..1d459781d 100644 --- a/cts_runner/src/main.rs +++ b/cts_runner/src/main.rs @@ -79,7 +79,7 @@ fn extension() -> deno_core::Extension { ]) .js(deno_core::include_js_files!( prefix "deno:cts_runner", - "src/bootstrap.js", + "bootstrap.js", )) .build() } diff --git a/deno_webgpu/Cargo.toml b/deno_webgpu/Cargo.toml index 80a914fbb..5d901c5c0 100644 --- a/deno_webgpu/Cargo.toml +++ b/deno_webgpu/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "deno_webgpu" -version = "0.44.0" +version = "0.54.0" authors = ["the Deno authors"] edition = "2018" license = "MIT" @@ -11,8 +11,8 @@ repository = "https://github.com/gfx-rs/wgpu" description = "WebGPU implementation for Deno" [dependencies] -deno_core = "0.125.0" +deno_core = "0.135.0" serde = { version = "1.0", features = ["derive"] } -tokio = { version = "1.10", features = ["full"] } +tokio = { version = "1.17", features = ["full"] } wgpu-core = { path = "../wgpu-core", features = ["trace", "replay", "serde"] } wgpu-types = { path = "../wgpu-types", features = ["trace", "replay", "serde"] } diff --git a/deno_webgpu/01_webgpu.js b/deno_webgpu/src/01_webgpu.js similarity index 97% rename from deno_webgpu/01_webgpu.js rename to deno_webgpu/src/01_webgpu.js index ffa6d6a8e..6bcc5f50c 100644 --- a/deno_webgpu/01_webgpu.js +++ b/deno_webgpu/src/01_webgpu.js @@ -154,15 +154,35 @@ } } - class GPUOutOfMemoryError extends Error { - name = "GPUOutOfMemoryError"; + class GPUError extends Error { constructor() { - super("device out of memory"); + super(); + webidl.illegalConstructor(); + } + + [_message]; + get message() { + webidl.assertBranded(this, GPUErrorPrototype); + return this[_message]; + } + } + const GPUErrorPrototype = GPUError.prototype; + + class GPUOutOfMemoryError extends GPUError { + name = "GPUOutOfMemoryError"; + constructor(message) { + const prefix = "Failed to construct 'GPUOutOfMemoryError'"; + webidl.requiredArguments(arguments.length, 1, { prefix }); + message = webidl.converters.DOMString(message, { + prefix, + context: "Argument 1", + }); + super(message); } } const GPUOutOfMemoryErrorPrototype = GPUOutOfMemoryError.prototype; - class GPUValidationError extends Error { + class GPUValidationError extends GPUError { name = "GPUValidationError"; /** @param {string} message */ constructor(message) { @@ -203,7 +223,7 @@ if (err) { return null; } else { - return createGPUAdapter(data.name, data); + return createGPUAdapter(data); } } @@ -213,7 +233,6 @@ } const GPUPrototype = GPU.prototype; - const _name = Symbol("[[name]]"); const _adapter = Symbol("[[adapter]]"); const _cleanup = Symbol("[[cleanup]]"); @@ -226,14 +245,12 @@ */ /** - * @param {string} name * @param {InnerGPUAdapter} inner * @returns {GPUAdapter} */ - function createGPUAdapter(name, inner) { + function createGPUAdapter(inner) { /** @type {GPUAdapter} */ const adapter = webidl.createBranded(GPUAdapter); - adapter[_name] = name; adapter[_adapter] = { ...inner, features: createGPUSupportedFeatures(inner.features), @@ -243,16 +260,9 @@ } class GPUAdapter { - /** @type {string} */ - [_name]; /** @type {InnerGPUAdapter} */ [_adapter]; - /** @returns {string} */ - get name() { - webidl.assertBranded(this, GPUAdapterPrototype); - return this[_name]; - } /** @returns {GPUSupportedFeatures} */ get features() { webidl.assertBranded(this, GPUAdapterPrototype); @@ -315,10 +325,43 @@ ); } + /** + * @param {string[]} unmaskHints + * @returns {Promise} + */ + async requestAdapterInfo(unmaskHints = []) { + webidl.assertBranded(this, GPUAdapterPrototype); + const prefix = "Failed to execute 'requestAdapterInfo' on 'GPUAdapter'"; + unmaskHints = webidl.converters["sequence"](unmaskHints, { + prefix, + context: "Argument 1", + }); + + const { + vendor, + architecture, + device, + description, + } = await core.opAsync( + "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[_device] = unmaskHints.includes("device") ? device : ""; + adapterInfo[_description] = unmaskHints.includes("description") + ? description + : ""; + return adapterInfo; + } + [SymbolFor("Deno.privateCustomInspect")](inspect) { return `${this.constructor.name} ${ inspect({ - name: this.name, features: this.features, limits: this.limits, }) @@ -327,6 +370,55 @@ } const GPUAdapterPrototype = GPUAdapter.prototype; + const _vendor = Symbol("[[vendor]]"); + const _architecture = Symbol("[[architecture]]"); + const _description = Symbol("[[description]]"); + class GPUAdapterInfo { + /** @type {string} */ + [_vendor]; + /** @returns {string} */ + get vendor() { + webidl.assertBranded(this, GPUAdapterInfoPrototype); + return this[_vendor]; + } + + /** @type {string} */ + [_architecture]; + /** @returns {string} */ + get architecture() { + webidl.assertBranded(this, GPUAdapterInfoPrototype); + return this[_architecture]; + } + + /** @type {string} */ + [_device]; + /** @returns {string} */ + get device() { + webidl.assertBranded(this, GPUAdapterInfoPrototype); + return this[_device]; + } + + /** @type {string} */ + [_description]; + /** @returns {string} */ + get description() { + webidl.assertBranded(this, GPUAdapterInfoPrototype); + return this[_description]; + } + + [SymbolFor("Deno.privateCustomInspect")](inspect) { + return `${this.constructor.name} ${ + inspect({ + vendor: this.vendor, + architecture: this.architecture, + device: this.device, + description: this.description, + }) + }`; + } + } + const GPUAdapterInfoPrototype = GPUAdapterInfo.prototype; + const _limits = Symbol("[[limits]]"); function createGPUSupportedLimits(features) { @@ -602,26 +694,24 @@ * @param {any} type */ function GPUObjectBaseMixin(name, type) { - type.prototype[_label] = undefined; + type.prototype[_label] = null; ObjectDefineProperty(type.prototype, "label", { /** - * @return {string | undefined} + * @return {string | null} */ get() { webidl.assertBranded(this, type.prototype); return this[_label]; }, /** - * @param {string | undefined} label + * @param {string | null} label */ set(label) { webidl.assertBranded(this, type.prototype); - if (label !== undefined) { - label = webidl.converters["UVString"](label, { - prefix: `Failed to set 'label' on '${name}'`, - context: "Argument 1", - }); - } + label = webidl.converters["UVString?"](label, { + prefix: `Failed to set 'label' on '${name}'`, + context: "Argument 1", + }); this[_label] = label; }, }); @@ -4213,9 +4303,14 @@ * @param {number} workgroupCountY * @param {number} workgroupCountZ */ - dispatchWorkgroups(workgroupCountX, workgroupCountY = 1, workgroupCountZ = 1) { + dispatchWorkgroups( + workgroupCountX, + workgroupCountY = 1, + workgroupCountZ = 1, + ) { webidl.assertBranded(this, GPUComputePassEncoderPrototype); - const prefix = "Failed to execute 'dispatchWorkgroups' on 'GPUComputePassEncoder'"; + const prefix = + "Failed to execute 'dispatchWorkgroups' on 'GPUComputePassEncoder'"; webidl.requiredArguments(arguments.length, 1, { prefix }); workgroupCountX = webidl.converters.GPUSize32(workgroupCountX, { prefix, @@ -5180,6 +5275,7 @@ GPURenderBundleEncoder, GPURenderBundle, GPUQuerySet, + GPUError, GPUOutOfMemoryError, GPUValidationError, }; diff --git a/deno_webgpu/02_idl_types.js b/deno_webgpu/src/02_idl_types.js similarity index 99% rename from deno_webgpu/02_idl_types.js rename to deno_webgpu/src/02_idl_types.js index 082571c90..cabd30a5f 100644 --- a/deno_webgpu/02_idl_types.js +++ b/deno_webgpu/src/02_idl_types.js @@ -540,6 +540,15 @@ ], ); + // ENUM: GPUMipmapFilterMode + webidl.converters["GPUMipmapFilterMode"] = webidl.createEnumConverter( + "GPUMipmapFilterMode", + [ + "nearest", + "linear", + ], + ); + // ENUM: GPUCompareFunction webidl.converters["GPUCompareFunction"] = webidl.createEnumConverter( "GPUCompareFunction", @@ -584,7 +593,7 @@ }, { key: "mipmapFilter", - converter: webidl.converters["GPUFilterMode"], + converter: webidl.converters["GPUMipmapFilterMode"], defaultValue: "nearest", }, { @@ -938,7 +947,10 @@ // DICTIONARY: GPUPipelineDescriptorBase const dictMembersGPUPipelineDescriptorBase = [ - { key: "layout", converter: webidl.converters["GPUPipelineLayout"] }, + { + key: "layout", + converter: webidl.converters["GPUPipelineLayout"], + }, ]; webidl.converters["GPUPipelineDescriptorBase"] = webidl .createDictionaryConverter( diff --git a/deno_webgpu/src/lib.rs b/deno_webgpu/src/lib.rs index 70644209b..9e3a9af15 100644 --- a/deno_webgpu/src/lib.rs +++ b/deno_webgpu/src/lib.rs @@ -215,7 +215,6 @@ pub enum GpuAdapterDeviceOrErr { #[serde(rename_all = "camelCase")] pub struct GpuAdapterDevice { rid: ResourceId, - name: Option, limits: wgpu_types::Limits, features: Vec<&'static str>, is_software: bool, @@ -262,7 +261,6 @@ pub async fn op_webgpu_request_adapter( }) } }; - let name = gfx_select!(adapter => instance.adapter_get_info(adapter))?.name; let adapter_features = gfx_select!(adapter => instance.adapter_features(adapter))?; let features = deserialize_features(&adapter_features); let adapter_limits = gfx_select!(adapter => instance.adapter_limits(adapter))?; @@ -271,7 +269,6 @@ pub async fn op_webgpu_request_adapter( Ok(GpuAdapterDeviceOrErr::Features(GpuAdapterDevice { rid, - name: Some(name), features, limits: adapter_limits, is_software: false, @@ -430,7 +427,6 @@ pub async fn op_webgpu_request_device( Ok(GpuAdapterDevice { rid, - name: None, features, limits, // TODO(lucacasonato): report correctly from wgpu @@ -438,6 +434,35 @@ pub async fn op_webgpu_request_device( }) } +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +pub struct GPUAdapterInfo { + vendor: String, + architecture: String, + device: String, + description: String, +} + +#[op] +pub async fn op_webgpu_request_adapter_info( + state: Rc>, + adapter_rid: ResourceId, +) -> Result { + let state = state.borrow_mut(); + let adapter_resource = state.resource_table.get::(adapter_rid)?; + let adapter = adapter_resource.0; + let instance = state.borrow::(); + + let info = gfx_select!(adapter => instance.adapter_get_info(adapter))?; + + Ok(GPUAdapterInfo { + vendor: info.vendor.to_string(), + architecture: String::new(), // TODO(#2170) + device: info.device.to_string(), + description: info.name, + }) +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct CreateQuerySetArgs { @@ -520,6 +545,7 @@ fn declare_webgpu_ops() -> Vec { // Request device/adapter op_webgpu_request_adapter::decl(), op_webgpu_request_device::decl(), + op_webgpu_request_adapter_info::decl(), // Query Set op_webgpu_create_query_set::decl(), // buffer diff --git a/deno_webgpu/src/sampler.rs b/deno_webgpu/src/sampler.rs index bdf541279..160e43aa7 100644 --- a/deno_webgpu/src/sampler.rs +++ b/deno_webgpu/src/sampler.rs @@ -27,7 +27,7 @@ pub struct CreateSamplerArgs { address_mode_w: wgpu_types::AddressMode, mag_filter: wgpu_types::FilterMode, min_filter: wgpu_types::FilterMode, - mipmap_filter: wgpu_types::FilterMode, + mipmap_filter: wgpu_types::FilterMode, // TODO: GPUMipmapFilterMode lod_min_clamp: f32, lod_max_clamp: f32, compare: Option, diff --git a/deno_webgpu/webgpu.idl b/deno_webgpu/webgpu.idl index 4a00c54a9..5ea251e77 100644 --- a/deno_webgpu/webgpu.idl +++ b/deno_webgpu/webgpu.idl @@ -1,5 +1,5 @@ interface mixin GPUObjectBase { - attribute (USVString or undefined) label; + attribute USVString label; }; dictionary GPUObjectDescriptorBase { @@ -41,6 +41,14 @@ interface GPUSupportedFeatures { readonly setlike; }; +[Exposed=(Window, DedicatedWorker), SecureContext] +interface GPUAdapterInfo { + readonly attribute DOMString vendor; + readonly attribute DOMString architecture; + readonly attribute DOMString device; + readonly attribute DOMString description; +}; + enum GPUPredefinedColorSpace { "srgb", }; @@ -68,12 +76,12 @@ enum GPUPowerPreference { [Exposed=(Window, DedicatedWorker), SecureContext] interface GPUAdapter { - readonly attribute DOMString name; [SameObject] readonly attribute GPUSupportedFeatures features; [SameObject] readonly attribute GPUSupportedLimits limits; readonly attribute boolean isFallbackAdapter; Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); + Promise requestAdapterInfo(optional sequence unmaskHints = []); }; dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase { @@ -141,7 +149,7 @@ dictionary GPUBufferDescriptor : GPUObjectDescriptorBase { typedef [EnforceRange] unsigned long GPUBufferUsageFlags; [Exposed=(Window, DedicatedWorker)] -interface GPUBufferUsage { +namespace GPUBufferUsage { const GPUFlagsConstant MAP_READ = 0x0001; const GPUFlagsConstant MAP_WRITE = 0x0002; const GPUFlagsConstant COPY_SRC = 0x0004; @@ -156,7 +164,7 @@ interface GPUBufferUsage { typedef [EnforceRange] unsigned long GPUMapModeFlags; [Exposed=(Window, DedicatedWorker)] -interface GPUMapMode { +namespace GPUMapMode { const GPUFlagsConstant READ = 0x0001; const GPUFlagsConstant WRITE = 0x0002; }; @@ -186,7 +194,7 @@ enum GPUTextureDimension { typedef [EnforceRange] unsigned long GPUTextureUsageFlags; [Exposed=(Window, DedicatedWorker)] -interface GPUTextureUsage { +namespace GPUTextureUsage { const GPUFlagsConstant COPY_SRC = 0x01; const GPUFlagsConstant COPY_DST = 0x02; const GPUFlagsConstant TEXTURE_BINDING = 0x04; @@ -358,7 +366,7 @@ dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase { GPUAddressMode addressModeW = "clamp-to-edge"; GPUFilterMode magFilter = "nearest"; GPUFilterMode minFilter = "nearest"; - GPUFilterMode mipmapFilter = "nearest"; + GPUMipmapFilterMode mipmapFilter = "nearest"; float lodMinClamp = 0; float lodMaxClamp = 32; GPUCompareFunction compare; @@ -376,6 +384,11 @@ enum GPUFilterMode { "linear", }; +enum GPUMipmapFilterMode { + "nearest", + "linear", +}; + enum GPUCompareFunction { "never", "less", @@ -396,14 +409,6 @@ dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase { required sequence entries; }; -typedef [EnforceRange] unsigned long GPUShaderStageFlags; -[Exposed=(Window, DedicatedWorker)] -interface GPUShaderStage { - const GPUFlagsConstant VERTEX = 0x1; - const GPUFlagsConstant FRAGMENT = 0x2; - const GPUFlagsConstant COMPUTE = 0x4; -}; - dictionary GPUBindGroupLayoutEntry { required GPUIndex32 binding; required GPUShaderStageFlags visibility; @@ -414,6 +419,14 @@ dictionary GPUBindGroupLayoutEntry { GPUStorageTextureBindingLayout storageTexture; }; +typedef [EnforceRange] unsigned long GPUShaderStageFlags; +[Exposed=(Window, DedicatedWorker)] +namespace GPUShaderStage { + const GPUFlagsConstant VERTEX = 0x1; + const GPUFlagsConstant FRAGMENT = 0x2; + const GPUFlagsConstant COMPUTE = 0x4; +}; + enum GPUBufferBindingType { "uniform", "storage", @@ -525,11 +538,11 @@ interface GPUCompilationInfo { }; dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase { - GPUPipelineLayout layout; + required GPUPipelineLayout layout; }; interface mixin GPUPipelineBase { - GPUBindGroupLayout getBindGroupLayout(unsigned long index); + [NewObject] GPUBindGroupLayout getBindGroupLayout(unsigned long index); }; dictionary GPUProgrammableStage { @@ -564,14 +577,6 @@ dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase { GPUFragmentState fragment; }; -enum GPUPrimitiveTopology { - "point-list", - "line-list", - "line-strip", - "triangle-list", - "triangle-strip", -}; - dictionary GPUPrimitiveState { GPUPrimitiveTopology topology = "triangle-list"; GPUIndexFormat stripIndexFormat; @@ -582,6 +587,14 @@ dictionary GPUPrimitiveState { boolean unclippedDepth = false; }; +enum GPUPrimitiveTopology { + "point-list", + "line-list", + "line-strip", + "triangle-list", + "triangle-strip", +}; + enum GPUFrontFace { "ccw", "cw", @@ -617,7 +630,7 @@ dictionary GPUBlendState { typedef [EnforceRange] unsigned long GPUColorWriteFlags; [Exposed=(Window, DedicatedWorker)] -interface GPUColorWrite { +namespace GPUColorWrite { const GPUFlagsConstant RED = 0x1; const GPUFlagsConstant GREEN = 0x2; const GPUFlagsConstant BLUE = 0x4; @@ -828,7 +841,7 @@ dictionary GPUImageCopyTexture { GPUTextureAspect aspect = "all"; }; -interface mixin GPUProgrammablePassEncoder { +interface mixin GPUBindingCommandsMixin { undefined setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup, optional sequence dynamicOffsets = []); @@ -860,28 +873,11 @@ interface GPUComputePassEncoder { GPUComputePassEncoder includes GPUObjectBase; GPUComputePassEncoder includes GPUCommandsMixin; GPUComputePassEncoder includes GPUDebugCommandsMixin; -GPUComputePassEncoder includes GPUProgrammablePassEncoder; +GPUComputePassEncoder includes GPUBindingCommandsMixin; dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase { }; -interface mixin GPURenderEncoderBase { - undefined setPipeline(GPURenderPipeline pipeline); - - undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size); - undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size); - - undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1, - optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0); - undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1, - optional GPUSize32 firstIndex = 0, - optional GPUSignedOffset32 baseVertex = 0, - optional GPUSize32 firstInstance = 0); - - undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); - undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); -}; - [Exposed=(Window, DedicatedWorker), SecureContext] interface GPURenderPassEncoder { undefined setViewport(float x, float y, @@ -908,8 +904,8 @@ interface GPURenderPassEncoder { GPURenderPassEncoder includes GPUObjectBase; GPURenderPassEncoder includes GPUCommandsMixin; GPURenderPassEncoder includes GPUDebugCommandsMixin; -GPURenderPassEncoder includes GPUProgrammablePassEncoder; -GPURenderPassEncoder includes GPURenderEncoderBase; +GPURenderPassEncoder includes GPUBindingCommandsMixin; +GPURenderPassEncoder includes GPURenderCommandsMixin; dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase { required sequence colorAttachments; @@ -956,6 +952,23 @@ dictionary GPURenderPassLayout: GPUObjectDescriptorBase { GPUSize32 sampleCount = 1; }; +interface mixin GPURenderCommandsMixin { + undefined setPipeline(GPURenderPipeline pipeline); + + undefined setIndexBuffer(GPUBuffer buffer, GPUIndexFormat indexFormat, optional GPUSize64 offset = 0, optional GPUSize64 size); + undefined setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0, optional GPUSize64 size); + + undefined draw(GPUSize32 vertexCount, optional GPUSize32 instanceCount = 1, + optional GPUSize32 firstVertex = 0, optional GPUSize32 firstInstance = 0); + undefined drawIndexed(GPUSize32 indexCount, optional GPUSize32 instanceCount = 1, + optional GPUSize32 firstIndex = 0, + optional GPUSignedOffset32 baseVertex = 0, + optional GPUSize32 firstInstance = 0); + + undefined drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); + undefined drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); +}; + [Exposed=(Window, DedicatedWorker), SecureContext] interface GPURenderBundle { }; @@ -971,8 +984,8 @@ interface GPURenderBundleEncoder { GPURenderBundleEncoder includes GPUObjectBase; GPURenderBundleEncoder includes GPUCommandsMixin; GPURenderBundleEncoder includes GPUDebugCommandsMixin; -GPURenderBundleEncoder includes GPUProgrammablePassEncoder; -GPURenderBundleEncoder includes GPURenderEncoderBase; +GPURenderBundleEncoder includes GPUBindingCommandsMixin; +GPURenderBundleEncoder includes GPURenderCommandsMixin; dictionary GPURenderBundleEncoderDescriptor : GPURenderPassLayout { boolean depthReadOnly = false; @@ -1046,17 +1059,19 @@ enum GPUErrorFilter { }; [Exposed=(Window, DedicatedWorker), SecureContext] -interface GPUOutOfMemoryError { - constructor(); -}; - -[Exposed=(Window, DedicatedWorker), SecureContext] -interface GPUValidationError { - constructor(DOMString message); +interface GPUError { readonly attribute DOMString message; }; -typedef (GPUOutOfMemoryError or GPUValidationError) GPUError; +[Exposed=(Window, DedicatedWorker), SecureContext] +interface GPUOutOfMemoryError : GPUError { + constructor(DOMString message); +}; + +[Exposed=(Window, DedicatedWorker), SecureContext] +interface GPUValidationError : GPUError { + constructor(DOMString message); +}; partial interface GPUDevice { undefined pushErrorScope(GPUErrorFilter filter);