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 @@
 /// <reference no-default-lib="true" />
 /// <reference lib="esnext" />
 
-// 8cc98b6f10b7f354473a08c3773bb1de839845b9
-
 interface GPUObjectBase {
-  label: string | null;
+  label: string;
 }
 
 declare interface GPUObjectDescriptorBase {
@@ -64,6 +62,13 @@ declare class GPUSupportedFeatures {
   values(): IterableIterator<GPUFeatureName>;
 }
 
+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<GPUDevice>;
+  requestAdapterInfo(unmaskHints?: string[]): Promise<GPUAdapterInfo>;
 }
 
 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<GPUDeviceLostInfo>;
   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<GPUCompilationInfo>;
 }
@@ -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<u32>;
-}; // this is used as both input and output for convenience
-
-[[group(0), binding(0)]]
-var<storage, read_write> v_indices: PrimeIndices;
+@group(0)
+@binding(0)
+var<storage, read_write> v_indices: array<u32>; // 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<u32>) {
-    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<u32>) {
+    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<f32> {
+@vertex
+fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
     let x = f32(i32(in_vertex_index) - 1);
     let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
     return vec4<f32>(x, y, 0.0, 1.0);
 }
-[[stage(fragment)]]
-fn fs_main() -> [[location(0)]] vec4<f32> {
+
+@fragment
+fn fs_main() -> @location(0) vec4<f32> {
     return vec4<f32>(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<GPUAdapterInfo>}
+     */
+    async requestAdapterInfo(unmaskHints = []) {
+      webidl.assertBranded(this, GPUAdapterPrototype);
+      const prefix = "Failed to execute 'requestAdapterInfo' on 'GPUAdapter'";
+      unmaskHints = webidl.converters["sequence<DOMString>"](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<GpuStorageTextureAccess> 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<GpuBindingType> for wgpu_types::BindingType {
-  type Error = AnyError;
-
-  fn try_from(
-    binding_type: GpuBindingType,
-  ) -> Result<wgpu_types::BindingType, Self::Error> {
-    let binding_type = match binding_type {
+impl From<GpuBindingType> 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<GpuBindingType> 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<String>,
-  entries: Vec<GpuBindGroupLayoutEntry>,
-}
-
 #[op]
 pub fn op_webgpu_create_bind_group_layout(
   state: &mut OpState,
-  args: CreateBindGroupLayoutArgs,
+  device_rid: ResourceId,
+  label: Option<String>,
+  entries: Vec<GpuBindGroupLayoutEntry>,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(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::<Vec<_>>();
 
   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<String>,
-  bind_group_layouts: Vec<u32>,
-}
-
 #[op]
 pub fn op_webgpu_create_pipeline_layout(
   state: &mut OpState,
-  args: CreatePipelineLayoutArgs,
+  device_rid: ResourceId,
+  label: Option<String>,
+  bind_group_layouts: Vec<u32>,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(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::<WebGpuBindGroupLayout>(*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::<WebGpuBindGroupLayout>(rid)?;
+      Ok(bind_group_layout.0)
+    })
+    .collect::<Result<Vec<_>, 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<u64>,
 }
 
-#[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<String>,
   layout: ResourceId,
   entries: Vec<GpuBindGroupEntry>,
-}
-
-#[op]
-pub fn op_webgpu_create_bind_group(
-  state: &mut OpState,
-  args: CreateBindGroupArgs,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(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::<super::sampler::WebGpuSampler>(entry.resource)?;
+            wgpu_core::binding_model::BindingResource::Sampler(
+              sampler_resource.0,
+            )
+          }
+          "GPUTextureView" => {
+            let texture_view_resource =
+              state
+                .resource_table
+                .get::<super::texture::WebGpuTextureView>(entry.resource)?;
+            wgpu_core::binding_model::BindingResource::TextureView(
+              texture_view_resource.0,
+            )
+          }
+          "GPUBufferBinding" => {
+            let buffer_resource =
+              state
+                .resource_table
+                .get::<super::buffer::WebGpuBuffer>(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::<Result<Vec<_>, 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::<super::sampler::WebGpuSampler>(entry.resource)?;
-          wgpu_core::binding_model::BindingResource::Sampler(sampler_resource.0)
-        }
-        "GPUTextureView" => {
-          let texture_view_resource =
-            state
-              .resource_table
-              .get::<super::texture::WebGpuTextureView>(entry.resource)?;
-          wgpu_core::binding_model::BindingResource::TextureView(
-            texture_view_resource.0,
-          )
-        }
-        "GPUBufferBinding" => {
-          let buffer_resource =
-            state
-              .resource_table
-              .get::<super::buffer::WebGpuBuffer>(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::<WebGpuBindGroupLayout>(args.layout)?;
+  let bind_group_layout =
+    state.resource_table.get::<WebGpuBindGroupLayout>(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<String>,
   size: u64,
   usage: u32,
   mapped_at_creation: bool,
-}
-
-#[op]
-pub fn op_webgpu_create_buffer(
-  state: &mut OpState,
-  args: CreateBufferArgs,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(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<RefCell<OpState>>,
   buffer_rid: ResourceId,
   device_rid: ResourceId,
   mode: u32,
   offset: u64,
   size: u64,
-}
-
-#[op]
-pub async fn op_webgpu_buffer_get_map_async(
-  state: Rc<RefCell<OpState>>,
-  args: BufferGetMapAsyncArgs,
 ) -> Result<WebGpuResult, AnyError> {
   let (sender, receiver) = oneshot::channel::<Result<(), AnyError>>();
 
@@ -90,47 +77,36 @@ pub async fn op_webgpu_buffer_get_map_async(
     let state_ = state.borrow();
     let instance = state_.borrow::<super::Instance>();
     let buffer_resource =
-      state_.resource_table.get::<WebGpuBuffer>(args.buffer_rid)?;
+      state_.resource_table.get::<WebGpuBuffer>(buffer_rid)?;
     let buffer = buffer_resource.0;
     let device_resource = state_
       .resource_table
-      .get::<super::WebGpuDevice>(args.device_rid)?;
+      .get::<super::WebGpuDevice>(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<Result<(), AnyError>>;
-      // 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::<super::Instance>();
-        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<u64>,
-}
-
 #[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<u64>,
+  mut buf: ZeroCopyBuf,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
-  let buffer_resource =
-    state.resource_table.get::<WebGpuBuffer>(args.buffer_rid)?;
+  let buffer_resource = state.resource_table.get::<WebGpuBuffer>(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<ZeroCopyBuf>,
+  buffer_rid: ResourceId,
+  mapped_rid: ResourceId,
+  buf: Option<ZeroCopyBuf>,
 ) -> Result<WebGpuResult, AnyError> {
   let mapped_resource = state
     .resource_table
-    .take::<WebGpuBufferMapped>(args.mapped_rid)?;
+    .take::<WebGpuBufferMapped>(mapped_rid)?;
   let instance = state.borrow::<super::Instance>();
-  let buffer_resource =
-    state.resource_table.get::<WebGpuBuffer>(args.buffer_rid)?;
+  let buffer_resource = state.resource_table.get::<WebGpuBuffer>(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<String>,
-  color_formats: Vec<wgpu_types::TextureFormat>,
+  color_formats: Vec<Option<wgpu_types::TextureFormat>>,
   depth_stencil_format: Option<wgpu_types::TextureFormat>,
   sample_count: u32,
   depth_read_only: bool,
@@ -50,25 +51,17 @@ pub fn op_webgpu_create_render_bundle_encoder(
     .get::<super::WebGpuDevice>(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<String>,
-}
-
 #[op]
 pub fn op_webgpu_render_bundle_encoder_finish(
   state: &mut OpState,
-  args: RenderBundleEncoderFinishArgs,
+  render_bundle_encoder_rid: ResourceId,
+  label: Option<String>,
 ) -> Result<WebGpuResult, AnyError> {
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .take::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .take::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let bind_group_resource =
     state
       .resource_table
-      .get::<super::binding::WebGpuBindGroup>(args.bind_group)?;
+      .get::<super::binding::WebGpuBindGroup>(bind_group)?;
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(render_bundle_encoder_rid)?;
 
   // Align the data
-  assert!(args.dynamic_offsets_data.len() % std::mem::size_of::<u32>() == 0);
+  assert!(dynamic_offsets_data.len() % std::mem::size_of::<u32>() == 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::<u32>() };
+  // 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::<u32>() };
   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<WebGpuResult, AnyError> {
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let render_pipeline_resource =
     state
       .resource_table
-      .get::<super::pipeline::WebGpuRenderPipeline>(args.pipeline)?;
+      .get::<super::pipeline::WebGpuRenderPipeline>(pipeline)?;
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(buffer)?;
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(buffer)?;
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
   let render_bundle_encoder_resource =
     state
       .resource_table
-      .get::<WebGpuRenderBundleEncoder>(args.render_bundle_encoder_rid)?;
+      .get::<WebGpuRenderBundleEncoder>(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<String>,
-  _measure_execution_time: Option<bool>, // not yet implemented
-}
-
 #[op]
 pub fn op_webgpu_create_command_encoder(
   state: &mut OpState,
-  args: CreateCommandEncoderArgs,
+  device_rid: ResourceId,
+  label: Option<String>,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(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<ResourceId>,
-  load_op: GpuLoadOp<wgpu_types::Color>,
+  clear_value: Option<wgpu_types::Color>,
+  load_op: wgpu_core::command::LoadOp,
   store_op: wgpu_core::command::StoreOp,
 }
 
-#[derive(Deserialize)]
-#[serde(rename_all = "kebab-case")]
-enum GpuLoadOp<T> {
-  Load,
-  Clear(T),
-}
-
 #[derive(Deserialize)]
 #[serde(rename_all = "camelCase")]
-struct GpuRenderPassDepthStencilAttachment {
+pub struct GpuRenderPassDepthStencilAttachment {
   view: ResourceId,
-  depth_load_op: GpuLoadOp<f32>,
+  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<u32>,
+  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<String>,
-  color_attachments: Vec<GpuRenderPassColorAttachment>,
-  depth_stencil_attachment: Option<GpuRenderPassDepthStencilAttachment>,
-  _occlusion_query_set: Option<u32>, // not yet implemented
-}
-
 #[op]
 pub fn op_webgpu_command_encoder_begin_render_pass(
   state: &mut OpState,
-  args: CommandEncoderBeginRenderPassArgs,
+  command_encoder_rid: ResourceId,
+  label: Option<String>,
+  color_attachments: Vec<Option<GpuRenderPassColorAttachment>>,
+  depth_stencil_attachment: Option<GpuRenderPassDepthStencilAttachment>,
+  _occlusion_query_set: Option<u32>, // not yet implemented
 ) -> Result<WebGpuResult, AnyError> {
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(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::<super::texture::WebGpuTextureView>(at.view)?;
 
-  for color_attachment in args.color_attachments {
-    let texture_view_resource =
-      state
-        .resource_table
-        .get::<super::texture::WebGpuTextureView>(color_attachment.view)?;
+        let resolve_target = at
+          .resolve_target
+          .map(|rid| {
+            state
+              .resource_table
+              .get::<super::texture::WebGpuTextureView>(rid)
+          })
+          .transpose()?
+          .map(|texture| texture.0);
 
-    let resolve_target = color_attachment
-      .resolve_target
-      .map(|rid| {
-        state
-          .resource_table
-          .get::<super::texture::WebGpuTextureView>(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::<Result<Vec<_>, 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::<super::texture::WebGpuTextureView>(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<String>,
-}
-
 #[op]
 pub fn op_webgpu_command_encoder_begin_compute_pass(
   state: &mut OpState,
-  args: CommandEncoderBeginComputePassArgs,
+  command_encoder_rid: ResourceId,
+  label: Option<String>,
 ) -> Result<WebGpuResult, AnyError> {
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
-  let source_buffer_resource =
-    state
-      .resource_table
-      .get::<super::buffer::WebGpuBuffer>(args.source)?;
+  let source_buffer_resource = state
+    .resource_table
+    .get::<super::buffer::WebGpuBuffer>(source)?;
   let source_buffer = source_buffer_resource.0;
   let destination_buffer_resource =
     state
       .resource_table
-      .get::<super::buffer::WebGpuBuffer>(args.destination)?;
+      .get::<super::buffer::WebGpuBuffer>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let source_buffer_resource =
     state
       .resource_table
-      .get::<super::buffer::WebGpuBuffer>(args.source.buffer)?;
+      .get::<super::buffer::WebGpuBuffer>(source.buffer)?;
   let destination_texture_resource =
     state
       .resource_table
-      .get::<super::texture::WebGpuTexture>(args.destination.texture)?;
+      .get::<super::texture::WebGpuTexture>(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
+    &copy_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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let source_texture_resource =
     state
       .resource_table
-      .get::<super::texture::WebGpuTexture>(args.source.texture)?;
+      .get::<super::texture::WebGpuTexture>(source.texture)?;
   let destination_buffer_resource =
     state
       .resource_table
-      .get::<super::buffer::WebGpuBuffer>(args.destination.buffer)?;
+      .get::<super::buffer::WebGpuBuffer>(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
+    &copy_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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let source_texture_resource =
     state
       .resource_table
-      .get::<super::texture::WebGpuTexture>(args.source.texture)?;
+      .get::<super::texture::WebGpuTexture>(source.texture)?;
   let destination_texture_resource =
     state
       .resource_table
-      .get::<super::texture::WebGpuTexture>(args.destination.texture)?;
+      .get::<super::texture::WebGpuTexture>(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
+    &copy_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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let destination_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.destination_rid)?;
+    .get::<super::buffer::WebGpuBuffer>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let query_set_resource = state
     .resource_table
-    .get::<super::WebGpuQuerySet>(args.query_set)?;
+    .get::<super::WebGpuQuerySet>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let command_encoder_resource = state
     .resource_table
-    .get::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .get::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let query_set_resource = state
     .resource_table
-    .get::<super::WebGpuQuerySet>(args.query_set)?;
+    .get::<super::WebGpuQuerySet>(query_set)?;
   let destination_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.destination)?;
+    .get::<super::buffer::WebGpuBuffer>(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<String>,
-}
-
 #[op]
 pub fn op_webgpu_command_encoder_finish(
   state: &mut OpState,
-  args: CommandEncoderFinishArgs,
+  command_encoder_rid: ResourceId,
+  label: Option<String>,
 ) -> Result<WebGpuResult, AnyError> {
   let command_encoder_resource = state
     .resource_table
-    .take::<WebGpuCommandEncoder>(args.command_encoder_rid)?;
+    .take::<WebGpuCommandEncoder>(command_encoder_rid)?;
   let command_encoder = command_encoder_resource.0;
   let instance = state.borrow::<super::Instance>();
 
   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<WebGpuResult, AnyError> {
   let compute_pipeline_resource =
     state
       .resource_table
-      .get::<super::pipeline::WebGpuComputePipeline>(args.pipeline)?;
+      .get::<super::pipeline::WebGpuComputePipeline>(pipeline)?;
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<WebGpuResult, AnyError> {
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<WebGpuResult, AnyError> {
-  let compute_pass_resource = state
-    .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
-  let query_set_resource = state
-    .resource_table
-    .get::<super::WebGpuQuerySet>(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<WebGpuResult, AnyError> {
+  let compute_pass_resource = state
+    .resource_table
+    .get::<WebGpuComputePass>(compute_pass_rid)?;
+  let query_set_resource = state
+    .resource_table
+    .get::<super::WebGpuQuerySet>(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<WebGpuResult, AnyError> {
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<WebGpuResult, AnyError> {
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(compute_pass_rid)?;
   let query_set_resource = state
     .resource_table
-    .get::<super::WebGpuQuerySet>(args.query_set)?;
+    .get::<super::WebGpuQuerySet>(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<WebGpuResult, AnyError> {
   let command_encoder_resource = state
     .resource_table
     .get::<super::command_encoder::WebGpuCommandEncoder>(
-    args.command_encoder_rid,
+    command_encoder_rid,
   )?;
   let command_encoder = command_encoder_resource.0;
   let compute_pass_resource = state
     .resource_table
-    .take::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .take::<WebGpuComputePass>(compute_pass_rid)?;
   let compute_pass = &compute_pass_resource.0.borrow();
   let instance = state.borrow::<super::Instance>();
 
@@ -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<WebGpuResult, AnyError> {
   let bind_group_resource =
     state
       .resource_table
-      .get::<super::binding::WebGpuBindGroup>(args.bind_group)?;
+      .get::<super::binding::WebGpuBindGroup>(bind_group)?;
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(compute_pass_rid)?;
 
   // Align the data
-  assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0);
+  assert!(dynamic_offsets_data_start % std::mem::size_of::<u32>() == 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::<u32>() };
+  // 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::<u32>() };
   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<WebGpuResult, AnyError> {
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<WebGpuResult, AnyError> {
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<WebGpuResult, AnyError> {
   let compute_pass_resource = state
     .resource_table
-    .get::<WebGpuComputePass>(args.compute_pass_rid)?;
+    .get::<WebGpuComputePass>(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<ResourceId>,
@@ -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<T: Into<WebGpuError>>(err: Option<T>) -> Self {
     Self {
       rid: None,
-      err: err.map(|e| e.into()),
+      err: err.map(Into::into),
     }
   }
 
@@ -82,7 +98,7 @@ impl From<CreateBufferError> 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<DeviceError> 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<BufferAccessError> 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<CreateBindGroupLayoutError> 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<CreatePipelineLayoutError> 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<CreateBindGroupError> 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<RenderBundleError> for WebGpuError {
   fn from(err: RenderBundleError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
 impl From<CreateRenderBundleError> for WebGpuError {
   fn from(err: CreateRenderBundleError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
 impl From<CopyError> for WebGpuError {
   fn from(err: CopyError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
 impl From<CommandEncoderError> for WebGpuError {
   fn from(err: CommandEncoderError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
 impl From<QueryError> for WebGpuError {
   fn from(err: QueryError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
 impl From<ComputePassError> for WebGpuError {
   fn from(err: ComputePassError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
@@ -173,14 +189,14 @@ impl From<CreateComputePipelineError> 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<GetBindGroupLayoutError> for WebGpuError {
   fn from(err: GetBindGroupLayoutError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
@@ -188,14 +204,14 @@ impl From<CreateRenderPipelineError> 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<RenderPassError> for WebGpuError {
   fn from(err: RenderPassError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
@@ -203,7 +219,7 @@ impl From<CreateSamplerError> 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<CreateShaderModuleError> 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<CreateTextureError> 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<CreateTextureViewError> for WebGpuError {
   fn from(err: CreateTextureViewError) -> Self {
-    WebGpuError::Validation(err.to_string())
+    WebGpuError::Validation(fmt_err(&err))
   }
 }
 
@@ -236,7 +252,7 @@ impl From<CreateQuerySetError> 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<QueueSubmitError> 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<QueueWriteError> 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<ClearError> 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<wgpu_types::PowerPreference>,
-  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<String>,
   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<RefCell<OpState>>,
-  args: RequestAdapterArgs,
+  power_preference: Option<wgpu_types::PowerPreference>,
+  force_fallback_adapter: bool,
 ) -> Result<GpuAdapterDeviceOrErr, AnyError> {
   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>() {
     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<String>,
-  required_features: Option<GpuRequiredFeatures>,
-  required_limits: Option<wgpu_types::Limits>,
-}
-
 #[derive(Deserialize)]
 pub struct GpuRequiredFeatures(HashSet<String>);
 
@@ -324,6 +294,14 @@ impl From<GpuRequiredFeatures> 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<GpuRequiredFeatures> 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<GpuRequiredFeatures> 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<GpuRequiredFeatures> 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<GpuRequiredFeatures> for wgpu_types::Features {
 #[op]
 pub async fn op_webgpu_request_device(
   state: Rc<RefCell<OpState>>,
-  args: RequestDeviceArgs,
+  adapter_rid: ResourceId,
+  label: Option<String>,
+  required_features: Option<GpuRequiredFeatures>,
+  required_limits: Option<wgpu_types::Limits>,
 ) -> Result<GpuAdapterDevice, AnyError> {
   let mut state = state.borrow_mut();
-  let adapter_resource = state
-    .resource_table
-    .get::<WebGpuAdapter>(args.adapter_rid)?;
+  let adapter_resource =
+    state.resource_table.get::<WebGpuAdapter>(adapter_rid)?;
   let adapter = adapter_resource.0;
   let instance = state.borrow::<Instance>();
 
   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<RefCell<OpState>>,
+  adapter_rid: ResourceId,
+) -> Result<GPUAdapterInfo, AnyError> {
+  let state = state.borrow_mut();
+  let adapter_resource =
+    state.resource_table.get::<WebGpuAdapter>(adapter_rid)?;
+  let adapter = adapter_resource.0;
+  let instance = state.borrow::<Instance>();
+
+  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<OpDecl> {
+fn declare_webgpu_ops() -> Vec<deno_core::OpDecl> {
   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<OpDecl> {
     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<OpDecl> {
     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<String, GPUPipelineConstantValue>
 }
 
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct CreateComputePipelineArgs {
-  device_rid: ResourceId,
-  label: Option<String>,
-  layout: Option<ResourceId>,
-  compute: GpuProgrammableStage,
-}
-
 #[op]
 pub fn op_webgpu_create_compute_pipeline(
   state: &mut OpState,
-  args: CreateComputePipelineArgs,
+  device_rid: ResourceId,
+  label: Option<String>,
+  layout: GPUPipelineLayoutOrGPUAutoLayoutMode,
+  compute: GpuProgrammableStage,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(device_rid)?;
   let device = device_resource.0;
 
-  let pipeline_layout = if let Some(rid) = args.layout {
-    let id = state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
-    Some(id.0)
-  } else {
-    None
+  let pipeline_layout = match layout {
+    GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => {
+      let id = state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
+      Some(id.0)
+    }
+    GPUPipelineLayoutOrGPUAutoLayoutMode::Auto(GPUAutoLayoutMode::Auto) => None,
   };
 
   let compute_shader_module_resource =
     state
       .resource_table
-      .get::<super::shader::WebGpuShaderModule>(args.compute.module)?;
+      .get::<super::shader::WebGpuShaderModule>(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<PipelineLayout, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let compute_pipeline_resource = state
     .resource_table
-    .get::<WebGpuComputePipeline>(args.compute_pipeline_rid)?;
+    .get::<WebGpuComputePipeline>(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<GpuDepthStencilState> for wgpu_types::DepthStencilState {
-  type Error = AnyError;
-  fn try_from(
-    state: GpuDepthStencilState,
-  ) -> Result<wgpu_types::DepthStencilState, AnyError> {
-    Ok(wgpu_types::DepthStencilState {
+impl From<GpuDepthStencilState> 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<GpuDepthStencilState> for wgpu_types::DepthStencilState {
         slope_scale: state.depth_bias_slope_scale,
         clamp: state.depth_bias_clamp,
       },
-    })
+    }
   }
 }
 
@@ -285,7 +286,7 @@ impl From<GpuMultisampleState> for wgpu_types::MultisampleState {
 #[derive(Deserialize)]
 #[serde(rename_all = "camelCase")]
 struct GpuFragmentState {
-  targets: Vec<wgpu_types::ColorTargetState>,
+  targets: Vec<Option<wgpu_types::ColorTargetState>>,
   module: u32,
   entry_point: String,
   // TODO(lucacasonato): constants
@@ -296,7 +297,7 @@ struct GpuFragmentState {
 pub struct CreateRenderPipelineArgs {
   device_rid: ResourceId,
   label: Option<String>,
-  layout: Option<ResourceId>,
+  layout: GPUPipelineLayoutOrGPUAutoLayoutMode,
   vertex: GpuVertexState,
   primitive: GpuPrimitiveState,
   depth_stencil: Option<GpuDepthStencilState>,
@@ -315,12 +316,13 @@ pub fn op_webgpu_create_render_pipeline(
     .get::<super::WebGpuDevice>(args.device_rid)?;
   let device = device_resource.0;
 
-  let layout = if let Some(rid) = args.layout {
-    let pipeline_layout_resource =
-      state.resource_table.get::<WebGpuPipelineLayout>(rid)?;
-    Some(pipeline_layout_resource.0)
-  } else {
-    None
+  let layout = match args.layout {
+    GPUPipelineLayoutOrGPUAutoLayoutMode::Layout(rid) => {
+      let pipeline_layout_resource =
+        state.resource_table.get::<WebGpuPipelineLayout>(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::<super::shader::WebGpuShaderModule>(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<PipelineLayout, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let render_pipeline_resource = state
     .resource_table
-    .get::<WebGpuRenderPipeline>(args.render_pipeline_rid)?;
+    .get::<WebGpuRenderPipeline>(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<ResourceId>,
-}
-
 #[op]
 pub fn op_webgpu_queue_submit(
   state: &mut OpState,
-  args: QueueSubmitArgs,
+  queue_rid: ResourceId,
+  command_buffers: Vec<ResourceId>,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
-  let queue_resource =
-    state.resource_table.get::<WebGpuQueue>(args.queue_rid)?;
+  let queue_resource = state.resource_table.get::<WebGpuQueue>(queue_rid)?;
   let queue = queue_resource.0;
 
-  let mut ids = vec![];
-
-  for rid in args.command_buffers {
-    let buffer_resource =
-      state
-        .resource_table
-        .get::<super::command_encoder::WebGpuCommandBuffer>(rid)?;
-    ids.push(buffer_resource.0);
-  }
+  let ids = command_buffers
+    .iter()
+    .map(|rid| {
+      let buffer_resource =
+        state
+          .resource_table
+          .get::<super::command_encoder::WebGpuCommandBuffer>(*rid)?;
+      Ok(buffer_resource.0)
+    })
+    .collect::<Result<Vec<_>, 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<u32>,
   rows_per_image: Option<u32>,
@@ -64,39 +62,32 @@ impl From<GpuImageDataLayout> 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<usize>,
-}
-
-#[op]
-pub fn op_webgpu_write_buffer(
-  state: &mut OpState,
-  args: QueueWriteBufferArgs,
-  zero_copy: ZeroCopyBuf,
+  buf: ZeroCopyBuf,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(buffer)?;
   let buffer = buffer_resource.0;
-  let queue_resource =
-    state.resource_table.get::<WebGpuQueue>(args.queue_rid)?;
+  let queue_resource = state.resource_table.get::<WebGpuQueue>(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<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let texture_resource = state
     .resource_table
-    .get::<super::texture::WebGpuTexture>(args.destination.texture)?;
-  let queue_resource =
-    state.resource_table.get::<WebGpuQueue>(args.queue_rid)?;
+    .get::<super::texture::WebGpuTexture>(destination.texture)?;
+  let queue_resource = state.resource_table.get::<WebGpuQueue>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(render_pass_rid)?;
   let query_set_resource = state
     .resource_table
-    .get::<super::WebGpuQuerySet>(args.query_set)?;
+    .get::<super::WebGpuQuerySet>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(render_pass_rid)?;
   let query_set_resource = state
     .resource_table
-    .get::<super::WebGpuQuerySet>(args.query_set)?;
+    .get::<super::WebGpuQuerySet>(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<u32>,
-}
-
 #[op]
 pub fn op_webgpu_render_pass_execute_bundles(
   state: &mut OpState,
-  args: RenderPassExecuteBundlesArgs,
+  render_pass_rid: ResourceId,
+  bundles: Vec<u32>,
 ) -> Result<WebGpuResult, AnyError> {
-  let mut render_bundle_ids = vec![];
-
-  for rid in &args.bundles {
-    let render_bundle_resource =
-      state
-        .resource_table
-        .get::<super::bundle::WebGpuRenderBundle>(*rid)?;
-    render_bundle_ids.push(render_bundle_resource.0);
-  }
+  let bundles = bundles
+    .iter()
+    .map(|rid| {
+      let render_bundle_resource =
+        state
+          .resource_table
+          .get::<super::bundle::WebGpuRenderBundle>(*rid)?;
+      Ok(render_bundle_resource.0)
+    })
+    .collect::<Result<Vec<_>, AnyError>>()?;
 
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let command_encoder_resource = state
     .resource_table
     .get::<super::command_encoder::WebGpuCommandEncoder>(
-    args.command_encoder_rid,
+    command_encoder_rid,
   )?;
   let command_encoder = command_encoder_resource.0;
   let render_pass_resource = state
     .resource_table
-    .take::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .take::<WebGpuRenderPass>(render_pass_rid)?;
   let render_pass = &render_pass_resource.0.borrow();
   let instance = state.borrow::<super::Instance>();
 
   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<WebGpuResult, AnyError> {
   let bind_group_resource =
     state
       .resource_table
-      .get::<super::binding::WebGpuBindGroup>(args.bind_group)?;
+      .get::<super::binding::WebGpuBindGroup>(bind_group)?;
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(render_pass_rid)?;
 
   // Align the data
-  assert!(args.dynamic_offsets_data_start % std::mem::size_of::<u32>() == 0);
+  assert_eq!(dynamic_offsets_data_start % std::mem::size_of::<u32>(), 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::<u32>() };
+  // 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::<u32>() };
   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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pipeline_resource =
     state
       .resource_table
-      .get::<super::pipeline::WebGpuRenderPipeline>(args.pipeline)?;
+      .get::<super::pipeline::WebGpuRenderPipeline>(pipeline)?;
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<u64>,
-}
-
-#[op]
-pub fn op_webgpu_render_pass_set_index_buffer(
-  state: &mut OpState,
-  args: RenderPassSetIndexBufferArgs,
 ) -> Result<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(buffer)?;
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<u64>,
-}
-
-#[op]
-pub fn op_webgpu_render_pass_set_vertex_buffer(
-  state: &mut OpState,
-  args: RenderPassSetVertexBufferArgs,
 ) -> Result<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(buffer)?;
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<WebGpuResult, AnyError> {
   let buffer_resource = state
     .resource_table
-    .get::<super::buffer::WebGpuBuffer>(args.indirect_buffer)?;
+    .get::<super::buffer::WebGpuBuffer>(indirect_buffer)?;
   let render_pass_resource = state
     .resource_table
-    .get::<WebGpuRenderPass>(args.render_pass_rid)?;
+    .get::<WebGpuRenderPass>(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<wgpu_types::CompareFunction>,
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<String>,
   code: String,
   _source_map: Option<()>, // not yet implemented
-}
-
-#[op]
-pub fn op_webgpu_create_shader_module(
-  state: &mut OpState,
-  args: CreateShaderModuleArgs,
 ) -> Result<WebGpuResult, AnyError> {
   let instance = state.borrow::<super::Instance>();
   let device_resource = state
     .resource_table
-    .get::<super::WebGpuDevice>(args.device_rid)?;
+    .get::<super::WebGpuDevice>(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<DOMString>;
 };
 
+[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<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
+    Promise<GPUAdapterInfo> requestAdapterInfo(optional sequence<DOMString> 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<GPUBindGroupLayoutEntry> 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<GPUCompilationMessage> 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<GPUColorTargetState> targets;
+    required sequence<GPUColorTargetState?> 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<GPUBufferDynamicOffset> 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<GPURenderBundle> 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<GPURenderPassColorAttachment> colorAttachments;
+    required sequence<GPURenderPassColorAttachment?> 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<GPUTextureFormat> colorFormats;
+    required sequence<GPUTextureFormat?> 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<GPUIntegerCoordinate> 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 = {}) {