Revert "Adds destroy handling for simple objects without new backend changes yet."

This reverts commit 9901c710d1f834fd3e98356f0842553e1ac4afb2.

Reason for revert: Breaking dawn roll due to include in ShaderMock

Original change's description:
> Adds destroy handling for simple objects without new backend changes yet.
>
> Simple objects are defined here as objects that do not already have a destroy or destroy-like API available. They include:
> - BindGroups
> - ComputePipelines
> - PipelineLayouts
> - RenderPipelines
> - Samplers
> - ShaderModules
> - SwapChains
>
> Changes include:
> - Adds necessary constructors for testing and caching
> - Adding mock objects, mock constructors, and tests
>
> Bug: dawn:628
> Change-Id: I26a5e37bc5580b9064db299a75ef1243521b266a
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/65864
> Commit-Queue: Loko Kung <lokokung@google.com>
> Reviewed-by: Austin Eng <enga@chromium.org>

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: dawn:628
Change-Id: Ic727106f3dc701dc25418adf9824fbc5397aa656
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/67960
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn_native/BindGroup.cpp b/src/dawn_native/BindGroup.cpp
index 874c369..361ca82 100644
--- a/src/dawn_native/BindGroup.cpp
+++ b/src/dawn_native/BindGroup.cpp
@@ -391,12 +391,6 @@
                 ++packedIdx;
             }
         }
-
-        TrackInDevice();
-    }
-
-    BindGroupBase::BindGroupBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
-        TrackInDevice();
     }
 
     BindGroupBase::~BindGroupBase() {
@@ -413,7 +407,7 @@
         // is destroyed after the bind group. The bind group is slab-allocated inside
         // memory owned by the layout (except for the null backend).
         Ref<BindGroupLayoutBase> layout = mLayout;
-        ApiObjectBase::DeleteThis();
+        RefCounted::DeleteThis();
     }
 
     BindGroupBase::BindGroupBase(DeviceBase* device, ObjectBase::ErrorTag tag)
diff --git a/src/dawn_native/BindGroup.h b/src/dawn_native/BindGroup.h
index 6792d61..1ce4b9f 100644
--- a/src/dawn_native/BindGroup.h
+++ b/src/dawn_native/BindGroup.h
@@ -73,9 +73,7 @@
             static_assert(std::is_base_of<BindGroupBase, Derived>::value, "");
         }
 
-        // Constructor used only for mocking and testing.
-        BindGroupBase(DeviceBase* device);
-
+      protected:
         ~BindGroupBase() override;
 
       private:
diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp
index aea7c40..c0097cc 100644
--- a/src/dawn_native/BindGroupLayout.cpp
+++ b/src/dawn_native/BindGroupLayout.cpp
@@ -416,13 +416,13 @@
         TrackInDevice();
     }
 
-    BindGroupLayoutBase::~BindGroupLayoutBase() = default;
-
     bool BindGroupLayoutBase::DestroyApiObject() {
         bool wasDestroyed = ApiObjectBase::DestroyApiObject();
-        if (wasDestroyed && IsCachedReference()) {
-            // Do not uncache the actual cached object if we are a blueprint or already destroyed.
-            GetDevice()->UncacheBindGroupLayout(this);
+        if (wasDestroyed) {
+            // Do not uncache the actual cached object if we are a blueprint
+            if (IsCachedReference()) {
+                GetDevice()->UncacheBindGroupLayout(this);
+            }
         }
         return wasDestroyed;
     }
diff --git a/src/dawn_native/BindGroupLayout.h b/src/dawn_native/BindGroupLayout.h
index 1c2c4e3..61b811f 100644
--- a/src/dawn_native/BindGroupLayout.h
+++ b/src/dawn_native/BindGroupLayout.h
@@ -49,7 +49,6 @@
         BindGroupLayoutBase(DeviceBase* device,
                             const BindGroupLayoutDescriptor* descriptor,
                             PipelineCompatibilityToken pipelineCompatibilityToken);
-        ~BindGroupLayoutBase() override;
 
         static BindGroupLayoutBase* MakeError(DeviceBase* device);
 
diff --git a/src/dawn_native/ComputePipeline.cpp b/src/dawn_native/ComputePipeline.cpp
index 9eca55c..72addc4 100644
--- a/src/dawn_native/ComputePipeline.cpp
+++ b/src/dawn_native/ComputePipeline.cpp
@@ -47,26 +47,17 @@
                          descriptor->compute.entryPoint, descriptor->compute.constantCount,
                          descriptor->compute.constants}}) {
         SetContentHash(ComputeContentHash());
-        TrackInDevice();
-    }
-
-    ComputePipelineBase::ComputePipelineBase(DeviceBase* device) : PipelineBase(device) {
-        TrackInDevice();
     }
 
     ComputePipelineBase::ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : PipelineBase(device, tag) {
     }
 
-    ComputePipelineBase::~ComputePipelineBase() = default;
-
-    bool ComputePipelineBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
-        if (wasDestroyed && IsCachedReference()) {
-            // Do not uncache the actual cached object if we are a blueprint or already destroyed.
+    ComputePipelineBase::~ComputePipelineBase() {
+        // Do not uncache the actual cached object if we are a blueprint
+        if (IsCachedReference()) {
             GetDevice()->UncacheComputePipeline(this);
         }
-        return wasDestroyed;
     }
 
     // static
diff --git a/src/dawn_native/ComputePipeline.h b/src/dawn_native/ComputePipeline.h
index 1872923..6352c19 100644
--- a/src/dawn_native/ComputePipeline.h
+++ b/src/dawn_native/ComputePipeline.h
@@ -34,7 +34,6 @@
 
         static ComputePipelineBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
         ObjectType GetType() const override;
 
         // Functors necessary for the unordered_set<ComputePipelineBase*>-based cache.
@@ -42,10 +41,6 @@
             bool operator()(const ComputePipelineBase* a, const ComputePipelineBase* b) const;
         };
 
-      protected:
-        // Constructor used only for mocking and testing.
-        ComputePipelineBase(DeviceBase* device);
-
       private:
         ComputePipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
     };
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index cf33c02..4ba8749 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -37,7 +37,6 @@
 #include "dawn_native/QuerySet.h"
 #include "dawn_native/Queue.h"
 #include "dawn_native/RenderBundleEncoder.h"
-#include "dawn_native/RenderPipeline.h"
 #include "dawn_native/Sampler.h"
 #include "dawn_native/Surface.h"
 #include "dawn_native/SwapChain.h"
@@ -266,19 +265,9 @@
         // that this only considers the immediate frontend dependencies, while backend objects could
         // add complications and extra dependencies.
         // TODO(dawn/628) Add types into the array as they are implemented.
