Bug 1469376 - Initial stubs for WebGPU sketch API. - r=kvark,qdot
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 13 Jun 2018 10:43:48 -0700
changeset 473232 3d7f2fdc5bf7ca7521013b28e0d8be0785d2b58a
parent 473231 d6b45def3335f3ad5eeed9c856bdd28d17d3b33c
child 473233 cc3401e78e8bbae22e6dbc854e525ceae4923bcf
child 473265 7efe662a874d20c9b7747c55f15900dc5da8545e
push id200
push userfmarier@mozilla.com
push dateThu, 05 Jul 2018 23:51:35 +0000
reviewerskvark, qdot
bugs1469376
milestone63.0a1
Bug 1469376 - Initial stubs for WebGPU sketch API. - r=kvark,qdot MozReview-Commit-ID: 3MZLQDNpHBk
.eslintignore
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/bindings/Bindings.conf
dom/bindings/moz.build
dom/moz.build
dom/webgpu/Adapter.cpp
dom/webgpu/Adapter.h
dom/webgpu/AttachmentState.cpp
dom/webgpu/AttachmentState.h
dom/webgpu/BindGroup.cpp
dom/webgpu/BindGroup.h
dom/webgpu/BindGroupLayout.cpp
dom/webgpu/BindGroupLayout.h
dom/webgpu/BlendState.cpp
dom/webgpu/BlendState.h
dom/webgpu/Buffer.cpp
dom/webgpu/Buffer.h
dom/webgpu/CommandBuffer.cpp
dom/webgpu/CommandBuffer.h
dom/webgpu/CommandEncoder.cpp
dom/webgpu/CommandEncoder.h
dom/webgpu/ComputePipeline.cpp
dom/webgpu/ComputePipeline.h
dom/webgpu/DepthStencilState.cpp
dom/webgpu/DepthStencilState.h
dom/webgpu/Device.cpp
dom/webgpu/Device.h
dom/webgpu/Fence.cpp
dom/webgpu/Fence.h
dom/webgpu/InputState.cpp
dom/webgpu/InputState.h
dom/webgpu/Instance.cpp
dom/webgpu/Instance.h
dom/webgpu/InstanceProvider.cpp
dom/webgpu/InstanceProvider.h
dom/webgpu/LogEntry.cpp
dom/webgpu/LogEntry.h
dom/webgpu/ObjectModel.cpp
dom/webgpu/ObjectModel.h
dom/webgpu/PipelineLayout.cpp
dom/webgpu/PipelineLayout.h
dom/webgpu/Queue.cpp
dom/webgpu/Queue.h
dom/webgpu/RenderPipeline.cpp
dom/webgpu/RenderPipeline.h
dom/webgpu/Sampler.cpp
dom/webgpu/Sampler.h
dom/webgpu/ShaderModule.cpp
dom/webgpu/ShaderModule.h
dom/webgpu/SwapChain.cpp
dom/webgpu/SwapChain.h
dom/webgpu/Texture.cpp
dom/webgpu/Texture.h
dom/webgpu/TextureView.cpp
dom/webgpu/TextureView.h
dom/webgpu/mochitest/mochitest-no-pref.ini
dom/webgpu/mochitest/mochitest.ini
dom/webgpu/mochitest/test_disabled.html
dom/webgpu/mochitest/test_enabled.html
dom/webgpu/moz.build
dom/webidl/WebGPU.webidl
dom/webidl/WebGPUExtras.webidl
dom/webidl/Window.webidl
dom/webidl/moz.build
modules/libpref/init/all.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -258,16 +258,17 @@ dom/tests/js/**
 dom/tests/mochitest/**
 dom/tests/unit/**
 dom/time/**
 dom/u2f/**
 dom/url/**
 dom/vr/**
 dom/webauthn/**
 dom/webbrowserpersist/**
+dom/webgpu/**
 dom/webidl/**
 dom/websocket/**
 dom/workers/**
 dom/worklet/**
 dom/xbl/**
 dom/xhr/**
 dom/xml/**
 dom/xslt/**
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -881,16 +881,17 @@ public:
 };
 
 //*****************************************************************************
 //***    nsGlobalWindowInner: Object Management
 //*****************************************************************************
 
 nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
   : nsPIDOMWindowInner(aOuterWindow->AsOuter()),
+    mozilla::webgpu::InstanceProvider(this),
     mIdleFuzzFactor(0),
     mIdleCallbackIndex(-1),
     mCurrentlyIdle(false),
     mAddActiveEventFuzzTime(true),
     mWasOffline(false),
     mHasHadSlowScript(false),
     mNotifyIdleObserversIdleOnThaw(false),
     mNotifyIdleObserversActiveOnThaw(false),
@@ -1474,16 +1475,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPromises)
 
   for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mPromise);
     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mCallback);
   }
 
+  static_cast<mozilla::webgpu::InstanceProvider*>(tmp)->CcTraverse(cb);
+
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
   tmp->CleanupCachedXBLHandlers();
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
@@ -1577,16 +1580,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPromises)
   for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mPromise);
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mCallback);
   }
   tmp->mDocumentFlushedResolvers.Clear();
 
+  static_cast<mozilla::webgpu::InstanceProvider*>(tmp)->CcUnlink();
+
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 #ifdef DEBUG
 void
 nsGlobalWindowInner::RiskyUnlink()
 {
   NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -40,16 +40,17 @@
 #include "mozilla/dom/StorageEvent.h"
 #include "mozilla/dom/StorageEventBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/webgpu/InstanceProvider.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIIdleObserver.h"
 #include "nsIDocument.h"
 #include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "Units.h"
 #include "nsComponentManagerUtils.h"
 #include "nsSize.h"
@@ -212,16 +213,17 @@ class nsGlobalWindowInner final
   // implemented on chrome windows.
   , private nsIDOMChromeWindow
   , public nsIScriptGlobalObject
   , public nsIScriptObjectPrincipal
   , public nsSupportsWeakReference
   , public nsIInterfaceRequestor
   , public PRCListStr
   , public nsAPostRefreshObserver
+  , public mozilla::webgpu::InstanceProvider
 {
 public:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
   typedef nsDataHashtable<nsUint64HashKey, nsGlobalWindowInner*> InnerWindowByIdTable;
 
   static void
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1292,16 +1292,149 @@ DOMInterfaces = {
     'headerFile': 'WebGLUniformLocation.h'
 },
 
 'WebGLVertexArrayObject': {
     'nativeType': 'mozilla::WebGLVertexArray',
     'headerFile': 'WebGLVertexArray.h'
 },
 
+# WebGPU
+
+'WebGPU': {
+    'nativeType': 'mozilla::webgpu::Instance',
+},
+'WebGPUAdapter': {
+    'nativeType': 'mozilla::webgpu::Adapter',
+},
+'WebGPUAttachmentState': {
+    'nativeType': 'mozilla::webgpu::AttachmentState',
+},
+'WebGPUBindGroup': {
+    'nativeType': 'mozilla::webgpu::BindGroup',
+},
+'WebGPUBindGroupLayout': {
+    'nativeType': 'mozilla::webgpu::BindGroupLayout',
+},
+'WebGPUBlendState': {
+    'nativeType': 'mozilla::webgpu::BlendState',
+},
+'WebGPUBuffer': {
+    'nativeType': 'mozilla::webgpu::Buffer',
+},
+'WebGPUCommandBuffer': {
+    'nativeType': 'mozilla::webgpu::CommandBuffer',
+},
+'WebGPUCommandEncoder': {
+    'nativeType': 'mozilla::webgpu::CommandEncoder',
+},
+'WebGPUComputePipeline': {
+    'nativeType': 'mozilla::webgpu::ComputePipeline',
+},
+'WebGPUDepthStencilState': {
+    'nativeType': 'mozilla::webgpu::DepthStencilState',
+},
+'WebGPUDevice': {
+    'nativeType': 'mozilla::webgpu::Device',
+},
+'WebGPUFence': {
+    'nativeType': 'mozilla::webgpu::Fence',
+},
+'WebGPUInputState': {
+    'nativeType': 'mozilla::webgpu::InputState',
+},
+'WebGPULogEntry': {
+    'nativeType': 'mozilla::webgpu::LogEntry',
+},
+'WebGPUPipelineLayout': {
+    'nativeType': 'mozilla::webgpu::PipelineLayout',
+},
+'WebGPUQueue': {
+    'nativeType': 'mozilla::webgpu::Queue',
+},
+'WebGPURenderPipeline': {
+    'nativeType': 'mozilla::webgpu::RenderPipeline',
+},
+'WebGPUSampler': {
+    'nativeType': 'mozilla::webgpu::Sampler',
+},
+'WebGPUShaderModule': {
+    'nativeType': 'mozilla::webgpu::ShaderModule',
+},
+'WebGPUSwapChain': {
+    'nativeType': 'mozilla::webgpu::SwapChain',
+},
+'WebGPUTexture': {
+    'nativeType': 'mozilla::webgpu::Texture',
+},
+'WebGPUTextureView': {
+    'nativeType': 'mozilla::webgpu::TextureView',
+},
+
+
+'WebGPUBindingType': {
+    'concrete': False,
+},
+'WebGPUBlendFactor': {
+    'concrete': False,
+},
+'WebGPUBlendOperation': {
+    'concrete': False,
+},
+'WebGPUBufferUsage': {
+    'concrete': False,
+},
+'WebGPUColorWriteBits': {
+    'concrete': False,
+},
+'WebGPUCompareFunction': {
+    'concrete': False,
+},
+'WebGPUFilterMode': {
+    'concrete': False,
+},
+'WebGPUIndexFormat': {
+    'concrete': False,
+},
+'WebGPUInputStepMode': {
+    'concrete': False,
+},
+'WebGPULoadOp': {
+    'concrete': False,
+},
+'WebGPUPrimitiveTopology': {
+    'concrete': False,
+},
+'WebGPUShaderStage': {
+    'concrete': False,
+},
+'WebGPUShaderStageBit': {
+    'concrete': False,
+},
+'WebGPUStencilOperation': {
+    'concrete': False,
+},
+'WebGPUStoreOp': {
+    'concrete': False,
+},
+'WebGPUTextureDimension': {
+    'concrete': False,
+},
+'WebGPUTextureFormat': {
+    'concrete': False,
+},
+'WebGPUTextureUsage': {
+    'concrete': False,
+},
+'WebGPUVertexFormat': {
+    'concrete': False,
+},
+
+# WebRTC
+
 'WebrtcGlobalInformation': {
     'nativeType': 'mozilla::dom::WebrtcGlobalInformation',
     'headerFile': 'WebrtcGlobalInformation.h',
     'wrapperCache': False,
     'concrete': False,
 },
 
 'Window': {
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -2,16 +2,19 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "DOM")
 
+if CONFIG['CC_TYPE'] == 'msvc':
+    CXXFLAGS += ['-bigobj']
+
 TEST_DIRS += ['test']
 
 XPIDL_SOURCES += [
     'nsIScriptError.idl'
 ]
 
 XPIDL_MODULE = 'dom_bindings'
 
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -34,16 +34,17 @@ DIRS += [
     'abort',
     'animation',
     'base',
     'bindings',
     'battery',
     'browser-element',
     'cache',
     'canvas',
+    'webgpu',
     'chrome-webidl',
     'clients',
     'commandhandler',
     'credentialmanagement',
     'crypto',
     'encoding',
     'events',
     'fetch',
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Adapter.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Adapter.h"
+
+#include "Instance.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Adapter::~Adapter() = default;
+
+void
+Adapter::Extensions(dom::WebGPUExtensions& out) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+Adapter::Features(dom::WebGPUFeatures& out) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Device>
+Adapter::CreateDevice(const dom::WebGPUDeviceDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(Adapter)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Adapter.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_Adapter_H_
+#define WEBGPU_Adapter_H_
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "nsString.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+struct WebGPUDeviceDescriptor;
+struct WebGPUExtensions;
+struct WebGPUFeatures;
+} // namespace dom
+
+namespace webgpu {
+class Device;
+class Instance;
+
+class Adapter final
+    : public ChildOf<Instance>
+{
+public:
+    WEBGPU_DECL_GOOP(Adapter)
+
+    const nsString mName;
+
+private:
+    Adapter() = delete;
+    virtual ~Adapter();
+
+public:
+    void GetName(nsString& out) const {
+        out = mName;
+    }
+
+    void Extensions(dom::WebGPUExtensions& out) const;
+    void Features(dom::WebGPUFeatures& out) const;
+    already_AddRefed<Device> CreateDevice(const dom::WebGPUDeviceDescriptor& desc) const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_Adapter_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/AttachmentState.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AttachmentState.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+AttachmentState::~AttachmentState() = default;
+
+WEBGPU_IMPL_GOOP_0(AttachmentState)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/AttachmentState.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_AttachmentState_H_
+#define WEBGPU_AttachmentState_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class AttachmentState final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(AttachmentState)
+
+private:
+    AttachmentState() = delete;
+    virtual ~AttachmentState();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_AttachmentState_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/BindGroup.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BindGroup.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+BindGroup::~BindGroup() = default;
+
+WEBGPU_IMPL_GOOP_0(BindGroup)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/BindGroup.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_BindGroup_H_
+#define WEBGPU_BindGroup_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class BindGroup final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(BindGroup)
+
+private:
+    BindGroup() = delete;
+    virtual ~BindGroup();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_BindGroup_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/BindGroupLayout.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BindGroupLayout.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+BindGroupLayout::~BindGroupLayout() = default;
+
+WEBGPU_IMPL_GOOP_0(BindGroupLayout)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/BindGroupLayout.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_BindGroupLayout_H_
+#define WEBGPU_BindGroupLayout_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class BindGroupLayout final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(BindGroupLayout)
+
+private:
+    BindGroupLayout() = delete;
+    virtual ~BindGroupLayout();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_BindGroupLayout_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/BlendState.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BlendState.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+BlendState::~BlendState() = default;
+
+WEBGPU_IMPL_GOOP_0(BlendState)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/BlendState.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_BlendState_H_
+#define WEBGPU_BlendState_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class BlendState final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(BlendState)
+
+private:
+    BlendState() = delete;
+    virtual ~BlendState();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_BlendState_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Buffer.cpp
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Buffer.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Buffer::Buffer(Device* const parent)
+    : ChildOf(parent)
+{
+    mozilla::HoldJSObjects(this); // Mimed from PushSubscriptionOptions
+}
+
+Buffer::~Buffer()
+{
+    mMapping = nullptr;
+    mozilla::DropJSObjects(this);
+}
+
+void
+Buffer::GetMapping(JSContext*, JS::MutableHandle<JSObject*> out) const
+{
+    out.set(mMapping);
+}
+
+void
+Buffer::Unmap() const
+{
+    MOZ_CRASH("todo");
+}
+
+JSObject*
+webgpu::Buffer::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
+{
+    return dom::WebGPUBuffer_Binding::Wrap(cx, this, givenProto);
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(Buffer)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Buffer)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+  tmp->mMapping = nullptr;
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Buffer)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Buffer)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMapping)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Buffer, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Buffer, Release)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Buffer.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_BUFFER_H_
+#define WEBGPU_BUFFER_H_
+
+#include "mozilla/dom/Nullable.h"
+#include "mozilla/dom/TypedArray.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class Buffer final
+    : public ChildOf<Device>
+{
+public:
+    JS::Heap<JSObject*> mMapping;
+
+    WEBGPU_DECL_GOOP(Buffer)
+
+private:
+    explicit Buffer(Device* parent);
+    virtual ~Buffer();
+
+public:
+    void GetMapping(JSContext* cx, JS::MutableHandle<JSObject*> out) const;
+    void Unmap() const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_BUFFER_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/CommandBuffer.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CommandBuffer.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+CommandBuffer::~CommandBuffer() = default;
+
+WEBGPU_IMPL_GOOP_0(CommandBuffer)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/CommandBuffer.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_CommandBuffer_H_
+#define WEBGPU_CommandBuffer_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class CommandBuffer final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(CommandBuffer)
+
+private:
+    CommandBuffer() = delete;
+    virtual ~CommandBuffer();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_CommandBuffer_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/CommandEncoder.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CommandEncoder.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+CommandEncoder::~CommandEncoder() = default;
+
+already_AddRefed<CommandBuffer>
+CommandEncoder::FinishEncoding() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::CopyBufferToBuffer(const Buffer& src, const uint32_t srcOffset,
+                                   const Buffer& dst, const uint32_t dstOffset,
+                                   const uint32_t size) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::CopyBufferToTexture() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::CopyTextureToBuffer() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::CopyTextureToTexture() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::Blit() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::TransitionBuffer(const Buffer& b, const uint32_t flags) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::SetPushConstants(const uint32_t stageFlags, const uint32_t offset,
+                                 const uint32_t count, const dom::ArrayBuffer& data) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::SetBindGroup(const uint32_t index, const BindGroup& bindGroup) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::SetPipeline(const dom::WebGPUComputePipelineOrWebGPURenderPipeline& pipeline) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::BeginComputePass() const
+{
+    MOZ_CRASH("todo");
+}
+void
+CommandEncoder::EndComputePass() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::Dispatch(const uint32_t x, const uint32_t y, const uint32_t z) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::BeginRenderPass(const dom::WebGPURenderPassDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::EndRenderPass() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::SetBlendColor(const float r, const float g, const float b,
+                              const float a) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::SetIndexBuffer(const Buffer& buffer, const uint32_t offset) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::SetVertexBuffers(const uint32_t startSlot,
+                                 const dom::Sequence<OwningNonNull<Buffer>>& buffers,
+                                 const dom::Sequence<uint32_t>& offsets) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::Draw(const uint32_t vertexCount, const uint32_t instanceCount,
+                     const uint32_t firstVertex, const uint32_t firstInstance) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+CommandEncoder::DrawIndexed(const uint32_t indexCount, const uint32_t instanceCount,
+                            const uint32_t firstIndex, const uint32_t firstInstance,
+                            const uint32_t firstVertex) const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(CommandEncoder)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/CommandEncoder.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_CommandEncoder_H_
+#define WEBGPU_CommandEncoder_H_
+
+#include "mozilla/dom/TypedArray.h"
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+template<typename T> class Sequence;
+class WebGPUComputePipelineOrWebGPURenderPipeline;
+struct WebGPURenderPassDescriptor;
+} // namespace dom
+namespace webgpu {
+
+class BindGroup;
+class Buffer;
+class CommandBuffer;
+class Device;
+
+class CommandEncoder final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(CommandEncoder)
+
+private:
+    CommandEncoder() = delete;
+    virtual ~CommandEncoder();
+
+public:
+    already_AddRefed<CommandBuffer> FinishEncoding() const;
+
+    // Commands allowed outside of "passes"
+    void CopyBufferToBuffer(const Buffer& src, uint32_t srcOffset, const Buffer& dst,
+                            uint32_t dstOffset, uint32_t size) const;
+    // TODO figure out all the arguments required for these
+    void CopyBufferToTexture() const;
+    void CopyTextureToBuffer() const;
+    void CopyTextureToTexture() const;
+    void Blit() const;
+
+    void TransitionBuffer(const Buffer& b, uint32_t flags) const;
+
+    // Allowed in both compute and render passes
+    void SetPushConstants(uint32_t stageFlags,
+                          uint32_t offset,
+                          uint32_t count,
+                          const dom::ArrayBuffer& data) const;
+    void SetBindGroup(uint32_t index, const BindGroup& bindGroup) const;
+    void SetPipeline(const dom::WebGPUComputePipelineOrWebGPURenderPipeline& pipeline) const;
+
+    // Compute pass commands
+    void BeginComputePass() const;
+    void EndComputePass() const;
+
+    void Dispatch(uint32_t x, uint32_t y, uint32_t z) const;
+
+    // Render pass commands
+    void BeginRenderPass(const dom::WebGPURenderPassDescriptor& desc) const;
+    void EndRenderPass() const;
+
+    void SetBlendColor(float r, float g, float b, float a) const;
+    void SetIndexBuffer(const Buffer& buffer, uint32_t offset) const;
+    void SetVertexBuffers(uint32_t startSlot,
+                          const dom::Sequence<OwningNonNull<Buffer>>& buffers,
+                          const dom::Sequence<uint32_t>& offsets) const;
+
+    void Draw(uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex,
+              uint32_t firstInstance) const;
+    void DrawIndexed(uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex,
+                     uint32_t firstInstance, uint32_t firstVertex) const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_CommandEncoder_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/ComputePipeline.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ComputePipeline.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+ComputePipeline::~ComputePipeline() = default;
+
+WEBGPU_IMPL_GOOP_0(ComputePipeline)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/ComputePipeline.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_ComputePipeline_H_
+#define WEBGPU_ComputePipeline_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class ComputePipeline final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(ComputePipeline)
+
+private:
+    ComputePipeline() = delete;
+    virtual ~ComputePipeline();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_ComputePipeline_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/DepthStencilState.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DepthStencilState.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+DepthStencilState::~DepthStencilState() = default;
+
+WEBGPU_IMPL_GOOP_0(DepthStencilState)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/DepthStencilState.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_DepthStencilState_H_
+#define WEBGPU_DepthStencilState_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class DepthStencilState final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(DepthStencilState)
+
+private:
+    DepthStencilState() = delete;
+    virtual ~DepthStencilState();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_DepthStencilState_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Device.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Device.h"
+
+#include "Adapter.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Device::~Device() = default;
+
+already_AddRefed<webgpu::Adapter>
+Device::Adapter() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+Device::Extensions(dom::WebGPUExtensions& out) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+Device::Features(dom::WebGPUFeatures& out) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+Device::Limits(dom::WebGPULimits& out) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Buffer>
+Device::CreateBuffer(const dom::WebGPUBufferDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Texture>
+Device::CreateTexture(const dom::WebGPUTextureDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Sampler>
+Device::CreateSampler(const dom::WebGPUSamplerDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+
+already_AddRefed<BindGroupLayout>
+Device::CreateBindGroupLayout(const dom::WebGPUBindGroupLayoutDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<PipelineLayout>
+Device::CreatePipelineLayout(const dom::WebGPUPipelineLayoutDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<BindGroup>
+Device::CreateBindGroup(const dom::WebGPUBindGroupDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+
+already_AddRefed<BlendState>
+Device::CreateBlendState(const dom::WebGPUBlendStateDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<DepthStencilState>
+Device::CreateDepthStencilState(const dom::WebGPUDepthStencilStateDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<InputState>
+Device::CreateInputState(const dom::WebGPUInputStateDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<ShaderModule>
+Device::CreateShaderModule(const dom::WebGPUShaderModuleDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<AttachmentState>
+Device::CreateAttachmentState(const dom::WebGPUAttachmentStateDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<ComputePipeline>
+Device::CreateComputePipeline(const dom::WebGPUComputePipelineDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<RenderPipeline>
+Device::CreateRenderPipeline(const dom::WebGPURenderPipelineDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<CommandEncoder>
+Device::CreateCommandEncoder(const dom::WebGPUCommandEncoderDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Queue>
+Device::GetQueue() const
+{
+    MOZ_CRASH("todo");
+}
+
+RefPtr<dom::WebGPULogCallback>
+Device::OnLog() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+Device::SetOnLog(const dom::WebGPULogCallback& callback) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<dom::Promise>
+Device::GetObjectStatus(const dom::WebGPUBufferOrWebGPUTexture& obj) const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(Device)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Device.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_DEVICE_H_
+#define WEBGPU_DEVICE_H_
+
+#include "mozilla/RefPtr.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+struct WebGPUExtensions;
+struct WebGPUFeatures;
+struct WebGPULimits;
+
+struct WebGPUBufferDescriptor;
+struct WebGPUTextureDescriptor;
+struct WebGPUSamplerDescriptor;
+struct WebGPUBindGroupLayoutDescriptor;
+struct WebGPUPipelineLayoutDescriptor;
+struct WebGPUBindGroupDescriptor;
+struct WebGPUBlendStateDescriptor;
+struct WebGPUDepthStencilStateDescriptor;
+struct WebGPUInputStateDescriptor;
+struct WebGPUShaderModuleDescriptor;
+struct WebGPUAttachmentStateDescriptor;
+struct WebGPUComputePipelineDescriptor;
+struct WebGPURenderPipelineDescriptor;
+struct WebGPUCommandEncoderDescriptor;
+
+class Promise;
+class WebGPUBufferOrWebGPUTexture;
+class WebGPULogCallback;
+} // namespace dom
+
+namespace webgpu {
+class Adapter;
+class AttachmentState;
+class BindGroup;
+class BindGroupLayout;
+class BlendState;
+class Buffer;
+class CommandEncoder;
+class ComputePipeline;
+class DepthStencilState;
+class Fence;
+class InputState;
+class PipelineLayout;
+class Queue;
+class RenderPipeline;
+class Sampler;
+class ShaderModule;
+class Texture;
+
+class Device final
+    : public ChildOf<Adapter>
+{
+public:
+    WEBGPU_DECL_GOOP(Device)
+
+private:
+    Device() = delete;
+    virtual ~Device();
+
+public:
+    already_AddRefed<webgpu::Adapter> Adapter() const;
+
+    void Extensions(dom::WebGPUExtensions& out) const;
+    void Features(dom::WebGPUFeatures& out) const;
+    void Limits(dom::WebGPULimits& out) const;
+
+    already_AddRefed<Buffer> CreateBuffer(const dom::WebGPUBufferDescriptor& desc) const;
+    already_AddRefed<Texture> CreateTexture(const dom::WebGPUTextureDescriptor& desc) const;
+    already_AddRefed<Sampler> CreateSampler(const dom::WebGPUSamplerDescriptor& desc) const;
+
+    already_AddRefed<BindGroupLayout> CreateBindGroupLayout(const dom::WebGPUBindGroupLayoutDescriptor& desc) const;
+    already_AddRefed<PipelineLayout> CreatePipelineLayout(const dom::WebGPUPipelineLayoutDescriptor& desc) const;
+    already_AddRefed<BindGroup> CreateBindGroup(const dom::WebGPUBindGroupDescriptor& desc) const;
+
+    already_AddRefed<BlendState> CreateBlendState(const dom::WebGPUBlendStateDescriptor& desc) const;
+    already_AddRefed<DepthStencilState> CreateDepthStencilState(const dom::WebGPUDepthStencilStateDescriptor& desc) const;
+    already_AddRefed<InputState> CreateInputState(const dom::WebGPUInputStateDescriptor& desc) const;
+    already_AddRefed<ShaderModule> CreateShaderModule(const dom::WebGPUShaderModuleDescriptor& desc) const;
+    already_AddRefed<AttachmentState> CreateAttachmentState(const dom::WebGPUAttachmentStateDescriptor& desc) const;
+    already_AddRefed<ComputePipeline> CreateComputePipeline(const dom::WebGPUComputePipelineDescriptor& desc) const;
+    already_AddRefed<RenderPipeline> CreateRenderPipeline(const dom::WebGPURenderPipelineDescriptor& desc) const;
+
+    already_AddRefed<CommandEncoder> CreateCommandEncoder(const dom::WebGPUCommandEncoderDescriptor& desc) const;
+
+    already_AddRefed<Queue> GetQueue() const;
+
+    RefPtr<dom::WebGPULogCallback> OnLog() const;
+    void SetOnLog(const dom::WebGPULogCallback& callback) const;
+
+    already_AddRefed<dom::Promise> GetObjectStatus(const dom::WebGPUBufferOrWebGPUTexture& obj) const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_DEVICE_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Fence.cpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Fence.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Fence::~Fence() = default;
+
+bool
+Fence::Wait(const double milliseconds) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<dom::Promise>
+Fence::Promise() const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(Fence)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Fence.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_Fence_H_
+#define WEBGPU_Fence_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+class Promise;
+} // namespace dom
+namespace webgpu {
+
+class Device;
+
+class Fence final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(Fence)
+
+private:
+    Fence() = delete;
+    virtual ~Fence();
+
+public:
+    bool Wait(double milliseconds) const;
+    already_AddRefed<dom::Promise> Promise() const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_Fence_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/InputState.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InputState.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+InputState::~InputState() = default;
+
+WEBGPU_IMPL_GOOP_0(InputState)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/InputState.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_InputState_H_
+#define WEBGPU_InputState_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class InputState final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(InputState)
+
+private:
+    InputState() = delete;
+    virtual ~InputState();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_InputState_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Instance.cpp
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Instance.h"
+
+#include "Adapter.h"
+#include "InstanceProvider.h"
+#include "mozilla/dom/WebGPUBinding.h"
+#include "nsIGlobalObject.h"
+
+namespace mozilla {
+namespace webgpu {
+
+/*static*/ RefPtr<Instance>
+Instance::Create(nsIGlobalObject* parent)
+{
+    return new Instance(parent);
+}
+
+Instance::Instance(nsIGlobalObject* parent)
+    : mParent(parent)
+{
+}
+
+Instance::~Instance() = default;
+
+already_AddRefed<Adapter>
+Instance::GetAdapter(const dom::WebGPUAdapterDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+template<typename T>
+void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
+                            const nsCOMPtr<T>& field,
+                            const char* name, uint32_t flags)
+{
+    CycleCollectionNoteChild(callback, field.get(), name, flags);
+}
+
+template<typename T>
+void
+ImplCycleCollectionUnlink(const nsCOMPtr<T>& field)
+{
+    const auto mut = const_cast<nsCOMPtr<T>*>(&field);
+    *mut = nullptr;
+}
+
+JSObject*
+Instance::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
+{
+    return dom::WebGPU_Binding::Wrap(cx, this, givenProto);
+}
+NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Instance, AddRef)
+NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Instance, Release)
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Instance, mParent)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Instance.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_INSTANCE_H_
+#define WEBGPU_INSTANCE_H_
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/RefPtr.h"
+#include "nsCOMPtr.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+struct WebGPUAdapterDescriptor;
+} // namespace dom
+
+namespace webgpu {
+class Adapter;
+class InstanceProvider;
+
+class Instance final
+    : public nsWrapperCache
+{
+public:
+    WEBGPU_DECL_GOOP(Instance)
+
+    const nsCOMPtr<nsIGlobalObject> mParent;
+
+    static RefPtr<Instance> Create(nsIGlobalObject* parent);
+
+private:
+    explicit Instance(nsIGlobalObject* parent);
+    virtual ~Instance();
+
+public:
+    nsIGlobalObject* GetParentObject() const { return mParent.get(); }
+
+    already_AddRefed<Adapter> GetAdapter(const dom::WebGPUAdapterDescriptor& desc) const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_INSTANCE_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/InstanceProvider.cpp
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InstanceProvider.h"
+
+#include "Instance.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+InstanceProvider::InstanceProvider(nsIGlobalObject* const global)
+    : mGlobal(global)
+{ }
+
+InstanceProvider::~InstanceProvider() = default;
+
+already_AddRefed<Instance>
+InstanceProvider::Webgpu() const
+{
+    if (!mInstance) {
+        const auto inst = Instance::Create(mGlobal);
+        mInstance = Some(inst);
+    }
+    auto ret = mInstance.value();
+    return ret.forget();
+}
+
+void
+InstanceProvider::CcTraverse(nsCycleCollectionTraversalCallback& callback) const
+{
+    if (mInstance) {
+        CycleCollectionNoteChild(callback, mInstance.ref().get(),
+                                 "webgpu::InstanceProvider::mInstance", 0);
+    }
+}
+
+void
+InstanceProvider::CcUnlink()
+{
+    mInstance = Some(nullptr);
+}
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/InstanceProvider.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_INSTANCE_PROVIDER_H_
+#define WEBGPU_INSTANCE_PROVIDER_H_
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/RefPtr.h"
+
+class nsCycleCollectionTraversalCallback;
+class nsIGlobalObject;
+
+namespace mozilla {
+namespace webgpu {
+class Instance;
+
+class InstanceProvider
+{
+private:
+    nsIGlobalObject* const mGlobal;
+    mutable Maybe<RefPtr<Instance>> mInstance;
+
+protected:
+    explicit InstanceProvider(nsIGlobalObject* global);
+    virtual ~InstanceProvider();
+
+public:
+    already_AddRefed<Instance> Webgpu() const;
+
+    nsIGlobalObject* GetParentObject() const { return mGlobal; }
+
+    void CcTraverse(nsCycleCollectionTraversalCallback&) const;
+    void CcUnlink();
+};
+
+template<typename T>
+void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
+                            const Maybe<T>& field,
+                            const char* name, uint32_t flags)
+{
+    if (field) {
+        CycleCollectionNoteChild(callback, field.value(), name, flags);
+    }
+}
+
+template<typename T>
+void
+ImplCycleCollectionUnlink(Maybe<T>& field)
+{
+    field = Nothing();
+}
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_INSTANCE_PROVIDER_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/LogEntry.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "LogEntry.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+LogEntry::~LogEntry() = default;
+
+dom::WebGPULogEntryType
+LogEntry::Type() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+LogEntry::GetObj(JSContext* cx, JS::MutableHandleValue out) const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+LogEntry::GetReason(nsString& out) const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(LogEntry)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/LogEntry.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_LogEntry_H_
+#define WEBGPU_LogEntry_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+enum class WebGPULogEntryType : uint8_t;
+} // namespace dom
+namespace webgpu {
+
+class Device;
+
+class LogEntry final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(LogEntry)
+
+private:
+    LogEntry() = delete;
+    virtual ~LogEntry();
+
+public:
+    dom::WebGPULogEntryType Type() const;
+    void GetObj(JSContext* cx, JS::MutableHandleValue out) const;
+    void GetReason(nsString& out) const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_LogEntry_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/ObjectModel.cpp
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ObjectModel.h"
+
+#include "Adapter.h"
+#include "Device.h"
+#include "Instance.h"
+
+namespace mozilla {
+namespace webgpu {
+
+template<typename T>
+ChildOf<T>::ChildOf(T* const parent)
+    : mParent(parent)
+{ }
+
+template<typename T>
+ChildOf<T>::~ChildOf() = default;
+
+template<typename T>
+nsIGlobalObject*
+ChildOf<T>::GetParentObject() const
+{
+    return mParent->GetParentObject();
+}
+
+template class ChildOf<Adapter>;
+template class ChildOf<Device>;
+template class ChildOf<Instance>;
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/ObjectModel.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_OBJECT_MODEL_H_
+#define WEBGPU_OBJECT_MODEL_H_
+
+#include "nsWrapperCache.h"
+
+class nsIGlobalObject;
+
+namespace mozilla {
+namespace webgpu {
+
+template<typename T>
+class ChildOf
+    : public nsWrapperCache
+{
+public:
+    const RefPtr<T> mParent;
+
+    explicit ChildOf(T* parent = nullptr); // TODO: This can't be nullptr eventually.
+protected:
+    virtual ~ChildOf();
+
+public:
+    nsIGlobalObject* GetParentObject() const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#define WEBGPU_DECL_GOOP(T) \
+    NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(T) \
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(T) \
+    virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
+
+#define WEBGPU_IMPL_GOOP_INTERNAL(T) \
+    JSObject* \
+    T::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) \
+    { \
+        return dom::WebGPU ## T ## _Binding::Wrap(cx, this, givenProto); \
+    } \
+    NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(T, AddRef) \
+    NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(T, Release)
+
+#define WEBGPU_IMPL_GOOP(T,...) \
+    WEBGPU_IMPL_GOOP_INTERNAL(T) \
+    NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(T, mParent, __VA_ARGS__)
+
+#define WEBGPU_IMPL_GOOP_0(T) \
+    WEBGPU_IMPL_GOOP_INTERNAL(T) \
+    NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(T, mParent)
+
+template<typename T>
+void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
+                            const RefPtr<T>& field,
+                            const char* name, uint32_t flags)
+{
+    CycleCollectionNoteChild(callback, field.get(), name, flags);
+}
+
+template<typename T>
+void
+ImplCycleCollectionUnlink(const RefPtr<T>& field)
+{
+    const auto mutPtr = const_cast< RefPtr<T>* >(&field);
+    ImplCycleCollectionUnlink(*mutPtr);
+}
+
+#endif // WEBGPU_OBJECT_MODEL_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/PipelineLayout.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "PipelineLayout.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+PipelineLayout::~PipelineLayout() = default;
+
+WEBGPU_IMPL_GOOP_0(PipelineLayout)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/PipelineLayout.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_PipelineLayout_H_
+#define WEBGPU_PipelineLayout_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class PipelineLayout final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(PipelineLayout)
+
+private:
+    PipelineLayout() = delete;
+    virtual ~PipelineLayout();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_PipelineLayout_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Queue.cpp
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Queue.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Queue::~Queue() = default;
+
+void
+Queue::Submit(const dom::Sequence<OwningNonNull<CommandBuffer>>& buffers) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Fence>
+Queue::InsertFence() const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(Queue)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Queue.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_Queue_H_
+#define WEBGPU_Queue_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+template<typename T> class Sequence;
+} // namespace dom
+
+namespace webgpu {
+
+class CommandBuffer;
+class Device;
+class Fence;
+
+class Queue final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(Queue)
+
+private:
+    Queue() = delete;
+    virtual ~Queue();
+
+public:
+    void Submit(const dom::Sequence<OwningNonNull<CommandBuffer>>& buffers) const;
+    already_AddRefed<Fence> InsertFence() const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_Queue_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/RenderPipeline.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RenderPipeline.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+RenderPipeline::~RenderPipeline() = default;
+
+WEBGPU_IMPL_GOOP_0(RenderPipeline)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/RenderPipeline.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_RenderPipeline_H_
+#define WEBGPU_RenderPipeline_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class RenderPipeline final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(RenderPipeline)
+
+private:
+    RenderPipeline() = delete;
+    virtual ~RenderPipeline();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_RenderPipeline_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Sampler.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Sampler.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Sampler::~Sampler() = default;
+
+WEBGPU_IMPL_GOOP_0(Sampler)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Sampler.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_SAMPLER_H_
+#define WEBGPU_SAMPLER_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class Sampler final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(Sampler)
+
+private:
+    Sampler() = delete;
+    virtual ~Sampler();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_SAMPLER_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/ShaderModule.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ShaderModule.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+ShaderModule::~ShaderModule() = default;
+
+WEBGPU_IMPL_GOOP_0(ShaderModule)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/ShaderModule.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_ShaderModule_H_
+#define WEBGPU_ShaderModule_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class ShaderModule final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(ShaderModule)
+
+private:
+    ShaderModule() = delete;
+    virtual ~ShaderModule();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_ShaderModule_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/SwapChain.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SwapChain.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+SwapChain::~SwapChain() = default;
+
+void
+SwapChain::Configure(const dom::WebGPUSwapChainDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+already_AddRefed<Texture>
+SwapChain::GetNextTexture() const
+{
+    MOZ_CRASH("todo");
+}
+
+void
+SwapChain::Present() const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(SwapChain)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/SwapChain.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_SwapChain_H_
+#define WEBGPU_SwapChain_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+struct WebGPUSwapChainDescriptor;
+} // namespace dom
+
+namespace webgpu {
+
+class Device;
+class Texture;
+
+class SwapChain final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(SwapChain)
+
+private:
+    SwapChain() = delete;
+    virtual ~SwapChain();
+
+public:
+    void Configure(const dom::WebGPUSwapChainDescriptor& desc) const;
+    already_AddRefed<Texture> GetNextTexture() const;
+    void Present() const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_SwapChain_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Texture.cpp
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Texture.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+#include "TextureView.h"
+
+namespace mozilla {
+namespace webgpu {
+
+Texture::~Texture() = default;
+
+already_AddRefed<TextureView>
+Texture::CreateTextureView(const dom::WebGPUTextureViewDescriptor& desc) const
+{
+    MOZ_CRASH("todo");
+}
+
+WEBGPU_IMPL_GOOP_0(Texture)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/Texture.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_Texture_H_
+#define WEBGPU_Texture_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace dom {
+struct WebGPUTextureViewDescriptor;
+} // namespace dom
+
+namespace webgpu {
+
+class Device;
+class TextureView;
+
+class Texture final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(Texture)
+
+private:
+    Texture() = delete;
+    virtual ~Texture();
+
+public:
+    already_AddRefed<TextureView> CreateTextureView(const dom::WebGPUTextureViewDescriptor&) const;
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_Texture_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/TextureView.cpp
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TextureView.h"
+
+#include "Device.h"
+#include "mozilla/dom/WebGPUBinding.h"
+
+namespace mozilla {
+namespace webgpu {
+
+TextureView::~TextureView() = default;
+
+WEBGPU_IMPL_GOOP_0(TextureView)
+
+} // namespace webgpu
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/TextureView.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef WEBGPU_TEXTURE_VIEW_H_
+#define WEBGPU_TEXTURE_VIEW_H_
+
+#include "nsWrapperCache.h"
+#include "ObjectModel.h"
+
+namespace mozilla {
+namespace webgpu {
+
+class Device;
+
+class TextureView final
+    : public ChildOf<Device>
+{
+public:
+    WEBGPU_DECL_GOOP(TextureView)
+
+private:
+    TextureView() = delete;
+    virtual ~TextureView();
+};
+
+} // namespace webgpu
+} // namespace mozilla
+
+#endif // WEBGPU_TEXTURE_VIEW_H_
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/mochitest/mochitest-no-pref.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+subsuite = webgl1-core
+
+[test_disabled.html]
+
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/mochitest/mochitest.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+subsuite = webgl1-core
+prefs = dom.webgpu.enable=true
+
+[test_enabled.html]
+
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/mochitest/test_disabled.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset='utf-8'>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<script>
+
+ok(!SpecialPowers.getBoolPref('dom.webgpu.enable'), 'Pref should be disabled.');
+ok(window.WebGPU === undefined, 'window.WebGPU === undefined');
+ok(window.webgpu === undefined, 'window.webgpu === undefined');
+
+</script>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/mochitest/test_enabled.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset='utf-8'>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<script>
+
+ok(SpecialPowers.getBoolPref('dom.webgpu.enable'), 'Pref should be enabled.');
+ok(window.WebGPU !== undefined, 'window.WebGPU !== undefined');
+ok(window.webgpu !== undefined, 'window.webgpu !== undefined');
+
+</script>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/webgpu/moz.build
@@ -0,0 +1,49 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Canvas: WebGL')
+
+MOCHITEST_MANIFESTS += [
+    'mochitest/mochitest-no-pref.ini',
+    'mochitest/mochitest.ini',
+]
+
+h_and_cpp = [
+    'Adapter',
+    'AttachmentState',
+    'BindGroup',
+    'BindGroupLayout',
+    'BlendState',
+    'Buffer',
+    'CommandBuffer',
+    'CommandEncoder',
+    'ComputePipeline',
+    'DepthStencilState',
+    'Device',
+    'Fence',
+    'InputState',
+    'Instance',
+    'InstanceProvider',
+    'LogEntry',
+    'ObjectModel',
+    'PipelineLayout',
+    'Queue',
+    'RenderPipeline',
+    'Sampler',
+    'ShaderModule',
+    'SwapChain',
+    'Texture',
+    'TextureView',
+]
+EXPORTS.mozilla.webgpu += [x + '.h' for x in h_and_cpp]
+UNIFIED_SOURCES += [x + '.cpp' for x in h_and_cpp]
+
+EXPORTS.mozilla.webgpu += [
+#    'ObjectModel.h',
+]
+
+FINAL_LIBRARY = 'xul'
new file mode 100644
--- /dev/null
+++ b/dom/webidl/WebGPU.webidl
@@ -0,0 +1,639 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl
+ */
+
+typedef unsigned long u32;
+typedef unsigned long long u64;
+
+// ****************************************************************************
+// ERROR HANDLING
+// ****************************************************************************
+
+enum WebGPULogEntryType {
+    "device-lost",
+    "validation-error",
+    "recoverable-out-of-memory",
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPULogEntry {
+    readonly attribute WebGPULogEntryType type;
+    readonly attribute any obj;
+    readonly attribute DOMString? reason;
+};
+
+enum WebGPUObjectStatus {
+    "valid",
+    "out-of-memory",
+    "invalid",
+};
+
+typedef (WebGPUBuffer or WebGPUTexture) WebGPUStatusable;
+
+callback WebGPULogCallback = void (WebGPULogEntry error);
+
+// ****************************************************************************
+// SHADER RESOURCES (buffer, textures, texture views, samples)
+// ****************************************************************************
+
+// Buffer
+typedef u32 WebGPUBufferUsageFlags;
+[Pref="dom.webgpu.enable"]
+interface WebGPUBufferUsage {
+    const u32 NONE = 0;
+    const u32 MAP_READ = 1;
+    const u32 MAP_WRITE = 2;
+    const u32 TRANSFER_SRC = 4;
+    const u32 TRANSFER_DST = 8;
+    const u32 INDEX = 16;
+    const u32 VERTEX = 32;
+    const u32 UNIFORM = 64;
+    const u32 STORAGE = 128;
+};
+
+dictionary WebGPUBufferDescriptor {
+    u32 size;
+    WebGPUBufferUsageFlags usage;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUBuffer {
+    readonly attribute ArrayBuffer? mapping;
+    void unmap();
+};
+
+// Texture view
+dictionary WebGPUTextureViewDescriptor {
+    // TODO Investigate what goes in there.
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUTextureView {
+};
+
+// Texture
+typedef u32 WebGPUTextureDimensionEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUTextureDimension {
+    const u32 e1D = 0;
+    const u32 e2D = 1;
+    const u32 e3D = 2;
+    // TODO other dimensions (cube, arrays)
+};
+
+typedef u32 WebGPUTextureFormatEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUTextureFormat {
+    const u32 R8_G8_B8_A8_UNORM = 0;
+    const u32 R8_G8_B8_A8_UINT = 1;
+    const u32 B8_G8_R8_A8_UNORM = 2;
+    const u32 D32_FLOAT_S8_UINT = 3;
+    // TODO other formats
+};
+
+typedef u32 WebGPUTextureUsageFlags;
+[Pref="dom.webgpu.enable"]
+interface WebGPUTextureUsage {
+    const u32 NONE = 0;
+    const u32 TRANSFER_SRC = 1;
+    const u32 TRANSFER_DST = 2;
+    const u32 SAMPLED = 4;
+    const u32 STORAGE = 8;
+    const u32 OUTPUT_ATTACHMENT = 16;
+    const u32 PRESENT = 32;
+};
+
+dictionary WebGPUTextureDescriptor {
+    u32 width;
+    u32 height;
+    u32 depth;
+    u32 arraySize;
+    WebGPUTextureDimensionEnum dimension;
+    WebGPUTextureFormatEnum format;
+    WebGPUTextureUsageFlags usage;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUTexture {
+    WebGPUTextureView createTextureView(optional WebGPUTextureViewDescriptor desc);
+};
+
+// Sampler
+typedef u32 WebGPUFilterModeEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUFilterMode {
+    const u32 NEAREST = 0;
+    const u32 LINEAR = 1;
+};
+
+dictionary WebGPUSamplerDescriptor {
+    WebGPUFilterModeEnum magFilter;
+    WebGPUFilterModeEnum minFilter;
+    WebGPUFilterModeEnum mipmapFilter;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUSampler {
+};
+
+// ****************************************************************************
+// BINDING MODEL (bindgroup layout, bindgroup)
+// ****************************************************************************
+
+// BindGroupLayout
+typedef u32 WebGPUShaderStageFlags;
+[Pref="dom.webgpu.enable"]
+interface WebGPUShaderStageBit {
+    const u32 NONE = 0;
+    const u32 VERTEX = 1;
+    const u32 FRAGMENT = 2;
+    const u32 COMPUTE = 4;
+};
+
+typedef u32 WebGPUBindingTypeEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUBindingType {
+    const u32 UNIFORM_BUFFER = 0;
+    const u32 SAMPLER = 1;
+    const u32 SAMPLED_TEXTURE = 2;
+    const u32 STORAGE_BUFFER = 3;
+    // TODO other binding types (storage images, ...)
+};
+
+dictionary WebGPUBindGroupBinding {
+    WebGPUShaderStageFlags visibility;
+    WebGPUBindingTypeEnum type;
+    u32 start;
+    u32 count;
+};
+
+dictionary WebGPUBindGroupLayoutDescriptor {
+    sequence<WebGPUBindGroupBinding> bindingTypes;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUBindGroupLayout {
+};
+
+// PipelineLayout
+dictionary WebGPUPipelineLayoutDescriptor {
+    sequence<WebGPUBindGroupLayout> bindGroupLayouts;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUPipelineLayout {
+};
+
+// BindGroup
+/* Moved to WebGPUExtras.webidl for now.
+dictionary WebGPUBufferBinding {
+    WebGPUBuffer buffer;
+    u32 offset;
+    u32 size;
+};
+*/
+
+typedef (WebGPUSampler or WebGPUTextureView or WebGPUBufferBinding) WebGPUBindingResource;
+
+dictionary WebGPUBinding {
+    sequence<WebGPUBindingResource> resources;
+    u32 start;
+    u32 count;
+};
+
+dictionary WebGPUBindGroupDescriptor {
+    WebGPUBindGroupLayout layout;
+    sequence<WebGPUBinding> bindings;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUBindGroup {
+};
+
+// ****************************************************************************
+// PIPELINE CREATION (blend state, DS state, ..., pipelines)
+// ****************************************************************************
+
+// BlendState
+typedef u32 WebGPUBlendFactorEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUBlendFactor {
+    const u32 ZERO = 0;
+    const u32 ONE = 1;
+    const u32 SRC_COLOR = 2;
+    const u32 ONE_MINUS_SRC_COLOR = 3;
+    const u32 SRC_ALPHA = 4;
+    const u32 ONE_MINUS_SRC_ALPHA = 5;
+    const u32 DST_COLOR = 6;
+    const u32 ONE_MINUS_DST_COLOR = 7;
+    const u32 DST_ALPHA = 8;
+    const u32 ONE_MINUS_DST_ALPHA = 9;
+    const u32 SRC_ALPHA_SATURATED = 10;
+    const u32 BLEND_COLOR = 11;
+    const u32 ONE_MINUS_BLEND_COLOR = 12;
+};
+
+typedef u32 WebGPUBlendOperationEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUBlendOperation {
+    const u32 ADD = 0;
+    const u32 SUBTRACT = 1;
+    const u32 REVERSE_SUBTRACT = 2;
+    const u32 MIN = 3;
+    const u32 MAX = 4;
+};
+
+typedef u32 WebGPUColorWriteFlags;
+[Pref="dom.webgpu.enable"]
+interface WebGPUColorWriteBits {
+    const u32 NONE = 0;
+    const u32 RED = 1;
+    const u32 GREEN = 2;
+    const u32 BLUE = 4;
+    const u32 ALPHA = 8;
+    const u32 ALL = 15;
+};
+
+dictionary WebGPUBlendDescriptor {
+    WebGPUBlendFactorEnum srcFactor;
+    WebGPUBlendFactorEnum dstFactor;
+    WebGPUBlendOperationEnum operation;
+};
+
+dictionary WebGPUBlendStateDescriptor {
+    boolean blendEnabled;
+    WebGPUBlendDescriptor alpha;
+    WebGPUBlendDescriptor color;
+    WebGPUColorWriteFlags writeMask;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUBlendState {
+};
+
+// DepthStencilState
+typedef u32 WebGPUCompareFunctionEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUCompareFunction {
+    const u32 NEVER = 0;
+    const u32 LESS = 1;
+    const u32 LESS_EQUAL = 2;
+    const u32 GREATER = 3;
+    const u32 GREATER_EQUAL = 4;
+    const u32 EQUAL = 5;
+    const u32 NOT_EQUAL = 6;
+    const u32 ALWAYS = 7;
+};
+
+typedef u32 WebGPUStencilOperationEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUStencilOperation {
+    const u32 KEEP = 0;
+    const u32 ZERO = 1;
+    const u32 REPLACE = 2;
+    const u32 INVERT = 3;
+    const u32 INCREMENT_CLAMP = 4;
+    const u32 DECREMENT_CLAMP = 5;
+    const u32 INCREMENT_WRAP = 6;
+    const u32 DECREMENT_WRAP = 7;
+};
+
+dictionary WebGPUStencilStateFaceDescriptor {
+    WebGPUCompareFunctionEnum compare;
+    WebGPUStencilOperationEnum stencilFailOp;
+    WebGPUStencilOperationEnum depthFailOp;
+    WebGPUStencilOperationEnum passOp;
+};
+
+dictionary WebGPUDepthStencilStateDescriptor {
+    boolean depthWriteEnabled;
+    WebGPUCompareFunctionEnum depthCompare;
+
+    WebGPUStencilStateFaceDescriptor front;
+    WebGPUStencilStateFaceDescriptor back;
+
+    u32 stencilReadMask;
+    u32 stencilWriteMask;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUDepthStencilState {
+};
+
+// InputState
+typedef u32 WebGPUIndexFormatEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUIndexFormat {
+    const u32 UINT16 = 0;
+    const u32 UINT32 = 1;
+};
+
+typedef u32 WebGPUVertexFormatEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUVertexFormat {
+    const u32 FLOAT_R32_G32_B32_A32 = 0;
+    const u32 FLOAT_R32_G32_B32 = 1;
+    const u32 FLOAT_R32_G32 = 2;
+    const u32 FLOAT_R32 = 3;
+    // TODO other vertex formats
+};
+
+typedef u32 WebGPUInputStepModeEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUInputStepMode {
+    const u32 VERTEX = 0;
+    const u32 INSTANCE = 1;
+};
+
+dictionary WebGPUVertexAttributeDescriptor {
+    u32 shaderLocation;
+    u32 inputSlot;
+    u32 offset;
+    WebGPUVertexFormatEnum format;
+};
+
+dictionary WebGPUVertexInputDescriptor {
+    u32 inputSlot;
+    u32 stride;
+    WebGPUInputStepModeEnum stepMode;
+};
+
+dictionary WebGPUInputStateDescriptor {
+    WebGPUIndexFormatEnum indexFormat;
+
+    sequence<WebGPUVertexAttributeDescriptor> attributes;
+    sequence<WebGPUVertexInputDescriptor> inputs;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUInputState {
+};
+
+// ShaderModule
+dictionary WebGPUShaderModuleDescriptor {
+    required ArrayBuffer code;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUShaderModule {
+};
+
+// AttachmentState
+dictionary WebGPUAttachmentStateDescriptor {
+    sequence<WebGPUTextureFormatEnum> formats;
+    // TODO other stuff like sample count etc.
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUAttachmentState {
+};
+
+// Common stuff for ComputePipeline and RenderPipeline
+typedef u32 WebGPUShaderStageEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUShaderStage {
+    const u32 VERTEX = 0;
+    const u32 FRAGMENT = 1;
+    const u32 COMPUTE = 2;
+};
+
+dictionary WebGPUPipelineStageDescriptor {
+    required WebGPUShaderModule shaderModule;
+    required WebGPUShaderStageEnum stage;
+    required DOMString entryPoint;
+    // TODO other stuff like specialization constants?
+};
+
+dictionary WebGPUPipelineDescriptorBase {
+    required WebGPUPipelineLayout layout;
+    sequence<WebGPUPipelineStageDescriptor> stages;
+};
+
+// ComputePipeline
+dictionary WebGPUComputePipelineDescriptor : WebGPUPipelineDescriptorBase {
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUComputePipeline {
+};
+
+// WebGPURenderPipeline
+typedef u32 WebGPUPrimitiveTopologyEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUPrimitiveTopology {
+    const u32 POINT_LIST = 0;
+    const u32 LINE_LIST = 1;
+    const u32 LINE_STRIP = 2;
+    const u32 TRIANGLE_LIST = 3;
+    const u32 TRIANGLE_STRIP = 4;
+};
+
+dictionary WebGPURenderPipelineDescriptor : WebGPUPipelineDescriptorBase {
+    WebGPUPrimitiveTopologyEnum primitiveTopology;
+    sequence<WebGPUBlendState> blendState;
+    WebGPUDepthStencilState depthStencilState;
+    WebGPUInputState inputState;
+    WebGPUAttachmentState attachmentState;
+    // TODO other properties
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPURenderPipeline {
+};
+// ****************************************************************************
+// COMMAND RECORDING (Command buffer and all relevant structures)
+// ****************************************************************************
+
+typedef u32 WebGPULoadOpEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPULoadOp {
+    const u32 CLEAR = 0;
+    const u32 LOAD = 1;
+};
+
+typedef u32 WebGPUStoreOpEnum;
+[Pref="dom.webgpu.enable"]
+interface WebGPUStoreOp {
+    const u32 STORE = 0;
+};
+
+dictionary WebGPURenderPassAttachmentDescriptor {
+    WebGPUTextureView attachment;
+    WebGPULoadOpEnum loadOp;
+    WebGPUStoreOpEnum storeOp;
+};
+
+dictionary WebGPURenderPassDescriptor {
+    sequence<WebGPURenderPassAttachmentDescriptor> colorAttachments;
+    WebGPURenderPassAttachmentDescriptor depthStencilAttachment;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUCommandBuffer {
+};
+
+dictionary WebGPUCommandEncoderDescriptor {
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUCommandEncoder {
+    WebGPUCommandBuffer finishEncoding();
+
+    // Commands allowed outside of "passes"
+    void copyBufferToBuffer(WebGPUBuffer src,
+                            u32 srcOffset,
+                            WebGPUBuffer dst,
+                            u32 dstOffset,
+                            u32 size);
+    // TODO figure out all the arguments required for these
+    void copyBufferToTexture();
+    void copyTextureToBuffer();
+    void copyTextureToTexture();
+    void blit();
+
+    void transitionBuffer(WebGPUBuffer b, WebGPUBufferUsageFlags f);
+
+    // Allowed in both compute and render passes
+    void setPushConstants(WebGPUShaderStageFlags stage,
+                          u32 offset,
+                          u32 count,
+                          ArrayBuffer data);
+    void setBindGroup(u32 index, WebGPUBindGroup bindGroup);
+    void setPipeline((WebGPUComputePipeline or WebGPURenderPipeline) pipeline);
+
+    // Compute pass commands
+    void beginComputePass();
+    void endComputePass();
+
+    void dispatch(u32 x, u32 y, u32 z);
+
+    // Render pass commands
+    void beginRenderPass(optional WebGPURenderPassDescriptor descriptor);
+    void endRenderPass();
+
+    void setBlendColor(float r, float g, float b, float a);
+    void setIndexBuffer(WebGPUBuffer buffer, u32 offset);
+    void setVertexBuffers(u32 startSlot, sequence<WebGPUBuffer> buffers, sequence<u32> offsets);
+
+    void draw(u32 vertexCount, u32 instanceCount, u32 firstVertex, u32 firstInstance);
+    void drawIndexed(u32 indexCount, u32 instanceCount, u32 firstIndex, u32 firstInstance, u32 firstVertex);
+
+    // TODO add missing commands
+};
+
+// ****************************************************************************
+// OTHER (Fence, Queue SwapChain, Device)
+// ****************************************************************************
+
+// Fence
+[Pref="dom.webgpu.enable"]
+interface WebGPUFence {
+    boolean wait(double milliseconds);
+    readonly attribute Promise<void> promise;
+};
+
+// Queue
+[Pref="dom.webgpu.enable"]
+interface WebGPUQueue {
+    void submit(sequence<WebGPUCommandBuffer> buffers);
+    WebGPUFence insertFence();
+};
+
+// SwapChain / RenderingContext
+dictionary WebGPUSwapChainDescriptor {
+    WebGPUTextureUsageFlags usage;
+    WebGPUTextureFormatEnum format;
+    u32 width;
+    u32 height;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUSwapChain {
+    void configure(optional WebGPUSwapChainDescriptor descriptor);
+    WebGPUTexture getNextTexture();
+    void present();
+};
+
+//[Pref="dom.webgpu.enable"]
+//interface WebGPURenderingContext : WebGPUSwapChain {
+//};
+
+// WebGPU "namespace" used for device creation
+dictionary WebGPUExtensions {
+    boolean anisotropicFiltering;
+    boolean logicOp; // Previously a "Feature".
+};
+
+dictionary WebGPULimits {
+    u32 maxBindGroups;
+};
+
+// Device
+[Pref="dom.webgpu.enable"]
+interface WebGPUDevice {
+    readonly attribute WebGPUAdapter adapter;
+    WebGPUExtensions extensions();
+    WebGPULimits limits();
+
+    WebGPUBuffer createBuffer(optional WebGPUBufferDescriptor descriptor);
+    WebGPUTexture createTexture(optional WebGPUTextureDescriptor descriptor);
+    WebGPUSampler createSampler(optional WebGPUSamplerDescriptor descriptor);
+
+    WebGPUBindGroupLayout createBindGroupLayout(optional WebGPUBindGroupLayoutDescriptor descriptor);
+    WebGPUPipelineLayout createPipelineLayout(optional WebGPUPipelineLayoutDescriptor descriptor);
+    WebGPUBindGroup createBindGroup(optional WebGPUBindGroupDescriptor descriptor);
+
+    WebGPUBlendState createBlendState(optional WebGPUBlendStateDescriptor descriptor);
+    WebGPUDepthStencilState createDepthStencilState(optional WebGPUDepthStencilStateDescriptor descriptor);
+    WebGPUInputState createInputState(optional WebGPUInputStateDescriptor descriptor);
+    WebGPUShaderModule createShaderModule(WebGPUShaderModuleDescriptor descriptor);
+    WebGPUAttachmentState createAttachmentState(optional WebGPUAttachmentStateDescriptor descriptor);
+    WebGPUComputePipeline createComputePipeline(WebGPUComputePipelineDescriptor descriptor);
+    WebGPURenderPipeline createRenderPipeline(WebGPURenderPipelineDescriptor descriptor);
+
+    WebGPUCommandEncoder createCommandEncoder(optional WebGPUCommandEncoderDescriptor descriptor);
+
+    WebGPUQueue getQueue();
+
+    attribute WebGPULogCallback onLog;
+    Promise<WebGPUObjectStatus> getObjectStatus(WebGPUStatusable obj);
+};
+
+dictionary WebGPUDeviceDescriptor {
+    WebGPUExtensions extensions;
+    //WebGPULimits limits; Don't expose higher limits for now.
+
+    // TODO are other things configurable like queues?
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPUAdapter {
+    readonly attribute DOMString name;
+    WebGPUExtensions extensions();
+    //WebGPULimits limits(); Don't expose higher limits for now.
+
+    WebGPUDevice createDevice(optional WebGPUDeviceDescriptor descriptor);
+};
+
+enum WebGPUPowerPreference { "default", "low-power", "high-performance" };
+
+dictionary WebGPUAdapterDescriptor {
+    WebGPUPowerPreference powerPreference;
+};
+
+[Pref="dom.webgpu.enable"]
+interface WebGPU {
+    WebGPUAdapter getAdapter(optional WebGPUAdapterDescriptor desc);
+};
+
+// Add a "webgpu" member to Window that contains the global instance of a "WebGPU"
+[NoInterfaceObject]
+interface WebGPUProvider {
+    [SameObject, Replaceable, Pref="dom.webgpu.enable"] readonly attribute WebGPU webgpu;
+};
+//Window includes WebGPUProvider;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/WebGPUExtras.webidl
@@ -0,0 +1,14 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Some parts of WebGPU.webidl need to be pulled into a different file due to a codegen
+ * bug/missing support.
+ */
+
+dictionary WebGPUBufferBinding {
+    WebGPUBuffer buffer;
+    u32 offset;
+    u32 size;
+};
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -558,8 +558,10 @@ partial interface Window {
 
   /**
    * Getter funcion for IntlUtils, which provides helper functions for
    * localization.
    */
   [Throws, Func="IsChromeOrXBL"]
   readonly attribute IntlUtils intlUtils;
 };
+
+Window implements WebGPUProvider;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -323,16 +323,19 @@ with Files("WaveShaperNode.webidl"):
     BUG_COMPONENT = ("Core", "Web Audio")
 
 with Files("WebAuthentication.webidl"):
     BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
 
 with Files("WebGL*"):
     BUG_COMPONENT = ("Core", "Canvas: WebGL")
 
+with Files("WebGPU*"):
+    BUG_COMPONENT = ("Core", "Canvas: WebGL")
+
 with Files("WebKitCSSMatrix.webidl"):
     BUG_COMPONENT = ("Core", "DOM: CSS Object Model")
 
 with Files("Webrtc*"):
     BUG_COMPONENT = ("Core", "WebRTC")
 
 with Files("WheelEvent.webidl"):
     BUG_COMPONENT = ("Core", "DOM: Events")
@@ -917,16 +920,18 @@ WEBIDL_FILES = [
     'VRServiceTest.webidl',
     'VTTCue.webidl',
     'VTTRegion.webidl',
     'WaveShaperNode.webidl',
     'WebAuthentication.webidl',
     'WebComponents.webidl',
     'WebGL2RenderingContext.webidl',
     'WebGLRenderingContext.webidl',
+    'WebGPU.webidl',
+    'WebGPUExtras.webidl',
     'WebKitCSSMatrix.webidl',
     'WebSocket.webidl',
     'WheelEvent.webidl',
     'WidevineCDMManifest.webidl',
     'WindowOrWorkerGlobalScope.webidl',
     'WindowRoot.webidl',
     'Worker.webidl',
     'WorkerDebuggerGlobalScope.webidl',
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4711,16 +4711,18 @@ pref("webgl.vendor-string-override", "")
 #ifdef XP_WIN
 pref("webgl.angle.try-d3d11", true);
 pref("webgl.angle.force-d3d11", false);
 pref("webgl.angle.force-warp", false);
 pref("webgl.dxgl.enabled", true);
 pref("webgl.dxgl.needs-finish", false);
 #endif
 
+pref("dom.webgpu.enable", false);
+
 pref("gfx.offscreencanvas.enabled", false);
 
 // sendbuffer of 0 means use OS default, sendbuffer unset means use
 // gecko default which varies depending on windows version and is OS
 // default on non windows
 // pref("network.tcp.sendbuffer", 0);
 
 // TCP Keepalive