From 2b1f145c3e51cf9885c073b78bd5882e80d258e3 Mon Sep 17 00:00:00 2001 From: Dante Issaias Date: Wed, 20 Jul 2022 01:22:26 +0100 Subject: [PATCH] chore(ext): update webgpu (#15059) --- Cargo.lock | 57 +- cli/dts/lib.deno_webgpu.d.ts | 134 +-- .../testdata/webgpu_computepass_shader.wgsl | 16 +- .../testdata/webgpu_hellotriangle_shader.wgsl | 9 +- cli/tests/unit/webgpu_test.ts | 10 +- ext/webgpu/Cargo.toml | 6 +- ext/webgpu/LICENSE.md | 2 +- ext/webgpu/src/01_webgpu.js | 863 ++++++++++-------- ext/webgpu/src/02_idl_types.js | 76 +- ext/webgpu/src/binding.rs | 194 ++-- ext/webgpu/src/buffer.rs | 139 +-- ext/webgpu/src/bundle.rs | 231 ++--- ext/webgpu/src/command_encoder.rs | 434 ++++----- ext/webgpu/src/compute_pass.rs | 220 ++--- ext/webgpu/src/error.rs | 68 +- ext/webgpu/src/lib.rs | 176 ++-- ext/webgpu/src/pipeline.rs | 144 ++- ext/webgpu/src/queue.rs | 96 +- ext/webgpu/src/render_pass.rs | 358 +++----- ext/webgpu/src/sampler.rs | 5 +- ext/webgpu/src/shader.rs | 23 +- ext/webgpu/src/texture.rs | 3 +- ext/webgpu/webgpu.idl | 201 ++-- tools/wgpu_sync.js | 7 +- 24 files changed, 1605 insertions(+), 1867 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c314da9b31..80a52170a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,6 +102,15 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android_system_properties" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20ae67ce26261f218e2b3f2f0d01887a9818283ca6fb260fa7c67e253d61c92" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -128,9 +137,9 @@ dependencies = [ [[package]] name = "ash" -version = "0.34.0+1.2.203" +version = "0.37.0+1.3.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df" +checksum = "006ca68e0f2b03f22d6fa9f2860f85aed430d257fec20f8879b2145e7c7ae1a6" dependencies = [ "libloading", ] @@ -687,9 +696,9 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "d3d12" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" +checksum = "827914e1f53b1e0e025ecd3d967a7836b7bcb54520f90e21ef8df7b4d88a2759" dependencies = [ "bitflags", "libloading", @@ -2358,6 +2367,7 @@ checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" dependencies = [ "libc", "libloading", + "pkg-config", ] [[package]] @@ -2625,9 +2635,9 @@ dependencies = [ [[package]] name = "metal" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" +checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" dependencies = [ "bitflags", "block", @@ -2684,9 +2694,9 @@ dependencies = [ [[package]] name = "naga" -version = "0.8.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705" +checksum = "5f50357e1167a3ab92d6b3c7f4bf5f7fd13fde3f4b28bf0d5ea07b5100fdb6c0" dependencies = [ "bit-set", "bitflags", @@ -2698,7 +2708,9 @@ dependencies = [ "rustc-hash", "serde", "spirv", + "termcolor", "thiserror", + "unicode-xid 0.2.3", ] [[package]] @@ -3236,7 +3248,7 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -4497,7 +4509,7 @@ checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" dependencies = [ "proc-macro2 0.4.30", "quote 0.6.13", - "unicode-xid", + "unicode-xid 0.1.0", ] [[package]] @@ -5086,6 +5098,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "unicode-xid" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" + [[package]] name = "universal-hash" version = "0.4.1" @@ -5331,11 +5349,12 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.12.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d" +checksum = "266ca6be6004fd1b2a768023b1cb0afbf7af0cbffaba19af25c5792d44e74784" dependencies = [ "arrayvec", + "bit-vec", "bitflags", "cfg_aliases", "codespan-reporting", @@ -5343,22 +5362,24 @@ dependencies = [ "fxhash", "log 0.4.17", "naga", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "profiling", "ron", "serde", "smallvec", "thiserror", + "web-sys", "wgpu-hal", "wgpu-types", ] [[package]] name = "wgpu-hal" -version = "0.12.5" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d684ea6a34974a2fc19f1dfd183d11a62e22d75c4f187a574bb1224df8e056c2" +checksum = "bef50e48812c7eb958fa52d28a912f8b77c96453ebab21c72b01cdda61d3e65d" dependencies = [ + "android_system_properties", "arrayvec", "ash", "bit-set", @@ -5379,7 +5400,7 @@ dependencies = [ "metal", "naga", "objc", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "profiling", "range-alloc", "raw-window-handle", @@ -5393,9 +5414,9 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2" +checksum = "f48d691b733b9d50ea8cb18f377fd1ed927c90c55ad1ec5b90f68885471977f7" dependencies = [ "bitflags", "bitflags_serde_shim", diff --git a/cli/dts/lib.deno_webgpu.d.ts b/cli/dts/lib.deno_webgpu.d.ts index 616df6bca3..8d1c9919f9 100644 --- a/cli/dts/lib.deno_webgpu.d.ts +++ b/cli/dts/lib.deno_webgpu.d.ts @@ -5,10 +5,8 @@ /// /// -// 8cc98b6f10b7f354473a08c3773bb1de839845b9 - interface GPUObjectBase { - label: string | null; + label: string; } declare interface GPUObjectDescriptorBase { @@ -64,6 +62,13 @@ declare class GPUSupportedFeatures { values(): IterableIterator; } +declare class GPUAdapterInfo { + readonly vendor: string; + readonly architecture: string; + readonly device: string; + readonly description: string; +} + declare class GPU { requestAdapter( options?: GPURequestAdapterOptions, @@ -78,12 +83,12 @@ declare interface GPURequestAdapterOptions { declare type GPUPowerPreference = "low-power" | "high-performance"; declare class GPUAdapter { - readonly name: string; readonly features: GPUSupportedFeatures; readonly limits: GPUSupportedLimits; readonly isFallbackAdapter: boolean; requestDevice(descriptor?: GPUDeviceDescriptor): Promise; + requestAdapterInfo(unmaskHints?: string[]): Promise; } declare interface GPUDeviceDescriptor extends GPUObjectDescriptorBase { @@ -101,6 +106,7 @@ declare type GPUFeatureName = | "texture-compression-astc" | "timestamp-query" | "indirect-first-instance" + | "shader-f16" // extended from spec | "mappable-primary-buffers" | "sampled-texture-binding-array" @@ -116,7 +122,7 @@ declare type GPUFeatureName = | "vertex-attribute-64bit"; declare class GPUDevice extends EventTarget implements GPUObjectBase { - label: string | null; + label: string; readonly lost: Promise; pushErrorScope(filter: GPUErrorFilter): undefined; @@ -168,7 +174,7 @@ declare class GPUDevice extends EventTarget implements GPUObjectBase { } declare class GPUBuffer implements GPUObjectBase { - label: string | null; + label: string; mapAsync( mode: GPUMapModeFlags, @@ -208,7 +214,7 @@ declare class GPUMapMode { } declare class GPUTexture implements GPUObjectBase { - label: string | null; + label: string; createView(descriptor?: GPUTextureViewDescriptor): GPUTextureView; destroy(): undefined; @@ -235,7 +241,7 @@ declare class GPUTextureUsage { } declare class GPUTextureView implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPUTextureViewDescriptor extends GPUObjectDescriptorBase { @@ -300,6 +306,8 @@ declare type GPUTextureFormat = | "depth24plus" | "depth24plus-stencil8" | "depth32float" + | "depth24unorm-stencil8" + | "depth32float-stencil8" | "bc1-rgba-unorm" | "bc1-rgba-unorm-srgb" | "bc2-rgba-unorm" @@ -351,12 +359,10 @@ declare type GPUTextureFormat = | "astc-12x10-unorm" | "astc-12x10-unorm-srgb" | "astc-12x12-unorm" - | "astc-12x12-unorm-srgb" - | "depth24unorm-stencil8" - | "depth32float-stencil8"; + | "astc-12x12-unorm-srgb"; declare class GPUSampler implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase { @@ -365,7 +371,7 @@ declare interface GPUSamplerDescriptor extends GPUObjectDescriptorBase { addressModeW?: GPUAddressMode; magFilter?: GPUFilterMode; minFilter?: GPUFilterMode; - mipmapFilter?: GPUFilterMode; + mipmapFilter?: GPUMipmapFilterMode; lodMinClamp?: number; lodMaxClamp?: number; compare?: GPUCompareFunction; @@ -376,6 +382,8 @@ declare type GPUAddressMode = "clamp-to-edge" | "repeat" | "mirror-repeat"; declare type GPUFilterMode = "nearest" | "linear"; +declare type GPUMipmapFilterMode = "nearest" | "linear"; + declare type GPUCompareFunction = | "never" | "less" @@ -387,7 +395,7 @@ declare type GPUCompareFunction = | "always"; declare class GPUBindGroupLayout implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPUBindGroupLayoutDescriptor extends GPUObjectDescriptorBase { @@ -450,7 +458,7 @@ declare interface GPUStorageTextureBindingLayout { } declare class GPUBindGroup implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPUBindGroupDescriptor extends GPUObjectDescriptorBase { @@ -475,7 +483,7 @@ declare interface GPUBufferBinding { } declare class GPUPipelineLayout implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPUPipelineLayoutDescriptor extends GPUObjectDescriptorBase { @@ -496,7 +504,7 @@ declare interface GPUCompilationInfo { } declare class GPUShaderModule implements GPUObjectBase { - label: string | null; + label: string; compilationInfo(): Promise; } @@ -506,8 +514,10 @@ declare interface GPUShaderModuleDescriptor extends GPUObjectDescriptorBase { sourceMap?: any; } +declare type GPUAutoLayoutMode = "auto"; + declare interface GPUPipelineDescriptorBase extends GPUObjectDescriptorBase { - layout?: GPUPipelineLayout; + layout: GPUPipelineLayout | GPUAutoLayoutMode; } declare interface GPUPipelineBase { @@ -520,7 +530,7 @@ declare interface GPUProgrammableStage { } declare class GPUComputePipeline implements GPUObjectBase, GPUPipelineBase { - label: string | null; + label: string; getBindGroupLayout(index: number): GPUBindGroupLayout; } @@ -531,7 +541,7 @@ declare interface GPUComputePipelineDescriptor } declare class GPURenderPipeline implements GPUObjectBase, GPUPipelineBase { - label: string | null; + label: string; getBindGroupLayout(index: number): GPUBindGroupLayout; } @@ -545,13 +555,6 @@ declare interface GPURenderPipelineDescriptor fragment?: GPUFragmentState; } -declare type GPUPrimitiveTopology = - | "point-list" - | "line-list" - | "line-strip" - | "triangle-list" - | "triangle-strip"; - declare interface GPUPrimitiveState { topology?: GPUPrimitiveTopology; stripIndexFormat?: GPUIndexFormat; @@ -560,6 +563,13 @@ declare interface GPUPrimitiveState { unclippedDepth?: boolean; } +declare type GPUPrimitiveTopology = + | "point-list" + | "line-list" + | "line-strip" + | "triangle-list" + | "triangle-strip"; + declare type GPUFrontFace = "ccw" | "cw"; declare type GPUCullMode = "none" | "front" | "back"; @@ -571,7 +581,7 @@ declare interface GPUMultisampleState { } declare interface GPUFragmentState extends GPUProgrammableStage { - targets: GPUColorTargetState[]; + targets: (GPUColorTargetState | null)[]; } declare interface GPUColorTargetState { @@ -710,13 +720,13 @@ declare interface GPUVertexAttribute { } declare class GPUCommandBuffer implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPUCommandBufferDescriptor extends GPUObjectDescriptorBase {} declare class GPUCommandEncoder implements GPUObjectBase { - label: string | null; + label: string; beginRenderPass(descriptor: GPURenderPassDescriptor): GPURenderPassEncoder; beginComputePass( @@ -751,8 +761,8 @@ declare class GPUCommandEncoder implements GPUObjectBase { clearBuffer( destination: GPUBuffer, - destinationOffset: number, - size: number, + destinationOffset?: number, + size?: number, ): undefined; pushDebugGroup(groupLabel: string): undefined; @@ -813,7 +823,7 @@ interface GPUProgrammablePassEncoder { declare class GPUComputePassEncoder implements GPUObjectBase, GPUProgrammablePassEncoder { - label: string | null; + label: string; setBindGroup( index: number, bindGroup: GPUBindGroup, @@ -830,8 +840,8 @@ declare class GPUComputePassEncoder popDebugGroup(): undefined; insertDebugMarker(markerLabel: string): undefined; setPipeline(pipeline: GPUComputePipeline): undefined; - dispatch(x: number, y?: number, z?: number): undefined; - dispatchIndirect( + dispatchWorkgroups(x: number, y?: number, z?: number): undefined; + dispatchWorkgroupsIndirect( indirectBuffer: GPUBuffer, indirectOffset: number, ): undefined; @@ -844,7 +854,7 @@ declare class GPUComputePassEncoder writeTimestamp(querySet: GPUQuerySet, queryIndex: number): undefined; - endPass(): undefined; + end(): undefined; } declare interface GPUComputePassDescriptor extends GPUObjectDescriptorBase {} @@ -888,7 +898,7 @@ interface GPURenderEncoderBase { declare class GPURenderPassEncoder implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase { - label: string | null; + label: string; setBindGroup( index: number, bindGroup: GPUBindGroup, @@ -967,11 +977,11 @@ declare class GPURenderPassEncoder writeTimestamp(querySet: GPUQuerySet, queryIndex: number): undefined; executeBundles(bundles: GPURenderBundle[]): undefined; - endPass(): undefined; + end(): undefined; } declare interface GPURenderPassDescriptor extends GPUObjectDescriptorBase { - colorAttachments: GPURenderPassColorAttachment[]; + colorAttachments: (GPURenderPassColorAttachment | null)[]; depthStencilAttachment?: GPURenderPassDepthStencilAttachment; occlusionQuerySet?: GPUQuerySet; } @@ -980,35 +990,38 @@ declare interface GPURenderPassColorAttachment { view: GPUTextureView; resolveTarget?: GPUTextureView; - loadValue: GPULoadOp | GPUColor; - storeOp?: GPUStoreOp; + clearValue?: GPUColor; + loadOp: GPULoadOp; + storeOp: GPUStoreOp; } declare interface GPURenderPassDepthStencilAttachment { view: GPUTextureView; - depthLoadValue: GPULoadOp | number; - depthStoreOp: GPUStoreOp; + depthClearValue?: number; + depthLoadOp?: GPULoadOp; + depthStoreOp?: GPUStoreOp; depthReadOnly?: boolean; - stencilLoadValue: GPULoadOp | number; - stencilStoreOp: GPUStoreOp; + stencilClearValue?: number; + stencilLoadOp?: GPULoadOp; + stencilStoreOp?: GPUStoreOp; stencilReadOnly?: boolean; } -declare type GPULoadOp = "load"; +declare type GPULoadOp = "load" | "clear"; declare type GPUStoreOp = "store" | "discard"; declare class GPURenderBundle implements GPUObjectBase { - label: string | null; + label: string; } declare interface GPURenderBundleDescriptor extends GPUObjectDescriptorBase {} declare class GPURenderBundleEncoder implements GPUObjectBase, GPUProgrammablePassEncoder, GPURenderEncoderBase { - label: string | null; + label: string; draw( vertexCount: number, instanceCount?: number, @@ -1060,7 +1073,7 @@ declare class GPURenderBundleEncoder } declare interface GPURenderPassLayout extends GPUObjectDescriptorBase { - colorFormats: GPUTextureFormat[]; + colorFormats: (GPUTextureFormat | null)[]; depthStencilFormat?: GPUTextureFormat; sampleCount?: number; } @@ -1071,7 +1084,7 @@ declare interface GPURenderBundleEncoderDescriptor extends GPURenderPassLayout { } declare class GPUQueue implements GPUObjectBase { - label: string | null; + label: string; submit(commandBuffers: GPUCommandBuffer[]): undefined; @@ -1094,7 +1107,7 @@ declare class GPUQueue implements GPUObjectBase { } declare class GPUQuerySet implements GPUObjectBase { - label: string | null; + label: string; destroy(): undefined; } @@ -1121,18 +1134,19 @@ declare interface GPUDeviceLostInfo { readonly message: string; } -declare type GPUErrorFilter = "out-of-memory" | "validation"; - -declare class GPUOutOfMemoryError { - constructor(); -} - -declare class GPUValidationError { - constructor(message: string); +declare class GPUError { readonly message: string; } -declare type GPUError = GPUOutOfMemoryError | GPUValidationError; +declare type GPUErrorFilter = "out-of-memory" | "validation"; + +declare class GPUOutOfMemoryError extends GPUError { + constructor(message: string); +} + +declare class GPUValidationError extends GPUError { + constructor(message: string); +} declare class GPUUncapturedErrorEvent extends Event { constructor( diff --git a/cli/tests/testdata/webgpu_computepass_shader.wgsl b/cli/tests/testdata/webgpu_computepass_shader.wgsl index df541aff5e..41af4363a2 100644 --- a/cli/tests/testdata/webgpu_computepass_shader.wgsl +++ b/cli/tests/testdata/webgpu_computepass_shader.wgsl @@ -1,9 +1,6 @@ -struct PrimeIndices { - data: [[stride(4)]] array; -}; // this is used as both input and output for convenience - -[[group(0), binding(0)]] -var v_indices: PrimeIndices; +@group(0) +@binding(0) +var v_indices: array; // this is used as both input and output for convenience // The Collatz Conjecture states that for any integer n: // If n is even, n = n/2 @@ -34,7 +31,8 @@ fn collatz_iterations(n_base: u32) -> u32{ return i; } -[[stage(compute), workgroup_size(1)]] -fn main([[builtin(global_invocation_id)]] global_id: vec3) { - v_indices.data[global_id.x] = collatz_iterations(v_indices.data[global_id.x]); +@compute +@workgroup_size(1) +fn main(@builtin(global_invocation_id) global_id: vec3) { + v_indices[global_id.x] = collatz_iterations(v_indices[global_id.x]); } diff --git a/cli/tests/testdata/webgpu_hellotriangle_shader.wgsl b/cli/tests/testdata/webgpu_hellotriangle_shader.wgsl index b8b2b69fca..f84ccfe94d 100644 --- a/cli/tests/testdata/webgpu_hellotriangle_shader.wgsl +++ b/cli/tests/testdata/webgpu_hellotriangle_shader.wgsl @@ -1,10 +1,11 @@ -[[stage(vertex)]] -fn vs_main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4 { +@vertex +fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4 { let x = f32(i32(in_vertex_index) - 1); let y = f32(i32(in_vertex_index & 1u) * 2 - 1); return vec4(x, y, 0.0, 1.0); } -[[stage(fragment)]] -fn fs_main() -> [[location(0)]] vec4 { + +@fragment +fn fs_main() -> @location(0) vec4 { return vec4(1.0, 0.0, 0.0, 1.0); } diff --git a/cli/tests/unit/webgpu_test.ts b/cli/tests/unit/webgpu_test.ts index 6ecf27fd0e..fa71ffcc81 100644 --- a/cli/tests/unit/webgpu_test.ts +++ b/cli/tests/unit/webgpu_test.ts @@ -56,6 +56,7 @@ Deno.test({ storageBuffer.unmap(); const computePipeline = device.createComputePipeline({ + layout: "auto", compute: { module: shaderModule, entryPoint: "main", @@ -81,8 +82,8 @@ Deno.test({ computePass.setPipeline(computePipeline); computePass.setBindGroup(0, bindGroup); computePass.insertDebugMarker("compute collatz iterations"); - computePass.dispatch(numbers.length); - computePass.endPass(); + computePass.dispatchWorkgroups(numbers.length); + computePass.end(); encoder.copyBufferToBuffer(storageBuffer, 0, stagingBuffer, 0, size); @@ -172,13 +173,14 @@ Deno.test({ { view, storeOp: "store", - loadValue: [0, 1, 0, 1], + loadOp: "clear", + clearValue: [0, 1, 0, 1], }, ], }); renderPass.setPipeline(renderPipeline); renderPass.draw(3, 1); - renderPass.endPass(); + renderPass.end(); encoder.copyTextureToBuffer( { diff --git a/ext/webgpu/Cargo.toml b/ext/webgpu/Cargo.toml index f46c16332d..fd323c14b8 100644 --- a/ext/webgpu/Cargo.toml +++ b/ext/webgpu/Cargo.toml @@ -1,4 +1,4 @@ -# Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +# Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. [package] name = "deno_webgpu" @@ -14,5 +14,5 @@ description = "WebGPU implementation for Deno" deno_core = { version = "0.143.0", path = "../../core" } serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.17", features = ["full"] } -wgpu-core = { version = "0.12", features = ["trace", "replay", "serde"] } -wgpu-types = { version = "0.12", features = ["trace", "replay", "serde"] } +wgpu-core = { version = "0.13", features = ["trace", "replay", "serde"] } +wgpu-types = { version = "0.13", features = ["trace", "replay", "serde"] } diff --git a/ext/webgpu/LICENSE.md b/ext/webgpu/LICENSE.md index bbf190721d..cfc3a5226e 100644 --- a/ext/webgpu/LICENSE.md +++ b/ext/webgpu/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright 2018-2021 the Deno authors +Copyright 2018-2022 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/ext/webgpu/src/01_webgpu.js b/ext/webgpu/src/01_webgpu.js index be880d81df..21599a117e 100644 --- a/ext/webgpu/src/01_webgpu.js +++ b/ext/webgpu/src/01_webgpu.js @@ -48,6 +48,31 @@ Uint8Array, } = window.__bootstrap.primordials; + const _rid = Symbol("[[rid]]"); + const _size = Symbol("[[size]]"); + const _usage = Symbol("[[usage]]"); + const _state = Symbol("[[state]]"); + const _mappingRange = Symbol("[[mapping_range]]"); + const _mappedRanges = Symbol("[[mapped_ranges]]"); + const _mapMode = Symbol("[[map_mode]]"); + const _adapter = Symbol("[[adapter]]"); + const _cleanup = Symbol("[[cleanup]]"); + const _vendor = Symbol("[[vendor]]"); + const _architecture = Symbol("[[architecture]]"); + const _description = Symbol("[[description]]"); + const _limits = Symbol("[[limits]]"); + const _features = Symbol("[[features]]"); + const _reason = Symbol("[[reason]]"); + const _message = Symbol("[[message]]"); + const _label = Symbol("[[label]]"); + const _device = Symbol("[[device]]"); + const _queue = Symbol("[[queue]]"); + const _views = Symbol("[[views]]"); + const _texture = Symbol("[[texture]]"); + const _encoders = Symbol("[[encoders]]"); + const _encoder = Symbol("[[encoder]]"); + const _descriptor = Symbol("[[descriptor]]"); + /** * @param {any} self * @param {{prefix: string, context: string}} opts @@ -154,15 +179,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) { @@ -196,13 +241,14 @@ const { err, ...data } = await core.opAsync( "op_webgpu_request_adapter", - { ...options }, + options.powerPreference, + options.forceFallbackAdapter, ); if (err) { return null; } else { - return createGPUAdapter(data.name, data); + return createGPUAdapter(data); } } @@ -212,10 +258,6 @@ } const GPUPrototype = GPU.prototype; - const _name = Symbol("[[name]]"); - const _adapter = Symbol("[[adapter]]"); - const _cleanup = Symbol("[[cleanup]]"); - /** * @typedef InnerGPUAdapter * @property {number} rid @@ -225,14 +267,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), @@ -242,16 +282,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); @@ -295,12 +328,10 @@ const { rid, features, limits } = await core.opAsync( "op_webgpu_request_device", - { - adapterRid: this[_adapter].rid, - labe: descriptor.label, - requiredFeatures, - requiredLimits, - }, + this[_adapter].rid, + descriptor.label, + requiredFeatures, + requiredLimits, ); const inner = new InnerGPUDevice({ @@ -316,10 +347,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, }) @@ -328,7 +392,51 @@ } const GPUAdapterPrototype = GPUAdapter.prototype; - const _limits = Symbol("[[limits]]"); + 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; function createGPUSupportedLimits(features) { /** @type {GPUSupportedLimits} */ @@ -485,8 +593,6 @@ } const GPUSupportedLimitsPrototype = GPUSupportedLimits.prototype; - const _features = Symbol("[[features]]"); - function createGPUSupportedFeatures(features) { /** @type {GPUSupportedFeatures} */ const adapterFeatures = webidl.createBranded(GPUSupportedFeatures); @@ -552,9 +658,6 @@ const GPUSupportedFeaturesPrototype = GPUSupportedFeatures.prototype; - const _reason = Symbol("[[reason]]"); - const _message = Symbol("[[message]]"); - /** * @param {string | undefined} reason * @param {string} message @@ -596,8 +699,6 @@ const GPUDeviceLostInfoPrototype = GPUDeviceLostInfo.prototype; - const _label = Symbol("[[label]]"); - /** * @param {string} name * @param {any} type @@ -626,9 +727,6 @@ }); } - const _device = Symbol("[[device]]"); - const _queue = Symbol("[[queue]]"); - /** * @typedef ErrorScope * @property {string} filter @@ -776,7 +874,6 @@ return device; } - // TODO(@crowlKats): https://gpuweb.github.io/gpuweb/#errors-and-debugging class GPUDevice extends eventTarget.EventTarget { /** @type {InnerGPUDevice} */ [_device]; @@ -837,10 +934,14 @@ context: "Argument 1", }); const device = assertDevice(this, { prefix, context: "this" }); - const { rid, err } = core.opSync("op_webgpu_create_buffer", { - deviceRid: device.rid, - ...descriptor, - }); + const { rid, err } = core.opSync( + "op_webgpu_create_buffer", + device.rid, + descriptor.label, + descriptor.size, + descriptor.usage, + descriptor.mappedAtCreation, + ); device.pushError(err); /** @type {CreateGPUBufferOptions} */ let options; @@ -954,10 +1055,9 @@ const { rid, err } = core.opSync( "op_webgpu_create_bind_group_layout", - { - deviceRid: device.rid, - ...descriptor, - }, + device.rid, + descriptor.label, + descriptor.entries, ); device.pushError(err); @@ -996,11 +1096,12 @@ return rid; }, ); - const { rid, err } = core.opSync("op_webgpu_create_pipeline_layout", { - deviceRid: device.rid, - label: descriptor.label, + const { rid, err } = core.opSync( + "op_webgpu_create_pipeline_layout", + device.rid, + descriptor.label, bindGroupLayouts, - }); + ); device.pushError(err); const pipelineLayout = createGPUPipelineLayout( @@ -1090,12 +1191,13 @@ } }); - const { rid, err } = core.opSync("op_webgpu_create_bind_group", { - deviceRid: device.rid, - label: descriptor.label, + const { rid, err } = core.opSync( + "op_webgpu_create_bind_group", + device.rid, + descriptor.label, layout, entries, - }); + ); device.pushError(err); const bindGroup = createGPUBindGroup( @@ -1121,12 +1223,10 @@ const device = assertDevice(this, { prefix, context: "this" }); const { rid, err } = core.opSync( "op_webgpu_create_shader_module", - { - deviceRid: device.rid, - label: descriptor.label, - code: descriptor.code, - sourceMap: descriptor.sourceMap, - }, + device.rid, + descriptor.label, + descriptor.code, + descriptor.sourceMap, ); device.pushError(err); @@ -1152,8 +1252,8 @@ context: "Argument 1", }); const device = assertDevice(this, { prefix, context: "this" }); - let layout = undefined; - if (descriptor.layout) { + let layout = descriptor.layout; + if (typeof descriptor.layout !== "string") { const context = "layout"; layout = assertResource(descriptor.layout, { prefix, context }); assertDeviceMatch(device, descriptor.layout, { @@ -1174,15 +1274,13 @@ const { rid, err } = core.opSync( "op_webgpu_create_compute_pipeline", + device.rid, + descriptor.label, + layout, { - deviceRid: device.rid, - label: descriptor.label, - layout, - compute: { - module, - entryPoint: descriptor.compute.entryPoint, - constants: descriptor.compute.constants, - }, + module, + entryPoint: descriptor.compute.entryPoint, + constants: descriptor.compute.constants, }, ); device.pushError(err); @@ -1209,8 +1307,8 @@ context: "Argument 1", }); const device = assertDevice(this, { prefix, context: "this" }); - let layout = undefined; - if (descriptor.layout) { + let layout = descriptor.layout; + if (typeof descriptor.layout !== "string") { const context = "layout"; layout = assertResource(descriptor.layout, { prefix, context }); assertDeviceMatch(device, descriptor.layout, { @@ -1293,10 +1391,11 @@ context: "Argument 1", }); const device = assertDevice(this, { prefix, context: "this" }); - const { rid, err } = core.opSync("op_webgpu_create_command_encoder", { - deviceRid: device.rid, - ...descriptor, - }); + const { rid, err } = core.opSync( + "op_webgpu_create_command_encoder", + device.rid, + descriptor.label, + ); device.pushError(err); const commandEncoder = createGPUCommandEncoder( @@ -1490,10 +1589,14 @@ return rid; }, ); - const { err } = core.opSync("op_webgpu_queue_submit", { - queueRid: device.rid, - commandBuffers: commandBufferRids, - }); + const { err } = core.opSync( + "op_webgpu_queue_submit", + device.rid, + commandBufferRids, + ); + for (const commandBuffer of commandBuffers) { + commandBuffer[_rid] = undefined; + } device.pushError(err); } @@ -1547,13 +1650,11 @@ }); const { err } = core.opSync( "op_webgpu_write_buffer", - { - queueRid: device.rid, - buffer: bufferRid, - bufferOffset, - dataOffset, - size, - }, + device.rid, + bufferRid, + bufferOffset, + dataOffset, + size, new Uint8Array(ArrayBufferIsView(data) ? data.buffer : data), ); device.pushError(err); @@ -1597,19 +1698,17 @@ }); const { err } = core.opSync( "op_webgpu_write_texture", + device.rid, { - queueRid: device.rid, - destination: { - texture: textureRid, - mipLevel: destination.mipLevel, - origin: destination.origin - ? normalizeGPUOrigin3D(destination.origin) - : undefined, - aspect: destination.aspect, - }, - dataLayout, - size: normalizeGPUExtent3D(size), + texture: textureRid, + mipLevel: destination.mipLevel, + origin: destination.origin + ? normalizeGPUOrigin3D(destination.origin) + : undefined, + aspect: destination.aspect, }, + dataLayout, + normalizeGPUExtent3D(size), new Uint8Array(ArrayBufferIsView(data) ? data.buffer : data), ); device.pushError(err); @@ -1629,15 +1728,6 @@ } GPUObjectBaseMixin("GPUQueue", GPUQueue); - const _rid = Symbol("[[rid]]"); - - const _size = Symbol("[[size]]"); - const _usage = Symbol("[[usage]]"); - const _state = Symbol("[[state]]"); - const _mappingRange = Symbol("[[mapping_range]]"); - const _mappedRanges = Symbol("[[mapped_ranges]]"); - const _mapMode = Symbol("[[map_mode]]"); - /** * @typedef CreateGPUBufferOptions * @property {ArrayBuffer | null} mapping @@ -1799,13 +1889,11 @@ const promise = PromisePrototypeThen( core.opAsync( "op_webgpu_buffer_get_map_async", - { - bufferRid, - deviceRid: device.rid, - mode, - offset, - size: rangeSize, - }, + bufferRid, + device.rid, + mode, + offset, + rangeSize, ), ({ err }) => err, ); @@ -1868,11 +1956,9 @@ const buffer = new ArrayBuffer(rangeSize); const { rid } = core.opSync( "op_webgpu_buffer_get_mapped_range", - { - bufferRid, - offset, - size, - }, + bufferRid, + offset, + size, new Uint8Array(buffer), ); @@ -1923,10 +2009,12 @@ throw new DOMException(`${prefix}: invalid state.`, "OperationError"); } for (const [buffer, mappedRid] of mappedRanges) { - const { err } = core.opSync("op_webgpu_buffer_unmap", { + const { err } = core.opSync( + "op_webgpu_buffer_unmap", bufferRid, mappedRid, - }, ...new SafeArrayIterator(write ? [new Uint8Array(buffer)] : [])); + ...new SafeArrayIterator(write ? [new Uint8Array(buffer)] : []), + ); device.pushError(err); if (err) return; } @@ -2002,8 +2090,6 @@ } } - const _views = Symbol("[[views]]"); - /** * @param {string | null} label * @param {InnerGPUDevice} device @@ -2113,8 +2199,6 @@ } } - const _texture = Symbol("[[texture]]"); - /** * @param {string | null} label * @param {GPUTexture} texture @@ -2448,7 +2532,8 @@ }); const { rid, label, err } = core.opSync( "op_webgpu_compute_pipeline_get_bind_group_layout", - { computePipelineRid, index }, + computePipelineRid, + index, ); device.pushError(err); @@ -2524,7 +2609,8 @@ }); const { rid, label, err } = core.opSync( "op_webgpu_render_pipeline_get_bind_group_layout", - { renderPipelineRid, index }, + renderPipelineRid, + index, ); device.pushError(err); @@ -2570,8 +2656,6 @@ } } - const _encoders = Symbol("[[encoders]]"); - /** * @param {string | null} label * @param {InnerGPUDevice} device @@ -2661,28 +2745,6 @@ ...descriptor.depthStencilAttachment, view, }; - - if ( - typeof descriptor.depthStencilAttachment.depthLoadValue === "string" - ) { - depthStencilAttachment.depthLoadOp = - descriptor.depthStencilAttachment.depthLoadValue; - } else { - depthStencilAttachment.depthLoadOp = { - clear: descriptor.depthStencilAttachment.depthLoadValue, - }; - } - - if ( - typeof descriptor.depthStencilAttachment.stencilLoadValue === "string" - ) { - depthStencilAttachment.stencilLoadOp = - descriptor.depthStencilAttachment.stencilLoadValue; - } else { - depthStencilAttachment.stencilLoadOp = { - clear: descriptor.depthStencilAttachment.stencilLoadValue, - }; - } } const colorAttachments = ArrayPrototypeMap( descriptor.colorAttachments, @@ -2729,32 +2791,22 @@ }, ); } - const attachment = { + return { view: view, resolveTarget, storeOp: colorAttachment.storeOp, + loadOp: colorAttachment.loadOp, + clearValue: normalizeGPUColor(colorAttachment.clearValue), }; - - if (typeof colorAttachment.loadValue === "string") { - attachment.loadOp = colorAttachment.loadValue; - } else { - attachment.loadOp = { - clear: normalizeGPUColor(colorAttachment.loadValue), - }; - } - - return attachment; }, ); const { rid } = core.opSync( "op_webgpu_command_encoder_begin_render_pass", - { - commandEncoderRid, - ...descriptor, - colorAttachments, - depthStencilAttachment, - }, + commandEncoderRid, + descriptor.label, + colorAttachments, + depthStencilAttachment, ); const renderPassEncoder = createGPURenderPassEncoder( @@ -2786,10 +2838,8 @@ const { rid } = core.opSync( "op_webgpu_command_encoder_begin_compute_pass", - { - commandEncoderRid, - ...descriptor, - }, + commandEncoderRid, + descriptor.label, ); const computePassEncoder = createGPUComputePassEncoder( @@ -2865,14 +2915,12 @@ const { err } = core.opSync( "op_webgpu_command_encoder_copy_buffer_to_buffer", - { - commandEncoderRid, - source: sourceRid, - sourceOffset, - destination: destinationRid, - destinationOffset, - size, - }, + commandEncoderRid, + sourceRid, + sourceOffset, + destinationRid, + destinationOffset, + size, ); device.pushError(err); } @@ -2925,22 +2973,20 @@ const { err } = core.opSync( "op_webgpu_command_encoder_copy_buffer_to_texture", + commandEncoderRid, { - commandEncoderRid, - source: { - ...source, - buffer: sourceBufferRid, - }, - destination: { - texture: destinationTextureRid, - mipLevel: destination.mipLevel, - origin: destination.origin - ? normalizeGPUOrigin3D(destination.origin) - : undefined, - aspect: destination.aspect, - }, - copySize: normalizeGPUExtent3D(copySize), + ...source, + buffer: sourceBufferRid, }, + { + texture: destinationTextureRid, + mipLevel: destination.mipLevel, + origin: destination.origin + ? normalizeGPUOrigin3D(destination.origin) + : undefined, + aspect: destination.aspect, + }, + normalizeGPUExtent3D(copySize), ); device.pushError(err); } @@ -2992,22 +3038,20 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_copy_texture_to_buffer", + commandEncoderRid, { - commandEncoderRid, - source: { - texture: sourceTextureRid, - mipLevel: source.mipLevel, - origin: source.origin - ? normalizeGPUOrigin3D(source.origin) - : undefined, - aspect: source.aspect, - }, - destination: { - ...destination, - buffer: destinationBufferRid, - }, - copySize: normalizeGPUExtent3D(copySize), + texture: sourceTextureRid, + mipLevel: source.mipLevel, + origin: source.origin + ? normalizeGPUOrigin3D(source.origin) + : undefined, + aspect: source.aspect, }, + { + ...destination, + buffer: destinationBufferRid, + }, + normalizeGPUExtent3D(copySize), ); device.pushError(err); } @@ -3059,44 +3103,42 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_copy_texture_to_texture", + commandEncoderRid, { - commandEncoderRid, - source: { - texture: sourceTextureRid, - mipLevel: source.mipLevel, - origin: source.origin - ? normalizeGPUOrigin3D(source.origin) - : undefined, - aspect: source.aspect, - }, - destination: { - texture: destinationTextureRid, - mipLevel: destination.mipLevel, - origin: destination.origin - ? normalizeGPUOrigin3D(destination.origin) - : undefined, - aspect: source.aspect, - }, - copySize: normalizeGPUExtent3D(copySize), + texture: sourceTextureRid, + mipLevel: source.mipLevel, + origin: source.origin + ? normalizeGPUOrigin3D(source.origin) + : undefined, + aspect: source.aspect, }, + { + texture: destinationTextureRid, + mipLevel: destination.mipLevel, + origin: destination.origin + ? normalizeGPUOrigin3D(destination.origin) + : undefined, + aspect: source.aspect, + }, + normalizeGPUExtent3D(copySize), ); device.pushError(err); } /** - * @param {GPUBuffer} destination - * @param {GPUSize64} destinationOffset + * @param {GPUBuffer} buffer + * @param {GPUSize64} offset * @param {GPUSize64} size */ - clearBuffer(destination, destinationOffset, size) { + clearBuffer(buffer, offset = 0, size = undefined) { webidl.assertBranded(this, GPUCommandEncoderPrototype); const prefix = "Failed to execute 'clearBuffer' on 'GPUCommandEncoder'"; webidl.requiredArguments(arguments.length, 3, { prefix }); - destination = webidl.converters.GPUBuffer(destination, { + buffer = webidl.converters.GPUBuffer(buffer, { prefix, context: "Argument 1", }); - destinationOffset = webidl.converters.GPUSize64(destinationOffset, { + offset = webidl.converters.GPUSize64(offset, { prefix, context: "Argument 2", }); @@ -3109,18 +3151,16 @@ prefix, context: "this", }); - const destinationRid = assertResource(destination, { + const bufferRid = assertResource(buffer, { prefix, context: "Argument 1", }); const { err } = core.opSync( "op_webgpu_command_encoder_clear_buffer", - { - commandEncoderRid, - destinationRid, - destinationOffset, - size, - }, + commandEncoderRid, + bufferRid, + offset, + size, ); device.pushError(err); } @@ -3144,10 +3184,8 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_push_debug_group", - { - commandEncoderRid, - groupLabel, - }, + commandEncoderRid, + groupLabel, ); device.pushError(err); } @@ -3162,9 +3200,7 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_pop_debug_group", - { - commandEncoderRid, - }, + commandEncoderRid, ); device.pushError(err); } @@ -3188,10 +3224,8 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_insert_debug_marker", - { - commandEncoderRid, - markerLabel, - }, + commandEncoderRid, + markerLabel, ); device.pushError(err); } @@ -3229,11 +3263,9 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_write_timestamp", - { - commandEncoderRid, - querySet: querySetRid, - queryIndex, - }, + commandEncoderRid, + querySetRid, + queryIndex, ); device.pushError(err); } @@ -3301,14 +3333,12 @@ }); const { err } = core.opSync( "op_webgpu_command_encoder_resolve_query_set", - { - commandEncoderRid, - querySet: querySetRid, - firstQuery, - queryCount, - destination: destinationRid, - destinationOffset, - }, + commandEncoderRid, + querySetRid, + firstQuery, + queryCount, + destinationRid, + destinationOffset, ); device.pushError(err); } @@ -3329,10 +3359,11 @@ prefix, context: "this", }); - const { rid, err } = core.opSync("op_webgpu_command_encoder_finish", { + const { rid, err } = core.opSync( + "op_webgpu_command_encoder_finish", commandEncoderRid, - ...descriptor, - }); + descriptor.label, + ); device.pushError(err); /** @type {number | undefined} */ this[_rid] = undefined; @@ -3357,8 +3388,6 @@ GPUObjectBaseMixin("GPUCommandEncoder", GPUCommandEncoder); const GPUCommandEncoderPrototype = GPUCommandEncoder.prototype; - const _encoder = Symbol("[[encoder]]"); - /** * @param {string | null} label * @param {GPUCommandEncoder} encoder @@ -3477,13 +3506,14 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_set_scissor_rect", { + core.opSync( + "op_webgpu_render_pass_set_scissor_rect", renderPassRid, x, y, width, height, - }); + ); } /** @@ -3507,10 +3537,11 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_set_blend_constant", { + core.opSync( + "op_webgpu_render_pass_set_blend_constant", renderPassRid, - color: normalizeGPUColor(color), - }); + normalizeGPUColor(color), + ); } /** @@ -3534,10 +3565,11 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_set_stencil_reference", { + core.opSync( + "op_webgpu_render_pass_set_stencil_reference", renderPassRid, reference, - }); + ); } beginOcclusionQuery(_queryIndex) { @@ -3583,11 +3615,12 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_begin_pipeline_statistics_query", { + core.opSync( + "op_webgpu_render_pass_begin_pipeline_statistics_query", renderPassRid, - querySet: querySetRid, + querySetRid, queryIndex, - }); + ); } endPipelineStatisticsQuery() { @@ -3603,9 +3636,10 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_end_pipeline_statistics_query", { + core.opSync( + "op_webgpu_render_pass_end_pipeline_statistics_query", renderPassRid, - }); + ); } /** @@ -3643,11 +3677,12 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_write_timestamp", { + core.opSync( + "op_webgpu_render_pass_write_timestamp", renderPassRid, - querySet: querySetRid, + querySetRid, queryIndex, - }); + ); } /** @@ -3681,15 +3716,16 @@ }); return rid; }); - core.opSync("op_webgpu_render_pass_execute_bundles", { + core.opSync( + "op_webgpu_render_pass_execute_bundles", renderPassRid, - bundles: bundleRids, - }); + bundleRids, + ); } - endPass() { + end() { webidl.assertBranded(this, GPURenderPassEncoderPrototype); - const prefix = "Failed to execute 'endPass' on 'GPURenderPassEncoder'"; + const prefix = "Failed to execute 'end' on 'GPURenderPassEncoder'"; const device = assertDevice(this[_encoder], { prefix, context: "encoder referenced by this", @@ -3699,10 +3735,11 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - const { err } = core.opSync("op_webgpu_render_pass_end_pass", { + const { err } = core.opSync( + "op_webgpu_render_pass_end", commandEncoderRid, renderPassRid, - }); + ); device.pushError(err); this[_rid] = undefined; } @@ -3746,14 +3783,15 @@ dynamicOffsetsDataStart = 0; dynamicOffsetsDataLength = dynamicOffsetsData.length; } - core.opSync("op_webgpu_render_pass_set_bind_group", { + core.opSync( + "op_webgpu_render_pass_set_bind_group", renderPassRid, index, - bindGroup: bindGroupRid, + bindGroupRid, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength, - }); + ); } /** @@ -3777,10 +3815,11 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_push_debug_group", { + core.opSync( + "op_webgpu_render_pass_push_debug_group", renderPassRid, groupLabel, - }); + ); } popDebugGroup() { @@ -3796,9 +3835,7 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_pop_debug_group", { - renderPassRid, - }); + core.opSync("op_webgpu_render_pass_pop_debug_group", renderPassRid); } /** @@ -3822,10 +3859,11 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_insert_debug_marker", { + core.opSync( + "op_webgpu_render_pass_insert_debug_marker", renderPassRid, markerLabel, - }); + ); } /** @@ -3858,10 +3896,11 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_set_pipeline", { + core.opSync( + "op_webgpu_render_pass_set_pipeline", renderPassRid, - pipeline: pipelineRid, - }); + pipelineRid, + ); } /** @@ -3911,13 +3950,14 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_set_index_buffer", { + core.opSync( + "op_webgpu_render_pass_set_index_buffer", renderPassRid, - buffer: bufferRid, + bufferRid, indexFormat, offset, size, - }); + ); } /** @@ -3967,13 +4007,14 @@ resourceContext: "Argument 2", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_set_vertex_buffer", { + core.opSync( + "op_webgpu_render_pass_set_vertex_buffer", renderPassRid, slot, - buffer: bufferRid, + bufferRid, offset, size, - }); + ); } /** @@ -4011,13 +4052,14 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_draw", { + core.opSync( + "op_webgpu_render_pass_draw", renderPassRid, vertexCount, instanceCount, firstVertex, firstInstance, - }); + ); } /** @@ -4067,14 +4109,15 @@ context: "encoder referenced by this", }); const renderPassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_render_pass_draw_indexed", { + core.opSync( + "op_webgpu_render_pass_draw_indexed", renderPassRid, indexCount, instanceCount, firstIndex, baseVertex, firstInstance, - }); + ); } /** @@ -4112,11 +4155,12 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_draw_indirect", { + core.opSync( + "op_webgpu_render_pass_draw_indirect", renderPassRid, - indirectBuffer: indirectBufferRid, + indirectBufferRid, indirectOffset, - }); + ); } /** @@ -4154,11 +4198,12 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_pass_draw_indexed_indirect", { + core.opSync( + "op_webgpu_render_pass_draw_indexed_indirect", renderPassRid, - indirectBuffer: indirectBufferRid, + indirectBufferRid, indirectOffset, - }); + ); } [SymbolFor("Deno.privateCustomInspect")](inspect) { @@ -4237,24 +4282,39 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_compute_pass_set_pipeline", { + core.opSync( + "op_webgpu_compute_pass_set_pipeline", computePassRid, - pipeline: pipelineRid, - }); + pipelineRid, + ); } /** - * @param {number} x - * @param {number} y - * @param {number} z + * @param {number} workgroupCountX + * @param {number} workgroupCountY + * @param {number} workgroupCountZ */ - dispatch(x, y = 1, z = 1) { + dispatchWorkgroups( + workgroupCountX, + workgroupCountY = 1, + workgroupCountZ = 1, + ) { webidl.assertBranded(this, GPUComputePassEncoderPrototype); - const prefix = "Failed to execute 'dispatch' on 'GPUComputePassEncoder'"; + const prefix = + "Failed to execute 'dispatchWorkgroups' on 'GPUComputePassEncoder'"; webidl.requiredArguments(arguments.length, 1, { prefix }); - x = webidl.converters.GPUSize32(x, { prefix, context: "Argument 1" }); - y = webidl.converters.GPUSize32(y, { prefix, context: "Argument 2" }); - z = webidl.converters.GPUSize32(z, { prefix, context: "Argument 3" }); + workgroupCountX = webidl.converters.GPUSize32(workgroupCountX, { + prefix, + context: "Argument 1", + }); + workgroupCountY = webidl.converters.GPUSize32(workgroupCountY, { + prefix, + context: "Argument 2", + }); + workgroupCountZ = webidl.converters.GPUSize32(workgroupCountZ, { + prefix, + context: "Argument 3", + }); assertDevice(this[_encoder], { prefix, context: "encoder referenced by this", @@ -4264,22 +4324,23 @@ context: "encoder referenced by this", }); const computePassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_compute_pass_dispatch", { + core.opSync( + "op_webgpu_compute_pass_dispatch_workgroups", computePassRid, - x, - y, - z, - }); + workgroupCountX, + workgroupCountY, + workgroupCountZ, + ); } /** * @param {GPUBuffer} indirectBuffer * @param {number} indirectOffset */ - dispatchIndirect(indirectBuffer, indirectOffset) { + dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset) { webidl.assertBranded(this, GPUComputePassEncoderPrototype); const prefix = - "Failed to execute 'dispatchIndirect' on 'GPUComputePassEncoder'"; + "Failed to execute 'dispatchWorkgroupsIndirect' on 'GPUComputePassEncoder'"; webidl.requiredArguments(arguments.length, 2, { prefix }); indirectBuffer = webidl.converters.GPUBuffer(indirectBuffer, { prefix, @@ -4307,11 +4368,12 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_compute_pass_dispatch_indirect", { - computePassRid: computePassRid, - indirectBuffer: indirectBufferRid, + core.opSync( + "op_webgpu_compute_pass_dispatch_workgroups_indirect", + computePassRid, + indirectBufferRid, indirectOffset, - }); + ); } /** @@ -4351,11 +4413,9 @@ }); core.opSync( "op_webgpu_compute_pass_begin_pipeline_statistics_query", - { - computePassRid, - querySet: querySetRid, - queryIndex, - }, + computePassRid, + querySetRid, + queryIndex, ); } @@ -4372,9 +4432,10 @@ context: "encoder referenced by this", }); const computePassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_compute_pass_end_pipeline_statistics_query", { + core.opSync( + "op_webgpu_compute_pass_end_pipeline_statistics_query", computePassRid, - }); + ); } /** @@ -4412,16 +4473,17 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_compute_pass_write_timestamp", { + core.opSync( + "op_webgpu_compute_pass_write_timestamp", computePassRid, - querySet: querySetRid, + querySetRid, queryIndex, - }); + ); } - endPass() { + end() { webidl.assertBranded(this, GPUComputePassEncoderPrototype); - const prefix = "Failed to execute 'endPass' on 'GPUComputePassEncoder'"; + const prefix = "Failed to execute 'end' on 'GPUComputePassEncoder'"; const device = assertDevice(this[_encoder], { prefix, context: "encoder referenced by this", @@ -4431,10 +4493,11 @@ context: "encoder referenced by this", }); const computePassRid = assertResource(this, { prefix, context: "this" }); - const { err } = core.opSync("op_webgpu_compute_pass_end_pass", { + const { err } = core.opSync( + "op_webgpu_compute_pass_end", commandEncoderRid, computePassRid, - }); + ); device.pushError(err); this[_rid] = undefined; } @@ -4478,14 +4541,15 @@ dynamicOffsetsDataStart = 0; dynamicOffsetsDataLength = dynamicOffsetsData.length; } - core.opSync("op_webgpu_compute_pass_set_bind_group", { + core.opSync( + "op_webgpu_compute_pass_set_bind_group", computePassRid, index, - bindGroup: bindGroupRid, + bindGroupRid, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength, - }); + ); } /** @@ -4509,10 +4573,11 @@ context: "encoder referenced by this", }); const computePassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_compute_pass_push_debug_group", { + core.opSync( + "op_webgpu_compute_pass_push_debug_group", computePassRid, groupLabel, - }); + ); } popDebugGroup() { @@ -4528,9 +4593,7 @@ context: "encoder referenced by this", }); const computePassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_compute_pass_pop_debug_group", { - computePassRid, - }); + core.opSync("op_webgpu_compute_pass_pop_debug_group", computePassRid); } /** @@ -4554,10 +4617,11 @@ context: "encoder referenced by this", }); const computePassRid = assertResource(this, { prefix, context: "this" }); - core.opSync("op_webgpu_compute_pass_insert_debug_marker", { + core.opSync( + "op_webgpu_compute_pass_insert_debug_marker", computePassRid, markerLabel, - }); + ); } [SymbolFor("Deno.privateCustomInspect")](inspect) { @@ -4666,10 +4730,8 @@ }); const { rid, err } = core.opSync( "op_webgpu_render_bundle_encoder_finish", - { - renderBundleEncoderRid, - ...descriptor, - }, + renderBundleEncoderRid, + descriptor.label, ); device.pushError(err); this[_rid] = undefined; @@ -4718,14 +4780,15 @@ dynamicOffsetsDataStart = 0; dynamicOffsetsDataLength = dynamicOffsetsData.length; } - core.opSync("op_webgpu_render_bundle_encoder_set_bind_group", { + core.opSync( + "op_webgpu_render_bundle_encoder_set_bind_group", renderBundleEncoderRid, index, - bindGroup: bindGroupRid, + bindGroupRid, dynamicOffsetsData, dynamicOffsetsDataStart, dynamicOffsetsDataLength, - }); + ); } /** @@ -4745,10 +4808,11 @@ prefix, context: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_push_debug_group", { + core.opSync( + "op_webgpu_render_bundle_encoder_push_debug_group", renderBundleEncoderRid, groupLabel, - }); + ); } popDebugGroup() { @@ -4760,9 +4824,10 @@ prefix, context: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_pop_debug_group", { + core.opSync( + "op_webgpu_render_bundle_encoder_pop_debug_group", renderBundleEncoderRid, - }); + ); } /** @@ -4782,10 +4847,11 @@ prefix, context: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_push_debug_group", { + core.opSync( + "op_webgpu_render_bundle_encoder_insert_debug_marker", renderBundleEncoderRid, markerLabel, - }); + ); } /** @@ -4814,10 +4880,11 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_set_pipeline", { + core.opSync( + "op_webgpu_render_bundle_encoder_set_pipeline", renderBundleEncoderRid, - pipeline: pipelineRid, - }); + pipelineRid, + ); } /** @@ -4861,13 +4928,14 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_set_index_buffer", { + core.opSync( + "op_webgpu_render_bundle_encoder_set_index_buffer", renderBundleEncoderRid, - buffer: bufferRid, + bufferRid, indexFormat, offset, size, - }); + ); } /** @@ -4911,13 +4979,14 @@ resourceContext: "Argument 2", selfContext: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_set_vertex_buffer", { + core.opSync( + "op_webgpu_render_bundle_encoder_set_vertex_buffer", renderBundleEncoderRid, slot, - buffer: bufferRid, + bufferRid, offset, size, - }); + ); } /** @@ -4951,13 +5020,14 @@ prefix, context: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_draw", { + core.opSync( + "op_webgpu_render_bundle_encoder_draw", renderBundleEncoderRid, vertexCount, instanceCount, firstVertex, firstInstance, - }); + ); } /** @@ -5003,14 +5073,15 @@ prefix, context: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_draw_indexed", { + core.opSync( + "op_webgpu_render_bundle_encoder_draw_indexed", renderBundleEncoderRid, indexCount, instanceCount, firstIndex, baseVertex, firstInstance, - }); + ); } /** @@ -5044,11 +5115,12 @@ resourceContext: "Argument 1", selfContext: "this", }); - core.opSync("op_webgpu_render_bundle_encoder_draw_indirect", { + core.opSync( + "op_webgpu_render_bundle_encoder_draw_indirect", renderBundleEncoderRid, - indirectBuffer: indirectBufferRid, + indirectBufferRid, indirectOffset, - }); + ); } drawIndexedIndirect(_indirectBuffer, _indirectOffset) { @@ -5109,8 +5181,6 @@ } GPUObjectBaseMixin("GPURenderBundle", GPURenderBundle); - const _descriptor = Symbol("[[descriptor]]"); - /** * @param {string | null} label * @param {InnerGPUDevice} device @@ -5194,6 +5264,7 @@ GPURenderBundleEncoder, GPURenderBundle, GPUQuerySet, + GPUError, GPUOutOfMemoryError, GPUValidationError, }; diff --git a/ext/webgpu/src/02_idl_types.js b/ext/webgpu/src/02_idl_types.js index 0dd8c00f94..c1532c7ec9 100644 --- a/ext/webgpu/src/02_idl_types.js +++ b/ext/webgpu/src/02_idl_types.js @@ -120,6 +120,7 @@ "texture-compression-astc", "timestamp-query", "indirect-first-instance", + "shader-f16", // extended from spec "mappable-primary-buffers", "texture-binding-array", @@ -341,6 +342,8 @@ "depth24plus", "depth24plus-stencil8", "depth32float", + "depth24unorm-stencil8", + "depth32float-stencil8", "bc1-rgba-unorm", "bc1-rgba-unorm-srgb", "bc2-rgba-unorm", @@ -393,8 +396,6 @@ "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", - "depth24unorm-stencil8", - "depth32float-stencil8", ], ); @@ -539,6 +540,15 @@ ], ); + // ENUM: GPUMipmapFilterMode + webidl.converters["GPUMipmapFilterMode"] = webidl.createEnumConverter( + "GPUMipmapFilterMode", + [ + "nearest", + "linear", + ], + ); + // ENUM: GPUCompareFunction webidl.converters["GPUCompareFunction"] = webidl.createEnumConverter( "GPUCompareFunction", @@ -583,7 +593,7 @@ }, { key: "mipmapFilter", - converter: webidl.converters["GPUFilterMode"], + converter: webidl.converters["GPUMipmapFilterMode"], defaultValue: "nearest", }, { @@ -935,9 +945,26 @@ // GPUCompilationInfo.prototype, // ); + webidl.converters["GPUAutoLayoutMode"] = webidl.createEnumConverter( + "GPUAutoLayoutMode", + [ + "auto", + ], + ); + + webidl.converters["GPUPipelineLayout or GPUAutoLayoutMode"] = (V, opts) => { + if (typeof V === "object") { + return webidl.converters["GPUPipelineLayout"](V, opts); + } + return webidl.converters["GPUAutoLayoutMode"](V, opts); + }; + // DICTIONARY: GPUPipelineDescriptorBase const dictMembersGPUPipelineDescriptorBase = [ - { key: "layout", converter: webidl.converters["GPUPipelineLayout"] }, + { + key: "layout", + converter: webidl.converters["GPUPipelineLayout or GPUAutoLayoutMode"], + }, ]; webidl.converters["GPUPipelineDescriptorBase"] = webidl .createDictionaryConverter( @@ -1427,7 +1454,9 @@ { key: "targets", converter: webidl.createSequenceConverter( - webidl.converters["GPUColorTargetState"], + webidl.createNullableConverter( + webidl.converters["GPUColorTargetState"], + ), ), required: true, }, @@ -1675,6 +1704,7 @@ // ENUM: GPULoadOp webidl.converters["GPULoadOp"] = webidl.createEnumConverter("GPULoadOp", [ "load", + "clear", ]); // DICTIONARY: GPUColorDict @@ -1724,8 +1754,12 @@ }, { key: "resolveTarget", converter: webidl.converters["GPUTextureView"] }, { - key: "loadValue", - converter: webidl.converters.any, /** put union here! **/ + key: "clearValue", + converter: webidl.converters["GPUColor"], + }, + { + key: "loadOp", + converter: webidl.converters["GPULoadOp"], required: true, }, { @@ -1748,14 +1782,17 @@ required: true, }, { - key: "depthLoadValue", - converter: webidl.converters.any, /** put union here! **/ - required: true, + key: "depthClearValue", + converter: webidl.converters["float"], + defaultValue: 0, + }, + { + key: "depthLoadOp", + converter: webidl.converters["GPULoadOp"], }, { key: "depthStoreOp", converter: webidl.converters["GPUStoreOp"], - required: true, }, { key: "depthReadOnly", @@ -1763,14 +1800,17 @@ defaultValue: false, }, { - key: "stencilLoadValue", - converter: webidl.converters.any, /** put union here! **/ - required: true, + key: "stencilClearValue", + converter: webidl.converters["GPUStencilValue"], + defaultValue: 0, + }, + { + key: "stencilLoadOp", + converter: webidl.converters["GPULoadOp"], }, { key: "stencilStoreOp", converter: webidl.converters["GPUStoreOp"], - required: true, }, { key: "stencilReadOnly", @@ -1795,7 +1835,9 @@ { key: "colorAttachments", converter: webidl.createSequenceConverter( - webidl.converters["GPURenderPassColorAttachment"], + webidl.createNullableConverter( + webidl.converters["GPURenderPassColorAttachment"], + ), ), required: true, }, @@ -1840,7 +1882,7 @@ { key: "colorFormats", converter: webidl.createSequenceConverter( - webidl.converters["GPUTextureFormat"], + webidl.createNullableConverter(webidl.converters["GPUTextureFormat"]), ), required: true, }, diff --git a/ext/webgpu/src/binding.rs b/ext/webgpu/src/binding.rs index cb0d9e034d..c13fe17a18 100644 --- a/ext/webgpu/src/binding.rs +++ b/ext/webgpu/src/binding.rs @@ -2,11 +2,11 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; -use deno_core::{OpState, Resource}; use serde::Deserialize; use std::borrow::Cow; -use std::convert::{TryFrom, TryInto}; use super::error::WebGpuResult; @@ -122,7 +122,7 @@ impl From for wgpu_types::StorageTextureAccess { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct GpuBindGroupLayoutEntry { +pub struct GpuBindGroupLayoutEntry { binding: u32, visibility: u32, #[serde(flatten)] @@ -138,13 +138,9 @@ enum GpuBindingType { StorageTexture(GpuStorageTextureBindingLayout), } -impl TryFrom for wgpu_types::BindingType { - type Error = AnyError; - - fn try_from( - binding_type: GpuBindingType, - ) -> Result { - let binding_type = match binding_type { +impl From for wgpu_types::BindingType { + fn from(binding_type: GpuBindingType) -> wgpu_types::BindingType { + match binding_type { GpuBindingType::Buffer(buffer) => wgpu_types::BindingType::Buffer { ty: buffer.r#type.into(), has_dynamic_offset: buffer.has_dynamic_offset, @@ -165,44 +161,38 @@ impl TryFrom for wgpu_types::BindingType { view_dimension: storage_texture.view_dimension, } } - }; - Ok(binding_type) + } } } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateBindGroupLayoutArgs { - device_rid: ResourceId, - label: Option, - entries: Vec, -} - #[op] pub fn op_webgpu_create_bind_group_layout( state: &mut OpState, - args: CreateBindGroupLayoutArgs, + device_rid: ResourceId, + label: Option, + entries: Vec, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; - let mut entries = vec![]; - - for entry in args.entries { - entries.push(wgpu_types::BindGroupLayoutEntry { - binding: entry.binding, - visibility: wgpu_types::ShaderStages::from_bits(entry.visibility) - .unwrap(), - ty: entry.binding_type.try_into()?, - count: None, // native-only - }); - } + let entries = entries + .into_iter() + .map(|entry| { + wgpu_types::BindGroupLayoutEntry { + binding: entry.binding, + visibility: wgpu_types::ShaderStages::from_bits(entry.visibility) + .unwrap(), + ty: entry.binding_type.into(), + count: None, // native-only + } + }) + .collect::>(); let descriptor = wgpu_core::binding_model::BindGroupLayoutDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), entries: Cow::from(entries), }; @@ -213,35 +203,30 @@ pub fn op_webgpu_create_bind_group_layout( ) => state, WebGpuBindGroupLayout) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreatePipelineLayoutArgs { - device_rid: ResourceId, - label: Option, - bind_group_layouts: Vec, -} - #[op] pub fn op_webgpu_create_pipeline_layout( state: &mut OpState, - args: CreatePipelineLayoutArgs, + device_rid: ResourceId, + label: Option, + bind_group_layouts: Vec, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; - let mut bind_group_layouts = vec![]; - - for rid in &args.bind_group_layouts { - let bind_group_layout = - state.resource_table.get::(*rid)?; - bind_group_layouts.push(bind_group_layout.0); - } + let bind_group_layouts = bind_group_layouts + .into_iter() + .map(|rid| { + let bind_group_layout = + state.resource_table.get::(rid)?; + Ok(bind_group_layout.0) + }) + .collect::, AnyError>>()?; let descriptor = wgpu_core::binding_model::PipelineLayoutDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), bind_group_layouts: Cow::from(bind_group_layouts), push_constant_ranges: Default::default(), }; @@ -255,7 +240,7 @@ pub fn op_webgpu_create_pipeline_layout( #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct GpuBindGroupEntry { +pub struct GpuBindGroupEntry { binding: u32, kind: String, resource: ResourceId, @@ -263,73 +248,68 @@ struct GpuBindGroupEntry { size: Option, } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateBindGroupArgs { +#[op] +pub fn op_webgpu_create_bind_group( + state: &mut OpState, device_rid: ResourceId, label: Option, layout: ResourceId, entries: Vec, -} - -#[op] -pub fn op_webgpu_create_bind_group( - state: &mut OpState, - args: CreateBindGroupArgs, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; - let mut entries = vec![]; + let entries = entries + .into_iter() + .map(|entry| { + Ok(wgpu_core::binding_model::BindGroupEntry { + binding: entry.binding, + resource: match entry.kind.as_str() { + "GPUSampler" => { + let sampler_resource = + state + .resource_table + .get::(entry.resource)?; + wgpu_core::binding_model::BindingResource::Sampler( + sampler_resource.0, + ) + } + "GPUTextureView" => { + let texture_view_resource = + state + .resource_table + .get::(entry.resource)?; + wgpu_core::binding_model::BindingResource::TextureView( + texture_view_resource.0, + ) + } + "GPUBufferBinding" => { + let buffer_resource = + state + .resource_table + .get::(entry.resource)?; + wgpu_core::binding_model::BindingResource::Buffer( + wgpu_core::binding_model::BufferBinding { + buffer_id: buffer_resource.0, + offset: entry.offset.unwrap_or(0), + size: std::num::NonZeroU64::new(entry.size.unwrap_or(0)), + }, + ) + } + _ => unreachable!(), + }, + }) + }) + .collect::, AnyError>>()?; - for entry in &args.entries { - let e = wgpu_core::binding_model::BindGroupEntry { - binding: entry.binding, - resource: match entry.kind.as_str() { - "GPUSampler" => { - let sampler_resource = - state - .resource_table - .get::(entry.resource)?; - wgpu_core::binding_model::BindingResource::Sampler(sampler_resource.0) - } - "GPUTextureView" => { - let texture_view_resource = - state - .resource_table - .get::(entry.resource)?; - wgpu_core::binding_model::BindingResource::TextureView( - texture_view_resource.0, - ) - } - "GPUBufferBinding" => { - let buffer_resource = - state - .resource_table - .get::(entry.resource)?; - wgpu_core::binding_model::BindingResource::Buffer( - wgpu_core::binding_model::BufferBinding { - buffer_id: buffer_resource.0, - offset: entry.offset.unwrap_or(0), - size: std::num::NonZeroU64::new(entry.size.unwrap_or(0)), - }, - ) - } - _ => unreachable!(), - }, - }; - entries.push(e); - } - - let bind_group_layout = state - .resource_table - .get::(args.layout)?; + let bind_group_layout = + state.resource_table.get::(layout)?; let descriptor = wgpu_core::binding_model::BindGroupDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), layout: bind_group_layout.0, entries: Cow::from(entries), }; diff --git a/ext/webgpu/src/buffer.rs b/ext/webgpu/src/buffer.rs index f8bc213a30..ebe83591c7 100644 --- a/ext/webgpu/src/buffer.rs +++ b/ext/webgpu/src/buffer.rs @@ -4,14 +4,13 @@ use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::futures::channel::oneshot; use deno_core::op; - use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; -use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; +use std::convert::TryFrom; use std::rc::Rc; use std::time::Duration; @@ -32,33 +31,27 @@ impl Resource for WebGpuBufferMapped { } } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateBufferArgs { +#[op] +pub fn op_webgpu_create_buffer( + state: &mut OpState, device_rid: ResourceId, label: Option, size: u64, usage: u32, mapped_at_creation: bool, -} - -#[op] -pub fn op_webgpu_create_buffer( - state: &mut OpState, - args: CreateBufferArgs, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; let descriptor = wgpu_core::resource::BufferDescriptor { - label: args.label.map(Cow::from), - size: args.size, - usage: wgpu_types::BufferUsages::from_bits(args.usage) + label: label.map(Cow::from), + size, + usage: wgpu_types::BufferUsages::from_bits(usage) .ok_or_else(|| type_error("usage is not valid"))?, - mapped_at_creation: args.mapped_at_creation, + mapped_at_creation, }; gfx_put!(device => instance.device_create_buffer( @@ -68,20 +61,14 @@ pub fn op_webgpu_create_buffer( ) => state, WebGpuBuffer) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct BufferGetMapAsyncArgs { +#[op] +pub async fn op_webgpu_buffer_get_map_async( + state: Rc>, buffer_rid: ResourceId, device_rid: ResourceId, mode: u32, offset: u64, size: u64, -} - -#[op] -pub async fn op_webgpu_buffer_get_map_async( - state: Rc>, - args: BufferGetMapAsyncArgs, ) -> Result { let (sender, receiver) = oneshot::channel::>(); @@ -90,47 +77,36 @@ pub async fn op_webgpu_buffer_get_map_async( let state_ = state.borrow(); let instance = state_.borrow::(); let buffer_resource = - state_.resource_table.get::(args.buffer_rid)?; + state_.resource_table.get::(buffer_rid)?; let buffer = buffer_resource.0; let device_resource = state_ .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; device = device_resource.0; - let boxed_sender = Box::new(sender); - let sender_ptr = Box::into_raw(boxed_sender) as *mut u8; - - extern "C" fn buffer_map_future_wrapper( - status: wgpu_core::resource::BufferMapAsyncStatus, - user_data: *mut u8, - ) { - let sender_ptr = user_data as *mut oneshot::Sender>; - // TODO(bartlomieju): - #[allow(clippy::undocumented_unsafe_blocks)] - let boxed_sender = unsafe { Box::from_raw(sender_ptr) }; - boxed_sender + let callback = Box::new(move |status| { + sender .send(match status { wgpu_core::resource::BufferMapAsyncStatus::Success => Ok(()), _ => unreachable!(), // TODO }) .unwrap(); - } + }); // TODO(lucacasonato): error handling let maybe_err = gfx_select!(buffer => instance.buffer_map_async( - buffer, - args.offset..(args.offset + args.size), - wgpu_core::resource::BufferMapOperation { - host: match args.mode { - 1 => wgpu_core::device::HostMap::Read, - 2 => wgpu_core::device::HostMap::Write, - _ => unreachable!(), - }, - callback: buffer_map_future_wrapper, - user_data: sender_ptr, - } - )) - .err(); + buffer, + offset..(offset + size), + wgpu_core::resource::BufferMapOperation { + host: match mode { + 1 => wgpu_core::device::HostMap::Read, + 2 => wgpu_core::device::HostMap::Write, + _ => unreachable!(), + }, + callback: wgpu_core::resource::BufferMapCallback::from_rust(callback), + } + )) + .err(); if maybe_err.is_some() { return Ok(WebGpuResult::maybe_err(maybe_err)); @@ -144,7 +120,7 @@ pub async fn op_webgpu_buffer_get_map_async( { let state = state.borrow(); let instance = state.borrow::(); - gfx_select!(device => instance.device_poll(device, false)).unwrap() + gfx_select!(device => instance.device_poll(device, wgpu_types::Maintain::Wait)).unwrap(); } tokio::time::sleep(Duration::from_millis(10)).await; } @@ -163,39 +139,32 @@ pub async fn op_webgpu_buffer_get_map_async( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct BufferGetMappedRangeArgs { - buffer_rid: ResourceId, - offset: u64, - size: Option, -} - #[op] pub fn op_webgpu_buffer_get_mapped_range( state: &mut OpState, - args: BufferGetMappedRangeArgs, - mut zero_copy: ZeroCopyBuf, + buffer_rid: ResourceId, + offset: u64, + size: Option, + mut buf: ZeroCopyBuf, ) -> Result { let instance = state.borrow::(); - let buffer_resource = - state.resource_table.get::(args.buffer_rid)?; + let buffer_resource = state.resource_table.get::(buffer_rid)?; let buffer = buffer_resource.0; let (slice_pointer, range_size) = gfx_select!(buffer => instance.buffer_get_mapped_range( buffer, - args.offset, - args.size + offset, + size )) .map_err(|e| DomExceptionOperationError::new(&e.to_string()))?; - // TODO(bartlomieju): + // TODO(crowlKats): #[allow(clippy::undocumented_unsafe_blocks)] let slice = unsafe { std::slice::from_raw_parts_mut(slice_pointer, range_size as usize) }; - zero_copy.copy_from_slice(slice); + buf.copy_from_slice(slice); let rid = state .resource_table @@ -204,35 +173,27 @@ pub fn op_webgpu_buffer_get_mapped_range( Ok(WebGpuResult::rid(rid)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct BufferUnmapArgs { - buffer_rid: ResourceId, - mapped_rid: ResourceId, -} - #[op] pub fn op_webgpu_buffer_unmap( state: &mut OpState, - args: BufferUnmapArgs, - zero_copy: Option, + buffer_rid: ResourceId, + mapped_rid: ResourceId, + buf: Option, ) -> Result { let mapped_resource = state .resource_table - .take::(args.mapped_rid)?; + .take::(mapped_rid)?; let instance = state.borrow::(); - let buffer_resource = - state.resource_table.get::(args.buffer_rid)?; + let buffer_resource = state.resource_table.get::(buffer_rid)?; let buffer = buffer_resource.0; - let slice_pointer = mapped_resource.0; - let size = mapped_resource.1; - - if let Some(buffer) = zero_copy { - // TODO(bartlomieju): + if let Some(buf) = buf { + // TODO(crowlKats): #[allow(clippy::undocumented_unsafe_blocks)] - let slice = unsafe { std::slice::from_raw_parts_mut(slice_pointer, size) }; - slice.copy_from_slice(&buffer); + let slice = unsafe { + std::slice::from_raw_parts_mut(mapped_resource.0, mapped_resource.1) + }; + slice.copy_from_slice(&buf); } gfx_ok!(buffer => instance.buffer_unmap(buffer)) diff --git a/ext/webgpu/src/bundle.rs b/ext/webgpu/src/bundle.rs index 1f5e4da7b8..c3019206c5 100644 --- a/ext/webgpu/src/bundle.rs +++ b/ext/webgpu/src/bundle.rs @@ -2,9 +2,10 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; -use deno_core::{OpState, Resource}; use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; @@ -33,7 +34,7 @@ impl Resource for WebGpuRenderBundle { pub struct CreateRenderBundleEncoderArgs { device_rid: ResourceId, label: Option, - color_formats: Vec, + color_formats: Vec>, depth_stencil_format: Option, sample_count: u32, depth_read_only: bool, @@ -50,25 +51,17 @@ pub fn op_webgpu_create_render_bundle_encoder( .get::(args.device_rid)?; let device = device_resource.0; - let mut color_formats = vec![]; - - for format in args.color_formats { - color_formats.push(format); - } - - let depth_stencil = if let Some(format) = args.depth_stencil_format { - Some(wgpu_types::RenderBundleDepthStencil { + let depth_stencil = args.depth_stencil_format.map(|format| { + wgpu_types::RenderBundleDepthStencil { format, depth_read_only: args.depth_read_only, stencil_read_only: args.stencil_read_only, - }) - } else { - None - }; + } + }); let descriptor = wgpu_core::command::RenderBundleEncoderDescriptor { label: args.label.map(Cow::from), - color_formats: Cow::from(color_formats), + color_formats: Cow::from(args.color_formats), sample_count: args.sample_count, depth_stencil, multiview: None, @@ -93,22 +86,16 @@ pub fn op_webgpu_create_render_bundle_encoder( Ok(WebGpuResult::rid_err(rid, maybe_err)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderFinishArgs { - render_bundle_encoder_rid: ResourceId, - label: Option, -} - #[op] pub fn op_webgpu_render_bundle_encoder_finish( state: &mut OpState, - args: RenderBundleEncoderFinishArgs, + render_bundle_encoder_rid: ResourceId, + label: Option, ) -> Result { let render_bundle_encoder_resource = state .resource_table - .take::(args.render_bundle_encoder_rid)?; + .take::(render_bundle_encoder_rid)?; let render_bundle_encoder = Rc::try_unwrap(render_bundle_encoder_resource) .ok() .expect("unwrapping render_bundle_encoder_resource should succeed") @@ -119,48 +106,42 @@ pub fn op_webgpu_render_bundle_encoder_finish( gfx_put!(render_bundle_encoder.parent() => instance.render_bundle_encoder_finish( render_bundle_encoder, &wgpu_core::command::RenderBundleDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), }, std::marker::PhantomData ) => state, WebGpuRenderBundle) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderSetBindGroupArgs { +#[op] +pub fn op_webgpu_render_bundle_encoder_set_bind_group( + state: &mut OpState, render_bundle_encoder_rid: ResourceId, index: u32, bind_group: ResourceId, dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data_start: usize, dynamic_offsets_data_length: usize, -} - -#[op] -pub fn op_webgpu_render_bundle_encoder_set_bind_group( - state: &mut OpState, - args: RenderBundleEncoderSetBindGroupArgs, ) -> Result { let bind_group_resource = state .resource_table - .get::(args.bind_group)?; + .get::(bind_group)?; let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; // Align the data - assert!(args.dynamic_offsets_data.len() % std::mem::size_of::() == 0); + assert!(dynamic_offsets_data.len() % std::mem::size_of::() == 0); let (prefix, dynamic_offsets_data, suffix) = - // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a - // multiple of 4. - unsafe { args.dynamic_offsets_data.align_to::() }; + // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a + // multiple of 4. + unsafe { dynamic_offsets_data.align_to::() }; assert!(prefix.is_empty()); assert!(suffix.is_empty()); - let start = args.dynamic_offsets_data_start; - let len = args.dynamic_offsets_data_length; + let start = dynamic_offsets_data_start; + let len = dynamic_offsets_data_length; // Assert that length and start are both in bounds assert!(start <= dynamic_offsets_data.len()); @@ -173,7 +154,7 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group( unsafe { wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_bind_group( &mut render_bundle_encoder_resource.0.borrow_mut(), - args.index, + index, bind_group_resource.0, dynamic_offsets_data.as_ptr(), dynamic_offsets_data.len(), @@ -183,24 +164,18 @@ pub fn op_webgpu_render_bundle_encoder_set_bind_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderPushDebugGroupArgs { - render_bundle_encoder_rid: ResourceId, - group_label: String, -} - #[op] pub fn op_webgpu_render_bundle_encoder_push_debug_group( state: &mut OpState, - args: RenderBundleEncoderPushDebugGroupArgs, + render_bundle_encoder_rid: ResourceId, + group_label: String, ) -> Result { let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; - let label = std::ffi::CString::new(args.group_label).unwrap(); + let label = std::ffi::CString::new(group_label).unwrap(); // SAFETY: the string the raw pointer points to lives longer than the below // function invocation. unsafe { @@ -213,21 +188,15 @@ pub fn op_webgpu_render_bundle_encoder_push_debug_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderPopDebugGroupArgs { - render_bundle_encoder_rid: ResourceId, -} - #[op] pub fn op_webgpu_render_bundle_encoder_pop_debug_group( state: &mut OpState, - args: RenderBundleEncoderPopDebugGroupArgs, + render_bundle_encoder_rid: ResourceId, ) -> Result { let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; wgpu_core::command::bundle_ffi::wgpu_render_bundle_pop_debug_group( &mut render_bundle_encoder_resource.0.borrow_mut(), @@ -236,24 +205,18 @@ pub fn op_webgpu_render_bundle_encoder_pop_debug_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderInsertDebugMarkerArgs { - render_bundle_encoder_rid: ResourceId, - marker_label: String, -} - #[op] pub fn op_webgpu_render_bundle_encoder_insert_debug_marker( state: &mut OpState, - args: RenderBundleEncoderInsertDebugMarkerArgs, + render_bundle_encoder_rid: ResourceId, + marker_label: String, ) -> Result { let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; - let label = std::ffi::CString::new(args.marker_label).unwrap(); + let label = std::ffi::CString::new(marker_label).unwrap(); // SAFETY: the string the raw pointer points to lives longer than the below // function invocation. unsafe { @@ -266,26 +229,20 @@ pub fn op_webgpu_render_bundle_encoder_insert_debug_marker( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderSetPipelineArgs { - render_bundle_encoder_rid: ResourceId, - pipeline: ResourceId, -} - #[op] pub fn op_webgpu_render_bundle_encoder_set_pipeline( state: &mut OpState, - args: RenderBundleEncoderSetPipelineArgs, + render_bundle_encoder_rid: ResourceId, + pipeline: ResourceId, ) -> Result { let render_pipeline_resource = state .resource_table - .get::(args.pipeline)?; + .get::(pipeline)?; let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_pipeline( &mut render_bundle_encoder_resource.0.borrow_mut(), @@ -295,165 +252,135 @@ pub fn op_webgpu_render_bundle_encoder_set_pipeline( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderSetIndexBufferArgs { +#[op] +pub fn op_webgpu_render_bundle_encoder_set_index_buffer( + state: &mut OpState, render_bundle_encoder_rid: ResourceId, buffer: ResourceId, index_format: wgpu_types::IndexFormat, offset: u64, size: u64, -} - -#[op] -pub fn op_webgpu_render_bundle_encoder_set_index_buffer( - state: &mut OpState, - args: RenderBundleEncoderSetIndexBufferArgs, ) -> Result { let buffer_resource = state .resource_table - .get::(args.buffer)?; + .get::(buffer)?; let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; render_bundle_encoder_resource .0 .borrow_mut() .set_index_buffer( buffer_resource.0, - args.index_format, - args.offset, - std::num::NonZeroU64::new(args.size), + index_format, + offset, + std::num::NonZeroU64::new(size), ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderSetVertexBufferArgs { +#[op] +pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer( + state: &mut OpState, render_bundle_encoder_rid: ResourceId, slot: u32, buffer: ResourceId, offset: u64, size: u64, -} - -#[op] -pub fn op_webgpu_render_bundle_encoder_set_vertex_buffer( - state: &mut OpState, - args: RenderBundleEncoderSetVertexBufferArgs, ) -> Result { let buffer_resource = state .resource_table - .get::(args.buffer)?; + .get::(buffer)?; let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; wgpu_core::command::bundle_ffi::wgpu_render_bundle_set_vertex_buffer( &mut render_bundle_encoder_resource.0.borrow_mut(), - args.slot, + slot, buffer_resource.0, - args.offset, - std::num::NonZeroU64::new(args.size), + offset, + std::num::NonZeroU64::new(size), ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderDrawArgs { - render_bundle_encoder_rid: ResourceId, - vertex_count: u32, - instance_count: u32, - first_vertex: u32, - first_instance: u32, -} - #[op] pub fn op_webgpu_render_bundle_encoder_draw( state: &mut OpState, - args: RenderBundleEncoderDrawArgs, + render_bundle_encoder_rid: ResourceId, + vertex_count: u32, + instance_count: u32, + first_vertex: u32, + first_instance: u32, ) -> Result { let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw( &mut render_bundle_encoder_resource.0.borrow_mut(), - args.vertex_count, - args.instance_count, - args.first_vertex, - args.first_instance, + vertex_count, + instance_count, + first_vertex, + first_instance, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderDrawIndexedArgs { +#[op] +pub fn op_webgpu_render_bundle_encoder_draw_indexed( + state: &mut OpState, render_bundle_encoder_rid: ResourceId, index_count: u32, instance_count: u32, first_index: u32, base_vertex: i32, first_instance: u32, -} - -#[op] -pub fn op_webgpu_render_bundle_encoder_draw_indexed( - state: &mut OpState, - args: RenderBundleEncoderDrawIndexedArgs, ) -> Result { let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indexed( &mut render_bundle_encoder_resource.0.borrow_mut(), - args.index_count, - args.instance_count, - args.first_index, - args.base_vertex, - args.first_instance, + index_count, + instance_count, + first_index, + base_vertex, + first_instance, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderBundleEncoderDrawIndirectArgs { - render_bundle_encoder_rid: ResourceId, - indirect_buffer: ResourceId, - indirect_offset: u64, -} - #[op] pub fn op_webgpu_render_bundle_encoder_draw_indirect( state: &mut OpState, - args: RenderBundleEncoderDrawIndirectArgs, + render_bundle_encoder_rid: ResourceId, + indirect_buffer: ResourceId, + indirect_offset: u64, ) -> Result { let buffer_resource = state .resource_table - .get::(args.indirect_buffer)?; + .get::(indirect_buffer)?; let render_bundle_encoder_resource = state .resource_table - .get::(args.render_bundle_encoder_rid)?; + .get::(render_bundle_encoder_rid)?; wgpu_core::command::bundle_ffi::wgpu_render_bundle_draw_indirect( &mut render_bundle_encoder_resource.0.borrow_mut(), buffer_resource.0, - args.indirect_offset, + indirect_offset, ); Ok(WebGpuResult::empty()) diff --git a/ext/webgpu/src/command_encoder.rs b/ext/webgpu/src/command_encoder.rs index dc777a85d4..d09199bbf2 100644 --- a/ext/webgpu/src/command_encoder.rs +++ b/ext/webgpu/src/command_encoder.rs @@ -2,8 +2,9 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; -use deno_core::{OpState, Resource}; use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; @@ -29,27 +30,20 @@ impl Resource for WebGpuCommandBuffer { } } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateCommandEncoderArgs { - device_rid: ResourceId, - label: Option, - _measure_execution_time: Option, // not yet implemented -} - #[op] pub fn op_webgpu_create_command_encoder( state: &mut OpState, - args: CreateCommandEncoderArgs, + device_rid: ResourceId, + label: Option, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; let descriptor = wgpu_types::CommandEncoderDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), }; gfx_put!(device => instance.device_create_command_encoder( @@ -64,134 +58,104 @@ pub fn op_webgpu_create_command_encoder( pub struct GpuRenderPassColorAttachment { view: ResourceId, resolve_target: Option, - load_op: GpuLoadOp, + clear_value: Option, + load_op: wgpu_core::command::LoadOp, store_op: wgpu_core::command::StoreOp, } -#[derive(Deserialize)] -#[serde(rename_all = "kebab-case")] -enum GpuLoadOp { - Load, - Clear(T), -} - #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct GpuRenderPassDepthStencilAttachment { +pub struct GpuRenderPassDepthStencilAttachment { view: ResourceId, - depth_load_op: GpuLoadOp, + depth_clear_value: f32, + depth_load_op: wgpu_core::command::LoadOp, depth_store_op: wgpu_core::command::StoreOp, depth_read_only: bool, - stencil_load_op: GpuLoadOp, + stencil_clear_value: u32, + stencil_load_op: wgpu_core::command::LoadOp, stencil_store_op: wgpu_core::command::StoreOp, stencil_read_only: bool, } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderBeginRenderPassArgs { - command_encoder_rid: ResourceId, - label: Option, - color_attachments: Vec, - depth_stencil_attachment: Option, - _occlusion_query_set: Option, // not yet implemented -} - #[op] pub fn op_webgpu_command_encoder_begin_render_pass( state: &mut OpState, - args: CommandEncoderBeginRenderPassArgs, + command_encoder_rid: ResourceId, + label: Option, + color_attachments: Vec>, + depth_stencil_attachment: Option, + _occlusion_query_set: Option, // not yet implemented ) -> Result { let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; - let mut color_attachments = vec![]; + let color_attachments = color_attachments + .into_iter() + .map(|color_attachment| { + let rp_at = if let Some(at) = color_attachment.as_ref() { + let texture_view_resource = + state + .resource_table + .get::(at.view)?; - for color_attachment in args.color_attachments { - let texture_view_resource = - state - .resource_table - .get::(color_attachment.view)?; + let resolve_target = at + .resolve_target + .map(|rid| { + state + .resource_table + .get::(rid) + }) + .transpose()? + .map(|texture| texture.0); - let resolve_target = color_attachment - .resolve_target - .map(|rid| { - state - .resource_table - .get::(rid) - }) - .transpose()? - .map(|texture| texture.0); + Some(wgpu_core::command::RenderPassColorAttachment { + view: texture_view_resource.0, + resolve_target, + channel: wgpu_core::command::PassChannel { + load_op: at.load_op, + store_op: at.store_op, + clear_value: at.clear_value.unwrap_or_default(), + read_only: false, + }, + }) + } else { + None + }; + Ok(rp_at) + }) + .collect::, AnyError>>()?; - let attachment = wgpu_core::command::RenderPassColorAttachment { - view: texture_view_resource.0, - resolve_target, - channel: match color_attachment.load_op { - GpuLoadOp::Load => wgpu_core::command::PassChannel { - load_op: wgpu_core::command::LoadOp::Load, - store_op: color_attachment.store_op, - clear_value: Default::default(), - read_only: false, - }, - GpuLoadOp::Clear(color) => wgpu_core::command::PassChannel { - load_op: wgpu_core::command::LoadOp::Clear, - store_op: color_attachment.store_op, - clear_value: color, - read_only: false, - }, - }, - }; + let mut processed_depth_stencil_attachment = None; - color_attachments.push(attachment) - } - - let mut depth_stencil_attachment = None; - - if let Some(attachment) = args.depth_stencil_attachment { + if let Some(attachment) = depth_stencil_attachment { let texture_view_resource = state .resource_table .get::(attachment.view)?; - depth_stencil_attachment = + processed_depth_stencil_attachment = Some(wgpu_core::command::RenderPassDepthStencilAttachment { view: texture_view_resource.0, - depth: match attachment.depth_load_op { - GpuLoadOp::Load => wgpu_core::command::PassChannel { - load_op: wgpu_core::command::LoadOp::Load, - store_op: attachment.depth_store_op, - clear_value: 0.0, - read_only: attachment.depth_read_only, - }, - GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel { - load_op: wgpu_core::command::LoadOp::Clear, - store_op: attachment.depth_store_op, - clear_value: value, - read_only: attachment.depth_read_only, - }, + depth: wgpu_core::command::PassChannel { + load_op: attachment.depth_load_op, + store_op: attachment.depth_store_op, + clear_value: attachment.depth_clear_value, + read_only: attachment.depth_read_only, }, - stencil: match attachment.stencil_load_op { - GpuLoadOp::Load => wgpu_core::command::PassChannel { - load_op: wgpu_core::command::LoadOp::Load, - store_op: attachment.stencil_store_op, - clear_value: 0, - read_only: attachment.stencil_read_only, - }, - GpuLoadOp::Clear(value) => wgpu_core::command::PassChannel { - load_op: wgpu_core::command::LoadOp::Clear, - store_op: attachment.stencil_store_op, - clear_value: value, - read_only: attachment.stencil_read_only, - }, + stencil: wgpu_core::command::PassChannel { + load_op: attachment.stencil_load_op, + store_op: attachment.stencil_store_op, + clear_value: attachment.stencil_clear_value, + read_only: attachment.stencil_read_only, }, }); } let descriptor = wgpu_core::command::RenderPassDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), color_attachments: Cow::from(color_attachments), - depth_stencil_attachment: depth_stencil_attachment.as_ref(), + depth_stencil_attachment: processed_depth_stencil_attachment.as_ref(), }; let render_pass = wgpu_core::command::RenderPass::new( @@ -208,24 +172,18 @@ pub fn op_webgpu_command_encoder_begin_render_pass( Ok(WebGpuResult::rid(rid)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderBeginComputePassArgs { - command_encoder_rid: ResourceId, - label: Option, -} - #[op] pub fn op_webgpu_command_encoder_begin_compute_pass( state: &mut OpState, - args: CommandEncoderBeginComputePassArgs, + command_encoder_rid: ResourceId, + label: Option, ) -> Result { let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let descriptor = wgpu_core::command::ComputePassDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), }; let compute_pass = wgpu_core::command::ComputePass::new( @@ -242,45 +200,38 @@ pub fn op_webgpu_command_encoder_begin_compute_pass( Ok(WebGpuResult::rid(rid)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderCopyBufferToBufferArgs { +#[op] +pub fn op_webgpu_command_encoder_copy_buffer_to_buffer( + state: &mut OpState, command_encoder_rid: ResourceId, source: ResourceId, source_offset: u64, destination: ResourceId, destination_offset: u64, size: u64, -} - -#[op] -pub fn op_webgpu_command_encoder_copy_buffer_to_buffer( - state: &mut OpState, - args: CommandEncoderCopyBufferToBufferArgs, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; - let source_buffer_resource = - state - .resource_table - .get::(args.source)?; + let source_buffer_resource = state + .resource_table + .get::(source)?; let source_buffer = source_buffer_resource.0; let destination_buffer_resource = state .resource_table - .get::(args.destination)?; + .get::(destination)?; let destination_buffer = destination_buffer_resource.0; gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_buffer( command_encoder, source_buffer, - args.source_offset, + source_offset, destination_buffer, - args.destination_offset, - args.size + destination_offset, + size )) } @@ -302,342 +253,277 @@ pub struct GpuImageCopyTexture { pub aspect: wgpu_types::TextureAspect, } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderCopyBufferToTextureArgs { +#[op] +pub fn op_webgpu_command_encoder_copy_buffer_to_texture( + state: &mut OpState, command_encoder_rid: ResourceId, source: GpuImageCopyBuffer, destination: GpuImageCopyTexture, copy_size: wgpu_types::Extent3d, -} - -#[op] -pub fn op_webgpu_command_encoder_copy_buffer_to_texture( - state: &mut OpState, - args: CommandEncoderCopyBufferToTextureArgs, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let source_buffer_resource = state .resource_table - .get::(args.source.buffer)?; + .get::(source.buffer)?; let destination_texture_resource = state .resource_table - .get::(args.destination.texture)?; + .get::(destination.texture)?; let source = wgpu_core::command::ImageCopyBuffer { buffer: source_buffer_resource.0, layout: wgpu_types::ImageDataLayout { - offset: args.source.offset, - bytes_per_row: NonZeroU32::new(args.source.bytes_per_row.unwrap_or(0)), - rows_per_image: NonZeroU32::new(args.source.rows_per_image.unwrap_or(0)), + offset: source.offset, + bytes_per_row: NonZeroU32::new(source.bytes_per_row.unwrap_or(0)), + rows_per_image: NonZeroU32::new(source.rows_per_image.unwrap_or(0)), }, }; let destination = wgpu_core::command::ImageCopyTexture { texture: destination_texture_resource.0, - mip_level: args.destination.mip_level, - origin: args.destination.origin, - aspect: args.destination.aspect, + mip_level: destination.mip_level, + origin: destination.origin, + aspect: destination.aspect, }; gfx_ok!(command_encoder => instance.command_encoder_copy_buffer_to_texture( command_encoder, &source, &destination, - &args.copy_size + ©_size )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderCopyTextureToBufferArgs { - command_encoder_rid: ResourceId, - source: GpuImageCopyTexture, - destination: GpuImageCopyBuffer, - copy_size: wgpu_types::Extent3d, -} - #[op] pub fn op_webgpu_command_encoder_copy_texture_to_buffer( state: &mut OpState, - args: CommandEncoderCopyTextureToBufferArgs, + command_encoder_rid: ResourceId, + source: GpuImageCopyTexture, + destination: GpuImageCopyBuffer, + copy_size: wgpu_types::Extent3d, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let source_texture_resource = state .resource_table - .get::(args.source.texture)?; + .get::(source.texture)?; let destination_buffer_resource = state .resource_table - .get::(args.destination.buffer)?; + .get::(destination.buffer)?; let source = wgpu_core::command::ImageCopyTexture { texture: source_texture_resource.0, - mip_level: args.source.mip_level, - origin: args.source.origin, - aspect: args.source.aspect, + mip_level: source.mip_level, + origin: source.origin, + aspect: source.aspect, }; let destination = wgpu_core::command::ImageCopyBuffer { buffer: destination_buffer_resource.0, layout: wgpu_types::ImageDataLayout { - offset: args.destination.offset, - bytes_per_row: NonZeroU32::new( - args.destination.bytes_per_row.unwrap_or(0), - ), - rows_per_image: NonZeroU32::new( - args.destination.rows_per_image.unwrap_or(0), - ), + offset: destination.offset, + bytes_per_row: NonZeroU32::new(destination.bytes_per_row.unwrap_or(0)), + rows_per_image: NonZeroU32::new(destination.rows_per_image.unwrap_or(0)), }, }; gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_buffer( command_encoder, &source, &destination, - &args.copy_size + ©_size )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderCopyTextureToTextureArgs { - command_encoder_rid: ResourceId, - source: GpuImageCopyTexture, - destination: GpuImageCopyTexture, - copy_size: wgpu_types::Extent3d, -} - #[op] pub fn op_webgpu_command_encoder_copy_texture_to_texture( state: &mut OpState, - args: CommandEncoderCopyTextureToTextureArgs, + command_encoder_rid: ResourceId, + source: GpuImageCopyTexture, + destination: GpuImageCopyTexture, + copy_size: wgpu_types::Extent3d, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let source_texture_resource = state .resource_table - .get::(args.source.texture)?; + .get::(source.texture)?; let destination_texture_resource = state .resource_table - .get::(args.destination.texture)?; + .get::(destination.texture)?; let source = wgpu_core::command::ImageCopyTexture { texture: source_texture_resource.0, - mip_level: args.source.mip_level, - origin: args.source.origin, - aspect: args.source.aspect, + mip_level: source.mip_level, + origin: source.origin, + aspect: source.aspect, }; let destination = wgpu_core::command::ImageCopyTexture { texture: destination_texture_resource.0, - mip_level: args.destination.mip_level, - origin: args.destination.origin, - aspect: args.destination.aspect, + mip_level: destination.mip_level, + origin: destination.origin, + aspect: destination.aspect, }; gfx_ok!(command_encoder => instance.command_encoder_copy_texture_to_texture( command_encoder, &source, &destination, - &args.copy_size + ©_size )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderClearBufferArgs { - command_encoder_rid: u32, - destination_rid: u32, - destination_offset: u64, - size: u64, -} - #[op] pub fn op_webgpu_command_encoder_clear_buffer( state: &mut OpState, - args: CommandEncoderClearBufferArgs, + command_encoder_rid: u32, + buffer_rid: u32, + offset: u64, + size: u64, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let destination_resource = state .resource_table - .get::(args.destination_rid)?; + .get::(buffer_rid)?; gfx_ok!(command_encoder => instance.command_encoder_clear_buffer( command_encoder, destination_resource.0, - args.destination_offset, - std::num::NonZeroU64::new(args.size) + offset, + std::num::NonZeroU64::new(size) )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderPushDebugGroupArgs { - command_encoder_rid: ResourceId, - group_label: String, -} - #[op] pub fn op_webgpu_command_encoder_push_debug_group( state: &mut OpState, - args: CommandEncoderPushDebugGroupArgs, + command_encoder_rid: ResourceId, + group_label: String, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; - gfx_ok!(command_encoder => instance - .command_encoder_push_debug_group(command_encoder, &args.group_label)) -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderPopDebugGroupArgs { - command_encoder_rid: ResourceId, + gfx_ok!(command_encoder => instance.command_encoder_push_debug_group(command_encoder, &group_label)) } #[op] pub fn op_webgpu_command_encoder_pop_debug_group( state: &mut OpState, - args: CommandEncoderPopDebugGroupArgs, + command_encoder_rid: ResourceId, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; gfx_ok!(command_encoder => instance.command_encoder_pop_debug_group(command_encoder)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderInsertDebugMarkerArgs { - command_encoder_rid: ResourceId, - marker_label: String, -} - #[op] pub fn op_webgpu_command_encoder_insert_debug_marker( state: &mut OpState, - args: CommandEncoderInsertDebugMarkerArgs, + command_encoder_rid: ResourceId, + marker_label: String, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; gfx_ok!(command_encoder => instance.command_encoder_insert_debug_marker( command_encoder, - &args.marker_label + &marker_label )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderWriteTimestampArgs { - command_encoder_rid: ResourceId, - query_set: ResourceId, - query_index: u32, -} - #[op] pub fn op_webgpu_command_encoder_write_timestamp( state: &mut OpState, - args: CommandEncoderWriteTimestampArgs, + command_encoder_rid: ResourceId, + query_set: ResourceId, + query_index: u32, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let query_set_resource = state .resource_table - .get::(args.query_set)?; + .get::(query_set)?; gfx_ok!(command_encoder => instance.command_encoder_write_timestamp( command_encoder, query_set_resource.0, - args.query_index + query_index )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderResolveQuerySetArgs { +#[op] +pub fn op_webgpu_command_encoder_resolve_query_set( + state: &mut OpState, command_encoder_rid: ResourceId, query_set: ResourceId, first_query: u32, query_count: u32, destination: ResourceId, destination_offset: u64, -} - -#[op] -pub fn op_webgpu_command_encoder_resolve_query_set( - state: &mut OpState, - args: CommandEncoderResolveQuerySetArgs, ) -> Result { let instance = state.borrow::(); let command_encoder_resource = state .resource_table - .get::(args.command_encoder_rid)?; + .get::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let query_set_resource = state .resource_table - .get::(args.query_set)?; + .get::(query_set)?; let destination_resource = state .resource_table - .get::(args.destination)?; + .get::(destination)?; gfx_ok!(command_encoder => instance.command_encoder_resolve_query_set( command_encoder, query_set_resource.0, - args.first_query, - args.query_count, + first_query, + query_count, destination_resource.0, - args.destination_offset + destination_offset )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CommandEncoderFinishArgs { - command_encoder_rid: ResourceId, - label: Option, -} - #[op] pub fn op_webgpu_command_encoder_finish( state: &mut OpState, - args: CommandEncoderFinishArgs, + command_encoder_rid: ResourceId, + label: Option, ) -> Result { let command_encoder_resource = state .resource_table - .take::(args.command_encoder_rid)?; + .take::(command_encoder_rid)?; let command_encoder = command_encoder_resource.0; let instance = state.borrow::(); let descriptor = wgpu_types::CommandBufferDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), }; gfx_put!(command_encoder => instance.command_encoder_finish( diff --git a/ext/webgpu/src/compute_pass.rs b/ext/webgpu/src/compute_pass.rs index 5e27583f4b..c4ae1608bb 100644 --- a/ext/webgpu/src/compute_pass.rs +++ b/ext/webgpu/src/compute_pass.rs @@ -2,10 +2,10 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; -use deno_core::{OpState, Resource}; -use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; @@ -20,25 +20,19 @@ impl Resource for WebGpuComputePass { } } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassSetPipelineArgs { - compute_pass_rid: ResourceId, - pipeline: ResourceId, -} - #[op] pub fn op_webgpu_compute_pass_set_pipeline( state: &mut OpState, - args: ComputePassSetPipelineArgs, + compute_pass_rid: ResourceId, + pipeline: ResourceId, ) -> Result { let compute_pipeline_resource = state .resource_table - .get::(args.pipeline)?; + .get::(pipeline)?; let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; wgpu_core::command::compute_ffi::wgpu_compute_pass_set_pipeline( &mut compute_pass_resource.0.borrow_mut(), @@ -48,106 +42,82 @@ pub fn op_webgpu_compute_pass_set_pipeline( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassDispatchArgs { +#[op] +pub fn op_webgpu_compute_pass_dispatch_workgroups( + state: &mut OpState, compute_pass_rid: ResourceId, x: u32, y: u32, z: u32, -} - -#[op] -pub fn op_webgpu_compute_pass_dispatch( - state: &mut OpState, - args: ComputePassDispatchArgs, ) -> Result { let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; - wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch( + wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups( &mut compute_pass_resource.0.borrow_mut(), - args.x, - args.y, - args.z, + x, + y, + z, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassDispatchIndirectArgs { +#[op] +pub fn op_webgpu_compute_pass_dispatch_workgroups_indirect( + state: &mut OpState, compute_pass_rid: ResourceId, indirect_buffer: ResourceId, indirect_offset: u64, -} - -#[op] -pub fn op_webgpu_compute_pass_dispatch_indirect( - state: &mut OpState, - args: ComputePassDispatchIndirectArgs, ) -> Result { let buffer_resource = state .resource_table - .get::(args.indirect_buffer)?; + .get::(indirect_buffer)?; let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; - wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_indirect( - &mut compute_pass_resource.0.borrow_mut(), - buffer_resource.0, - args.indirect_offset, - ); - - Ok(WebGpuResult::empty()) -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassBeginPipelineStatisticsQueryArgs { - compute_pass_rid: ResourceId, - query_set: ResourceId, - query_index: u32, -} - -#[op] -pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query( - state: &mut OpState, - args: ComputePassBeginPipelineStatisticsQueryArgs, -) -> Result { - let compute_pass_resource = state - .resource_table - .get::(args.compute_pass_rid)?; - let query_set_resource = state - .resource_table - .get::(args.query_set)?; - - wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query( + wgpu_core::command::compute_ffi::wgpu_compute_pass_dispatch_workgroups_indirect( &mut compute_pass_resource.0.borrow_mut(), - query_set_resource.0, - args.query_index, + buffer_resource.0, + indirect_offset, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassEndPipelineStatisticsQueryArgs { +#[op] +pub fn op_webgpu_compute_pass_begin_pipeline_statistics_query( + state: &mut OpState, compute_pass_rid: ResourceId, + query_set: ResourceId, + query_index: u32, +) -> Result { + let compute_pass_resource = state + .resource_table + .get::(compute_pass_rid)?; + let query_set_resource = state + .resource_table + .get::(query_set)?; + + wgpu_core::command::compute_ffi::wgpu_compute_pass_begin_pipeline_statistics_query( + &mut compute_pass_resource.0.borrow_mut(), + query_set_resource.0, + query_index, + ); + + Ok(WebGpuResult::empty()) } #[op] pub fn op_webgpu_compute_pass_end_pipeline_statistics_query( state: &mut OpState, - args: ComputePassEndPipelineStatisticsQueryArgs, + compute_pass_rid: ResourceId, ) -> Result { let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; wgpu_core::command::compute_ffi::wgpu_compute_pass_end_pipeline_statistics_query( &mut compute_pass_resource.0.borrow_mut(), @@ -156,56 +126,44 @@ pub fn op_webgpu_compute_pass_end_pipeline_statistics_query( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassWriteTimestampArgs { - compute_pass_rid: ResourceId, - query_set: ResourceId, - query_index: u32, -} - #[op] pub fn op_webgpu_compute_pass_write_timestamp( state: &mut OpState, - args: ComputePassWriteTimestampArgs, + compute_pass_rid: ResourceId, + query_set: ResourceId, + query_index: u32, ) -> Result { let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; let query_set_resource = state .resource_table - .get::(args.query_set)?; + .get::(query_set)?; wgpu_core::command::compute_ffi::wgpu_compute_pass_write_timestamp( &mut compute_pass_resource.0.borrow_mut(), query_set_resource.0, - args.query_index, + query_index, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassEndPassArgs { +#[op] +pub fn op_webgpu_compute_pass_end( + state: &mut OpState, command_encoder_rid: ResourceId, compute_pass_rid: ResourceId, -} - -#[op] -pub fn op_webgpu_compute_pass_end_pass( - state: &mut OpState, - args: ComputePassEndPassArgs, ) -> Result { let command_encoder_resource = state .resource_table .get::( - args.command_encoder_rid, + command_encoder_rid, )?; let command_encoder = command_encoder_resource.0; let compute_pass_resource = state .resource_table - .take::(args.compute_pass_rid)?; + .take::(compute_pass_rid)?; let compute_pass = &compute_pass_resource.0.borrow(); let instance = state.borrow::(); @@ -215,41 +173,35 @@ pub fn op_webgpu_compute_pass_end_pass( )) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassSetBindGroupArgs { +#[op] +pub fn op_webgpu_compute_pass_set_bind_group( + state: &mut OpState, compute_pass_rid: ResourceId, index: u32, bind_group: ResourceId, dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data_start: usize, dynamic_offsets_data_length: usize, -} - -#[op] -pub fn op_webgpu_compute_pass_set_bind_group( - state: &mut OpState, - args: ComputePassSetBindGroupArgs, ) -> Result { let bind_group_resource = state .resource_table - .get::(args.bind_group)?; + .get::(bind_group)?; let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; // Align the data - assert!(args.dynamic_offsets_data_start % std::mem::size_of::() == 0); + assert!(dynamic_offsets_data_start % std::mem::size_of::() == 0); let (prefix, dynamic_offsets_data, suffix) = - // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a - // multiple of 4. - unsafe { args.dynamic_offsets_data.align_to::() }; + // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a + // multiple of 4. + unsafe { dynamic_offsets_data.align_to::() }; assert!(prefix.is_empty()); assert!(suffix.is_empty()); - let start = args.dynamic_offsets_data_start; - let len = args.dynamic_offsets_data_length; + let start = dynamic_offsets_data_start; + let len = dynamic_offsets_data_length; // Assert that length and start are both in bounds assert!(start <= dynamic_offsets_data.len()); @@ -262,7 +214,7 @@ pub fn op_webgpu_compute_pass_set_bind_group( unsafe { wgpu_core::command::compute_ffi::wgpu_compute_pass_set_bind_group( &mut compute_pass_resource.0.borrow_mut(), - args.index, + index, bind_group_resource.0, dynamic_offsets_data.as_ptr(), dynamic_offsets_data.len(), @@ -272,23 +224,17 @@ pub fn op_webgpu_compute_pass_set_bind_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassPushDebugGroupArgs { - compute_pass_rid: ResourceId, - group_label: String, -} - #[op] pub fn op_webgpu_compute_pass_push_debug_group( state: &mut OpState, - args: ComputePassPushDebugGroupArgs, + compute_pass_rid: ResourceId, + group_label: String, ) -> Result { let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; - let label = std::ffi::CString::new(args.group_label).unwrap(); + let label = std::ffi::CString::new(group_label).unwrap(); // SAFETY: the string the raw pointer points to lives longer than the below // function invocation. unsafe { @@ -302,20 +248,14 @@ pub fn op_webgpu_compute_pass_push_debug_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassPopDebugGroupArgs { - compute_pass_rid: ResourceId, -} - #[op] pub fn op_webgpu_compute_pass_pop_debug_group( state: &mut OpState, - args: ComputePassPopDebugGroupArgs, + compute_pass_rid: ResourceId, ) -> Result { let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; wgpu_core::command::compute_ffi::wgpu_compute_pass_pop_debug_group( &mut compute_pass_resource.0.borrow_mut(), @@ -324,23 +264,17 @@ pub fn op_webgpu_compute_pass_pop_debug_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePassInsertDebugMarkerArgs { - compute_pass_rid: ResourceId, - marker_label: String, -} - #[op] pub fn op_webgpu_compute_pass_insert_debug_marker( state: &mut OpState, - args: ComputePassInsertDebugMarkerArgs, + compute_pass_rid: ResourceId, + marker_label: String, ) -> Result { let compute_pass_resource = state .resource_table - .get::(args.compute_pass_rid)?; + .get::(compute_pass_rid)?; - let label = std::ffi::CString::new(args.marker_label).unwrap(); + let label = std::ffi::CString::new(marker_label).unwrap(); // SAFETY: the string the raw pointer points to lives longer than the below // function invocation. unsafe { diff --git a/ext/webgpu/src/error.rs b/ext/webgpu/src/error.rs index ae6e480546..fae0259a86 100644 --- a/ext/webgpu/src/error.rs +++ b/ext/webgpu/src/error.rs @@ -3,7 +3,9 @@ use deno_core::error::AnyError; use deno_core::ResourceId; use serde::Serialize; use std::convert::From; +use std::error::Error; use std::fmt; +use std::fmt::Write; use wgpu_core::binding_model::CreateBindGroupError; use wgpu_core::binding_model::CreateBindGroupLayoutError; use wgpu_core::binding_model::CreatePipelineLayoutError; @@ -29,6 +31,20 @@ use wgpu_core::resource::CreateSamplerError; use wgpu_core::resource::CreateTextureError; use wgpu_core::resource::CreateTextureViewError; +fn fmt_err(err: &(dyn Error + 'static)) -> String { + let mut output = err.to_string(); + + let mut e = err.source(); + while let Some(source) = e { + // No error possible, unwrap is fine here. + // https://github.com/rust-lang/rust/blob/1.47.0/library/alloc/src/string.rs#L2414-L2427 + write!(output, ": {source}").unwrap(); + e = source.source(); + } + + output +} + #[derive(Serialize)] pub struct WebGpuResult { pub rid: Option, @@ -49,14 +65,14 @@ impl WebGpuResult { ) -> Self { Self { rid: Some(rid), - err: err.map(|e| e.into()), + err: err.map(Into::into), } } pub fn maybe_err>(err: Option) -> Self { Self { rid: None, - err: err.map(|e| e.into()), + err: err.map(Into::into), } } @@ -82,7 +98,7 @@ impl From for WebGpuError { match err { CreateBufferError::Device(err) => err.into(), CreateBufferError::AccessError(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -92,7 +108,7 @@ impl From for WebGpuError { match err { DeviceError::Lost => WebGpuError::Lost, DeviceError::OutOfMemory => WebGpuError::OutOfMemory, - DeviceError::Invalid => WebGpuError::Validation(err.to_string()), + DeviceError::Invalid => WebGpuError::Validation(fmt_err(&err)), } } } @@ -101,7 +117,7 @@ impl From for WebGpuError { fn from(err: BufferAccessError) -> Self { match err { BufferAccessError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -110,7 +126,7 @@ impl From for WebGpuError { fn from(err: CreateBindGroupLayoutError) -> Self { match err { CreateBindGroupLayoutError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -119,7 +135,7 @@ impl From for WebGpuError { fn from(err: CreatePipelineLayoutError) -> Self { match err { CreatePipelineLayoutError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -128,44 +144,44 @@ impl From for WebGpuError { fn from(err: CreateBindGroupError) -> Self { match err { CreateBindGroupError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: RenderBundleError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CreateRenderBundleError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CopyError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: CommandEncoderError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: QueryError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } impl From for WebGpuError { fn from(err: ComputePassError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } @@ -173,14 +189,14 @@ impl From for WebGpuError { fn from(err: CreateComputePipelineError) -> Self { match err { CreateComputePipelineError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: GetBindGroupLayoutError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } @@ -188,14 +204,14 @@ impl From for WebGpuError { fn from(err: CreateRenderPipelineError) -> Self { match err { CreateRenderPipelineError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: RenderPassError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } @@ -203,7 +219,7 @@ impl From for WebGpuError { fn from(err: CreateSamplerError) -> Self { match err { CreateSamplerError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -212,7 +228,7 @@ impl From for WebGpuError { fn from(err: CreateShaderModuleError) -> Self { match err { CreateShaderModuleError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -221,14 +237,14 @@ impl From for WebGpuError { fn from(err: CreateTextureError) -> Self { match err { CreateTextureError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: CreateTextureViewError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } @@ -236,7 +252,7 @@ impl From for WebGpuError { fn from(err: CreateQuerySetError) -> Self { match err { CreateQuerySetError::Device(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -245,7 +261,7 @@ impl From for WebGpuError { fn from(err: QueueSubmitError) -> Self { match err { QueueSubmitError::Queue(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } @@ -254,14 +270,14 @@ impl From for WebGpuError { fn from(err: QueueWriteError) -> Self { match err { QueueWriteError::Queue(err) => err.into(), - err => WebGpuError::Validation(err.to_string()), + err => WebGpuError::Validation(fmt_err(&err)), } } } impl From for WebGpuError { fn from(err: ClearError) -> Self { - WebGpuError::Validation(err.to_string()) + WebGpuError::Validation(fmt_err(&err)) } } diff --git a/ext/webgpu/src/lib.rs b/ext/webgpu/src/lib.rs index 6904b68e43..1620532a6c 100644 --- a/ext/webgpu/src/lib.rs +++ b/ext/webgpu/src/lib.rs @@ -3,9 +3,7 @@ use deno_core::error::AnyError; use deno_core::include_js_files; use deno_core::op; - use deno_core::Extension; -use deno_core::OpDecl; use deno_core::OpState; use deno_core::Resource; use deno_core::ResourceId; @@ -14,10 +12,10 @@ use serde::Serialize; use std::borrow::Cow; use std::cell::RefCell; use std::collections::HashSet; +use std::convert::TryFrom; use std::rc::Rc; pub use wgpu_core; pub use wgpu_types; -use wgpu_types::PowerPreference; use error::DomExceptionOperationError; use error::WebGpuResult; @@ -130,6 +128,12 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { if features.contains(wgpu_types::Features::DEPTH_CLIP_CONTROL) { return_features.push("depth-clip-control"); } + if features.contains(wgpu_types::Features::DEPTH24UNORM_STENCIL8) { + return_features.push("depth24unorm-stencil8"); + } + if features.contains(wgpu_types::Features::DEPTH32FLOAT_STENCIL8) { + return_features.push("depth32float-stencil8"); + } if features.contains(wgpu_types::Features::PIPELINE_STATISTICS_QUERY) { return_features.push("pipeline-statistics-query"); } @@ -148,6 +152,9 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { if features.contains(wgpu_types::Features::INDIRECT_FIRST_INSTANCE) { return_features.push("indirect-first-instance"); } + if features.contains(wgpu_types::Features::SHADER_FLOAT16) { + return_features.push("shader-f16") + } // extended from spec if features.contains(wgpu_types::Features::MAPPABLE_PRIMARY_BUFFERS) { @@ -172,18 +179,6 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { ) { return_features.push("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"); } - if features.contains(wgpu_types::Features::UNSIZED_BINDING_ARRAY) { - return_features.push("unsized-binding-array"); - } - if features.contains(wgpu_types::Features::MULTI_DRAW_INDIRECT) { - return_features.push("multi-draw-indirect"); - } - if features.contains(wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT) { - return_features.push("multi-draw-indirect-count"); - } - if features.contains(wgpu_types::Features::PUSH_CONSTANTS) { - return_features.push("push-constants"); - } if features.contains(wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER) { return_features.push("address-mode-clamp-to-border"); } @@ -198,32 +193,22 @@ fn deserialize_features(features: &wgpu_types::Features) -> Vec<&'static str> { if features.contains(wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT) { return_features.push("vertex-attribute-64bit"); } - if features.contains(wgpu_types::Features::CONSERVATIVE_RASTERIZATION) { - return_features.push("conservative-rasterization"); - } if features.contains(wgpu_types::Features::VERTEX_WRITABLE_STORAGE) { return_features.push("vertex-writable-storage"); } - if features.contains(wgpu_types::Features::CLEAR_COMMANDS) { + if features.contains(wgpu_types::Features::CLEAR_TEXTURE) { return_features.push("clear-texture"); } - if features.contains(wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH) { - return_features.push("spirv-shader-passthrough"); - } if features.contains(wgpu_types::Features::SHADER_PRIMITIVE_INDEX) { return_features.push("shader-primitive-index"); } + if features.contains(wgpu_types::Features::PARTIALLY_BOUND_BINDING_ARRAY) { + return_features.push("shader-primitive-index"); + } return_features } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RequestAdapterArgs { - power_preference: Option, - force_fallback_adapter: bool, -} - #[derive(Serialize)] #[serde(untagged)] pub enum GpuAdapterDeviceOrErr { @@ -235,7 +220,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, @@ -244,15 +228,15 @@ pub struct GpuAdapterDevice { #[op] pub async fn op_webgpu_request_adapter( state: Rc>, - args: RequestAdapterArgs, + power_preference: Option, + force_fallback_adapter: bool, ) -> Result { let mut state = state.borrow_mut(); check_unstable(&state, "navigator.gpu.requestAdapter"); - let backends = std::env::var("DENO_WEBGPU_BACKEND") - .ok() - .map_or_else(wgpu_types::Backends::all, |s| { - wgpu_core::instance::parse_backends_from_comma_list(&s) - }); + 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), + ); let instance = if let Some(instance) = state.try_borrow::() { instance } else { @@ -265,11 +249,8 @@ pub async fn op_webgpu_request_adapter( }; let descriptor = wgpu_core::instance::RequestAdapterOptions { - power_preference: match args.power_preference { - Some(power_preference) => power_preference, - None => PowerPreference::default(), - }, - force_fallback_adapter: args.force_fallback_adapter, + power_preference: power_preference.unwrap_or_default(), + force_fallback_adapter, compatible_surface: None, // windowless }; let res = instance.request_adapter( @@ -287,7 +268,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); @@ -298,22 +278,12 @@ pub async fn op_webgpu_request_adapter( Ok(GpuAdapterDeviceOrErr::Features(GpuAdapterDevice { rid, - name: Some(name), features, limits: adapter_limits, is_software: false, })) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RequestDeviceArgs { - adapter_rid: ResourceId, - label: Option, - required_features: Option, - required_limits: Option, -} - #[derive(Deserialize)] pub struct GpuRequiredFeatures(HashSet); @@ -324,6 +294,14 @@ impl From for wgpu_types::Features { wgpu_types::Features::DEPTH_CLIP_CONTROL, required_features.0.contains("depth-clip-control"), ); + features.set( + wgpu_types::Features::DEPTH24UNORM_STENCIL8, + required_features.0.contains("depth24unorm-stencil8"), + ); + features.set( + wgpu_types::Features::DEPTH32FLOAT_STENCIL8, + required_features.0.contains("depth32float-stencil8"), + ); features.set( wgpu_types::Features::PIPELINE_STATISTICS_QUERY, required_features.0.contains("pipeline-statistics-query"), @@ -348,6 +326,10 @@ impl From for wgpu_types::Features { wgpu_types::Features::INDIRECT_FIRST_INSTANCE, required_features.0.contains("indirect-first-instance"), ); + features.set( + wgpu_types::Features::SHADER_FLOAT16, + required_features.0.contains("shader-f16"), + ); // extended from spec features.set( @@ -380,22 +362,6 @@ impl From for wgpu_types::Features { .0 .contains("uniform-buffer-and-storage-buffer-texture-non-uniform-indexing"), ); - features.set( - wgpu_types::Features::UNSIZED_BINDING_ARRAY, - required_features.0.contains("unsized-binding-array"), - ); - features.set( - wgpu_types::Features::MULTI_DRAW_INDIRECT, - required_features.0.contains("multi-draw-indirect"), - ); - features.set( - wgpu_types::Features::MULTI_DRAW_INDIRECT_COUNT, - required_features.0.contains("multi-draw-indirect-count"), - ); - features.set( - wgpu_types::Features::PUSH_CONSTANTS, - required_features.0.contains("push-constants"), - ); features.set( wgpu_types::Features::ADDRESS_MODE_CLAMP_TO_BORDER, required_features.0.contains("address-mode-clamp-to-border"), @@ -414,26 +380,24 @@ impl From for wgpu_types::Features { wgpu_types::Features::VERTEX_ATTRIBUTE_64BIT, required_features.0.contains("vertex-attribute-64bit"), ); - features.set( - wgpu_types::Features::CONSERVATIVE_RASTERIZATION, - required_features.0.contains("conservative-rasterization"), - ); features.set( wgpu_types::Features::VERTEX_WRITABLE_STORAGE, required_features.0.contains("vertex-writable-storage"), ); features.set( - wgpu_types::Features::CLEAR_COMMANDS, + wgpu_types::Features::CLEAR_TEXTURE, required_features.0.contains("clear-commands"), ); - features.set( - wgpu_types::Features::SPIRV_SHADER_PASSTHROUGH, - required_features.0.contains("spirv-shader-passthrough"), - ); features.set( wgpu_types::Features::SHADER_PRIMITIVE_INDEX, required_features.0.contains("shader-primitive-index"), ); + features.set( + wgpu_types::Features::PARTIALLY_BOUND_BINDING_ARRAY, + required_features + .0 + .contains("partially-bound-binding-array"), + ); features } @@ -442,19 +406,21 @@ impl From for wgpu_types::Features { #[op] pub async fn op_webgpu_request_device( state: Rc>, - args: RequestDeviceArgs, + adapter_rid: ResourceId, + label: Option, + required_features: Option, + required_limits: Option, ) -> Result { let mut state = state.borrow_mut(); - let adapter_resource = state - .resource_table - .get::(args.adapter_rid)?; + let adapter_resource = + state.resource_table.get::(adapter_rid)?; let adapter = adapter_resource.0; let instance = state.borrow::(); let descriptor = wgpu_types::DeviceDescriptor { - label: args.label.map(Cow::from), - features: args.required_features.map(Into::into).unwrap_or_default(), - limits: args.required_limits.map(Into::into).unwrap_or_default(), + label: label.map(Cow::from), + features: required_features.map(Into::into).unwrap_or_default(), + limits: required_limits.map(Into::into).unwrap_or_default(), }; let (device, maybe_err) = gfx_select!(adapter => instance.adapter_request_device( @@ -476,7 +442,6 @@ pub async fn op_webgpu_request_device( Ok(GpuAdapterDevice { rid, - name: None, features, limits, // TODO(lucacasonato): report correctly from wgpu @@ -484,6 +449,36 @@ 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 { @@ -562,11 +557,12 @@ pub fn op_webgpu_create_query_set( ) => state, WebGpuQuerySet) } -fn declare_webgpu_ops() -> Vec { +fn declare_webgpu_ops() -> Vec { 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 @@ -615,7 +611,7 @@ fn declare_webgpu_ops() -> Vec { render_pass::op_webgpu_render_pass_end_pipeline_statistics_query::decl(), render_pass::op_webgpu_render_pass_write_timestamp::decl(), render_pass::op_webgpu_render_pass_execute_bundles::decl(), - render_pass::op_webgpu_render_pass_end_pass::decl(), + render_pass::op_webgpu_render_pass_end::decl(), render_pass::op_webgpu_render_pass_set_bind_group::decl(), render_pass::op_webgpu_render_pass_push_debug_group::decl(), render_pass::op_webgpu_render_pass_pop_debug_group::decl(), @@ -629,13 +625,13 @@ fn declare_webgpu_ops() -> Vec { render_pass::op_webgpu_render_pass_draw_indexed_indirect::decl(), // compute_pass compute_pass::op_webgpu_compute_pass_set_pipeline::decl(), - compute_pass::op_webgpu_compute_pass_dispatch::decl(), - compute_pass::op_webgpu_compute_pass_dispatch_indirect::decl(), + compute_pass::op_webgpu_compute_pass_dispatch_workgroups::decl(), + compute_pass::op_webgpu_compute_pass_dispatch_workgroups_indirect::decl(), compute_pass::op_webgpu_compute_pass_begin_pipeline_statistics_query::decl( ), compute_pass::op_webgpu_compute_pass_end_pipeline_statistics_query::decl(), compute_pass::op_webgpu_compute_pass_write_timestamp::decl(), - compute_pass::op_webgpu_compute_pass_end_pass::decl(), + compute_pass::op_webgpu_compute_pass_end::decl(), compute_pass::op_webgpu_compute_pass_set_bind_group::decl(), compute_pass::op_webgpu_compute_pass_push_debug_group::decl(), compute_pass::op_webgpu_compute_pass_pop_debug_group::decl(), diff --git a/ext/webgpu/src/pipeline.rs b/ext/webgpu/src/pipeline.rs index 8dd0e7e0f6..1b69e118d1 100644 --- a/ext/webgpu/src/pipeline.rs +++ b/ext/webgpu/src/pipeline.rs @@ -2,12 +2,12 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; -use deno_core::{OpState, Resource}; use serde::Deserialize; use serde::Serialize; use std::borrow::Cow; -use std::convert::{TryFrom, TryInto}; use super::error::WebGpuError; use super::error::WebGpuResult; @@ -43,59 +43,69 @@ impl Resource for WebGpuRenderPipeline { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct GpuProgrammableStage { +pub enum GPUAutoLayoutMode { + Auto, +} + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum GPUPipelineLayoutOrGPUAutoLayoutMode { + Layout(ResourceId), + Auto(GPUAutoLayoutMode), +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GpuProgrammableStage { module: ResourceId, entry_point: String, // constants: HashMap } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateComputePipelineArgs { - device_rid: ResourceId, - label: Option, - layout: Option, - compute: GpuProgrammableStage, -} - #[op] pub fn op_webgpu_create_compute_pipeline( state: &mut OpState, - args: CreateComputePipelineArgs, + device_rid: ResourceId, + label: Option, + layout: GPUPipelineLayoutOrGPUAutoLayoutMode, + compute: GpuProgrammableStage, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; - let pipeline_layout = if let Some(rid) = args.layout { - let id = state.resource_table.get::(rid)?; - Some(id.0) - } else { - None + let pipeline_layout = match layout { + GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => { + let id = state.resource_table.get::(rid)?; + Some(id.0) + } + GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None, }; let compute_shader_module_resource = state .resource_table - .get::(args.compute.module)?; + .get::(compute.module)?; let descriptor = wgpu_core::pipeline::ComputePipelineDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), layout: pipeline_layout, stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: compute_shader_module_resource.0, - entry_point: Cow::from(args.compute.entry_point), + entry_point: Cow::from(compute.entry_point), // TODO(lucacasonato): support args.compute.constants }, }; - let implicit_pipelines = match args.layout { - Some(_) => None, - None => Some(wgpu_core::device::ImplicitPipelineIds { - root_id: std::marker::PhantomData, - group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS], - }), + let implicit_pipelines = match layout { + GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(_) => None, + GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => { + Some(wgpu_core::device::ImplicitPipelineIds { + root_id: std::marker::PhantomData, + group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS], + }) + } }; let (compute_pipeline, maybe_err) = gfx_select!(device => instance.device_create_compute_pipeline( @@ -112,13 +122,6 @@ pub fn op_webgpu_create_compute_pipeline( Ok(WebGpuResult::rid_err(rid, maybe_err)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ComputePipelineGetBindGroupLayoutArgs { - compute_pipeline_rid: ResourceId, - index: u32, -} - #[derive(Serialize)] #[serde(rename_all = "camelCase")] pub struct PipelineLayout { @@ -130,15 +133,16 @@ pub struct PipelineLayout { #[op] pub fn op_webgpu_compute_pipeline_get_bind_group_layout( state: &mut OpState, - args: ComputePipelineGetBindGroupLayoutArgs, + compute_pipeline_rid: ResourceId, + index: u32, ) -> Result { let instance = state.borrow::(); let compute_pipeline_resource = state .resource_table - .get::(args.compute_pipeline_rid)?; + .get::(compute_pipeline_rid)?; let compute_pipeline = compute_pipeline_resource.0; - let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, args.index, std::marker::PhantomData)); + let (bind_group_layout, maybe_err) = gfx_select!(compute_pipeline => instance.compute_pipeline_get_bind_group_layout(compute_pipeline, index, std::marker::PhantomData)); let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout)); @@ -210,12 +214,9 @@ struct GpuDepthStencilState { depth_bias_clamp: f32, } -impl TryFrom for wgpu_types::DepthStencilState { - type Error = AnyError; - fn try_from( - state: GpuDepthStencilState, - ) -> Result { - Ok(wgpu_types::DepthStencilState { +impl From for wgpu_types::DepthStencilState { + fn from(state: GpuDepthStencilState) -> wgpu_types::DepthStencilState { + wgpu_types::DepthStencilState { format: state.format, depth_write_enabled: state.depth_write_enabled, depth_compare: state.depth_compare, @@ -230,7 +231,7 @@ impl TryFrom for wgpu_types::DepthStencilState { slope_scale: state.depth_bias_slope_scale, clamp: state.depth_bias_clamp, }, - }) + } } } @@ -285,7 +286,7 @@ impl From for wgpu_types::MultisampleState { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct GpuFragmentState { - targets: Vec, + targets: Vec>, module: u32, entry_point: String, // TODO(lucacasonato): constants @@ -296,7 +297,7 @@ struct GpuFragmentState { pub struct CreateRenderPipelineArgs { device_rid: ResourceId, label: Option, - layout: Option, + layout: GPUPipelineLayoutOrGPUAutoLayoutMode, vertex: GpuVertexState, primitive: GpuPrimitiveState, depth_stencil: Option, @@ -315,12 +316,13 @@ pub fn op_webgpu_create_render_pipeline( .get::(args.device_rid)?; let device = device_resource.0; - let layout = if let Some(rid) = args.layout { - let pipeline_layout_resource = - state.resource_table.get::(rid)?; - Some(pipeline_layout_resource.0) - } else { - None + let layout = match args.layout { + GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => { + let pipeline_layout_resource = + state.resource_table.get::(rid)?; + Some(pipeline_layout_resource.0) + } + GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None, }; let vertex_shader_module_resource = @@ -334,18 +336,12 @@ pub fn op_webgpu_create_render_pipeline( .resource_table .get::(fragment.module)?; - let mut targets = Vec::with_capacity(fragment.targets.len()); - - for target in fragment.targets { - targets.push(target); - } - Some(wgpu_core::pipeline::FragmentState { stage: wgpu_core::pipeline::ProgrammableStageDescriptor { module: fragment_shader_module_resource.0, entry_point: Cow::from(fragment.entry_point), }, - targets: Cow::from(targets), + targets: Cow::from(fragment.targets), }) } else { None @@ -370,18 +366,20 @@ pub fn op_webgpu_create_render_pipeline( buffers: Cow::Owned(vertex_buffers), }, primitive: args.primitive.into(), - depth_stencil: args.depth_stencil.map(TryInto::try_into).transpose()?, + depth_stencil: args.depth_stencil.map(Into::into), multisample: args.multisample, fragment, multiview: None, }; let implicit_pipelines = match args.layout { - Some(_) => None, - None => Some(wgpu_core::device::ImplicitPipelineIds { - root_id: std::marker::PhantomData, - group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS], - }), + GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(_) => None, + GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => { + Some(wgpu_core::device::ImplicitPipelineIds { + root_id: std::marker::PhantomData, + group_ids: &[std::marker::PhantomData; MAX_BIND_GROUPS], + }) + } }; let (render_pipeline, maybe_err) = gfx_select!(device => instance.device_create_render_pipeline( @@ -398,25 +396,19 @@ pub fn op_webgpu_create_render_pipeline( Ok(WebGpuResult::rid_err(rid, maybe_err)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPipelineGetBindGroupLayoutArgs { - render_pipeline_rid: ResourceId, - index: u32, -} - #[op] pub fn op_webgpu_render_pipeline_get_bind_group_layout( state: &mut OpState, - args: RenderPipelineGetBindGroupLayoutArgs, + render_pipeline_rid: ResourceId, + index: u32, ) -> Result { let instance = state.borrow::(); let render_pipeline_resource = state .resource_table - .get::(args.render_pipeline_rid)?; + .get::(render_pipeline_rid)?; let render_pipeline = render_pipeline_resource.0; - let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, args.index, std::marker::PhantomData)); + let (bind_group_layout, maybe_err) = gfx_select!(render_pipeline => instance.render_pipeline_get_bind_group_layout(render_pipeline, index, std::marker::PhantomData)); let label = gfx_select!(bind_group_layout => instance.bind_group_layout_label(bind_group_layout)); diff --git a/ext/webgpu/src/queue.rs b/ext/webgpu/src/queue.rs index b4532cf0c6..5490369705 100644 --- a/ext/webgpu/src/queue.rs +++ b/ext/webgpu/src/queue.rs @@ -13,42 +13,40 @@ use super::error::WebGpuResult; type WebGpuQueue = super::WebGpuDevice; -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct QueueSubmitArgs { - queue_rid: ResourceId, - command_buffers: Vec, -} - #[op] pub fn op_webgpu_queue_submit( state: &mut OpState, - args: QueueSubmitArgs, + queue_rid: ResourceId, + command_buffers: Vec, ) -> Result { let instance = state.borrow::(); - let queue_resource = - state.resource_table.get::(args.queue_rid)?; + let queue_resource = state.resource_table.get::(queue_rid)?; let queue = queue_resource.0; - let mut ids = vec![]; - - for rid in args.command_buffers { - let buffer_resource = - state - .resource_table - .get::(rid)?; - ids.push(buffer_resource.0); - } + let ids = command_buffers + .iter() + .map(|rid| { + let buffer_resource = + state + .resource_table + .get::(*rid)?; + Ok(buffer_resource.0) + }) + .collect::, AnyError>>()?; let maybe_err = gfx_select!(queue => instance.queue_submit(queue, &ids)).err(); + for rid in command_buffers { + state.resource_table.close(rid)?; + } + Ok(WebGpuResult::maybe_err(maybe_err)) } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] -struct GpuImageDataLayout { +pub struct GpuImageDataLayout { offset: u64, bytes_per_row: Option, rows_per_image: Option, @@ -64,39 +62,32 @@ impl From for wgpu_types::ImageDataLayout { } } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct QueueWriteBufferArgs { +#[op] +pub fn op_webgpu_write_buffer( + state: &mut OpState, queue_rid: ResourceId, buffer: ResourceId, buffer_offset: u64, data_offset: usize, size: Option, -} - -#[op] -pub fn op_webgpu_write_buffer( - state: &mut OpState, - args: QueueWriteBufferArgs, - zero_copy: ZeroCopyBuf, + buf: ZeroCopyBuf, ) -> Result { let instance = state.borrow::(); let buffer_resource = state .resource_table - .get::(args.buffer)?; + .get::(buffer)?; let buffer = buffer_resource.0; - let queue_resource = - state.resource_table.get::(args.queue_rid)?; + let queue_resource = state.resource_table.get::(queue_rid)?; let queue = queue_resource.0; - let data = match args.size { - Some(size) => &zero_copy[args.data_offset..(args.data_offset + size)], - None => &zero_copy[args.data_offset..], + let data = match size { + Some(size) => &buf[data_offset..(data_offset + size)], + None => &buf[data_offset..], }; let maybe_err = gfx_select!(queue => instance.queue_write_buffer( queue, buffer, - args.buffer_offset, + buffer_offset, data )) .err(); @@ -104,42 +95,35 @@ pub fn op_webgpu_write_buffer( Ok(WebGpuResult::maybe_err(maybe_err)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct QueueWriteTextureArgs { +#[op] +pub fn op_webgpu_write_texture( + state: &mut OpState, queue_rid: ResourceId, destination: super::command_encoder::GpuImageCopyTexture, data_layout: GpuImageDataLayout, size: wgpu_types::Extent3d, -} - -#[op] -pub fn op_webgpu_write_texture( - state: &mut OpState, - args: QueueWriteTextureArgs, - zero_copy: ZeroCopyBuf, + buf: ZeroCopyBuf, ) -> Result { let instance = state.borrow::(); let texture_resource = state .resource_table - .get::(args.destination.texture)?; - let queue_resource = - state.resource_table.get::(args.queue_rid)?; + .get::(destination.texture)?; + let queue_resource = state.resource_table.get::(queue_rid)?; let queue = queue_resource.0; let destination = wgpu_core::command::ImageCopyTexture { texture: texture_resource.0, - mip_level: args.destination.mip_level, - origin: args.destination.origin, - aspect: args.destination.aspect, + mip_level: destination.mip_level, + origin: destination.origin, + aspect: destination.aspect, }; - let data_layout = args.data_layout.into(); + let data_layout = data_layout.into(); gfx_ok!(queue => instance.queue_write_texture( queue, &destination, - &*zero_copy, + &*buf, &data_layout, - &args.size + &size )) } diff --git a/ext/webgpu/src/render_pass.rs b/ext/webgpu/src/render_pass.rs index 5d2cd6e5a1..9fe5f71fc2 100644 --- a/ext/webgpu/src/render_pass.rs +++ b/ext/webgpu/src/render_pass.rs @@ -3,9 +3,10 @@ use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; use deno_core::ZeroCopyBuf; -use deno_core::{OpState, Resource}; use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; @@ -55,127 +56,97 @@ pub fn op_webgpu_render_pass_set_viewport( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetScissorRectArgs { +#[op] +pub fn op_webgpu_render_pass_set_scissor_rect( + state: &mut OpState, render_pass_rid: ResourceId, x: u32, y: u32, width: u32, height: u32, -} - -#[op] -pub fn op_webgpu_render_pass_set_scissor_rect( - state: &mut OpState, - args: RenderPassSetScissorRectArgs, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_set_scissor_rect( &mut render_pass_resource.0.borrow_mut(), - args.x, - args.y, - args.width, - args.height, + x, + y, + width, + height, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetBlendConstantArgs { - render_pass_rid: ResourceId, - color: wgpu_types::Color, -} - #[op] pub fn op_webgpu_render_pass_set_blend_constant( state: &mut OpState, - args: RenderPassSetBlendConstantArgs, + render_pass_rid: ResourceId, + color: wgpu_types::Color, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_set_blend_constant( &mut render_pass_resource.0.borrow_mut(), - &args.color, + &color, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetStencilReferenceArgs { - render_pass_rid: ResourceId, - reference: u32, -} - #[op] pub fn op_webgpu_render_pass_set_stencil_reference( state: &mut OpState, - args: RenderPassSetStencilReferenceArgs, + render_pass_rid: ResourceId, + reference: u32, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_set_stencil_reference( &mut render_pass_resource.0.borrow_mut(), - args.reference, + reference, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassBeginPipelineStatisticsQueryArgs { - render_pass_rid: ResourceId, - query_set: u32, - query_index: u32, -} - #[op] pub fn op_webgpu_render_pass_begin_pipeline_statistics_query( state: &mut OpState, - args: RenderPassBeginPipelineStatisticsQueryArgs, + render_pass_rid: ResourceId, + query_set: u32, + query_index: u32, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; let query_set_resource = state .resource_table - .get::(args.query_set)?; + .get::(query_set)?; wgpu_core::command::render_ffi::wgpu_render_pass_begin_pipeline_statistics_query( &mut render_pass_resource.0.borrow_mut(), query_set_resource.0, - args.query_index, + query_index, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassEndPipelineStatisticsQueryArgs { - render_pass_rid: ResourceId, -} - #[op] pub fn op_webgpu_render_pass_end_pipeline_statistics_query( state: &mut OpState, - args: RenderPassEndPipelineStatisticsQueryArgs, + render_pass_rid: ResourceId, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_end_pipeline_statistics_query( &mut render_pass_resource.0.borrow_mut(), @@ -184,136 +155,113 @@ pub fn op_webgpu_render_pass_end_pipeline_statistics_query( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassWriteTimestampArgs { - render_pass_rid: ResourceId, - query_set: u32, - query_index: u32, -} - #[op] pub fn op_webgpu_render_pass_write_timestamp( state: &mut OpState, - args: RenderPassWriteTimestampArgs, + render_pass_rid: ResourceId, + query_set: u32, + query_index: u32, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; let query_set_resource = state .resource_table - .get::(args.query_set)?; + .get::(query_set)?; wgpu_core::command::render_ffi::wgpu_render_pass_write_timestamp( &mut render_pass_resource.0.borrow_mut(), query_set_resource.0, - args.query_index, + query_index, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassExecuteBundlesArgs { - render_pass_rid: ResourceId, - bundles: Vec, -} - #[op] pub fn op_webgpu_render_pass_execute_bundles( state: &mut OpState, - args: RenderPassExecuteBundlesArgs, + render_pass_rid: ResourceId, + bundles: Vec, ) -> Result { - let mut render_bundle_ids = vec![]; - - for rid in &args.bundles { - let render_bundle_resource = - state - .resource_table - .get::(*rid)?; - render_bundle_ids.push(render_bundle_resource.0); - } + let bundles = bundles + .iter() + .map(|rid| { + let render_bundle_resource = + state + .resource_table + .get::(*rid)?; + Ok(render_bundle_resource.0) + }) + .collect::, AnyError>>()?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; // SAFETY: the raw pointer and length are of the same slice, and that slice // lives longer than the below function invocation. unsafe { wgpu_core::command::render_ffi::wgpu_render_pass_execute_bundles( &mut render_pass_resource.0.borrow_mut(), - render_bundle_ids.as_ptr(), - render_bundle_ids.len(), + bundles.as_ptr(), + bundles.len(), ); } Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassEndPassArgs { +#[op] +pub fn op_webgpu_render_pass_end( + state: &mut OpState, command_encoder_rid: ResourceId, render_pass_rid: ResourceId, -} - -#[op] -pub fn op_webgpu_render_pass_end_pass( - state: &mut OpState, - args: RenderPassEndPassArgs, ) -> Result { let command_encoder_resource = state .resource_table .get::( - args.command_encoder_rid, + command_encoder_rid, )?; let command_encoder = command_encoder_resource.0; let render_pass_resource = state .resource_table - .take::(args.render_pass_rid)?; + .take::(render_pass_rid)?; let render_pass = &render_pass_resource.0.borrow(); let instance = state.borrow::(); gfx_ok!(command_encoder => instance.command_encoder_run_render_pass(command_encoder, render_pass)) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetBindGroupArgs { +#[op] +pub fn op_webgpu_render_pass_set_bind_group( + state: &mut OpState, render_pass_rid: ResourceId, index: u32, bind_group: u32, dynamic_offsets_data: ZeroCopyBuf, dynamic_offsets_data_start: usize, dynamic_offsets_data_length: usize, -} - -#[op] -pub fn op_webgpu_render_pass_set_bind_group( - state: &mut OpState, - args: RenderPassSetBindGroupArgs, ) -> Result { let bind_group_resource = state .resource_table - .get::(args.bind_group)?; + .get::(bind_group)?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; // Align the data - assert!(args.dynamic_offsets_data_start % std::mem::size_of::() == 0); + assert_eq!(dynamic_offsets_data_start % std::mem::size_of::(), 0); let (prefix, dynamic_offsets_data, suffix) = - // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a - // multiple of 4. - unsafe { args.dynamic_offsets_data.align_to::() }; + // SAFETY: A u8 to u32 cast is safe because we asserted that the length is a + // multiple of 4. + unsafe { dynamic_offsets_data.align_to::() }; assert!(prefix.is_empty()); assert!(suffix.is_empty()); - let start = args.dynamic_offsets_data_start; - let len = args.dynamic_offsets_data_length; + let start = dynamic_offsets_data_start; + let len = dynamic_offsets_data_length; // Assert that length and start are both in bounds assert!(start <= dynamic_offsets_data.len()); @@ -326,7 +274,7 @@ pub fn op_webgpu_render_pass_set_bind_group( unsafe { wgpu_core::command::render_ffi::wgpu_render_pass_set_bind_group( &mut render_pass_resource.0.borrow_mut(), - args.index, + index, bind_group_resource.0, dynamic_offsets_data.as_ptr(), dynamic_offsets_data.len(), @@ -336,23 +284,17 @@ pub fn op_webgpu_render_pass_set_bind_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassPushDebugGroupArgs { - render_pass_rid: ResourceId, - group_label: String, -} - #[op] pub fn op_webgpu_render_pass_push_debug_group( state: &mut OpState, - args: RenderPassPushDebugGroupArgs, + render_pass_rid: ResourceId, + group_label: String, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; - let label = std::ffi::CString::new(args.group_label).unwrap(); + let label = std::ffi::CString::new(group_label).unwrap(); // SAFETY: the string the raw pointer points to lives longer than the below // function invocation. unsafe { @@ -366,20 +308,14 @@ pub fn op_webgpu_render_pass_push_debug_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassPopDebugGroupArgs { - render_pass_rid: ResourceId, -} - #[op] pub fn op_webgpu_render_pass_pop_debug_group( state: &mut OpState, - args: RenderPassPopDebugGroupArgs, + render_pass_rid: ResourceId, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_pop_debug_group( &mut render_pass_resource.0.borrow_mut(), @@ -388,23 +324,17 @@ pub fn op_webgpu_render_pass_pop_debug_group( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassInsertDebugMarkerArgs { - render_pass_rid: ResourceId, - marker_label: String, -} - #[op] pub fn op_webgpu_render_pass_insert_debug_marker( state: &mut OpState, - args: RenderPassInsertDebugMarkerArgs, + render_pass_rid: ResourceId, + marker_label: String, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; - let label = std::ffi::CString::new(args.marker_label).unwrap(); + let label = std::ffi::CString::new(marker_label).unwrap(); // SAFETY: the string the raw pointer points to lives longer than the below // function invocation. unsafe { @@ -418,25 +348,19 @@ pub fn op_webgpu_render_pass_insert_debug_marker( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetPipelineArgs { - render_pass_rid: ResourceId, - pipeline: u32, -} - #[op] pub fn op_webgpu_render_pass_set_pipeline( state: &mut OpState, - args: RenderPassSetPipelineArgs, + render_pass_rid: ResourceId, + pipeline: u32, ) -> Result { let render_pipeline_resource = state .resource_table - .get::(args.pipeline)?; + .get::(pipeline)?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_set_pipeline( &mut render_pass_resource.0.borrow_mut(), @@ -446,29 +370,23 @@ pub fn op_webgpu_render_pass_set_pipeline( Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetIndexBufferArgs { +#[op] +pub fn op_webgpu_render_pass_set_index_buffer( + state: &mut OpState, render_pass_rid: ResourceId, buffer: u32, index_format: wgpu_types::IndexFormat, offset: u64, size: Option, -} - -#[op] -pub fn op_webgpu_render_pass_set_index_buffer( - state: &mut OpState, - args: RenderPassSetIndexBufferArgs, ) -> Result { let buffer_resource = state .resource_table - .get::(args.buffer)?; + .get::(buffer)?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; - let size = if let Some(size) = args.size { + let size = if let Some(size) = size { Some( std::num::NonZeroU64::new(size) .ok_or_else(|| type_error("size must be larger than 0"))?, @@ -479,37 +397,31 @@ pub fn op_webgpu_render_pass_set_index_buffer( render_pass_resource.0.borrow_mut().set_index_buffer( buffer_resource.0, - args.index_format, - args.offset, + index_format, + offset, size, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassSetVertexBufferArgs { +#[op] +pub fn op_webgpu_render_pass_set_vertex_buffer( + state: &mut OpState, render_pass_rid: ResourceId, slot: u32, buffer: u32, offset: u64, size: Option, -} - -#[op] -pub fn op_webgpu_render_pass_set_vertex_buffer( - state: &mut OpState, - args: RenderPassSetVertexBufferArgs, ) -> Result { let buffer_resource = state .resource_table - .get::(args.buffer)?; + .get::(buffer)?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; - let size = if let Some(size) = args.size { + let size = if let Some(size) = size { Some( std::num::NonZeroU64::new(size) .ok_or_else(|| type_error("size must be larger than 0"))?, @@ -520,130 +432,106 @@ pub fn op_webgpu_render_pass_set_vertex_buffer( wgpu_core::command::render_ffi::wgpu_render_pass_set_vertex_buffer( &mut render_pass_resource.0.borrow_mut(), - args.slot, + slot, buffer_resource.0, - args.offset, + offset, size, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassDrawArgs { +#[op] +pub fn op_webgpu_render_pass_draw( + state: &mut OpState, render_pass_rid: ResourceId, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32, -} - -#[op] -pub fn op_webgpu_render_pass_draw( - state: &mut OpState, - args: RenderPassDrawArgs, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_draw( &mut render_pass_resource.0.borrow_mut(), - args.vertex_count, - args.instance_count, - args.first_vertex, - args.first_instance, + vertex_count, + instance_count, + first_vertex, + first_instance, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassDrawIndexedArgs { +#[op] +pub fn op_webgpu_render_pass_draw_indexed( + state: &mut OpState, render_pass_rid: ResourceId, index_count: u32, instance_count: u32, first_index: u32, base_vertex: i32, first_instance: u32, -} - -#[op] -pub fn op_webgpu_render_pass_draw_indexed( - state: &mut OpState, - args: RenderPassDrawIndexedArgs, ) -> Result { let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed( &mut render_pass_resource.0.borrow_mut(), - args.index_count, - args.instance_count, - args.first_index, - args.base_vertex, - args.first_instance, + index_count, + instance_count, + first_index, + base_vertex, + first_instance, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassDrawIndirectArgs { - render_pass_rid: ResourceId, - indirect_buffer: u32, - indirect_offset: u64, -} - #[op] pub fn op_webgpu_render_pass_draw_indirect( state: &mut OpState, - args: RenderPassDrawIndirectArgs, + render_pass_rid: ResourceId, + indirect_buffer: u32, + indirect_offset: u64, ) -> Result { let buffer_resource = state .resource_table - .get::(args.indirect_buffer)?; + .get::(indirect_buffer)?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_draw_indirect( &mut render_pass_resource.0.borrow_mut(), buffer_resource.0, - args.indirect_offset, + indirect_offset, ); Ok(WebGpuResult::empty()) } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RenderPassDrawIndexedIndirectArgs { - render_pass_rid: ResourceId, - indirect_buffer: u32, - indirect_offset: u64, -} - #[op] pub fn op_webgpu_render_pass_draw_indexed_indirect( state: &mut OpState, - args: RenderPassDrawIndexedIndirectArgs, + render_pass_rid: ResourceId, + indirect_buffer: u32, + indirect_offset: u64, ) -> Result { let buffer_resource = state .resource_table - .get::(args.indirect_buffer)?; + .get::(indirect_buffer)?; let render_pass_resource = state .resource_table - .get::(args.render_pass_rid)?; + .get::(render_pass_rid)?; wgpu_core::command::render_ffi::wgpu_render_pass_draw_indexed_indirect( &mut render_pass_resource.0.borrow_mut(), buffer_resource.0, - args.indirect_offset, + indirect_offset, ); Ok(WebGpuResult::empty()) diff --git a/ext/webgpu/src/sampler.rs b/ext/webgpu/src/sampler.rs index c6827f4cb6..bad700535b 100644 --- a/ext/webgpu/src/sampler.rs +++ b/ext/webgpu/src/sampler.rs @@ -2,8 +2,9 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; -use deno_core::{OpState, Resource}; use serde::Deserialize; use std::borrow::Cow; @@ -26,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/ext/webgpu/src/shader.rs b/ext/webgpu/src/shader.rs index a5e4e5d431..5053a73d00 100644 --- a/ext/webgpu/src/shader.rs +++ b/ext/webgpu/src/shader.rs @@ -2,9 +2,9 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; -use deno_core::{OpState, Resource}; -use serde::Deserialize; use std::borrow::Cow; use super::error::WebGpuResult; @@ -16,31 +16,24 @@ impl Resource for WebGpuShaderModule { } } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateShaderModuleArgs { +#[op] +pub fn op_webgpu_create_shader_module( + state: &mut OpState, device_rid: ResourceId, label: Option, code: String, _source_map: Option<()>, // not yet implemented -} - -#[op] -pub fn op_webgpu_create_shader_module( - state: &mut OpState, - args: CreateShaderModuleArgs, ) -> Result { let instance = state.borrow::(); let device_resource = state .resource_table - .get::(args.device_rid)?; + .get::(device_rid)?; let device = device_resource.0; - let source = - wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::from(args.code)); + let source = wgpu_core::pipeline::ShaderModuleSource::Wgsl(Cow::from(code)); let descriptor = wgpu_core::pipeline::ShaderModuleDescriptor { - label: args.label.map(Cow::from), + label: label.map(Cow::from), shader_bound_checks: wgpu_types::ShaderBoundChecks::default(), }; diff --git a/ext/webgpu/src/texture.rs b/ext/webgpu/src/texture.rs index 0d11544090..f75a145c51 100644 --- a/ext/webgpu/src/texture.rs +++ b/ext/webgpu/src/texture.rs @@ -2,8 +2,9 @@ use deno_core::error::AnyError; use deno_core::op; +use deno_core::OpState; +use deno_core::Resource; use deno_core::ResourceId; -use deno_core::{OpState, Resource}; use serde::Deserialize; use std::borrow::Cow; diff --git a/ext/webgpu/webgpu.idl b/ext/webgpu/webgpu.idl index 79d65791d4..cda505715f 100644 --- a/ext/webgpu/webgpu.idl +++ b/ext/webgpu/webgpu.idl @@ -1,5 +1,5 @@ interface mixin GPUObjectBase { - attribute USVString? 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 { @@ -85,12 +93,12 @@ enum GPUFeatureName { "depth-clip-control", "depth24unorm-stencil8", "depth32float-stencil8", - "pipeline-statistics-query", "texture-compression-bc", "texture-compression-etc2", "texture-compression-astc", "timestamp-query", "indirect-first-instance", + "shader-f16", }; [Exposed=(Window, DedicatedWorker), SecureContext] @@ -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; @@ -272,13 +280,19 @@ enum GPUTextureFormat { "rgba32sint", "rgba32float", - // Depth and stencil formats + // Depth/stencil formats "stencil8", "depth16unorm", "depth24plus", "depth24plus-stencil8", "depth32float", + // "depth24unorm-stencil8" feature + "depth24unorm-stencil8", + + // "depth32float-stencil8" feature + "depth32float-stencil8", + // BC compressed formats usable if "texture-compression-bc" is both // supported by the device/user agent and enabled in requestDevice. "bc1-rgba-unorm", @@ -339,12 +353,6 @@ enum GPUTextureFormat { "astc-12x10-unorm-srgb", "astc-12x12-unorm", "astc-12x12-unorm-srgb", - - // "depth24unorm-stencil8" feature - "depth24unorm-stencil8", - - // "depth32float-stencil8" feature - "depth32float-stencil8", }; [Exposed=(Window, DedicatedWorker), SecureContext] @@ -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", @@ -524,12 +537,16 @@ interface GPUCompilationInfo { readonly attribute FrozenArray messages; }; +enum GPUAutoLayoutMode { + "auto" +}; + dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase { - GPUPipelineLayout layout; + required (GPUPipelineLayout or GPUAutoLayoutMode) layout; }; interface mixin GPUPipelineBase { - GPUBindGroupLayout getBindGroupLayout(unsigned long index); + [NewObject] GPUBindGroupLayout getBindGroupLayout(unsigned long index); }; dictionary GPUProgrammableStage { @@ -564,14 +581,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 +591,14 @@ dictionary GPUPrimitiveState { boolean unclippedDepth = false; }; +enum GPUPrimitiveTopology { + "point-list", + "line-list", + "line-strip", + "triangle-list", + "triangle-strip", +}; + enum GPUFrontFace { "ccw", "cw", @@ -600,7 +617,7 @@ dictionary GPUMultisampleState { }; dictionary GPUFragmentState : GPUProgrammableStage { - required sequence targets; + required sequence targets; }; dictionary GPUColorTargetState { @@ -617,7 +634,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; @@ -758,6 +775,9 @@ GPUCommandBuffer includes GPUObjectBase; dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase { }; +interface mixin GPUCommandsMixin { +}; + [Exposed=(Window, DedicatedWorker), SecureContext] interface GPUCommandEncoder { GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); @@ -786,13 +806,9 @@ interface GPUCommandEncoder { GPUExtent3D copySize); undefined clearBuffer( - GPUBuffer destination, - GPUSize64 destinationOffset, - GPUSize64 size); - - undefined pushDebugGroup(USVString groupLabel); - undefined popDebugGroup(); - undefined insertDebugMarker(USVString markerLabel); + GPUBuffer buffer, + optional GPUSize64 offset = 0, + optional GPUSize64 size); undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); @@ -806,6 +822,8 @@ interface GPUCommandEncoder { GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {}); }; GPUCommandEncoder includes GPUObjectBase; +GPUCommandEncoder includes GPUCommandsMixin; +GPUCommandEncoder includes GPUDebugCommandsMixin; dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase { }; @@ -827,7 +845,7 @@ dictionary GPUImageCopyTexture { GPUTextureAspect aspect = "all"; }; -interface mixin GPUProgrammablePassEncoder { +interface mixin GPUBindingCommandsMixin { undefined setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup, optional sequence dynamicOffsets = []); @@ -835,7 +853,9 @@ interface mixin GPUProgrammablePassEncoder { Uint32Array dynamicOffsetsData, GPUSize64 dynamicOffsetsDataStart, GPUSize32 dynamicOffsetsDataLength); +}; +interface mixin GPUDebugCommandsMixin { undefined pushDebugGroup(USVString groupLabel); undefined popDebugGroup(); undefined insertDebugMarker(USVString markerLabel); @@ -844,39 +864,24 @@ interface mixin GPUProgrammablePassEncoder { [Exposed=(Window, DedicatedWorker), SecureContext] interface GPUComputePassEncoder { undefined setPipeline(GPUComputePipeline pipeline); - undefined dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1); - undefined dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); + undefined dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1); + undefined dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset); undefined beginPipelineStatisticsQuery(GPUQuerySet querySet, GPUSize32 queryIndex); undefined endPipelineStatisticsQuery(); undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); - undefined endPass(); + undefined end(); }; GPUComputePassEncoder includes GPUObjectBase; -GPUComputePassEncoder includes GPUProgrammablePassEncoder; +GPUComputePassEncoder includes GPUCommandsMixin; +GPUComputePassEncoder includes GPUDebugCommandsMixin; +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, @@ -898,14 +903,16 @@ interface GPURenderPassEncoder { undefined writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); undefined executeBundles(sequence bundles); - undefined endPass(); + undefined end(); }; GPURenderPassEncoder includes GPUObjectBase; -GPURenderPassEncoder includes GPUProgrammablePassEncoder; -GPURenderPassEncoder includes GPURenderEncoderBase; +GPURenderPassEncoder includes GPUCommandsMixin; +GPURenderPassEncoder includes GPUDebugCommandsMixin; +GPURenderPassEncoder includes GPUBindingCommandsMixin; +GPURenderPassEncoder includes GPURenderCommandsMixin; dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase { - required sequence colorAttachments; + required sequence colorAttachments; GPURenderPassDepthStencilAttachment depthStencilAttachment; GPUQuerySet occlusionQuerySet; }; @@ -914,24 +921,28 @@ dictionary GPURenderPassColorAttachment { required GPUTextureView view; GPUTextureView resolveTarget; - required (GPULoadOp or GPUColor) loadValue; + GPUColor clearValue; + required GPULoadOp loadOp; required GPUStoreOp storeOp; }; dictionary GPURenderPassDepthStencilAttachment { required GPUTextureView view; - required (GPULoadOp or float) depthLoadValue; - required GPUStoreOp depthStoreOp; + float depthClearValue = 0; + GPULoadOp depthLoadOp; + GPUStoreOp depthStoreOp; boolean depthReadOnly = false; - required (GPULoadOp or GPUStencilValue) stencilLoadValue; - required GPUStoreOp stencilStoreOp; + GPUStencilValue stencilClearValue = 0; + GPULoadOp stencilLoadOp; + GPUStoreOp stencilStoreOp; boolean stencilReadOnly = false; }; enum GPULoadOp { "load", + "clear", }; enum GPUStoreOp { @@ -940,11 +951,28 @@ enum GPUStoreOp { }; dictionary GPURenderPassLayout: GPUObjectDescriptorBase { - required sequence colorFormats; + required sequence colorFormats; GPUTextureFormat depthStencilFormat; 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 { }; @@ -958,8 +986,10 @@ interface GPURenderBundleEncoder { GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {}); }; GPURenderBundleEncoder includes GPUObjectBase; -GPURenderBundleEncoder includes GPUProgrammablePassEncoder; -GPURenderBundleEncoder includes GPURenderEncoderBase; +GPURenderBundleEncoder includes GPUCommandsMixin; +GPURenderBundleEncoder includes GPUDebugCommandsMixin; +GPURenderBundleEncoder includes GPUBindingCommandsMixin; +GPURenderBundleEncoder includes GPURenderCommandsMixin; dictionary GPURenderBundleEncoderDescriptor : GPURenderPassLayout { boolean depthReadOnly = false; @@ -1033,17 +1063,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); @@ -1056,7 +1088,7 @@ interface GPUUncapturedErrorEvent : Event { DOMString type, GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict ); - [SameObject] readonly attribute GPUError error; + readonly attribute GPUError error; }; dictionary GPUUncapturedErrorEventInit : EventInit { @@ -1108,4 +1140,3 @@ dictionary GPUExtent3DDict { GPUIntegerCoordinate depthOrArrayLayers = 1; }; typedef (sequence or GPUExtent3DDict) GPUExtent3D; - diff --git a/tools/wgpu_sync.js b/tools/wgpu_sync.js index 3c62177092..eda5c5e188 100755 --- a/tools/wgpu_sync.js +++ b/tools/wgpu_sync.js @@ -3,10 +3,9 @@ import { join, ROOT_PATH, walk } from "./util.js"; -// const COMMIT = "c00e471274b6c21acda89b4b13d41742c0285d71"; // Release 12 -const COMMIT = "c4aa3eaed020a640fec06b48f0a5ea93490d41bb"; // tip of PR (needs merge) -const REPO = "kvark/wgpu"; -const V_WGPU = "0.12"; +const COMMIT = "076df1a56812eee01614b7a3a4c88798012e79ab"; +const REPO = "gfx-rs/wgpu"; +const V_WGPU = "0.13"; const TARGET_DIR = join(ROOT_PATH, "ext", "webgpu"); async function bash(subcmd, opts = {}) {