-
-        // clang-format off
-        static constexpr std::array<ObjectType, 8> kObjectTypeDependencyOrder = {
-            ObjectType::RenderPipeline,
-            ObjectType::ComputePipeline,
-            ObjectType::PipelineLayout,
-            ObjectType::SwapChain,
-            ObjectType::BindGroup,
+        static constexpr std::array<ObjectType, 1> kObjectTypeDependencyOrder = {
             ObjectType::BindGroupLayout,
-            ObjectType::ShaderModule,
-            ObjectType::Sampler,
         };
-        // clang-format on
 
         // We first move all objects out from the tracking list into a separate list so that we can
         // avoid locking the same mutex twice. We can then iterate across the separate list to call
@@ -725,7 +714,7 @@
 
     ResultOrError<Ref<PipelineLayoutBase>> DeviceBase::GetOrCreatePipelineLayout(
         const PipelineLayoutDescriptor* descriptor) {
-        PipelineLayoutBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
+        PipelineLayoutBase blueprint(this, descriptor);
 
         const size_t blueprintHash = blueprint.ComputeContentHash();
         blueprint.SetContentHash(blueprintHash);
@@ -758,7 +747,7 @@
 
     ResultOrError<Ref<SamplerBase>> DeviceBase::GetOrCreateSampler(
         const SamplerDescriptor* descriptor) {
-        SamplerBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
+        SamplerBase blueprint(this, descriptor);
 
         const size_t blueprintHash = blueprint.ComputeContentHash();
         blueprint.SetContentHash(blueprintHash);
@@ -789,7 +778,7 @@
         OwnedCompilationMessages* compilationMessages) {
         ASSERT(parseResult != nullptr);
 
-        ShaderModuleBase blueprint(this, descriptor, ApiObjectBase::kUntrackedByDevice);
+        ShaderModuleBase blueprint(this, descriptor);
 
         const size_t blueprintHash = blueprint.ComputeContentHash();
         blueprint.SetContentHash(blueprintHash);
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 6d01302..7852c6a 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -24,6 +24,7 @@
 #include "dawn_native/Limits.h"
 #include "dawn_native/ObjectBase.h"
 #include "dawn_native/ObjectType_autogen.h"
+#include "dawn_native/RenderPipeline.h"
 #include "dawn_native/StagingBuffer.h"
 #include "dawn_native/Toggles.h"
 
diff --git a/src/dawn_native/ObjectBase.h b/src/dawn_native/ObjectBase.h
index 291e806..d05a56e 100644
--- a/src/dawn_native/ObjectBase.h
+++ b/src/dawn_native/ObjectBase.h
@@ -51,7 +51,7 @@
         ApiObjectBase(DeviceBase* device, LabelNotImplementedTag tag);
         ApiObjectBase(DeviceBase* device, const char* label);
         ApiObjectBase(DeviceBase* device, ErrorTag tag);
-        ~ApiObjectBase() override;
+        virtual ~ApiObjectBase() override;
 
         virtual ObjectType GetType() const = 0;
         const std::string& GetLabel() const;
diff --git a/src/dawn_native/Pipeline.cpp b/src/dawn_native/Pipeline.cpp
index bb846fd..ab232c3 100644
--- a/src/dawn_native/Pipeline.cpp
+++ b/src/dawn_native/Pipeline.cpp
@@ -142,15 +142,10 @@
         }
     }
 
-    PipelineBase::PipelineBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
-    }
-
     PipelineBase::PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : ApiObjectBase(device, tag) {
     }
 
-    PipelineBase::~PipelineBase() = default;
-
     PipelineLayoutBase* PipelineBase::GetLayout() {
         ASSERT(!IsError());
         return mLayout.Get();
diff --git a/src/dawn_native/Pipeline.h b/src/dawn_native/Pipeline.h
index 7a1e09a..7444293 100644
--- a/src/dawn_native/Pipeline.h
+++ b/src/dawn_native/Pipeline.h
@@ -50,8 +50,6 @@
 
     class PipelineBase : public ApiObjectBase, public CachedObject {
       public:
-        ~PipelineBase() override;
-
         PipelineLayoutBase* GetLayout();
         const PipelineLayoutBase* GetLayout() const;
         const RequiredBufferSizes& GetMinBufferSizes() const;
@@ -78,9 +76,6 @@
                      std::vector<StageAndDescriptor> stages);
         PipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
 
-        // Constructor used only for mocking and testing.
-        PipelineBase(DeviceBase* device);
-
       private:
         MaybeError ValidateGetBindGroupLayout(uint32_t group);
 
diff --git a/src/dawn_native/PipelineLayout.cpp b/src/dawn_native/PipelineLayout.cpp
index eb23756..9b1b707 100644
--- a/src/dawn_native/PipelineLayout.cpp
+++ b/src/dawn_native/PipelineLayout.cpp
@@ -57,8 +57,7 @@
     // PipelineLayoutBase
 
     PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
-                                           const PipelineLayoutDescriptor* descriptor,
-                                           ApiObjectBase::UntrackedByDeviceTag tag)
+                                           const PipelineLayoutDescriptor* descriptor)
         : ApiObjectBase(device, kLabelNotImplemented) {
         ASSERT(descriptor->bindGroupLayoutCount <= kMaxBindGroups);
         for (BindGroupIndex group(0); group < BindGroupIndex(descriptor->bindGroupLayoutCount);
@@ -68,30 +67,15 @@
         }
     }
 
-    PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
-                                           const PipelineLayoutDescriptor* descriptor)
-        : PipelineLayoutBase(device, descriptor, kUntrackedByDevice) {
-        TrackInDevice();
-    }
-
-    PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device)
-        : ApiObjectBase(device, kLabelNotImplemented) {
-        TrackInDevice();
-    }
-
     PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : ApiObjectBase(device, tag) {
     }
 
-    PipelineLayoutBase::~PipelineLayoutBase() = default;
-
-    bool PipelineLayoutBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
-        if (wasDestroyed && IsCachedReference()) {
-            // Do not uncache the actual cached object if we are a blueprint
+    PipelineLayoutBase::~PipelineLayoutBase() {
+        // Do not uncache the actual cached object if we are a blueprint
+        if (IsCachedReference()) {
             GetDevice()->UncachePipelineLayout(this);
         }
-        return wasDestroyed;
     }
 
     // static
diff --git a/src/dawn_native/PipelineLayout.h b/src/dawn_native/PipelineLayout.h
index 597de45..7371dab 100644
--- a/src/dawn_native/PipelineLayout.h
+++ b/src/dawn_native/PipelineLayout.h
@@ -50,9 +50,6 @@
 
     class PipelineLayoutBase : public ApiObjectBase, public CachedObject {
       public:
-        PipelineLayoutBase(DeviceBase* device,
-                           const PipelineLayoutDescriptor* descriptor,
-                           ApiObjectBase::UntrackedByDeviceTag tag);
         PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor);
         ~PipelineLayoutBase() override;
 
@@ -61,7 +58,6 @@
             DeviceBase* device,
             std::vector<StageAndDescriptor> stages);
 
