Renames DestroyApiObject* to Destroy* for simplicity.

- Also updates and adds tests for CommandBuffer since it is the last object with a Destroy name clash.

Bug: dawn:628
Change-Id: I028e0101a91a785aa90d2b656556d48fe0d6e736
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/68101
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp
index aea7c40..5061864 100644
--- a/src/dawn_native/BindGroupLayout.cpp
+++ b/src/dawn_native/BindGroupLayout.cpp
@@ -418,8 +418,8 @@
 
     BindGroupLayoutBase::~BindGroupLayoutBase() = default;
 
-    bool BindGroupLayoutBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+    bool BindGroupLayoutBase::Destroy() {
+        bool wasDestroyed = ApiObjectBase::Destroy();
         if (wasDestroyed && IsCachedReference()) {
             // Do not uncache the actual cached object if we are a blueprint or already destroyed.
             GetDevice()->UncacheBindGroupLayout(this);
diff --git a/src/dawn_native/BindGroupLayout.h b/src/dawn_native/BindGroupLayout.h
index 1c2c4e3..101b032 100644
--- a/src/dawn_native/BindGroupLayout.h
+++ b/src/dawn_native/BindGroupLayout.h
@@ -53,7 +53,7 @@
 
         static BindGroupLayoutBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         // A map from the BindingNumber to its packed BindingIndex.
diff --git a/src/dawn_native/Buffer.cpp b/src/dawn_native/Buffer.cpp
index 4bef77f..6e4415c 100644
--- a/src/dawn_native/Buffer.cpp
+++ b/src/dawn_native/Buffer.cpp
@@ -91,7 +91,7 @@
                 mFakeMappedData.reset();
             }
 
-            void DestroyApiObjectImpl() override {
+            void DestroyImpl() override {
                 mFakeMappedData.reset();
             }
 
@@ -181,7 +181,7 @@
         ASSERT(mState == BufferState::Unmapped || mState == BufferState::Destroyed);
     }
 
-    bool BufferBase::DestroyApiObject() {
+    bool BufferBase::Destroy() {
         bool marked = MarkDestroyed();
         if (!marked) {
             return false;
@@ -197,7 +197,7 @@
             }
         }
 
-        DestroyApiObjectImpl();
+        DestroyImpl();
         mState = BufferState::Destroyed;
         return true;
     }
@@ -397,7 +397,7 @@
     }
 
     void BufferBase::APIDestroy() {
-        DestroyApiObject();
+        Destroy();
     }
 
     MaybeError BufferBase::CopyFromStagingBuffer() {
diff --git a/src/dawn_native/Buffer.h b/src/dawn_native/Buffer.h
index cc7e32e..505c873 100644
--- a/src/dawn_native/Buffer.h
+++ b/src/dawn_native/Buffer.h
@@ -52,7 +52,7 @@
 
         static BufferBase* MakeError(DeviceBase* device, const BufferDescriptor* descriptor);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         uint64_t GetSize() const;
diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp
index 3fadb1a..c6535f3 100644
--- a/src/dawn_native/CommandBuffer.cpp
+++ b/src/dawn_native/CommandBuffer.cpp
@@ -29,16 +29,18 @@
         : ApiObjectBase(encoder->GetDevice(), kLabelNotImplemented),
           mCommands(encoder->AcquireCommands()),
           mResourceUsages(encoder->AcquireResourceUsages()) {
+        TrackInDevice();
+    }
+
+    CommandBufferBase::CommandBufferBase(DeviceBase* device)
+        : ApiObjectBase(device, kLabelNotImplemented) {
+        TrackInDevice();
     }
 
     CommandBufferBase::CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag)
         : ApiObjectBase(device, tag) {
     }
 
