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 482657 3d7f2fdc5bf7ca7521013b28e0d8be0785d2b58a
parent 482656 d6b45def3335f3ad5eeed9c856bdd28d17d3b33c
child 482716 cc3401e78e8bbae22e6dbc854e525ceae4923bcf
child 482720 7efe662a874d20c9b7747c55f15900dc5da8545e
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark, qdot
bugs1469376
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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