-        bool DestroyApiObject() override;
         ObjectType GetType() const override;
 
         const BindGroupLayoutBase* GetBindGroupLayout(BindGroupIndex group) const;
@@ -84,8 +80,6 @@
         };
 
       protected:
-        // Constructor used only for mocking and testing.
-        PipelineLayoutBase(DeviceBase* device);
         PipelineLayoutBase(DeviceBase* device, ObjectBase::ErrorTag tag);
 
         BindGroupLayoutArray mBindGroupLayouts;
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index d130513..1c16bba 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -670,28 +670,12 @@
         }
 
         SetContentHash(ComputeContentHash());
-        TrackInDevice();
-    }
-
-    RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
-        TrackInDevice();
     }
 
     RenderPipelineBase::RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : PipelineBase(device, tag) {
     }
 
-    RenderPipelineBase::~RenderPipelineBase() = default;
-
-    bool RenderPipelineBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
-        if (wasDestroyed && IsCachedReference()) {
-            // Do not uncache the actual cached object if we are a blueprint or already destroyed.
-            GetDevice()->UncacheRenderPipeline(this);
-        }
-        return wasDestroyed;
-    }
-
     // static
     RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) {
         class ErrorRenderPipeline final : public RenderPipelineBase {
@@ -713,6 +697,12 @@
         return ObjectType::RenderPipeline;
     }
 
+    RenderPipelineBase::~RenderPipelineBase() {
+        if (IsCachedReference()) {
+            GetDevice()->UncacheRenderPipeline(this);
+        }
+    }
+
     const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
     RenderPipelineBase::GetAttributeLocationsUsed() const {
         ASSERT(!IsError());
@@ -938,64 +928,62 @@
             return false;
         }
 
-        if (a->mAttachmentState.Get() != nullptr) {
-            for (ColorAttachmentIndex i :
-                 IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
-                const ColorTargetState& descA = *a->GetColorTargetState(i);
-                const ColorTargetState& descB = *b->GetColorTargetState(i);
-                if (descA.writeMask != descB.writeMask) {
+        for (ColorAttachmentIndex i :
+             IterateBitSet(a->mAttachmentState->GetColorAttachmentsMask())) {
+            const ColorTargetState& descA = *a->GetColorTargetState(i);
+            const ColorTargetState& descB = *b->GetColorTargetState(i);
+            if (descA.writeMask != descB.writeMask) {
+                return false;
+            }
+            if ((descA.blend == nullptr) != (descB.blend == nullptr)) {
+                return false;
+            }
+            if (descA.blend != nullptr) {
+                if (descA.blend->color.operation != descB.blend->color.operation ||
+                    descA.blend->color.srcFactor != descB.blend->color.srcFactor ||
+                    descA.blend->color.dstFactor != descB.blend->color.dstFactor) {
                     return false;
                 }
-                if ((descA.blend == nullptr) != (descB.blend == nullptr)) {
+                if (descA.blend->alpha.operation != descB.blend->alpha.operation ||
+                    descA.blend->alpha.srcFactor != descB.blend->alpha.srcFactor ||
+                    descA.blend->alpha.dstFactor != descB.blend->alpha.dstFactor) {
                     return false;
                 }
-                if (descA.blend != nullptr) {
-                    if (descA.blend->color.operation != descB.blend->color.operation ||
-                        descA.blend->color.srcFactor != descB.blend->color.srcFactor ||
-                        descA.blend->color.dstFactor != descB.blend->color.dstFactor) {
-                        return false;
-                    }
-                    if (descA.blend->alpha.operation != descB.blend->alpha.operation ||
-                        descA.blend->alpha.srcFactor != descB.blend->alpha.srcFactor ||
-                        descA.blend->alpha.dstFactor != descB.blend->alpha.dstFactor) {
-                        return false;
-                    }
-                }
             }
+        }
 
-            // Check depth/stencil state
-            if (a->mAttachmentState->HasDepthStencilAttachment()) {
-                const DepthStencilState& stateA = a->mDepthStencil;
-                const DepthStencilState& stateB = b->mDepthStencil;
+        // Check depth/stencil state
+        if (a->mAttachmentState->HasDepthStencilAttachment()) {
+            const DepthStencilState& stateA = a->mDepthStencil;
+            const DepthStencilState& stateB = b->mDepthStencil;
 
-                ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
-                ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
-                ASSERT(!std::isnan(stateA.depthBiasClamp));
-                ASSERT(!std::isnan(stateB.depthBiasClamp));
+            ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
+            ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
+            ASSERT(!std::isnan(stateA.depthBiasClamp));
+            ASSERT(!std::isnan(stateB.depthBiasClamp));
 
-                if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
-                    stateA.depthCompare != stateB.depthCompare ||
-                    stateA.depthBias != stateB.depthBias ||
-                    stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
-                    stateA.depthBiasClamp != stateB.depthBiasClamp) {
-                    return false;
-                }
-                if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
-                    stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
-                    stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
-                    stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
-                    return false;
-                }
-                if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
-                    stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
-                    stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
-                    stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
-                    return false;
-                }
-                if (stateA.stencilReadMask != stateB.stencilReadMask ||
-                    stateA.stencilWriteMask != stateB.stencilWriteMask) {
-                    return false;
-                }
+            if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
+                stateA.depthCompare != stateB.depthCompare ||
+                stateA.depthBias != stateB.depthBias ||
+                stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
+                stateA.depthBiasClamp != stateB.depthBiasClamp) {
+                return false;
+            }
+            if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
+                stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
+                stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
+                stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
+                return false;
+            }
+            if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
+                stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
+                stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
+                stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
+                return false;
+            }
+            if (stateA.stencilReadMask != stateB.stencilReadMask ||
+                stateA.stencilWriteMask != stateB.stencilWriteMask) {
+                return false;
             }
         }
 
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index b69b6ed..bd354ab 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -63,7 +63,6 @@
 
         static RenderPipelineBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
         ObjectType GetType() const override;
 
         const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
@@ -108,10 +107,6 @@
             bool operator()(const RenderPipelineBase* a, const RenderPipelineBase* b) const;
         };
 
-      protected:
-        // Constructor used only for mocking and testing.
-        RenderPipelineBase(DeviceBase* device);
-
       private:
         RenderPipelineBase(DeviceBase* device, ObjectBase::ErrorTag tag);
 
diff --git a/src/dawn_native/Sampler.cpp b/src/dawn_native/Sampler.cpp
index 94c26dd..ec3266c 100644
--- a/src/dawn_native/Sampler.cpp
+++ b/src/dawn_native/Sampler.cpp
@@ -69,9 +69,7 @@
 
     // SamplerBase
 
-    SamplerBase::SamplerBase(DeviceBase* device,
-                             const SamplerDescriptor* descriptor,
-                             ApiObjectBase::UntrackedByDeviceTag tag)
+    SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
         : ApiObjectBase(device, kLabelNotImplemented),
           mAddressModeU(descriptor->addressModeU),
           mAddressModeV(descriptor->addressModeV),