-    CommandBufferBase::~CommandBufferBase() {
-        Destroy();
-    }
-
     // static
     CommandBufferBase* CommandBufferBase::MakeError(DeviceBase* device) {
         return new CommandBufferBase(device, ObjectBase::kError);
@@ -51,14 +53,13 @@
     MaybeError CommandBufferBase::ValidateCanUseInSubmitNow() const {
         ASSERT(!IsError());
 
-        DAWN_INVALID_IF(mDestroyed, "%s cannot be submitted more than once.", this);
+        DAWN_INVALID_IF(!IsAlive(), "%s cannot be submitted more than once.", this);
         return {};
     }
 
-    void CommandBufferBase::Destroy() {
+    void CommandBufferBase::DestroyImpl() {
         FreeCommands(&mCommands);
         mResourceUsages = {};
-        mDestroyed = true;
     }
 
     const CommandBufferResourceUsage& CommandBufferBase::GetResourceUsages() const {
diff --git a/src/dawn_native/CommandBuffer.h b/src/dawn_native/CommandBuffer.h
index 023208b..70c4ed6 100644
--- a/src/dawn_native/CommandBuffer.h
+++ b/src/dawn_native/CommandBuffer.h
@@ -36,17 +36,18 @@
 
         static CommandBufferBase* MakeError(DeviceBase* device);
 
+        void DestroyImpl() override;
         ObjectType GetType() const override;
 
         MaybeError ValidateCanUseInSubmitNow() const;
-        void Destroy();
 
         const CommandBufferResourceUsage& GetResourceUsages() const;
 
         CommandIterator* GetCommandIteratorForTesting();
 
       protected:
-        ~CommandBufferBase() override;
+        // Constructor used only for mocking and testing.
+        CommandBufferBase(DeviceBase* device);
 
         CommandIterator mCommands;
 
@@ -54,7 +55,6 @@
         CommandBufferBase(DeviceBase* device, ObjectBase::ErrorTag tag);
 
         CommandBufferResourceUsage mResourceUsages;
-        bool mDestroyed = false;
     };
 
     bool IsCompleteSubresourceCopiedTo(const TextureBase* texture,
diff --git a/src/dawn_native/ComputePipeline.cpp b/src/dawn_native/ComputePipeline.cpp
index 9eca55c..68bbf16 100644
--- a/src/dawn_native/ComputePipeline.cpp
+++ b/src/dawn_native/ComputePipeline.cpp
@@ -60,8 +60,8 @@
 
     ComputePipelineBase::~ComputePipelineBase() = default;
 
-    bool ComputePipelineBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+    bool ComputePipelineBase::Destroy() {
+        bool wasDestroyed = ApiObjectBase::Destroy();
         if (wasDestroyed && IsCachedReference()) {
             // Do not uncache the actual cached object if we are a blueprint or already destroyed.
             GetDevice()->UncacheComputePipeline(this);
diff --git a/src/dawn_native/ComputePipeline.h b/src/dawn_native/ComputePipeline.h
index 1872923..fdeb902 100644
--- a/src/dawn_native/ComputePipeline.h
+++ b/src/dawn_native/ComputePipeline.h
@@ -34,7 +34,7 @@
 
         static ComputePipelineBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         // Functors necessary for the unordered_set<ComputePipelineBase*>-based cache.
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index ce114a5..f514a33 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -269,7 +269,8 @@
         // TODO(dawn/628) Add types into the array as they are implemented.
 
         // clang-format off
-        static constexpr std::array<ObjectType, 13> kObjectTypeDependencyOrder = {
+        static constexpr std::array<ObjectType, 14> kObjectTypeDependencyOrder = {
+            ObjectType::CommandBuffer,
             ObjectType::RenderPipeline,
             ObjectType::ComputePipeline,
             ObjectType::PipelineLayout,
@@ -296,7 +297,7 @@
             objList.objects.MoveInto(&objects);
         }
         for (LinkNode<ApiObjectBase>* node : objects) {
-            node->value()->DestroyApiObject();
+            node->value()->Destroy();
         }
     }
 
diff --git a/src/dawn_native/ExternalTexture.cpp b/src/dawn_native/ExternalTexture.cpp
index f8556d8..82a7e3e 100644
--- a/src/dawn_native/ExternalTexture.cpp
+++ b/src/dawn_native/ExternalTexture.cpp
@@ -119,12 +119,12 @@
         if (GetDevice()->ConsumedError(GetDevice()->ValidateObject(this))) {
             return;
         }
-        DestroyApiObject();
+        Destroy();
     }
 
-    bool ExternalTextureBase::DestroyApiObject() {
+    bool ExternalTextureBase::Destroy() {
         mState = ExternalTextureState::Destroyed;
-        return ApiObjectBase::DestroyApiObject();
+        return ApiObjectBase::Destroy();
     }
 
     // static
diff --git a/src/dawn_native/ExternalTexture.h b/src/dawn_native/ExternalTexture.h
index af8264b..94b8ef2 100644
--- a/src/dawn_native/ExternalTexture.h
+++ b/src/dawn_native/ExternalTexture.h
@@ -42,7 +42,7 @@
 
         static ExternalTextureBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         void APIDestroy();
diff --git a/src/dawn_native/ObjectBase.cpp b/src/dawn_native/ObjectBase.cpp
index 971c048..ee87702 100644
--- a/src/dawn_native/ObjectBase.cpp
+++ b/src/dawn_native/ObjectBase.cpp
@@ -71,7 +71,7 @@
     }
 
     void ApiObjectBase::DeleteThis() {
-        DestroyApiObject();
+        Destroy();
         RefCounted::DeleteThis();
     }
 
@@ -85,15 +85,15 @@
         return RemoveFromList();
     }
 
-    bool ApiObjectBase::DestroyApiObject() {
+    bool ApiObjectBase::Destroy() {
         bool marked = MarkDestroyed();
         if (marked) {
-            DestroyApiObjectImpl();
+            DestroyImpl();
         }
         return marked;
     }
 
-    void ApiObjectBase::DestroyApiObjectImpl() {
+    void ApiObjectBase::DestroyImpl() {
     }
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/ObjectBase.h b/src/dawn_native/ObjectBase.h
index 0059506..c234da0 100644
--- a/src/dawn_native/ObjectBase.h
+++ b/src/dawn_native/ObjectBase.h
@@ -65,17 +65,17 @@
         // class's implementation in the override. This needs to be public because it can be called
         // from the device owning the object. Returns true iff destruction occurs. Upon any re-calls
         // of the function it will return false to indicate no further operations should be taken.
-        virtual bool DestroyApiObject();
+        virtual bool Destroy();
 
         // Dawn API
         void APISetLabel(const char* label);
 
       protected:
         // Overriding of the RefCounted's DeleteThis function ensures that instances of objects
-        // always call their derived class implementation of DestroyApiObject prior to the derived
+        // always call their derived class implementation of Destroy prior to the derived
         // class being destroyed. This guarantees that when ApiObjects' reference counts drop to 0,
         // then the underlying backend's Destroy calls are executed. We cannot naively put the call
-        // to DestroyApiObject in the destructor of this class because it calls DestroyApiObjectImpl
+        // to Destroy in the destructor of this class because it calls DestroyImpl
         // which is a virtual function often implemented in the Derived class which would already
         // have been destroyed by the time ApiObject's destructor is called by C++'s destruction
         // order. Note that some classes like BindGroup may override the DeleteThis function again,
@@ -89,7 +89,7 @@
         // pre-destruction steps that need to occur only once, i.e. Buffer needs to be unmapped
         // before being destroyed.
         bool MarkDestroyed();
-        virtual void DestroyApiObjectImpl();
+        virtual void DestroyImpl();
 
       private:
         virtual void SetLabelImpl();
diff --git a/src/dawn_native/PipelineLayout.cpp b/src/dawn_native/PipelineLayout.cpp
index eb23756..9e11a3d 100644
--- a/src/dawn_native/PipelineLayout.cpp
+++ b/src/dawn_native/PipelineLayout.cpp
@@ -85,8 +85,8 @@
 
     PipelineLayoutBase::~PipelineLayoutBase() = default;
 
-    bool PipelineLayoutBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+    bool PipelineLayoutBase::Destroy() {
+        bool wasDestroyed = ApiObjectBase::Destroy();
         if (wasDestroyed && IsCachedReference()) {
             // Do not uncache the actual cached object if we are a blueprint
             GetDevice()->UncachePipelineLayout(this);
diff --git a/src/dawn_native/PipelineLayout.h b/src/dawn_native/PipelineLayout.h
index 597de45..1e4d873 100644
--- a/src/dawn_native/PipelineLayout.h
+++ b/src/dawn_native/PipelineLayout.h
@@ -61,7 +61,7 @@
             DeviceBase* device,
             std::vector<StageAndDescriptor> stages);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         const BindGroupLayoutBase* GetBindGroupLayout(BindGroupIndex group) const;
diff --git a/src/dawn_native/QuerySet.cpp b/src/dawn_native/QuerySet.cpp
index 855277d..88fff48 100644
--- a/src/dawn_native/QuerySet.cpp
+++ b/src/dawn_native/QuerySet.cpp
@@ -31,7 +31,7 @@
             }
 
           private:
-            void DestroyApiObjectImpl() override {
+            void DestroyImpl() override {
                 UNREACHABLE();
             }
         };
@@ -126,9 +126,9 @@
         ASSERT(mState == QuerySetState::Unavailable || mState == QuerySetState::Destroyed);
     }
 
-    bool QuerySetBase::DestroyApiObject() {
+    bool QuerySetBase::Destroy() {
         mState = QuerySetState::Destroyed;
-        return ApiObjectBase::DestroyApiObject();
+        return ApiObjectBase::Destroy();
     }
 
     // static
@@ -170,7 +170,7 @@
         if (GetDevice()->ConsumedError(ValidateDestroy())) {
             return;
         }
-        DestroyApiObject();
+        Destroy();
     }
 
     MaybeError QuerySetBase::ValidateDestroy() const {
diff --git a/src/dawn_native/QuerySet.h b/src/dawn_native/QuerySet.h
index d2a0263..08e0b74 100644
--- a/src/dawn_native/QuerySet.h
+++ b/src/dawn_native/QuerySet.h
@@ -31,7 +31,7 @@
 
         static QuerySetBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         wgpu::QueryType GetQueryType() const;
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index d130513..833ccff 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -683,8 +683,8 @@
 
     RenderPipelineBase::~RenderPipelineBase() = default;
 
-    bool RenderPipelineBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+    bool RenderPipelineBase::Destroy() {
+        bool wasDestroyed = ApiObjectBase::Destroy();
         if (wasDestroyed && IsCachedReference()) {
             // Do not uncache the actual cached object if we are a blueprint or already destroyed.
             GetDevice()->UncacheRenderPipeline(this);
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index b69b6ed..083188e 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -63,7 +63,7 @@
 
         static RenderPipelineBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
diff --git a/src/dawn_native/Sampler.cpp b/src/dawn_native/Sampler.cpp
index 94c26dd..5d73aea 100644
--- a/src/dawn_native/Sampler.cpp
+++ b/src/dawn_native/Sampler.cpp
@@ -100,8 +100,8 @@
 
     SamplerBase::~SamplerBase() = default;
 
-    bool SamplerBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+    bool SamplerBase::Destroy() {
+        bool wasDestroyed = ApiObjectBase::Destroy();
         if (wasDestroyed && IsCachedReference()) {
             // Do not uncache the actual cached object if we are a blueprint or already destroyed.
             GetDevice()->UncacheSampler(this);
diff --git a/src/dawn_native/Sampler.h b/src/dawn_native/Sampler.h
index 6d9e945..97cc4cc 100644
--- a/src/dawn_native/Sampler.h
+++ b/src/dawn_native/Sampler.h
@@ -38,7 +38,7 @@
 
         static SamplerBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         bool IsComparison() const;
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 4f4cc3c..d1168f5 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -1204,8 +1204,8 @@
 
     ShaderModuleBase::~ShaderModuleBase() = default;
 
-    bool ShaderModuleBase::DestroyApiObject() {
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+    bool ShaderModuleBase::Destroy() {
+        bool wasDestroyed = ApiObjectBase::Destroy();
         if (wasDestroyed && IsCachedReference()) {
             // Do not uncache the actual cached object if we are a blueprint or already destroyed.
             GetDevice()->UncacheShaderModule(this);
diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h
index 2b13a21..4c69343 100644
--- a/src/dawn_native/ShaderModule.h
+++ b/src/dawn_native/ShaderModule.h
@@ -248,7 +248,7 @@
 
         static Ref<ShaderModuleBase> MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         // Return true iff the program has an entrypoint called `entryPoint`.
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index cdfb9ce..5cb547a 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -483,12 +483,12 @@
         : ApiObjectBase(device, tag), mFormat(kUnusedFormat) {
     }
 
-    bool TextureBase::DestroyApiObject() {
+    bool TextureBase::Destroy() {
         // We need to run the destroy operations prior to setting the state to destroyed so that
         // the state is both consistent, and implementations of the destroy that may check the
         // state do not skip operations unintentionally. (Example in Vulkan backend, the destroy
         // implementation will not be ran if we are already in the Destroyed state.)
-        bool wasDestroyed = ApiObjectBase::DestroyApiObject();
+        bool wasDestroyed = ApiObjectBase::Destroy();
         mState = TextureState::Destroyed;
         return wasDestroyed;
     }
@@ -686,7 +686,7 @@
             return;
         }
         ASSERT(!IsError());
-        DestroyApiObject();
+        Destroy();
     }
 
     MaybeError TextureBase::ValidateDestroy() const {
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index e16be44..dee515b 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -51,7 +51,7 @@
 
         static TextureBase* MakeError(DeviceBase* device);
 
-        bool DestroyApiObject() override;
+        bool Destroy() override;
         ObjectType GetType() const override;
 
         wgpu::TextureDimension GetDimension() const;
diff --git a/src/dawn_native/d3d12/BindGroupD3D12.cpp b/src/dawn_native/d3d12/BindGroupD3D12.cpp
index 485d220..3960b51 100644
--- a/src/dawn_native/d3d12/BindGroupD3D12.cpp
+++ b/src/dawn_native/d3d12/BindGroupD3D12.cpp
@@ -207,7 +207,7 @@
 
     BindGroup::~BindGroup() = default;
 
-    void BindGroup::DestroyApiObjectImpl() {
+    void BindGroup::DestroyImpl() {
         ToBackend(GetLayout())->DeallocateBindGroup(this, &mCPUViewAllocation);
         ASSERT(!mCPUViewAllocation.IsValid());
     }
diff --git a/src/dawn_native/d3d12/BindGroupD3D12.h b/src/dawn_native/d3d12/BindGroupD3D12.h
index 7ffda1d..a59590e 100644
--- a/src/dawn_native/d3d12/BindGroupD3D12.h
+++ b/src/dawn_native/d3d12/BindGroupD3D12.h
@@ -48,7 +48,7 @@
       private:
         ~BindGroup() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         Ref<SamplerHeapCacheEntry> mSamplerAllocationEntry;
 
diff --git a/src/dawn_native/d3d12/BufferD3D12.cpp b/src/dawn_native/d3d12/BufferD3D12.cpp
index 91f2c00..301b952 100644
--- a/src/dawn_native/d3d12/BufferD3D12.cpp
+++ b/src/dawn_native/d3d12/BufferD3D12.cpp
@@ -378,7 +378,7 @@
         return mMappedData;
     }
 
-    void Buffer::DestroyApiObjectImpl() {
+    void Buffer::DestroyImpl() {
         // TODO(crbug.com/dawn/1189) Reintroduce optimization to skip flushing the writes to the GPU
         // memory when we unmap in destruction case since the buffer will be destroyed anyways.
         ToBackend(GetDevice())->DeallocateMemory(mResourceAllocation);
diff --git a/src/dawn_native/d3d12/BufferD3D12.h b/src/dawn_native/d3d12/BufferD3D12.h
index eb9191f..d6fcbbd 100644
--- a/src/dawn_native/d3d12/BufferD3D12.h
+++ b/src/dawn_native/d3d12/BufferD3D12.h
@@ -58,7 +58,7 @@
         MaybeError Initialize(bool mappedAtCreation);
         MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
         void UnmapImpl() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         bool IsCPUWritableAtCreation() const override;
         virtual MaybeError MapAtCreationImpl() override;
         void* GetMappedPointerImpl() override;
diff --git a/src/dawn_native/d3d12/ComputePipelineD3D12.cpp b/src/dawn_native/d3d12/ComputePipelineD3D12.cpp
index 1cbbdc5..f73f1da 100644
--- a/src/dawn_native/d3d12/ComputePipelineD3D12.cpp
+++ b/src/dawn_native/d3d12/ComputePipelineD3D12.cpp
@@ -64,7 +64,7 @@
 
     ComputePipeline::~ComputePipeline() = default;
 
-    void ComputePipeline::DestroyApiObjectImpl() {
+    void ComputePipeline::DestroyImpl() {
         ToBackend(GetDevice())->ReferenceUntilUnused(mPipelineState);
     }
 
diff --git a/src/dawn_native/d3d12/ComputePipelineD3D12.h b/src/dawn_native/d3d12/ComputePipelineD3D12.h
index 0bf9254..fdba24f 100644
--- a/src/dawn_native/d3d12/ComputePipelineD3D12.h
+++ b/src/dawn_native/d3d12/ComputePipelineD3D12.h
@@ -45,7 +45,7 @@
       private:
         ~ComputePipeline() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         using ComputePipelineBase::ComputePipelineBase;
         ComPtr<ID3D12PipelineState> mPipelineState;
diff --git a/src/dawn_native/d3d12/QuerySetD3D12.cpp b/src/dawn_native/d3d12/QuerySetD3D12.cpp
index f766933..0c778fc 100644
--- a/src/dawn_native/d3d12/QuerySetD3D12.cpp
+++ b/src/dawn_native/d3d12/QuerySetD3D12.cpp
@@ -57,7 +57,7 @@
 
     QuerySet::~QuerySet() = default;
 
-    void QuerySet::DestroyApiObjectImpl() {
+    void QuerySet::DestroyImpl() {
         ToBackend(GetDevice())->ReferenceUntilUnused(mQueryHeap);
         mQueryHeap = nullptr;
     }
diff --git a/src/dawn_native/d3d12/QuerySetD3D12.h b/src/dawn_native/d3d12/QuerySetD3D12.h
index dc2c157..16c49d1 100644
--- a/src/dawn_native/d3d12/QuerySetD3D12.h
+++ b/src/dawn_native/d3d12/QuerySetD3D12.h
@@ -35,7 +35,7 @@
         MaybeError Initialize();
 
         // Dawn API
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         ComPtr<ID3D12QueryHeap> mQueryHeap;
     };
diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
index 6718e79..44fd0c4 100644
--- a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
+++ b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
@@ -419,7 +419,7 @@
 
     RenderPipeline::~RenderPipeline() = default;
 
-    void RenderPipeline::DestroyApiObjectImpl() {
+    void RenderPipeline::DestroyImpl() {
         ToBackend(GetDevice())->ReferenceUntilUnused(mPipelineState);
     }
 
diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.h b/src/dawn_native/d3d12/RenderPipelineD3D12.h
index 251b16e..66f0ea6 100644
--- a/src/dawn_native/d3d12/RenderPipelineD3D12.h
+++ b/src/dawn_native/d3d12/RenderPipelineD3D12.h
@@ -46,7 +46,7 @@
       private:
         ~RenderPipeline() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         using RenderPipelineBase::RenderPipelineBase;
         D3D12_INPUT_LAYOUT_DESC ComputeInputLayout(
diff --git a/src/dawn_native/d3d12/SwapChainD3D12.cpp b/src/dawn_native/d3d12/SwapChainD3D12.cpp
index 9fe83de..29a414c 100644
--- a/src/dawn_native/d3d12/SwapChainD3D12.cpp
+++ b/src/dawn_native/d3d12/SwapChainD3D12.cpp
@@ -143,7 +143,7 @@
 
     SwapChain::~SwapChain() = default;
 
-    void SwapChain::DestroyApiObjectImpl() {
+    void SwapChain::DestroyImpl() {
         DetachFromSurface();
     }
 
diff --git a/src/dawn_native/d3d12/SwapChainD3D12.h b/src/dawn_native/d3d12/SwapChainD3D12.h
index 9f951e4..8b9c8ae 100644
--- a/src/dawn_native/d3d12/SwapChainD3D12.h
+++ b/src/dawn_native/d3d12/SwapChainD3D12.h
@@ -48,7 +48,7 @@
       private:
         ~SwapChain() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         using NewSwapChainBase::NewSwapChainBase;
         MaybeError Initialize(NewSwapChainBase* previousSwapChain);
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index 95d4476..084634c 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -649,7 +649,7 @@
     Texture::~Texture() {
     }
 
-    void Texture::DestroyApiObjectImpl() {
+    void Texture::DestroyImpl() {
         Device* device = ToBackend(GetDevice());
 
         // In PIX's D3D12-only mode, there is no way to determine frame boundaries
diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h
index 6919e20..4d49d6f 100644
--- a/src/dawn_native/d3d12/TextureD3D12.h
+++ b/src/dawn_native/d3d12/TextureD3D12.h
@@ -105,7 +105,7 @@
 
         // Dawn API
         void SetLabelImpl() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         MaybeError ClearTexture(CommandRecordingContext* commandContext,
                                 const SubresourceRange& range,
diff --git a/src/dawn_native/metal/BindGroupMTL.h b/src/dawn_native/metal/BindGroupMTL.h
index da14250..9c87583 100644
--- a/src/dawn_native/metal/BindGroupMTL.h
+++ b/src/dawn_native/metal/BindGroupMTL.h
@@ -31,7 +31,7 @@
       private:
         ~BindGroup() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
     };
 
 }}  // namespace dawn_native::metal
diff --git a/src/dawn_native/metal/BindGroupMTL.mm b/src/dawn_native/metal/BindGroupMTL.mm
index aba1429..2d4b3c2 100644
--- a/src/dawn_native/metal/BindGroupMTL.mm
+++ b/src/dawn_native/metal/BindGroupMTL.mm
@@ -24,7 +24,7 @@
 
     BindGroup::~BindGroup() = default;
 
-    void BindGroup::DestroyApiObjectImpl() {
+    void BindGroup::DestroyImpl() {
         ToBackend(GetLayout())->DeallocateBindGroup(this);
     }
 
diff --git a/src/dawn_native/metal/BufferMTL.h b/src/dawn_native/metal/BufferMTL.h
index 13e89b9..c04a2e7 100644
--- a/src/dawn_native/metal/BufferMTL.h
+++ b/src/dawn_native/metal/BufferMTL.h
@@ -48,7 +48,7 @@
         ~Buffer() override;
         MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
         void UnmapImpl() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         void* GetMappedPointerImpl() override;
         bool IsCPUWritableAtCreation() const override;
         MaybeError MapAtCreationImpl() override;
diff --git a/src/dawn_native/metal/BufferMTL.mm b/src/dawn_native/metal/BufferMTL.mm
index 7ac489c..f2509eb 100644
--- a/src/dawn_native/metal/BufferMTL.mm
+++ b/src/dawn_native/metal/BufferMTL.mm
@@ -171,7 +171,7 @@
         // Nothing to do, Metal StorageModeShared buffers are always mapped.
     }
 
-    void Buffer::DestroyApiObjectImpl() {
+    void Buffer::DestroyImpl() {
         mMtlBuffer = nullptr;
     }
 
diff --git a/src/dawn_native/metal/QuerySetMTL.h b/src/dawn_native/metal/QuerySetMTL.h
index b77bd31..a7b1ad7 100644
--- a/src/dawn_native/metal/QuerySetMTL.h
+++ b/src/dawn_native/metal/QuerySetMTL.h
@@ -40,7 +40,7 @@
         MaybeError Initialize();
 
         // Dawn API
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         NSPRef<id<MTLBuffer>> mVisibilityBuffer;
         // Note that mCounterSampleBuffer cannot be an NSRef because the API_AVAILABLE macros don't
diff --git a/src/dawn_native/metal/QuerySetMTL.mm b/src/dawn_native/metal/QuerySetMTL.mm
index 9dea304..90bca0c 100644
--- a/src/dawn_native/metal/QuerySetMTL.mm
+++ b/src/dawn_native/metal/QuerySetMTL.mm
@@ -123,7 +123,7 @@
 
     QuerySet::~QuerySet() = default;
 
-    void QuerySet::DestroyApiObjectImpl() {
+    void QuerySet::DestroyImpl() {
         mVisibilityBuffer = nullptr;
 
         // mCounterSampleBuffer isn't an NSRef because API_AVAILABLE doesn't work will with
diff --git a/src/dawn_native/metal/SwapChainMTL.h b/src/dawn_native/metal/SwapChainMTL.h
index 2d76043..3b72163 100644
--- a/src/dawn_native/metal/SwapChainMTL.h
+++ b/src/dawn_native/metal/SwapChainMTL.h
@@ -47,7 +47,7 @@
         ~SwapChain() override;
 
       private:
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         using NewSwapChainBase::NewSwapChainBase;
         MaybeError Initialize(NewSwapChainBase* previousSwapChain);
diff --git a/src/dawn_native/metal/SwapChainMTL.mm b/src/dawn_native/metal/SwapChainMTL.mm
index 9ba8696..d61bf50 100644
--- a/src/dawn_native/metal/SwapChainMTL.mm
+++ b/src/dawn_native/metal/SwapChainMTL.mm
@@ -75,7 +75,7 @@
 
     SwapChain::~SwapChain() = default;
 
-    void SwapChain::DestroyApiObjectImpl() {
+    void SwapChain::DestroyImpl() {
         DetachFromSurface();
     }
 
diff --git a/src/dawn_native/metal/TextureMTL.h b/src/dawn_native/metal/TextureMTL.h
index be32b8e..bfcf02f 100644
--- a/src/dawn_native/metal/TextureMTL.h
+++ b/src/dawn_native/metal/TextureMTL.h
@@ -66,7 +66,7 @@
         void InitializeAsWrapping(const TextureDescriptor* descriptor,
                                   NSPRef<id<MTLTexture>> wrapped);
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         MaybeError ClearTexture(CommandRecordingContext* commandContext,
                                 const SubresourceRange& range,
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index 34d2694..4edde09 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -495,7 +495,7 @@
     Texture::~Texture() {
     }
 
-    void Texture::DestroyApiObjectImpl() {
+    void Texture::DestroyImpl() {
         mMtlTexture = nullptr;
     }
 
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index c07b0ca..1abeec4 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -329,7 +329,7 @@
     void Buffer::UnmapImpl() {
     }
 
-    void Buffer::DestroyApiObjectImpl() {
+    void Buffer::DestroyImpl() {
         ToBackend(GetDevice())->DecrementMemoryUsage(GetSize());
     }
 
@@ -345,7 +345,7 @@
         : QuerySetBase(device, descriptor) {
     }
 
-    void QuerySet::DestroyApiObjectImpl() {
+    void QuerySet::DestroyImpl() {
     }
 
     // Queue
diff --git a/src/dawn_native/null/DeviceNull.h b/src/dawn_native/null/DeviceNull.h
index 010d9d1..35e42cb 100644
--- a/src/dawn_native/null/DeviceNull.h
+++ b/src/dawn_native/null/DeviceNull.h
@@ -228,7 +228,7 @@
       private:
         MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
         void UnmapImpl() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         bool IsCPUWritableAtCreation() const override;
         MaybeError MapAtCreationImpl() override;
         void* GetMappedPointerImpl() override;
@@ -246,7 +246,7 @@
         QuerySet(Device* device, const QuerySetDescriptor* descriptor);
 
       private:
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
     };
 
     class Queue final : public QueueBase {
diff --git a/src/dawn_native/opengl/BindGroupGL.cpp b/src/dawn_native/opengl/BindGroupGL.cpp
index 0a43de2..70975a9 100644
--- a/src/dawn_native/opengl/BindGroupGL.cpp
+++ b/src/dawn_native/opengl/BindGroupGL.cpp
@@ -52,7 +52,7 @@
 
     BindGroup::~BindGroup() = default;
 
-    void BindGroup::DestroyApiObjectImpl() {
+    void BindGroup::DestroyImpl() {
         ToBackend(GetLayout())->DeallocateBindGroup(this);
     }
 
diff --git a/src/dawn_native/opengl/BindGroupGL.h b/src/dawn_native/opengl/BindGroupGL.h
index 39c990e..994795a 100644
--- a/src/dawn_native/opengl/BindGroupGL.h
+++ b/src/dawn_native/opengl/BindGroupGL.h
@@ -33,7 +33,7 @@
       private:
         ~BindGroup() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
     };
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/BufferGL.cpp b/src/dawn_native/opengl/BufferGL.cpp
index f03ce49..dc357a4 100644
--- a/src/dawn_native/opengl/BufferGL.cpp
+++ b/src/dawn_native/opengl/BufferGL.cpp
@@ -174,7 +174,7 @@
         mMappedData = nullptr;
     }
 
-    void Buffer::DestroyApiObjectImpl() {
+    void Buffer::DestroyImpl() {
         ToBackend(GetDevice())->gl.DeleteBuffers(1, &mBuffer);
         mBuffer = 0;
     }
diff --git a/src/dawn_native/opengl/BufferGL.h b/src/dawn_native/opengl/BufferGL.h
index fdba81b..2259161 100644
--- a/src/dawn_native/opengl/BufferGL.h
+++ b/src/dawn_native/opengl/BufferGL.h
@@ -42,7 +42,7 @@
         ~Buffer() override;
         MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
         void UnmapImpl() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         bool IsCPUWritableAtCreation() const override;
         MaybeError MapAtCreationImpl() override;
         void* GetMappedPointerImpl() override;
diff --git a/src/dawn_native/opengl/ComputePipelineGL.cpp b/src/dawn_native/opengl/ComputePipelineGL.cpp
index 42b3d72..53dc767 100644
--- a/src/dawn_native/opengl/ComputePipelineGL.cpp
+++ b/src/dawn_native/opengl/ComputePipelineGL.cpp
@@ -27,7 +27,7 @@
 
     ComputePipeline::~ComputePipeline() = default;
 
-    void ComputePipeline::DestroyApiObjectImpl() {
+    void ComputePipeline::DestroyImpl() {
         DeleteProgram(ToBackend(GetDevice())->gl);
     }
 
diff --git a/src/dawn_native/opengl/ComputePipelineGL.h b/src/dawn_native/opengl/ComputePipelineGL.h
index cba762c..f5646ba 100644
--- a/src/dawn_native/opengl/ComputePipelineGL.h
+++ b/src/dawn_native/opengl/ComputePipelineGL.h
@@ -38,7 +38,7 @@
       private:
         using ComputePipelineBase::ComputePipelineBase;
         ~ComputePipeline() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
     };
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/QuerySetGL.cpp b/src/dawn_native/opengl/QuerySetGL.cpp
index 6ec9041..bf85c46 100644
--- a/src/dawn_native/opengl/QuerySetGL.cpp
+++ b/src/dawn_native/opengl/QuerySetGL.cpp
@@ -24,7 +24,7 @@
 
     QuerySet::~QuerySet() = default;
 
-    void QuerySet::DestroyApiObjectImpl() {
+    void QuerySet::DestroyImpl() {
     }
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/QuerySetGL.h b/src/dawn_native/opengl/QuerySetGL.h
index cd16dc8..2a83bdd 100644
--- a/src/dawn_native/opengl/QuerySetGL.h
+++ b/src/dawn_native/opengl/QuerySetGL.h
@@ -28,7 +28,7 @@
       private:
         ~QuerySet() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
     };
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/opengl/RenderPipelineGL.cpp b/src/dawn_native/opengl/RenderPipelineGL.cpp
index 7a56927..2f8e372 100644
--- a/src/dawn_native/opengl/RenderPipelineGL.cpp
+++ b/src/dawn_native/opengl/RenderPipelineGL.cpp
@@ -236,7 +236,7 @@
 
     RenderPipeline::~RenderPipeline() = default;
 
-    void RenderPipeline::DestroyApiObjectImpl() {
+    void RenderPipeline::DestroyImpl() {
         const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
         gl.DeleteVertexArrays(1, &mVertexArrayObject);
         gl.BindVertexArray(0);
diff --git a/src/dawn_native/opengl/RenderPipelineGL.h b/src/dawn_native/opengl/RenderPipelineGL.h
index ce2cce3..75aab20 100644
--- a/src/dawn_native/opengl/RenderPipelineGL.h
+++ b/src/dawn_native/opengl/RenderPipelineGL.h
@@ -43,7 +43,7 @@
       private:
         RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
         ~RenderPipeline() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         void CreateVAOForVertexState();
 
diff --git a/src/dawn_native/opengl/SamplerGL.cpp b/src/dawn_native/opengl/SamplerGL.cpp
index b4c7c26..5799eca 100644
--- a/src/dawn_native/opengl/SamplerGL.cpp
+++ b/src/dawn_native/opengl/SamplerGL.cpp
@@ -78,7 +78,7 @@
 
     Sampler::~Sampler() = default;
 
-    void Sampler::DestroyApiObjectImpl() {
+    void Sampler::DestroyImpl() {
         const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
         gl.DeleteSamplers(1, &mFilteringHandle);
         gl.DeleteSamplers(1, &mNonFilteringHandle);
diff --git a/src/dawn_native/opengl/SamplerGL.h b/src/dawn_native/opengl/SamplerGL.h
index ab55626..f08930e 100644
--- a/src/dawn_native/opengl/SamplerGL.h
+++ b/src/dawn_native/opengl/SamplerGL.h
@@ -32,7 +32,7 @@
 
       private:
         ~Sampler() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         void SetupGLSampler(GLuint sampler, const SamplerDescriptor* descriptor, bool forceNearest);
 
diff --git a/src/dawn_native/opengl/TextureGL.cpp b/src/dawn_native/opengl/TextureGL.cpp
index 8fc3f0e..d798223 100644
--- a/src/dawn_native/opengl/TextureGL.cpp
+++ b/src/dawn_native/opengl/TextureGL.cpp
@@ -190,7 +190,7 @@
     Texture::~Texture() {
     }
 
-    void Texture::DestroyApiObjectImpl() {
+    void Texture::DestroyImpl() {
         if (GetTextureState() == TextureState::OwnedInternal) {
             ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
             mHandle = 0;
@@ -560,7 +560,7 @@
     TextureView::~TextureView() {
     }
 
-    void TextureView::DestroyApiObjectImpl() {
+    void TextureView::DestroyImpl() {
         if (mOwnsHandle) {
             ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
         }
diff --git a/src/dawn_native/opengl/TextureGL.h b/src/dawn_native/opengl/TextureGL.h
index 6f92134..28b35d3 100644
--- a/src/dawn_native/opengl/TextureGL.h
+++ b/src/dawn_native/opengl/TextureGL.h
@@ -41,7 +41,7 @@
       private:
         ~Texture() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         MaybeError ClearTexture(const SubresourceRange& range, TextureBase::ClearValue clearValue);
 
         GLuint mHandle;
@@ -57,7 +57,7 @@
 
       private:
         ~TextureView() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         GLuint mHandle;
         GLenum mTarget;
diff --git a/src/dawn_native/vulkan/BindGroupVk.cpp b/src/dawn_native/vulkan/BindGroupVk.cpp
index 7704d9b..f54eabd 100644
--- a/src/dawn_native/vulkan/BindGroupVk.cpp
+++ b/src/dawn_native/vulkan/BindGroupVk.cpp
@@ -160,7 +160,7 @@
 
     BindGroup::~BindGroup() = default;
 
-    void BindGroup::DestroyApiObjectImpl() {
+    void BindGroup::DestroyImpl() {
         ToBackend(GetLayout())->DeallocateBindGroup(this, &mDescriptorSetAllocation);
     }
 
diff --git a/src/dawn_native/vulkan/BindGroupVk.h b/src/dawn_native/vulkan/BindGroupVk.h
index de69ef6..de00a01 100644
--- a/src/dawn_native/vulkan/BindGroupVk.h
+++ b/src/dawn_native/vulkan/BindGroupVk.h
@@ -40,7 +40,7 @@
       private:
         ~BindGroup() override;
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         // The descriptor set in this allocation outlives the BindGroup because it is owned by
         // the BindGroupLayout which is referenced by the BindGroup.
diff --git a/src/dawn_native/vulkan/BufferVk.cpp b/src/dawn_native/vulkan/BufferVk.cpp
index 62b6e11..01ee392 100644
--- a/src/dawn_native/vulkan/BufferVk.cpp
+++ b/src/dawn_native/vulkan/BufferVk.cpp
@@ -329,7 +329,7 @@
         return memory;
     }
 
-    void Buffer::DestroyApiObjectImpl() {
+    void Buffer::DestroyImpl() {
         ToBackend(GetDevice())->GetResourceMemoryAllocator()->Deallocate(&mMemoryAllocation);
 
         if (mHandle != VK_NULL_HANDLE) {
diff --git a/src/dawn_native/vulkan/BufferVk.h b/src/dawn_native/vulkan/BufferVk.h
index 30703c8..3fcab60 100644
--- a/src/dawn_native/vulkan/BufferVk.h
+++ b/src/dawn_native/vulkan/BufferVk.h
@@ -65,7 +65,7 @@
 
         MaybeError MapAsyncImpl(wgpu::MapMode mode, size_t offset, size_t size) override;
         void UnmapImpl() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         bool IsCPUWritableAtCreation() const override;
         MaybeError MapAtCreationImpl() override;
         void* GetMappedPointerImpl() override;
diff --git a/src/dawn_native/vulkan/ComputePipelineVk.cpp b/src/dawn_native/vulkan/ComputePipelineVk.cpp
index adeb793..6ead4ab 100644
--- a/src/dawn_native/vulkan/ComputePipelineVk.cpp
+++ b/src/dawn_native/vulkan/ComputePipelineVk.cpp
@@ -91,7 +91,7 @@
 
     ComputePipeline::~ComputePipeline() = default;
 
-    void ComputePipeline::DestroyApiObjectImpl() {
+    void ComputePipeline::DestroyImpl() {
         if (mHandle != VK_NULL_HANDLE) {
             ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
             mHandle = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/ComputePipelineVk.h b/src/dawn_native/vulkan/ComputePipelineVk.h
index 6c04660..26bf4c2 100644
--- a/src/dawn_native/vulkan/ComputePipelineVk.h
+++ b/src/dawn_native/vulkan/ComputePipelineVk.h
@@ -42,7 +42,7 @@
 
       private:
         ~ComputePipeline() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         using ComputePipelineBase::ComputePipelineBase;
 
         VkPipeline mHandle = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/PipelineLayoutVk.cpp b/src/dawn_native/vulkan/PipelineLayoutVk.cpp
index 11d21d0..c83e89d 100644
--- a/src/dawn_native/vulkan/PipelineLayoutVk.cpp
+++ b/src/dawn_native/vulkan/PipelineLayoutVk.cpp
@@ -59,7 +59,7 @@
 
     PipelineLayout::~PipelineLayout() = default;
 
-    void PipelineLayout::DestroyApiObjectImpl() {
+    void PipelineLayout::DestroyImpl() {
         if (mHandle != VK_NULL_HANDLE) {
             ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
             mHandle = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/PipelineLayoutVk.h b/src/dawn_native/vulkan/PipelineLayoutVk.h
index 6d3144e..bf3e2c4 100644
--- a/src/dawn_native/vulkan/PipelineLayoutVk.h
+++ b/src/dawn_native/vulkan/PipelineLayoutVk.h
@@ -34,7 +34,7 @@
 
       private:
         ~PipelineLayout() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         using PipelineLayoutBase::PipelineLayoutBase;
         MaybeError Initialize();
diff --git a/src/dawn_native/vulkan/QuerySetVk.cpp b/src/dawn_native/vulkan/QuerySetVk.cpp
index 7a15296..643cb7d 100644
--- a/src/dawn_native/vulkan/QuerySetVk.cpp
+++ b/src/dawn_native/vulkan/QuerySetVk.cpp
@@ -96,7 +96,7 @@
 
     QuerySet::~QuerySet() = default;
 
-    void QuerySet::DestroyApiObjectImpl() {
+    void QuerySet::DestroyImpl() {
         if (mHandle != VK_NULL_HANDLE) {
             ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
             mHandle = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/QuerySetVk.h b/src/dawn_native/vulkan/QuerySetVk.h
index 03b0a7b..80e7bef 100644
--- a/src/dawn_native/vulkan/QuerySetVk.h
+++ b/src/dawn_native/vulkan/QuerySetVk.h
@@ -35,7 +35,7 @@
         using QuerySetBase::QuerySetBase;
         MaybeError Initialize();
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         VkQueryPool mHandle = VK_NULL_HANDLE;
     };
diff --git a/src/dawn_native/vulkan/RenderPipelineVk.cpp b/src/dawn_native/vulkan/RenderPipelineVk.cpp
index abb1462..41ef3a0 100644
--- a/src/dawn_native/vulkan/RenderPipelineVk.cpp
+++ b/src/dawn_native/vulkan/RenderPipelineVk.cpp
@@ -601,7 +601,7 @@
 
     RenderPipeline::~RenderPipeline() = default;
 
-    void RenderPipeline::DestroyApiObjectImpl() {
+    void RenderPipeline::DestroyImpl() {
         if (mHandle != VK_NULL_HANDLE) {
             ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
             mHandle = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/RenderPipelineVk.h b/src/dawn_native/vulkan/RenderPipelineVk.h
index b883aad..9cfd078 100644
--- a/src/dawn_native/vulkan/RenderPipelineVk.h
+++ b/src/dawn_native/vulkan/RenderPipelineVk.h
@@ -41,7 +41,7 @@
 
       private:
         ~RenderPipeline() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         using RenderPipelineBase::RenderPipelineBase;
 
         struct PipelineVertexInputStateCreateInfoTemporaryAllocations {
diff --git a/src/dawn_native/vulkan/SamplerVk.cpp b/src/dawn_native/vulkan/SamplerVk.cpp
index d859f35..d1736ca 100644
--- a/src/dawn_native/vulkan/SamplerVk.cpp
+++ b/src/dawn_native/vulkan/SamplerVk.cpp
@@ -107,7 +107,7 @@
 
     Sampler::~Sampler() = default;
 
-    void Sampler::DestroyApiObjectImpl() {
+    void Sampler::DestroyImpl() {
         if (mHandle != VK_NULL_HANDLE) {
             ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mHandle);
             mHandle = VK_NULL_HANDLE;
diff --git a/src/dawn_native/vulkan/SamplerVk.h b/src/dawn_native/vulkan/SamplerVk.h
index ce00667..5d6528c 100644
--- a/src/dawn_native/vulkan/SamplerVk.h
+++ b/src/dawn_native/vulkan/SamplerVk.h
@@ -33,7 +33,7 @@
 
       private:
         ~Sampler() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         using SamplerBase::SamplerBase;
         MaybeError Initialize(const SamplerDescriptor* descriptor);
 
diff --git a/src/dawn_native/vulkan/SwapChainVk.cpp b/src/dawn_native/vulkan/SwapChainVk.cpp
index 13a6490..642a1d9 100644
--- a/src/dawn_native/vulkan/SwapChainVk.cpp
+++ b/src/dawn_native/vulkan/SwapChainVk.cpp
@@ -225,7 +225,7 @@
 
     SwapChain::~SwapChain() = default;
 
-    void SwapChain::DestroyApiObjectImpl() {
+    void SwapChain::DestroyImpl() {
         DetachFromSurface();
     }
 
diff --git a/src/dawn_native/vulkan/SwapChainVk.h b/src/dawn_native/vulkan/SwapChainVk.h
index 6ab3f21..e93039b 100644
--- a/src/dawn_native/vulkan/SwapChainVk.h
+++ b/src/dawn_native/vulkan/SwapChainVk.h
@@ -53,7 +53,7 @@
       private:
         using NewSwapChainBase::NewSwapChainBase;
         MaybeError Initialize(NewSwapChainBase* previousSwapChain);
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
 
         struct Config {
             // Information that's passed to vulkan swapchain creation.
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 9b220f5..ed3fd41 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -792,7 +792,7 @@
         mSignalSemaphore = VK_NULL_HANDLE;
 
         // Destroy the texture so it can't be used again
-        DestroyApiObject();
+        Destroy();
         return {};
     }
 
@@ -808,7 +808,7 @@
         SetLabelHelper("Dawn_InternalTexture");
     }
 
-    void Texture::DestroyApiObjectImpl() {
+    void Texture::DestroyImpl() {
         if (GetTextureState() == TextureState::OwnedInternal) {
             Device* device = ToBackend(GetDevice());
 
@@ -1301,7 +1301,7 @@
     TextureView::~TextureView() {
     }
 
-    void TextureView::DestroyApiObjectImpl() {
+    void TextureView::DestroyImpl() {
         Device* device = ToBackend(GetTexture()->GetDevice());
 
         if (mHandle != VK_NULL_HANDLE) {
diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h
index d2f5676..27280b6 100644
--- a/src/dawn_native/vulkan/TextureVk.h
+++ b/src/dawn_native/vulkan/TextureVk.h
@@ -107,7 +107,7 @@
                                           external_memory::Service* externalMemoryService);
         void InitializeForSwapChain(VkImage nativeImage);
 
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         MaybeError ClearTexture(CommandRecordingContext* recordingContext,
                                 const SubresourceRange& range,
                                 TextureBase::ClearValue);
@@ -176,7 +176,7 @@
 
       private:
         ~TextureView() override;
-        void DestroyApiObjectImpl() override;
+        void DestroyImpl() override;
         using TextureViewBase::TextureViewBase;
         MaybeError Initialize(const TextureViewDescriptor* descriptor);
 
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index d903f8f..23671a9 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -144,6 +144,7 @@
   sources = [
     "unittests/native/mocks/BindGroupLayoutMock.h",
     "unittests/native/mocks/BindGroupMock.h",
+    "unittests/native/mocks/CommandBufferMock.h",
     "unittests/native/mocks/ComputePipelineMock.h",
     "unittests/native/mocks/DeviceMock.h",
     "unittests/native/mocks/ExternalTextureMock.h",
diff --git a/src/tests/unittests/native/DestroyObjectTests.cpp b/src/tests/unittests/native/DestroyObjectTests.cpp
index 7623a26..fee5ed9 100644
--- a/src/tests/unittests/native/DestroyObjectTests.cpp
+++ b/src/tests/unittests/native/DestroyObjectTests.cpp
@@ -18,6 +18,7 @@
 #include "mocks/BindGroupLayoutMock.h"
 #include "mocks/BindGroupMock.h"
 #include "mocks/BufferMock.h"
+#include "mocks/CommandBufferMock.h"
 #include "mocks/ComputePipelineMock.h"
 #include "mocks/DeviceMock.h"
 #include "mocks/ExternalTextureMock.h"
@@ -52,7 +53,7 @@
             }
             mTexture =
                 AcquireRef(new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal));
-            EXPECT_CALL(*mTexture.Get(), DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*mTexture.Get(), DestroyImpl).Times(1);
             return mTexture;
         }
 
@@ -61,7 +62,7 @@
                 return mPipelineLayout;
             }
             mPipelineLayout = AcquireRef(new PipelineLayoutMock(&mDevice));
-            EXPECT_CALL(*mPipelineLayout.Get(), DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*mPipelineLayout.Get(), DestroyImpl).Times(1);
             return mPipelineLayout;
         }
 
@@ -75,7 +76,7 @@
                 return vec4<f32>(0.0, 0.0, 0.0, 1.0);
             })"),
                 { ASSERT(false); }, mVsModule);
-            EXPECT_CALL(*mVsModule.Get(), DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*mVsModule.Get(), DestroyImpl).Times(1);
             return mVsModule;
         }
 
@@ -88,7 +89,7 @@
             [[stage(compute), workgroup_size(1)]] fn main() {
             })"),
                 { ASSERT(false); }, mCsModule);
-            EXPECT_CALL(*mCsModule.Get(), DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*mCsModule.Get(), DestroyImpl).Times(1);
             return mCsModule;
         }
 
@@ -105,10 +106,10 @@
 
     TEST_F(DestroyObjectTests, BindGroupExplicit) {
         BindGroupMock bindGroupMock(&mDevice);
-        EXPECT_CALL(bindGroupMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(bindGroupMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(bindGroupMock.IsAlive());
-        bindGroupMock.DestroyApiObject();
+        bindGroupMock.Destroy();
         EXPECT_FALSE(bindGroupMock.IsAlive());
     }
 
@@ -116,7 +117,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, BindGroupImplicit) {
         BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
-        EXPECT_CALL(*bindGroupMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*bindGroupMock, DestroyImpl).Times(1);
         {
             BindGroupDescriptor desc = {};
             Ref<BindGroupBase> bindGroup;
@@ -130,10 +131,10 @@
 
     TEST_F(DestroyObjectTests, BindGroupLayoutExplicit) {
         BindGroupLayoutMock bindGroupLayoutMock(&mDevice);
-        EXPECT_CALL(bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(bindGroupLayoutMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(bindGroupLayoutMock.IsAlive());
-        bindGroupLayoutMock.DestroyApiObject();
+        bindGroupLayoutMock.Destroy();
         EXPECT_FALSE(bindGroupLayoutMock.IsAlive());
     }
 
@@ -141,7 +142,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, BindGroupLayoutImplicit) {
         BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&mDevice);
-        EXPECT_CALL(*bindGroupLayoutMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*bindGroupLayoutMock, DestroyImpl).Times(1);
         {
             BindGroupLayoutDescriptor desc = {};
             Ref<BindGroupLayoutBase> bindGroupLayout;
@@ -157,10 +158,10 @@
     TEST_F(DestroyObjectTests, BufferExplicit) {
         {
             BufferMock bufferMock(&mDevice, BufferBase::BufferState::Unmapped);
-            EXPECT_CALL(bufferMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(bufferMock, DestroyImpl).Times(1);
 
             EXPECT_TRUE(bufferMock.IsAlive());
-            bufferMock.DestroyApiObject();
+            bufferMock.Destroy();
             EXPECT_FALSE(bufferMock.IsAlive());
         }
         {
@@ -168,11 +169,11 @@
             {
                 InSequence seq;
                 EXPECT_CALL(bufferMock, UnmapImpl).Times(1);
-                EXPECT_CALL(bufferMock, DestroyApiObjectImpl).Times(1);
+                EXPECT_CALL(bufferMock, DestroyImpl).Times(1);
             }
 
             EXPECT_TRUE(bufferMock.IsAlive());
-            bufferMock.DestroyApiObject();
+            bufferMock.Destroy();
             EXPECT_FALSE(bufferMock.IsAlive());
         }
     }
@@ -182,7 +183,7 @@
     TEST_F(DestroyObjectTests, BufferImplicit) {
         {
             BufferMock* bufferMock = new BufferMock(&mDevice, BufferBase::BufferState::Unmapped);
-            EXPECT_CALL(*bufferMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*bufferMock, DestroyImpl).Times(1);
             {
                 BufferDescriptor desc = {};
                 Ref<BufferBase> buffer;
@@ -198,7 +199,7 @@
             {
                 InSequence seq;
                 EXPECT_CALL(*bufferMock, UnmapImpl).Times(1);
-                EXPECT_CALL(*bufferMock, DestroyApiObjectImpl).Times(1);
+                EXPECT_CALL(*bufferMock, DestroyImpl).Times(1);
             }
             {
                 BufferDescriptor desc = {};
@@ -212,12 +213,37 @@
         }
     }
 
+    TEST_F(DestroyObjectTests, CommandBufferExplicit) {
+        CommandBufferMock commandBufferMock(&mDevice);
+        EXPECT_CALL(commandBufferMock, DestroyImpl).Times(1);
+
+        EXPECT_TRUE(commandBufferMock.IsAlive());
+        commandBufferMock.Destroy();
+        EXPECT_FALSE(commandBufferMock.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, CommandBufferImplicit) {
+        CommandBufferMock* commandBufferMock = new CommandBufferMock(&mDevice);
+        EXPECT_CALL(*commandBufferMock, DestroyImpl).Times(1);
+        {
+            CommandBufferDescriptor desc = {};
+            Ref<CommandBufferBase> commandBuffer;
+            EXPECT_CALL(mDevice, CreateCommandBuffer)
+                .WillOnce(Return(ByMove(AcquireRef(commandBufferMock))));
+            DAWN_ASSERT_AND_ASSIGN(commandBuffer, mDevice.CreateCommandBuffer(nullptr, &desc));
+
+            EXPECT_TRUE(commandBuffer->IsAlive());
+        }
+    }
+
     TEST_F(DestroyObjectTests, ComputePipelineExplicit) {
         ComputePipelineMock computePipelineMock(&mDevice);
-        EXPECT_CALL(computePipelineMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(computePipelineMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(computePipelineMock.IsAlive());
-        computePipelineMock.DestroyApiObject();
+        computePipelineMock.Destroy();
         EXPECT_FALSE(computePipelineMock.IsAlive());
     }
 
@@ -233,7 +259,7 @@
 
         // Compute pipelines are initialized during their creation via the device.
         EXPECT_CALL(*computePipelineMock, Initialize).Times(1);
-        EXPECT_CALL(*computePipelineMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*computePipelineMock, DestroyImpl).Times(1);
 
         {
             ComputePipelineDescriptor desc = {};
@@ -252,10 +278,10 @@
 
     TEST_F(DestroyObjectTests, ExternalTextureExplicit) {
         ExternalTextureMock externalTextureMock(&mDevice);
-        EXPECT_CALL(externalTextureMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(externalTextureMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(externalTextureMock.IsAlive());
-        externalTextureMock.DestroyApiObject();
+        externalTextureMock.Destroy();
         EXPECT_FALSE(externalTextureMock.IsAlive());
     }
 
@@ -270,10 +296,10 @@
 
     TEST_F(DestroyObjectTests, PipelineLayoutExplicit) {
         PipelineLayoutMock pipelineLayoutMock(&mDevice);
-        EXPECT_CALL(pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(pipelineLayoutMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(pipelineLayoutMock.IsAlive());
-        pipelineLayoutMock.DestroyApiObject();
+        pipelineLayoutMock.Destroy();
         EXPECT_FALSE(pipelineLayoutMock.IsAlive());
     }
 
@@ -281,7 +307,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, PipelineLayoutImplicit) {
         PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
-        EXPECT_CALL(*pipelineLayoutMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*pipelineLayoutMock, DestroyImpl).Times(1);
         {
             PipelineLayoutDescriptor desc = {};
             Ref<PipelineLayoutBase> pipelineLayout;
@@ -296,10 +322,10 @@
 
     TEST_F(DestroyObjectTests, QuerySetExplicit) {
         QuerySetMock querySetMock(&mDevice);
-        EXPECT_CALL(querySetMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(querySetMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(querySetMock.IsAlive());
-        querySetMock.DestroyApiObject();
+        querySetMock.Destroy();
         EXPECT_FALSE(querySetMock.IsAlive());
     }
 
@@ -307,7 +333,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, QuerySetImplicit) {
         QuerySetMock* querySetMock = new QuerySetMock(&mDevice);
-        EXPECT_CALL(*querySetMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*querySetMock, DestroyImpl).Times(1);
         {
             QuerySetDescriptor desc = {};
             Ref<QuerySetBase> querySet;
@@ -321,10 +347,10 @@
 
     TEST_F(DestroyObjectTests, RenderPipelineExplicit) {
         RenderPipelineMock renderPipelineMock(&mDevice);
-        EXPECT_CALL(renderPipelineMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(renderPipelineMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(renderPipelineMock.IsAlive());
-        renderPipelineMock.DestroyApiObject();
+        renderPipelineMock.Destroy();
         EXPECT_FALSE(renderPipelineMock.IsAlive());
     }
 
@@ -340,7 +366,7 @@
 
         // Render pipelines are initialized during their creation via the device.
         EXPECT_CALL(*renderPipelineMock, Initialize).Times(1);
-        EXPECT_CALL(*renderPipelineMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*renderPipelineMock, DestroyImpl).Times(1);
 
         {
             RenderPipelineDescriptor desc = {};
@@ -359,10 +385,10 @@
 
     TEST_F(DestroyObjectTests, SamplerExplicit) {
         SamplerMock samplerMock(&mDevice);
-        EXPECT_CALL(samplerMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(samplerMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(samplerMock.IsAlive());
-        samplerMock.DestroyApiObject();
+        samplerMock.Destroy();
         EXPECT_FALSE(samplerMock.IsAlive());
     }
 
@@ -370,7 +396,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, SamplerImplicit) {
         SamplerMock* samplerMock = new SamplerMock(&mDevice);
-        EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*samplerMock, DestroyImpl).Times(1);
         {
             SamplerDescriptor desc = {};
             Ref<SamplerBase> sampler;
@@ -385,10 +411,10 @@
 
     TEST_F(DestroyObjectTests, ShaderModuleExplicit) {
         ShaderModuleMock shaderModuleMock(&mDevice);
-        EXPECT_CALL(shaderModuleMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(shaderModuleMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(shaderModuleMock.IsAlive());
-        shaderModuleMock.DestroyApiObject();
+        shaderModuleMock.Destroy();
         EXPECT_FALSE(shaderModuleMock.IsAlive());
     }
 
@@ -396,7 +422,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, ShaderModuleImplicit) {
         ShaderModuleMock* shaderModuleMock = new ShaderModuleMock(&mDevice);
-        EXPECT_CALL(*shaderModuleMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*shaderModuleMock, DestroyImpl).Times(1);
         {
             ShaderModuleWGSLDescriptor wgslDesc;
             wgslDesc.source = R"(
@@ -417,10 +443,10 @@
 
     TEST_F(DestroyObjectTests, SwapChainExplicit) {
         SwapChainMock swapChainMock(&mDevice);
-        EXPECT_CALL(swapChainMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(swapChainMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(swapChainMock.IsAlive());
-        swapChainMock.DestroyApiObject();
+        swapChainMock.Destroy();
         EXPECT_FALSE(swapChainMock.IsAlive());
     }
 
@@ -428,7 +454,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, SwapChainImplicit) {
         SwapChainMock* swapChainMock = new SwapChainMock(&mDevice);
-        EXPECT_CALL(*swapChainMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*swapChainMock, DestroyImpl).Times(1);
         {
             SwapChainDescriptor desc = {};
             Ref<SwapChainBase> swapChain;
@@ -443,18 +469,18 @@
     TEST_F(DestroyObjectTests, TextureExplicit) {
         {
             TextureMock textureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
-            EXPECT_CALL(textureMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(textureMock, DestroyImpl).Times(1);
 
             EXPECT_TRUE(textureMock.IsAlive());
-            textureMock.DestroyApiObject();
+            textureMock.Destroy();
             EXPECT_FALSE(textureMock.IsAlive());
         }
         {
             TextureMock textureMock(&mDevice, TextureBase::TextureState::OwnedExternal);
-            EXPECT_CALL(textureMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(textureMock, DestroyImpl).Times(1);
 
             EXPECT_TRUE(textureMock.IsAlive());
-            textureMock.DestroyApiObject();
+            textureMock.Destroy();
             EXPECT_FALSE(textureMock.IsAlive());
         }
     }
@@ -465,7 +491,7 @@
         {
             TextureMock* textureMock =
                 new TextureMock(&mDevice, TextureBase::TextureState::OwnedInternal);
-            EXPECT_CALL(*textureMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*textureMock, DestroyImpl).Times(1);
             {
                 TextureDescriptor desc = {};
                 Ref<TextureBase> texture;
@@ -479,7 +505,7 @@
         {
             TextureMock* textureMock =
                 new TextureMock(&mDevice, TextureBase::TextureState::OwnedExternal);
-            EXPECT_CALL(*textureMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*textureMock, DestroyImpl).Times(1);
             {
                 TextureDescriptor desc = {};
                 Ref<TextureBase> texture;
@@ -494,10 +520,10 @@
 
     TEST_F(DestroyObjectTests, TextureViewExplicit) {
         TextureViewMock textureViewMock(GetTexture().Get());
-        EXPECT_CALL(textureViewMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(textureViewMock, DestroyImpl).Times(1);
 
         EXPECT_TRUE(textureViewMock.IsAlive());
-        textureViewMock.DestroyApiObject();
+        textureViewMock.Destroy();
         EXPECT_FALSE(textureViewMock.IsAlive());
     }
 
@@ -505,7 +531,7 @@
     // will also complain if there is a memory leak.
     TEST_F(DestroyObjectTests, TextureViewImplicit) {
         TextureViewMock* textureViewMock = new TextureViewMock(GetTexture().Get());
-        EXPECT_CALL(*textureViewMock, DestroyApiObjectImpl).Times(1);
+        EXPECT_CALL(*textureViewMock, DestroyImpl).Times(1);
         {
             TextureViewDescriptor desc = {};
             Ref<TextureViewBase> textureView;
@@ -524,6 +550,7 @@
         BindGroupMock* bindGroupMock = new BindGroupMock(&mDevice);
         BindGroupLayoutMock* bindGroupLayoutMock = new BindGroupLayoutMock(&mDevice);
         BufferMock* bufferMock = new BufferMock(&mDevice, BufferBase::BufferState::Unmapped);
+        CommandBufferMock* commandBufferMock = new CommandBufferMock(&mDevice);
         ComputePipelineMock* computePipelineMock = new ComputePipelineMock(&mDevice);
         PipelineLayoutMock* pipelineLayoutMock = new PipelineLayoutMock(&mDevice);
         QuerySetMock* querySetMock = new QuerySetMock(&mDevice);
@@ -536,18 +563,19 @@
         TextureViewMock* textureViewMock = new TextureViewMock(GetTexture().Get());
         {
             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(*textureViewMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*textureMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*querySetMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*samplerMock, DestroyApiObjectImpl).Times(1);
-            EXPECT_CALL(*bufferMock, DestroyApiObjectImpl).Times(1);
+            EXPECT_CALL(*commandBufferMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*renderPipelineMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*computePipelineMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*pipelineLayoutMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*swapChainMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*bindGroupMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*bindGroupLayoutMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*shaderModuleMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*textureViewMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*textureMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*querySetMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*samplerMock, DestroyImpl).Times(1);
+            EXPECT_CALL(*bufferMock, DestroyImpl).Times(1);
         }
 
         Ref<BindGroupBase> bindGroup;
@@ -577,6 +605,15 @@
             EXPECT_TRUE(buffer->IsAlive());
         }
 
+        Ref<CommandBufferBase> commandBuffer;
+        {
+            CommandBufferDescriptor desc = {};
+            EXPECT_CALL(mDevice, CreateCommandBuffer)
+                .WillOnce(Return(ByMove(AcquireRef(commandBufferMock))));
+            DAWN_ASSERT_AND_ASSIGN(commandBuffer, mDevice.CreateCommandBuffer(nullptr, &desc));
+            EXPECT_TRUE(commandBuffer->IsAlive());
+        }
+
         Ref<ComputePipelineBase> computePipeline;
         {
             // Compute pipelines usually set their hash values at construction, but the mock does
@@ -704,6 +741,7 @@
         EXPECT_FALSE(bindGroup->IsAlive());
         EXPECT_FALSE(bindGroupLayout->IsAlive());
         EXPECT_FALSE(buffer->IsAlive());
+        EXPECT_FALSE(commandBuffer->IsAlive());
         EXPECT_FALSE(computePipeline->IsAlive());
         EXPECT_FALSE(externalTexture->IsAlive());
         EXPECT_FALSE(pipelineLayout->IsAlive());
diff --git a/src/tests/unittests/native/mocks/BindGroupLayoutMock.h b/src/tests/unittests/native/mocks/BindGroupLayoutMock.h
index dcd8692..b4c4962 100644
--- a/src/tests/unittests/native/mocks/BindGroupLayoutMock.h
+++ b/src/tests/unittests/native/mocks/BindGroupLayoutMock.h
@@ -28,7 +28,7 @@
         }
         ~BindGroupLayoutMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/BindGroupMock.h b/src/tests/unittests/native/mocks/BindGroupMock.h
index e36dc84..af79cf6 100644
--- a/src/tests/unittests/native/mocks/BindGroupMock.h
+++ b/src/tests/unittests/native/mocks/BindGroupMock.h
@@ -28,7 +28,7 @@
         }
         ~BindGroupMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/BufferMock.h b/src/tests/unittests/native/mocks/BufferMock.h
index 4bf1ba7..e576e77 100644
--- a/src/tests/unittests/native/mocks/BufferMock.h
+++ b/src/tests/unittests/native/mocks/BufferMock.h
@@ -28,7 +28,7 @@
         }
         ~BufferMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
 
         MOCK_METHOD(MaybeError, MapAtCreationImpl, (), (override));
         MOCK_METHOD(MaybeError,
diff --git a/src/tests/unittests/native/mocks/CommandBufferMock.h b/src/tests/unittests/native/mocks/CommandBufferMock.h
new file mode 100644
index 0000000..52c6034
--- /dev/null
+++ b/src/tests/unittests/native/mocks/CommandBufferMock.h
@@ -0,0 +1,36 @@
+// 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_COMMANDBUFFER_MOCK_H_
+#define TESTS_UNITTESTS_NATIVE_MOCKS_COMMANDBUFFER_MOCK_H_
+
+#include "dawn_native/CommandBuffer.h"
+#include "dawn_native/Device.h"
+
+#include <gmock/gmock.h>
+
+namespace dawn_native {
+
+    class CommandBufferMock : public CommandBufferBase {
+      public:
+        CommandBufferMock(DeviceBase* device) : CommandBufferBase(device) {
+        }
+        ~CommandBufferMock() override = default;
+
+        MOCK_METHOD(void, DestroyImpl, (), (override));
+    };
+
+}  // namespace dawn_native
+
+#endif  // TESTS_UNITTESTS_NATIVE_MOCKS_COMMANDBUFFER_MOCK_H_
diff --git a/src/tests/unittests/native/mocks/ComputePipelineMock.h b/src/tests/unittests/native/mocks/ComputePipelineMock.h
index 6289b56..fbf9df6 100644
--- a/src/tests/unittests/native/mocks/ComputePipelineMock.h
+++ b/src/tests/unittests/native/mocks/ComputePipelineMock.h
@@ -30,7 +30,7 @@
 
         MOCK_METHOD(MaybeError, Initialize, (), (override));
         MOCK_METHOD(size_t, ComputeContentHash, (), (override));
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/ExternalTextureMock.h b/src/tests/unittests/native/mocks/ExternalTextureMock.h
index 617de3f..b61746c 100644
--- a/src/tests/unittests/native/mocks/ExternalTextureMock.h
+++ b/src/tests/unittests/native/mocks/ExternalTextureMock.h
@@ -28,7 +28,7 @@
         }
         ~ExternalTextureMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/PipelineLayoutMock.h b/src/tests/unittests/native/mocks/PipelineLayoutMock.h
index 4b9201a..036cffe 100644
--- a/src/tests/unittests/native/mocks/PipelineLayoutMock.h
+++ b/src/tests/unittests/native/mocks/PipelineLayoutMock.h
@@ -28,7 +28,7 @@
         }
         ~PipelineLayoutMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/QuerySetMock.h b/src/tests/unittests/native/mocks/QuerySetMock.h
index 56f2298..faf5f4b 100644
--- a/src/tests/unittests/native/mocks/QuerySetMock.h
+++ b/src/tests/unittests/native/mocks/QuerySetMock.h
@@ -28,7 +28,7 @@
         }
         ~QuerySetMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/RenderPipelineMock.h b/src/tests/unittests/native/mocks/RenderPipelineMock.h
index fa82ab5..8cba770 100644
--- a/src/tests/unittests/native/mocks/RenderPipelineMock.h
+++ b/src/tests/unittests/native/mocks/RenderPipelineMock.h
@@ -30,7 +30,7 @@
 
         MOCK_METHOD(MaybeError, Initialize, (), (override));
         MOCK_METHOD(size_t, ComputeContentHash, (), (override));
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/SamplerMock.h b/src/tests/unittests/native/mocks/SamplerMock.h
index ca9a6b0..7948eaa 100644
--- a/src/tests/unittests/native/mocks/SamplerMock.h
+++ b/src/tests/unittests/native/mocks/SamplerMock.h
@@ -28,7 +28,7 @@
         }
         ~SamplerMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native
diff --git a/src/tests/unittests/native/mocks/ShaderModuleMock.h b/src/tests/unittests/native/mocks/ShaderModuleMock.h
index c1c518f..e5e5cc5 100644
--- a/src/tests/unittests/native/mocks/ShaderModuleMock.h
+++ b/src/tests/unittests/native/mocks/ShaderModuleMock.h
@@ -31,7 +31,7 @@
         }
         ~ShaderModuleMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
 
         // Creates a shader module mock based on the wgsl source.
         static ResultOrError<Ref<ShaderModuleMock>> Create(DeviceBase* device, const char* source);
diff --git a/src/tests/unittests/native/mocks/SwapChainMock.h b/src/tests/unittests/native/mocks/SwapChainMock.h
index cee332b..c8a3f74 100644
--- a/src/tests/unittests/native/mocks/SwapChainMock.h
+++ b/src/tests/unittests/native/mocks/SwapChainMock.h
@@ -28,7 +28,7 @@
         }
         ~SwapChainMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
 
         MOCK_METHOD(void,
                     APIConfigure,
diff --git a/src/tests/unittests/native/mocks/TextureMock.h b/src/tests/unittests/native/mocks/TextureMock.h
index 2108cfe..1e2b6a4 100644
--- a/src/tests/unittests/native/mocks/TextureMock.h
+++ b/src/tests/unittests/native/mocks/TextureMock.h
@@ -29,7 +29,7 @@
         }
         ~TextureMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
     class TextureViewMock : public TextureViewBase {
@@ -38,7 +38,7 @@
         }
         ~TextureViewMock() override = default;
 
-        MOCK_METHOD(void, DestroyApiObjectImpl, (), (override));
+        MOCK_METHOD(void, DestroyImpl, (), (override));
     };
 
 }  // namespace dawn_native