@@ -85,28 +83,14 @@
           mMaxAnisotropy(descriptor->maxAnisotropy) {
     }
 
-    SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor)
-        : SamplerBase(device, descriptor, kUntrackedByDevice) {
-        TrackInDevice();
-    }
-
-    SamplerBase::SamplerBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
-        TrackInDevice();
-    }
-
     SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : ApiObjectBase(device, tag) {
     }
 
-    SamplerBase::~SamplerBase() = default;
-
-    bool SamplerBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
-        if (wasDestroyed && IsCachedReference()) {
-            // Do not uncache the actual cached object if we are a blueprint or already destroyed.
+    SamplerBase::~SamplerBase() {
+        if (IsCachedReference()) {
             GetDevice()->UncacheSampler(this);
         }
-        return wasDestroyed;
     }
 
     // static
diff --git a/src/dawn_native/Sampler.h b/src/dawn_native/Sampler.h
index 6d9e945..3e7d1fb 100644
--- a/src/dawn_native/Sampler.h
+++ b/src/dawn_native/Sampler.h
@@ -30,15 +30,11 @@
 
     class SamplerBase : public ApiObjectBase, public CachedObject {
       public:
-        SamplerBase(DeviceBase* device,
-                    const SamplerDescriptor* descriptor,
-                    ApiObjectBase::UntrackedByDeviceTag tag);
         SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor);
         ~SamplerBase() override;
 
         static SamplerBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
         ObjectType GetType() const override;
 
         bool IsComparison() const;
@@ -55,10 +51,6 @@
             return mMaxAnisotropy;
         }
 
-      protected:
-        // Constructor used only for mocking and testing.
-        SamplerBase(DeviceBase* device);
-
       private:
         SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag);
 
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 3a8c26c..058f886e 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -1145,9 +1145,7 @@
 
     // ShaderModuleBase
 
-    ShaderModuleBase::ShaderModuleBase(DeviceBase* device,
-                                       const ShaderModuleDescriptor* descriptor,
-                                       ApiObjectBase::UntrackedByDeviceTag tag)
+    ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
         : ApiObjectBase(device, descriptor->label), mType(Type::Undefined) {
         ASSERT(descriptor->nextInChain != nullptr);
         const ShaderModuleSPIRVDescriptor* spirvDesc = nullptr;
@@ -1165,29 +1163,14 @@
         }
     }
 
-    ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor)
-        : ShaderModuleBase(device, descriptor, kUntrackedByDevice) {
-        TrackInDevice();
-    }
-
-    ShaderModuleBase::ShaderModuleBase(DeviceBase* device)
-        : ApiObjectBase(device, kLabelNotImplemented) {
-        TrackInDevice();
-    }
-
     ShaderModuleBase::ShaderModuleBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : ApiObjectBase(device, tag), mType(Type::Undefined) {
     }
 
-    ShaderModuleBase::~ShaderModuleBase() = default;
-
-    bool ShaderModuleBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
-        if (wasDestroyed && IsCachedReference()) {
-            // Do not uncache the actual cached object if we are a blueprint or already destroyed.
+    ShaderModuleBase::~ShaderModuleBase() {
+        if (IsCachedReference()) {
             GetDevice()->UncacheShaderModule(this);
         }
-        return wasDestroyed;
     }
 
     // static
diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h
index 30f3294..09bede5 100644
--- a/src/dawn_native/ShaderModule.h
+++ b/src/dawn_native/ShaderModule.h
@@ -221,15 +221,11 @@
 
     class ShaderModuleBase : public ApiObjectBase, public CachedObject {
       public:
-        ShaderModuleBase(DeviceBase* device,
-                         const ShaderModuleDescriptor* descriptor,
-                         ApiObjectBase::UntrackedByDeviceTag tag);
         ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
         ~ShaderModuleBase() override;
 
         static Ref<ShaderModuleBase> MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
         ObjectType GetType() const override;
 
         // Return true iff the program has an entrypoint called `entryPoint`.
@@ -256,9 +252,6 @@
         OwnedCompilationMessages* GetCompilationMessages() const;
 
       protected:
-        // Constructor used only for mocking and testing.
-        ShaderModuleBase(DeviceBase* device);
-
         MaybeError InitializeBase(ShaderModuleParseResult* parseResult);
 
       private:
diff --git a/src/dawn_native/SwapChain.cpp b/src/dawn_native/SwapChain.cpp
index 26617b1..7bba116 100644
--- a/src/dawn_native/SwapChain.cpp
+++ b/src/dawn_native/SwapChain.cpp
@@ -115,7 +115,6 @@
     // SwapChainBase
 
     SwapChainBase::SwapChainBase(DeviceBase* device) : ApiObjectBase(device, kLabelNotImplemented) {
-        TrackInDevice();
     }
 
     SwapChainBase::SwapChainBase(DeviceBase* device, ObjectBase::ErrorTag tag)
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index 8ffd921..37b6a59 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -138,20 +138,9 @@
     "${dawn_root}/src/utils:dawn_utils",
   ]
 
-  # Add internal dawn_native config for internal unittests.
-  configs += [ "${dawn_root}/src/dawn_native:dawn_native_internal" ]
-
   sources = [
     "unittests/native/mocks/BindGroupLayoutMock.h",
-    "unittests/native/mocks/BindGroupMock.h",
-    "unittests/native/mocks/ComputePipelineMock.h",
     "unittests/native/mocks/DeviceMock.h",
-    "unittests/native/mocks/PipelineLayoutMock.h",
-    "unittests/native/mocks/RenderPipelineMock.h",
-    "unittests/native/mocks/SamplerMock.h",
-    "unittests/native/mocks/ShaderModuleMock.cpp",
-    "unittests/native/mocks/ShaderModuleMock.h",
-    "unittests/native/mocks/SwapChainMock.h",
   ]
 }
 
diff --git a/src/tests/unittests/native/DestroyObjectTests.cpp b/src/tests/unittests/native/DestroyObjectTests.cpp
index a82a7f4..6e9c283 100644
--- a/src/tests/unittests/native/DestroyObjectTests.cpp
+++ b/src/tests/unittests/native/DestroyObjectTests.cpp
@@ -16,453 +16,80 @@
 
 #include "dawn_native/Toggles.h"
 #include "mocks/BindGroupLayoutMock.h"
-#include "mocks/BindGroupMock.h"
-#include "mocks/ComputePipelineMock.h"
 #include "mocks/DeviceMock.h"
-#include "mocks/PipelineLayoutMock.h"
-#include "mocks/RenderPipelineMock.h"
-#include "mocks/SamplerMock.h"
-#include "mocks/ShaderModuleMock.h"
-#include "mocks/SwapChainMock.h"
 #include "tests/DawnNativeTest.h"
-#include "utils/ComboRenderPipelineDescriptor.h"
 
 namespace dawn_native { namespace {
 
-    using ::testing::_;
     using ::testing::ByMove;
     using ::testing::InSequence;
     using ::testing::Return;
-    using ::testing::Test;
 
-    class DestroyObjectTests : public Test {
-      public:
-        DestroyObjectTests() : Test() {
-            // Skipping validation on descriptors as coverage for validation is already present.
-            mDevice.SetToggle(Toggle::SkipValidation, true);
-        }
+    TEST(DestroyObjectTests, BindGroupLayoutExplicit) {
+        // Skipping validation on descriptors as coverage for validation is already present.
+        DeviceMock device;
+        device.SetToggle(Toggle::SkipValidation, true);
 
-        Ref<PipelineLayoutMock> GetPipelineLayout() {
-            if (mPipelineLayout != nullptr) {
-                return mPipelineLayout;
-            }
-            mPipelineLayout = AcquireRef(new PipelineLayoutMock(&mDevice));
-            EXPECT_CALL(*mPipelineLayout.Get(), DestroyApiObjectImpl).Times(1);
-            return mPipelineLayout;
-        }
-
-        Ref<ShaderModuleMock> GetVertexShaderModule() {
-            if (mVsModule != nullptr) {
-                return mVsModule;
-            }
-            DAWN_TRY_ASSIGN_WITH_CLEANUP(
-                mVsModule, ShaderModuleMock::Create(&mDevice, R"(
-            [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4<f32> {
-                return vec4<f32>(0.0, 0.0, 0.0, 1.0);
-            })"),
-                { ASSERT(false); }, mVsModule);
-            EXPECT_CALL(*mVsModule.Get(), DestroyApiObjectImpl).Times(1);
-            return mVsModule;
-        }
-
-        Ref<ShaderModuleMock> GetComputeShaderModule() {
-            if (mCsModule != nullptr) {
-                return mCsModule;
-            }
-            DAWN_TRY_ASSIGN_WITH_CLEANUP(
-                mCsModule, ShaderModuleMock::Create(&mDevice, R"(
-            [[stage(compute), workgroup_size(1)]] fn main() {
-            })"),
-                { ASSERT(false); }, mCsModule);
-            EXPECT_CALL(*mCsModule.Get(), DestroyApiObjectImpl).Times(1);
-            return mCsModule;
-        }
-
-      protected:
-        DeviceMock mDevice;
-
-        // The following lazy-initialized objects are used to facilitate creation of dependent
-        // objects under test.
-        Ref<PipelineLayoutMock> mPipelineLayout;
-        Ref<ShaderModuleMock> mVsModule;
-        Ref<ShaderModuleMock> mCsModule;
-    };
-
-    TEST_F(DestroyObjectTests, BindGroupExplicit) {
-        BindGroupMock bindGroupMock(&mDevice);
-        EXPECT_CALL(bindGroupMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(bindGroupMock.IsAlive());
-        bindGroupMock.DestroyApiObject();
-        EXPECT_FALSE(bindGroupMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, BindGroupImplicit) {
-        BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
-        EXPECT_CALL(*bindGroupMock, DestroyApiObjectImpl).Times(1);
-        {
-            BindGroupDescriptor desc = {};
-            Ref<BindGroupBase> bindGroup;
-            EXPECT_CALL(mDevice, CreateBindGroupImpl)
-                .WillOnce(Return(ByMove(AcquireRef(bindGroupMock))));
-            DAWN_ASSERT_AND_ASSIGN(bindGroup, mDevice.CreateBindGroup(&desc));
-
-            EXPECT_TRUE(bindGroup->IsAlive());
-        }
-    }
-
-    TEST_F(DestroyObjectTests, BindGroupLayoutExplicit) {
-        BindGroupLayoutMock bindGroupLayoutMock(&mDevice);
-        EXPECT_CALL(bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(bindGroupLayoutMock.IsAlive());
-        bindGroupLayoutMock.DestroyApiObject();
-        EXPECT_FALSE(bindGroupLayoutMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, BindGroupLayoutImplicit) {
-        BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&mDevice);
+        BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
         EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
+
+        BindGroupLayoutDescriptor desc = {};
+        Ref<BindGroupLayoutBase> bindGroupLayout;
+        EXPECT_CALL(device, CreateBindGroupLayoutImpl)
+            .WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
+        DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
+
+        EXPECT_TRUE(bindGroupLayout->IsAlive());
+        EXPECT_TRUE(bindGroupLayout->IsCachedReference());
+
+        bindGroupLayout->DestroyApiObject();
+        EXPECT_FALSE(bindGroupLayout->IsAlive());
+    }
+
+    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
+    // will also complain if there is a memory leak.
+    TEST(DestroyObjectTests, BindGroupLayoutImplicit) {
+        // Skipping validation on descriptors as coverage for validation is already present.
+        DeviceMock device;
+        device.SetToggle(Toggle::SkipValidation, true);
+
+        BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
+        EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
+
         {
             BindGroupLayoutDescriptor desc = {};
             Ref<BindGroupLayoutBase> bindGroupLayout;
-            EXPECT_CALL(mDevice, CreateBindGroupLayoutImpl)
+            EXPECT_CALL(device, CreateBindGroupLayoutImpl)
                 .WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
-            DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, mDevice.CreateBindGroupLayout(&desc));
+            DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
 
             EXPECT_TRUE(bindGroupLayout->IsAlive());
             EXPECT_TRUE(bindGroupLayout->IsCachedReference());
         }
     }
 
-    TEST_F(DestroyObjectTests, ComputePipelineExplicit) {
-        ComputePipelineMock computePipelineMock(&mDevice);
-        EXPECT_CALL(computePipelineMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(computePipelineMock.IsAlive());
-        computePipelineMock.DestroyApiObject();
-        EXPECT_FALSE(computePipelineMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, ComputePipelineImplicit) {
-        // ComputePipelines usually set their hash values at construction, but the mock does not, so
-        // we set it here.
-        constexpr size_t hash = 0x12345;
-        ComputePipelineMock* computePipelineMock = new ComputePipelineMock(&mDevice);
-        computePipelineMock->SetContentHash(hash);
-        ON_CALL(*computePipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
-        // Compute pipelines are initialized during their creation via the device.
-        EXPECT_CALL(*computePipelineMock, Initialize).Times(1);
-        EXPECT_CALL(*computePipelineMock, DestroyApiObjectImpl).Times(1);
-
-        {
-            ComputePipelineDescriptor desc = {};
-            desc.layout = GetPipelineLayout().Get();
-            desc.compute.module = GetComputeShaderModule().Get();
-
-            Ref<ComputePipelineBase> computePipeline;
-            EXPECT_CALL(mDevice, CreateUninitializedComputePipelineImpl)
-                .WillOnce(Return(ByMove(AcquireRef(computePipelineMock))));
-            DAWN_ASSERT_AND_ASSIGN(computePipeline, mDevice.CreateComputePipeline(&desc));
-
-            EXPECT_TRUE(computePipeline->IsAlive());
-            EXPECT_TRUE(computePipeline->IsCachedReference());
-        }
-    }
-
-    TEST_F(DestroyObjectTests, PipelineLayoutExplicit) {
-        PipelineLayoutMock pipelineLayoutMock(&mDevice);
-        EXPECT_CALL(pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(pipelineLayoutMock.IsAlive());
-        pipelineLayoutMock.DestroyApiObject();
-        EXPECT_FALSE(pipelineLayoutMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, PipelineLayoutImplicit) {
-        PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
-        EXPECT_CALL(*pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
-        {
-            PipelineLayoutDescriptor desc = {};
-            Ref<PipelineLayoutBase> pipelineLayout;
-            EXPECT_CALL(mDevice, CreatePipelineLayoutImpl)
-                .WillOnce(Return(ByMove(AcquireRef(pipelineLayoutMock))));
-            DAWN_ASSERT_AND_ASSIGN(pipelineLayout, mDevice.CreatePipelineLayout(&desc));
-
-            EXPECT_TRUE(pipelineLayout->IsAlive());
-            EXPECT_TRUE(pipelineLayout->IsCachedReference());
-        }
-    }
-
-    TEST_F(DestroyObjectTests, RenderPipelineExplicit) {
-        RenderPipelineMock renderPipelineMock(&mDevice);
-        EXPECT_CALL(renderPipelineMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(renderPipelineMock.IsAlive());
-        renderPipelineMock.DestroyApiObject();
-        EXPECT_FALSE(renderPipelineMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, RenderPipelineImplicit) {
-        // RenderPipelines usually set their hash values at construction, but the mock does not, so
-        // we set it here.
-        constexpr size_t hash = 0x12345;
-        RenderPipelineMock* renderPipelineMock = new RenderPipelineMock(&mDevice);
-        renderPipelineMock->SetContentHash(hash);
-        ON_CALL(*renderPipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
-        // Render pipelines are initialized during their creation via the device.
-        EXPECT_CALL(*renderPipelineMock, Initialize).Times(1);
-        EXPECT_CALL(*renderPipelineMock, DestroyApiObjectImpl).Times(1);
-
-        {
-            RenderPipelineDescriptor desc = {};
-            desc.layout = GetPipelineLayout().Get();
-            desc.vertex.module = GetVertexShaderModule().Get();
-
-            Ref<RenderPipelineBase> renderPipeline;
-            EXPECT_CALL(mDevice, CreateUninitializedRenderPipelineImpl)
-                .WillOnce(Return(ByMove(AcquireRef(renderPipelineMock))));
-            DAWN_ASSERT_AND_ASSIGN(renderPipeline, mDevice.CreateRenderPipeline(&desc));
-
-            EXPECT_TRUE(renderPipeline->IsAlive());
-            EXPECT_TRUE(renderPipeline->IsCachedReference());
-        }
-    }
-
-    TEST_F(DestroyObjectTests, SamplerExplicit) {
-        SamplerMock samplerMock(&mDevice);
-        EXPECT_CALL(samplerMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(samplerMock.IsAlive());
-        samplerMock.DestroyApiObject();
-        EXPECT_FALSE(samplerMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, SamplerImplicit) {
-        SamplerMock* samplerMock = new SamplerMock(&mDevice);
-        EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
-        {
-            SamplerDescriptor desc = {};
-            Ref<SamplerBase> sampler;
-            EXPECT_CALL(mDevice, CreateSamplerImpl)
-                .WillOnce(Return(ByMove(AcquireRef(samplerMock))));
-            DAWN_ASSERT_AND_ASSIGN(sampler, mDevice.CreateSampler(&desc));
-
-            EXPECT_TRUE(sampler->IsAlive());
-            EXPECT_TRUE(sampler->IsCachedReference());
-        }
-    }
-
-    TEST_F(DestroyObjectTests, ShaderModuleExplicit) {
-        ShaderModuleMock shaderModuleMock(&mDevice);
-        EXPECT_CALL(shaderModuleMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(shaderModuleMock.IsAlive());
-        shaderModuleMock.DestroyApiObject();
-        EXPECT_FALSE(shaderModuleMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, ShaderModuleImplicit) {
-        ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
-        EXPECT_CALL(*shaderModuleMock, DestroyApiObjectImpl).Times(1);
-        {
-            ShaderModuleWGSLDescriptor wgslDesc;
-            wgslDesc.source = R"(
-                [[stage(compute), workgroup_size(1)]] fn main() {
-                }
-            )";
-            ShaderModuleDescriptor desc = {};
-            desc.nextInChain = &wgslDesc;
-            Ref<ShaderModuleBase> shaderModule;
-            EXPECT_CALL(mDevice, CreateShaderModuleImpl)
-                .WillOnce(Return(ByMove(AcquireRef(shaderModuleMock))));
-            DAWN_ASSERT_AND_ASSIGN(shaderModule, mDevice.CreateShaderModule(&desc));
-
-            EXPECT_TRUE(shaderModule->IsAlive());
-            EXPECT_TRUE(shaderModule->IsCachedReference());
-        }
-    }
-
-    TEST_F(DestroyObjectTests, SwapChainExplicit) {
-        SwapChainMock swapChainMock(&mDevice);
-        EXPECT_CALL(swapChainMock, DestroyApiObjectImpl).Times(1);
-
-        EXPECT_TRUE(swapChainMock.IsAlive());
-        swapChainMock.DestroyApiObject();
-        EXPECT_FALSE(swapChainMock.IsAlive());
-    }
-
-    // If the reference count on API objects reach 0, they should delete themselves. Note that GTest
-    // will also complain if there is a memory leak.
-    TEST_F(DestroyObjectTests, SwapChainImplicit) {
-        SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
-        EXPECT_CALL(*swapChainMock, DestroyApiObjectImpl).Times(1);
-        {
-            SwapChainDescriptor desc = {};
-            Ref<SwapChainBase> swapChain;
-            EXPECT_CALL(mDevice, CreateSwapChainImpl(_))
-                .WillOnce(Return(ByMove(AcquireRef(swapChainMock))));
-            DAWN_ASSERT_AND_ASSIGN(swapChain, mDevice.CreateSwapChain(nullptr, &desc));
-
-            EXPECT_TRUE(swapChain->IsAlive());
-        }
-    }
-
-    // Destroying the objects on the mDevice should result in all created objects being destroyed in
+    // Destroying the objects on the device should result in all created objects being destroyed in
     // order.
-    TEST_F(DestroyObjectTests, DestroyObjects) {
-        BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
-        BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&mDevice);
-        ComputePipelineMock* computePipelineMock = new ComputePipelineMock(&mDevice);
-        PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
-        RenderPipelineMock* renderPipelineMock = new RenderPipelineMock(&mDevice);
-        SamplerMock* samplerMock = new SamplerMock(&mDevice);
-        ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
-        SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
+    TEST(DestroyObjectTests, DestroyObjects) {
+        DeviceMock device;
+        device.SetToggle(Toggle::SkipValidation, true);
+
+        BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&device);
         {
             InSequence seq;
-            EXPECT_CALL(*renderPipelineMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*computePipelineMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*swapChainMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*bindGroupMock, DestroyApiObjectImpl).Times(1);
             EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*shaderModuleMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
         }
 
-        Ref<BindGroupBase> bindGroup;
-        {
-            BindGroupDescriptor desc = {};
-            EXPECT_CALL(mDevice, CreateBindGroupImpl)
-                .WillOnce(Return(ByMove(AcquireRef(bindGroupMock))));
-            DAWN_ASSERT_AND_ASSIGN(bindGroup, mDevice.CreateBindGroup(&desc));
-            EXPECT_TRUE(bindGroup->IsAlive());
-        }
-
+        BindGroupLayoutDescriptor desc = {};
         Ref<BindGroupLayoutBase> bindGroupLayout;
-        {
-            BindGroupLayoutDescriptor desc = {};
-            EXPECT_CALL(mDevice, CreateBindGroupLayoutImpl)
-                .WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
-            DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, mDevice.CreateBindGroupLayout(&desc));
-            EXPECT_TRUE(bindGroupLayout->IsAlive());
-            EXPECT_TRUE(bindGroupLayout->IsCachedReference());
-        }
+        EXPECT_CALL(device, CreateBindGroupLayoutImpl)
+            .WillOnce(Return(ByMove(AcquireRef(bindGroupLayoutMock))));
+        DAWN_ASSERT_AND_ASSIGN(bindGroupLayout, device.CreateBindGroupLayout(&desc));
+        EXPECT_TRUE(bindGroupLayout->IsAlive());
+        EXPECT_TRUE(bindGroupLayout->IsCachedReference());
 
-        Ref<ComputePipelineBase> computePipeline;
-        {
-            // Compute pipelines usually set their hash values at construction, but the mock does
-            // not, so we set it here.
-            constexpr size_t hash = 0x12345;
-            computePipelineMock->SetContentHash(hash);
-            ON_CALL(*computePipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
-            // Compute pipelines are initialized during their creation via the device.
-            EXPECT_CALL(*computePipelineMock, Initialize).Times(1);
-
-            ComputePipelineDescriptor desc = {};
-            desc.layout = GetPipelineLayout().Get();
-            desc.compute.module = GetComputeShaderModule().Get();
-            EXPECT_CALL(mDevice, CreateUninitializedComputePipelineImpl)
-                .WillOnce(Return(ByMove(AcquireRef(computePipelineMock))));
-            DAWN_ASSERT_AND_ASSIGN(computePipeline, mDevice.CreateComputePipeline(&desc));
-            EXPECT_TRUE(computePipeline->IsAlive());
-            EXPECT_TRUE(computePipeline->IsCachedReference());
-        }
-
-        Ref<PipelineLayoutBase> pipelineLayout;
-        {
-            PipelineLayoutDescriptor desc = {};
-            EXPECT_CALL(mDevice, CreatePipelineLayoutImpl)
-                .WillOnce(Return(ByMove(AcquireRef(pipelineLayoutMock))));
-            DAWN_ASSERT_AND_ASSIGN(pipelineLayout, mDevice.CreatePipelineLayout(&desc));
-            EXPECT_TRUE(pipelineLayout->IsAlive());
-            EXPECT_TRUE(pipelineLayout->IsCachedReference());
-        }
-
-        Ref<RenderPipelineBase> renderPipeline;
-        {
-            // Render pipelines usually set their hash values at construction, but the mock does
-            // not, so we set it here.
-            constexpr size_t hash = 0x12345;
-            renderPipelineMock->SetContentHash(hash);
-            ON_CALL(*renderPipelineMock, ComputeContentHash).WillByDefault(Return(hash));
-
-            // Render pipelines are initialized during their creation via the device.
-            EXPECT_CALL(*renderPipelineMock, Initialize).Times(1);
-
-            RenderPipelineDescriptor desc = {};
-            desc.layout = GetPipelineLayout().Get();
-            desc.vertex.module = GetVertexShaderModule().Get();
-            EXPECT_CALL(mDevice, CreateUninitializedRenderPipelineImpl)
-                .WillOnce(Return(ByMove(AcquireRef(renderPipelineMock))));
-            DAWN_ASSERT_AND_ASSIGN(renderPipeline, mDevice.CreateRenderPipeline(&desc));
-            EXPECT_TRUE(renderPipeline->IsAlive());
-            EXPECT_TRUE(renderPipeline->IsCachedReference());
-        }
-
-        Ref<SamplerBase> sampler;
-        {
-            SamplerDescriptor desc = {};
-            EXPECT_CALL(mDevice, CreateSamplerImpl)
-                .WillOnce(Return(ByMove(AcquireRef(samplerMock))));
-            DAWN_ASSERT_AND_ASSIGN(sampler, mDevice.CreateSampler(&desc));
-            EXPECT_TRUE(sampler->IsAlive());
-            EXPECT_TRUE(sampler->IsCachedReference());
-        }
-
-        Ref<ShaderModuleBase> shaderModule;
-        {
-            ShaderModuleWGSLDescriptor wgslDesc;
-            wgslDesc.source = R"(
-                [[stage(compute), workgroup_size(1)]] fn main() {
-                }
-            )";
-            ShaderModuleDescriptor desc = {};
-            desc.nextInChain = &wgslDesc;
-
-            EXPECT_CALL(mDevice, CreateShaderModuleImpl)
-                .WillOnce(Return(ByMove(AcquireRef(shaderModuleMock))));
-            DAWN_ASSERT_AND_ASSIGN(shaderModule, mDevice.CreateShaderModule(&desc));
-            EXPECT_TRUE(shaderModule->IsAlive());
-            EXPECT_TRUE(shaderModule->IsCachedReference());
-        }
-
-        Ref<SwapChainBase> swapChain;
-        {
-            SwapChainDescriptor desc = {};
-            EXPECT_CALL(mDevice, CreateSwapChainImpl(_))
-                .WillOnce(Return(ByMove(AcquireRef(swapChainMock))));
-            DAWN_ASSERT_AND_ASSIGN(swapChain, mDevice.CreateSwapChain(nullptr, &desc));
-            EXPECT_TRUE(swapChain->IsAlive());
-        }
-
-        mDevice.DestroyObjects();
-        EXPECT_FALSE(bindGroup->IsAlive());
+        device.DestroyObjects();
         EXPECT_FALSE(bindGroupLayout->IsAlive());
-        EXPECT_FALSE(computePipeline->IsAlive());
-        EXPECT_FALSE(pipelineLayout->IsAlive());
-        EXPECT_FALSE(renderPipeline->IsAlive());
-        EXPECT_FALSE(sampler->IsAlive());
-        EXPECT_FALSE(shaderModule->IsAlive());
-        EXPECT_FALSE(swapChain->IsAlive());
     }
 
 }}  // namespace dawn_native::
diff --git a/src/tests/unittests/native/mocks/BindGroupMock.h b/src/tests/unittests/native/mocks/BindGroupMock.h
deleted file mode 100644
index e36dc84..0000000
--- a/src/tests/unittests/native/mocks/BindGroupMock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_BINDGROUP_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_BINDGROUP_MOCK_H_
-
-#include "dawn_native/BindGroup.h"
-#include "dawn_native/Device.h"
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class BindGroupMock : public BindGroupBase {
-      public:
-        BindGroupMock(DeviceBase* device) : BindGroupBase(device) {
-        }
-        ~BindGroupMock() override = default;
-
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_BINDGROUP_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/ComputePipelineMock.h b/src/tests/unittests/native/mocks/ComputePipelineMock.h
deleted file mode 100644
index 6289b56..0000000
--- a/src/tests/unittests/native/mocks/ComputePipelineMock.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_COMPUTEPIPELINE_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_COMPUTEPIPELINE_MOCK_H_
-
-#include "dawn_native/ComputePipeline.h"
-#include "dawn_native/Device.h"
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class ComputePipelineMock : public ComputePipelineBase {
-      public:
-        ComputePipelineMock(DeviceBase* device) : ComputePipelineBase(device) {
-        }
-        ~ComputePipelineMock() override = default;
-
-        MOCK_METHOD(MaybeError, Initialize, (), (override));
-        MOCK_METHOD(size_t, ComputeContentHash, (), (override));
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_COMPUTEPIPELINE_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/PipelineLayoutMock.h b/src/tests/unittests/native/mocks/PipelineLayoutMock.h
deleted file mode 100644
index 4b9201a..0000000
--- a/src/tests/unittests/native/mocks/PipelineLayoutMock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_PIPELINELAYOUT_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_PIPELINELAYOUT_MOCK_H_
-
-#include "dawn_native/Device.h"
-#include "dawn_native/PipelineLayout.h"
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class PipelineLayoutMock : public PipelineLayoutBase {
-      public:
-        PipelineLayoutMock(DeviceBase* device) : PipelineLayoutBase(device) {
-        }
-        ~PipelineLayoutMock() override = default;
-
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_PIPELINELAYOUT_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/RenderPipelineMock.h b/src/tests/unittests/native/mocks/RenderPipelineMock.h
deleted file mode 100644
index fa82ab5..0000000
--- a/src/tests/unittests/native/mocks/RenderPipelineMock.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_RENDERPIPELINE_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_RENDERPIPELINE_MOCK_H_
-
-#include "dawn_native/Device.h"
-#include "dawn_native/RenderPipeline.h"
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class RenderPipelineMock : public RenderPipelineBase {
-      public:
-        RenderPipelineMock(DeviceBase* device) : RenderPipelineBase(device) {
-        }
-        ~RenderPipelineMock() override = default;
-
-        MOCK_METHOD(MaybeError, Initialize, (), (override));
-        MOCK_METHOD(size_t, ComputeContentHash, (), (override));
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_RENDERPIPELINE_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/SamplerMock.h b/src/tests/unittests/native/mocks/SamplerMock.h
deleted file mode 100644
index ca9a6b0..0000000
--- a/src/tests/unittests/native/mocks/SamplerMock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_SAMPLER_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_SAMPLER_MOCK_H_
-
-#include "dawn_native/Device.h"
-#include "dawn_native/Sampler.h"
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class SamplerMock : public SamplerBase {
-      public:
-        SamplerMock(DeviceBase* device) : SamplerBase(device) {
-        }
-        ~SamplerMock() override = default;
-
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_SAMPLER_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/ShaderModuleMock.cpp b/src/tests/unittests/native/mocks/ShaderModuleMock.cpp
deleted file mode 100644
index 4d0f0f2..0000000
--- a/src/tests/unittests/native/mocks/ShaderModuleMock.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "ShaderModuleMock.h"
-
-namespace dawn_native {
-
-    ResultOrError<Ref<ShaderModuleMock>> ShaderModuleMock::Create(DeviceBase* device,
-                                                                  const char* source) {
-        ShaderModuleMock* mock = new ShaderModuleMock(device);
-
-        ShaderModuleWGSLDescriptor wgslDesc;
-        wgslDesc.source = source;
-        ShaderModuleDescriptor desc;
-        desc.nextInChain = &wgslDesc;
-
-        ShaderModuleParseResult parseResult;
-        DAWN_TRY(ValidateShaderModuleDescriptor(device, &desc, &parseResult, nullptr));
-        DAWN_TRY(mock->InitializeBase(&parseResult));
-        return AcquireRef(mock);
-    }
-
-}  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/ShaderModuleMock.h b/src/tests/unittests/native/mocks/ShaderModuleMock.h
deleted file mode 100644
index ebe2357..0000000
--- a/src/tests/unittests/native/mocks/ShaderModuleMock.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULE_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULE_MOCK_H_
-
-#include "dawn_native/Error.h"
-#include "dawn_native/ShaderModule.h"
-#include "src/dawn_native/Device.h"
-
-#include <memory>
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class ShaderModuleMock : public ShaderModuleBase {
-      public:
-        ShaderModuleMock(DeviceBase* device) : ShaderModuleBase(device) {
-        }
-        ~ShaderModuleMock() override = default;
-
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-
-        // Creates a shader module mock based on the wgsl source.
-        static ResultOrError<Ref<ShaderModuleMock>> Create(DeviceBase* device, const char* source);
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_SHADERMODULE_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/SwapChainMock.h b/src/tests/unittests/native/mocks/SwapChainMock.h
deleted file mode 100644
index cee332b..0000000
--- a/src/tests/unittests/native/mocks/SwapChainMock.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2021 The Dawn Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef TESTS_UNITTESTS_NATIVE_MOCKS_SWAPCHAIN_MOCK_H_
-#define TESTS_UNITTESTS_NATIVE_MOCKS_SWAPCHAIN_MOCK_H_
-
-#include "dawn_native/Device.h"
-#include "dawn_native/SwapChain.h"
-
-#include <gmock/gmock.h>
-
-namespace dawn_native {
-
-    class SwapChainMock : public SwapChainBase {
-      public:
-        SwapChainMock(DeviceBase* device) : SwapChainBase(device) {
-        }
-        ~SwapChainMock() override = default;
-
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
-
-        MOCK_METHOD(void,
-                    APIConfigure,
-                    (wgpu::TextureFormat, wgpu::TextureUsage, uint32_t, uint32_t),
-                    (override));
-        MOCK_METHOD(TextureViewBase*, APIGetCurrentTextureView, (), (override));
-        MOCK_METHOD(void, APIPresent, (), (override));
-    };
-
-}  // namespace dawn_native
-
-#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_SWAPCHAIN_MOCK_H_