Put the reference to DeviceBase in a new ObjectBase

ObjectBase will contain data that all WebGPU objects have such as a
pointer back to the device, a refcount (via inheriting from RefCounted),
a name, an error status etc.

BUG=dawn:24

Change-Id: I919e1a6d4a68811ceb6e503b2a793815c92f2528
Reviewed-on: https://dawn-review.googlesource.com/c/1620
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 10660d9..3fc7711 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -364,6 +364,8 @@
     "src/dawn_native/Forward.h",
     "src/dawn_native/InputState.cpp",
     "src/dawn_native/InputState.h",
+    "src/dawn_native/ObjectBase.cpp",
+    "src/dawn_native/ObjectBase.h",
     "src/dawn_native/PassResourceUsage.h",
     "src/dawn_native/PerStage.cpp",
     "src/dawn_native/PerStage.h",
diff --git a/src/dawn_native/BindGroup.cpp b/src/dawn_native/BindGroup.cpp
index fbf9fb8..637b4b2 100644
--- a/src/dawn_native/BindGroup.cpp
+++ b/src/dawn_native/BindGroup.cpp
@@ -26,7 +26,8 @@
     // BindGroup
 
     BindGroupBase::BindGroupBase(BindGroupBuilder* builder)
-        : mLayout(std::move(builder->mLayout)),
+        : ObjectBase(builder->GetDevice()),
+          mLayout(std::move(builder->mLayout)),
           mBindings(std::move(builder->mBindings)) {
     }
 
@@ -56,10 +57,6 @@
         return reinterpret_cast<TextureViewBase*>(mBindings[binding].Get());
     }
 
-    DeviceBase* BindGroupBase::GetDevice() const {
-        return mLayout->GetDevice();
-    }
-
     // BindGroupBuilder
 
     enum BindGroupSetProperties {
@@ -81,7 +78,7 @@
             return nullptr;
         }
 
-        return mDevice->CreateBindGroup(this);
+        return GetDevice()->CreateBindGroup(this);
     }
 
     void BindGroupBuilder::SetLayout(BindGroupLayoutBase* layout) {
@@ -130,7 +127,7 @@
             }
         }
 
-        SetBindingsBase(start, count, reinterpret_cast<RefCounted* const*>(bufferViews));
+        SetBindingsBase(start, count, reinterpret_cast<ObjectBase* const*>(bufferViews));
     }
 
     void BindGroupBuilder::SetSamplers(uint32_t start,
@@ -148,7 +145,7 @@
             }
         }
 
-        SetBindingsBase(start, count, reinterpret_cast<RefCounted* const*>(samplers));
+        SetBindingsBase(start, count, reinterpret_cast<ObjectBase* const*>(samplers));
     }
 
     void BindGroupBuilder::SetTextureViews(uint32_t start,
@@ -171,12 +168,12 @@
             }
         }
 
-        SetBindingsBase(start, count, reinterpret_cast<RefCounted* const*>(textureViews));
+        SetBindingsBase(start, count, reinterpret_cast<ObjectBase* const*>(textureViews));
     }
 
     void BindGroupBuilder::SetBindingsBase(uint32_t start,
                                            uint32_t count,
-                                           RefCounted* const* objects) {
+                                           ObjectBase* const* objects) {
         for (size_t i = start, j = 0; i < start + count; ++i, ++j) {
             mSetMask.set(i);
             mBindings[i] = objects[j];
diff --git a/src/dawn_native/BindGroup.h b/src/dawn_native/BindGroup.h
index cd4846e..115b825 100644
--- a/src/dawn_native/BindGroup.h
+++ b/src/dawn_native/BindGroup.h
@@ -19,7 +19,7 @@
 #include "dawn_native/BindGroupLayout.h"
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -28,7 +28,7 @@
 
 namespace dawn_native {
 
-    class BindGroupBase : public RefCounted {
+    class BindGroupBase : public ObjectBase {
       public:
         BindGroupBase(BindGroupBuilder* builder);
 
@@ -37,11 +37,9 @@
         SamplerBase* GetBindingAsSampler(size_t binding);
         TextureViewBase* GetBindingAsTextureView(size_t binding);
 
-        DeviceBase* GetDevice() const;
-
       private:
         Ref<BindGroupLayoutBase> mLayout;
-        std::array<Ref<RefCounted>, kMaxBindingsPerGroup> mBindings;
+        std::array<Ref<ObjectBase>, kMaxBindingsPerGroup> mBindings;
     };
 
     class BindGroupBuilder : public Builder<BindGroupBase> {
@@ -59,14 +57,14 @@
         friend class BindGroupBase;
 
         BindGroupBase* GetResultImpl() override;
-        void SetBindingsBase(uint32_t start, uint32_t count, RefCounted* const* objects);
+        void SetBindingsBase(uint32_t start, uint32_t count, ObjectBase* const* objects);
         bool SetBindingsValidationBase(uint32_t start, uint32_t count);
 
         std::bitset<kMaxBindingsPerGroup> mSetMask;
         int mPropertiesSet = 0;
 
         Ref<BindGroupLayoutBase> mLayout;
-        std::array<Ref<RefCounted>, kMaxBindingsPerGroup> mBindings;
+        std::array<Ref<ObjectBase>, kMaxBindingsPerGroup> mBindings;
     };
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/BindGroupLayout.cpp b/src/dawn_native/BindGroupLayout.cpp
index af89f56..b9306b7 100644
--- a/src/dawn_native/BindGroupLayout.cpp
+++ b/src/dawn_native/BindGroupLayout.cpp
@@ -79,7 +79,7 @@
     BindGroupLayoutBase::BindGroupLayoutBase(DeviceBase* device,
                                              const BindGroupLayoutDescriptor* descriptor,
                                              bool blueprint)
-        : mDevice(device), mIsBlueprint(blueprint) {
+        : ObjectBase(device), mIsBlueprint(blueprint) {
         for (uint32_t i = 0; i < descriptor->numBindings; ++i) {
             auto& binding = descriptor->bindings[i];
 
@@ -95,7 +95,7 @@
     BindGroupLayoutBase::~BindGroupLayoutBase() {
         // Do not uncache the actual cached object if we are a blueprint
         if (!mIsBlueprint) {
-            mDevice->UncacheBindGroupLayout(this);
+            GetDevice()->UncacheBindGroupLayout(this);
         }
     }
 
@@ -103,10 +103,6 @@
         return mBindingInfo;
     }
 
-    DeviceBase* BindGroupLayoutBase::GetDevice() const {
-        return mDevice;
-    }
-
     // BindGroupLayoutCacheFuncs
 
     size_t BindGroupLayoutCacheFuncs::operator()(const BindGroupLayoutBase* bgl) const {
diff --git a/src/dawn_native/BindGroupLayout.h b/src/dawn_native/BindGroupLayout.h
index 62cd8e3..3a1f454 100644
--- a/src/dawn_native/BindGroupLayout.h
+++ b/src/dawn_native/BindGroupLayout.h
@@ -18,7 +18,7 @@
 #include "common/Constants.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -30,7 +30,7 @@
     MaybeError ValidateBindGroupLayoutDescriptor(DeviceBase*,
                                                  const BindGroupLayoutDescriptor* descriptor);
 
-    class BindGroupLayoutBase : public RefCounted {
+    class BindGroupLayoutBase : public ObjectBase {
       public:
         BindGroupLayoutBase(DeviceBase* device,
                             const BindGroupLayoutDescriptor* descriptor,
@@ -44,10 +44,7 @@
         };
         const LayoutBindingInfo& GetBindingInfo() const;
 
-        DeviceBase* GetDevice() const;
-
       private:
-        DeviceBase* mDevice;
         LayoutBindingInfo mBindingInfo;
         bool mIsBlueprint = false;
     };
diff --git a/src/dawn_native/BlendState.cpp b/src/dawn_native/BlendState.cpp
index ef9e192..ba1a717 100644
--- a/src/dawn_native/BlendState.cpp
+++ b/src/dawn_native/BlendState.cpp
@@ -20,7 +20,8 @@
 
     // BlendStateBase
 
-    BlendStateBase::BlendStateBase(BlendStateBuilder* builder) : mBlendInfo(builder->mBlendInfo) {
+    BlendStateBase::BlendStateBase(BlendStateBuilder* builder)
+        : ObjectBase(builder->GetDevice()), mBlendInfo(builder->mBlendInfo) {
     }
 
     const BlendStateBase::BlendInfo& BlendStateBase::GetBlendInfo() const {
@@ -40,7 +41,7 @@
     }
 
     BlendStateBase* BlendStateBuilder::GetResultImpl() {
-        return mDevice->CreateBlendState(this);
+        return GetDevice()->CreateBlendState(this);
     }
 
     void BlendStateBuilder::SetBlendEnabled(bool blendEnabled) {
diff --git a/src/dawn_native/BlendState.h b/src/dawn_native/BlendState.h
index 636dc2f..695a524 100644
--- a/src/dawn_native/BlendState.h
+++ b/src/dawn_native/BlendState.h
@@ -17,13 +17,13 @@
 
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
 namespace dawn_native {
 
-    class BlendStateBase : public RefCounted {
+    class BlendStateBase : public ObjectBase {
       public:
         BlendStateBase(BlendStateBuilder* builder);
 
diff --git a/src/dawn_native/Buffer.cpp b/src/dawn_native/Buffer.cpp
index db113d6..145ed6e 100644
--- a/src/dawn_native/Buffer.cpp
+++ b/src/dawn_native/Buffer.cpp
@@ -50,7 +50,7 @@
     // Buffer
 
     BufferBase::BufferBase(DeviceBase* device, const BufferDescriptor* descriptor)
-        : mDevice(device), mSize(descriptor->size), mUsage(descriptor->usage) {
+        : ObjectBase(device), mSize(descriptor->size), mUsage(descriptor->usage) {
     }
 
     BufferBase::~BufferBase() {
@@ -61,11 +61,7 @@
     }
 
     BufferViewBuilder* BufferBase::CreateBufferViewBuilder() {
-        return new BufferViewBuilder(mDevice, this);
-    }
-
-    DeviceBase* BufferBase::GetDevice() const {
-        return mDevice;
+        return new BufferViewBuilder(GetDevice(), this);
     }
 
     uint32_t BufferBase::GetSize() const {
@@ -103,7 +99,7 @@
     }
 
     void BufferBase::SetSubData(uint32_t start, uint32_t count, const uint8_t* data) {
-        if (mDevice->ConsumedError(ValidateSetSubData(start, count))) {
+        if (GetDevice()->ConsumedError(ValidateSetSubData(start, count))) {
             return;
         }
 
@@ -114,7 +110,7 @@
                                   uint32_t size,
                                   dawnBufferMapReadCallback callback,
                                   dawnCallbackUserdata userdata) {
-        if (mDevice->ConsumedError(ValidateMap(start, size, dawn::BufferUsageBit::MapRead))) {
+        if (GetDevice()->ConsumedError(ValidateMap(start, size, dawn::BufferUsageBit::MapRead))) {
             callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata);
             return;
         }
@@ -134,7 +130,7 @@
                                    uint32_t size,
                                    dawnBufferMapWriteCallback callback,
                                    dawnCallbackUserdata userdata) {
-        if (mDevice->ConsumedError(ValidateMap(start, size, dawn::BufferUsageBit::MapWrite))) {
+        if (GetDevice()->ConsumedError(ValidateMap(start, size, dawn::BufferUsageBit::MapWrite))) {
             callback(DAWN_BUFFER_MAP_ASYNC_STATUS_ERROR, nullptr, userdata);
             return;
         }
@@ -151,7 +147,7 @@
     }
 
     void BufferBase::Unmap() {
-        if (mDevice->ConsumedError(ValidateUnmap())) {
+        if (GetDevice()->ConsumedError(ValidateUnmap())) {
             return;
         }
 
@@ -209,7 +205,10 @@
     // BufferViewBase
 
     BufferViewBase::BufferViewBase(BufferViewBuilder* builder)
-        : mBuffer(std::move(builder->mBuffer)), mSize(builder->mSize), mOffset(builder->mOffset) {
+        : ObjectBase(builder->GetDevice()),
+          mBuffer(std::move(builder->mBuffer)),
+          mSize(builder->mSize),
+          mOffset(builder->mOffset) {
     }
 
     BufferBase* BufferViewBase::GetBuffer() {
@@ -241,7 +240,7 @@
             return nullptr;
         }
 
-        return mDevice->CreateBufferView(this);
+        return GetDevice()->CreateBufferView(this);
     }
 
     void BufferViewBuilder::SetExtent(uint32_t offset, uint32_t size) {
diff --git a/src/dawn_native/Buffer.h b/src/dawn_native/Buffer.h
index 851a31d..a80032f 100644
--- a/src/dawn_native/Buffer.h
+++ b/src/dawn_native/Buffer.h
@@ -18,7 +18,7 @@
 #include "dawn_native/Builder.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -34,7 +34,7 @@
         dawn::BufferUsageBit::MapWrite | dawn::BufferUsageBit::TransferDst |
         dawn::BufferUsageBit::Storage;
 
-    class BufferBase : public RefCounted {
+    class BufferBase : public ObjectBase {
       public:
         BufferBase(DeviceBase* device, const BufferDescriptor* descriptor);
         ~BufferBase();
@@ -42,8 +42,6 @@
         uint32_t GetSize() const;
         dawn::BufferUsageBit GetUsage() const;
 
-        DeviceBase* GetDevice() const;
-
         // Dawn API
         BufferViewBuilder* CreateBufferViewBuilder();
         void SetSubData(uint32_t start, uint32_t count, const uint8_t* data);
@@ -75,7 +73,6 @@
                                dawn::BufferUsageBit requiredUsage) const;
         MaybeError ValidateUnmap() const;
 
-        DeviceBase* mDevice;
         uint32_t mSize;
         dawn::BufferUsageBit mUsage = dawn::BufferUsageBit::None;
 
@@ -87,7 +84,7 @@
         bool mIsMapped = false;
     };
 
-    class BufferViewBase : public RefCounted {
+    class BufferViewBase : public ObjectBase {
       public:
         BufferViewBase(BufferViewBuilder* builder);
 
diff --git a/src/dawn_native/Builder.cpp b/src/dawn_native/Builder.cpp
index e6b70ad..e9deb23 100644
--- a/src/dawn_native/Builder.cpp
+++ b/src/dawn_native/Builder.cpp
@@ -23,10 +23,6 @@
         return !mIsConsumed && !mGotStatus;
     }
 
-    DeviceBase* BuilderBase::GetDevice() {
-        return mDevice;
-    }
-
     void BuilderBase::HandleError(const char* message) {
         SetStatus(dawn::BuilderErrorStatus::Error, message);
     }
@@ -39,7 +35,7 @@
         mUserdata2 = userdata2;
     }
 
-    BuilderBase::BuilderBase(DeviceBase* device) : mDevice(device) {
+    BuilderBase::BuilderBase(DeviceBase* device) : ObjectBase(device) {
     }
 
     BuilderBase::~BuilderBase() {
@@ -59,7 +55,7 @@
         mStoredMessage = message;
     }
 
-    bool BuilderBase::HandleResult(RefCounted* result) {
+    bool BuilderBase::HandleResult(ObjectBase* result) {
         // GetResult can only be called once.
         ASSERT(!mIsConsumed);
         mIsConsumed = true;
@@ -80,7 +76,7 @@
 
             // Unhandled builder errors are promoted to device errors
             if (!mCallback)
-                mDevice->HandleError(("Unhandled builder error: " + mStoredMessage).c_str());
+                GetDevice()->HandleError(("Unhandled builder error: " + mStoredMessage).c_str());
         } else {
             ASSERT(mStoredStatus == dawn::BuilderErrorStatus::Success);
             ASSERT(mStoredMessage.empty());
diff --git a/src/dawn_native/Builder.h b/src/dawn_native/Builder.h
index 3739a51..19fef8e 100644
--- a/src/dawn_native/Builder.h
+++ b/src/dawn_native/Builder.h
@@ -16,7 +16,7 @@
 #define DAWNNATIVE_BUILDER_H_
 
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -35,19 +35,18 @@
     // builder "set" function performance validation inline. Because of this we have to store the
     // status in the builder and defer calling the callback to GetResult.
 
-    class BuilderBase : public RefCounted {
+    class BuilderBase : public ObjectBase {
       public:
         // Used by the auto-generated validation to prevent usage of the builder
         // after GetResult or an error.
         bool CanBeUsed() const;
-        DeviceBase* GetDevice();
 
         // Set the status of the builder to an error.
         void HandleError(const char* message);
 
         // Internal API, to be used by builder and BackendProcTable only.
         // Returns true for success cases, and calls the callback with appropriate status.
-        bool HandleResult(RefCounted* result);
+        bool HandleResult(ObjectBase* result);
 
         // Dawn API
         void SetErrorCallback(dawn::BuilderErrorCallback callback,
@@ -58,7 +57,6 @@
         BuilderBase(DeviceBase* device);
         ~BuilderBase();
 
-        DeviceBase* const mDevice;
         bool mGotStatus = false;
 
       private:
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
index 90e9f37..1f06adb 100644
--- a/src/dawn_native/CMakeLists.txt
+++ b/src/dawn_native/CMakeLists.txt
@@ -351,8 +351,8 @@
     ${DAWN_NATIVE_DIR}/Forward.h
     ${DAWN_NATIVE_DIR}/InputState.cpp
     ${DAWN_NATIVE_DIR}/InputState.h
-    ${DAWN_NATIVE_DIR}/RenderPipeline.cpp
-    ${DAWN_NATIVE_DIR}/RenderPipeline.h
+    ${DAWN_NATIVE_DIR}/ObjectBase.cpp
+    ${DAWN_NATIVE_DIR}/ObjectBase.h
     ${DAWN_NATIVE_DIR}/PassResourceUsage.h
     ${DAWN_NATIVE_DIR}/PerStage.cpp
     ${DAWN_NATIVE_DIR}/PerStage.h
@@ -364,12 +364,14 @@
     ${DAWN_NATIVE_DIR}/ProgrammablePassEncoder.h
     ${DAWN_NATIVE_DIR}/Queue.cpp
     ${DAWN_NATIVE_DIR}/Queue.h
+    ${DAWN_NATIVE_DIR}/RefCounted.cpp
+    ${DAWN_NATIVE_DIR}/RefCounted.h
     ${DAWN_NATIVE_DIR}/RenderPassDescriptor.cpp
     ${DAWN_NATIVE_DIR}/RenderPassDescriptor.h
     ${DAWN_NATIVE_DIR}/RenderPassEncoder.cpp
     ${DAWN_NATIVE_DIR}/RenderPassEncoder.h
-    ${DAWN_NATIVE_DIR}/RefCounted.cpp
-    ${DAWN_NATIVE_DIR}/RefCounted.h
+    ${DAWN_NATIVE_DIR}/RenderPipeline.cpp
+    ${DAWN_NATIVE_DIR}/RenderPipeline.h
     ${DAWN_NATIVE_DIR}/Sampler.cpp
     ${DAWN_NATIVE_DIR}/Sampler.h
     ${DAWN_NATIVE_DIR}/ShaderModule.cpp
diff --git a/src/dawn_native/CommandBuffer.cpp b/src/dawn_native/CommandBuffer.cpp
index 32c5caa..919f72c 100644
--- a/src/dawn_native/CommandBuffer.cpp
+++ b/src/dawn_native/CommandBuffer.cpp
@@ -286,11 +286,7 @@
     // CommandBuffer
 
     CommandBufferBase::CommandBufferBase(CommandBufferBuilder* builder)
-        : mDevice(builder->mDevice) {
-    }
-
-    DeviceBase* CommandBufferBase::GetDevice() {
-        return mDevice;
+        : ObjectBase(builder->GetDevice()) {
     }
 
     // CommandBufferBuilder
@@ -322,7 +318,7 @@
         mEncodingState = EncodingState::Finished;
 
         MoveToIterator();
-        return mDevice->CreateCommandBuffer(this);
+        return GetDevice()->CreateCommandBuffer(this);
     }
 
     void CommandBufferBuilder::MoveToIterator() {
@@ -590,7 +586,7 @@
         mAllocator.Allocate<BeginComputePassCmd>(Command::BeginComputePass);
 
         mEncodingState = EncodingState::ComputePass;
-        return new ComputePassEncoderBase(mDevice, this, &mAllocator);
+        return new ComputePassEncoderBase(GetDevice(), this, &mAllocator);
     }
 
     RenderPassEncoderBase* CommandBufferBuilder::BeginRenderPass(RenderPassDescriptorBase* info) {
@@ -599,7 +595,7 @@
         cmd->info = info;
 
         mEncodingState = EncodingState::RenderPass;
-        return new RenderPassEncoderBase(mDevice, this, &mAllocator);
+        return new RenderPassEncoderBase(GetDevice(), this, &mAllocator);
     }
 
     void CommandBufferBuilder::CopyBufferToBuffer(BufferBase* source,
diff --git a/src/dawn_native/CommandBuffer.h b/src/dawn_native/CommandBuffer.h
index 56d6251..553fe6e 100644
--- a/src/dawn_native/CommandBuffer.h
+++ b/src/dawn_native/CommandBuffer.h
@@ -20,8 +20,8 @@
 #include "dawn_native/Builder.h"
 #include "dawn_native/CommandAllocator.h"
 #include "dawn_native/Error.h"
+#include "dawn_native/ObjectBase.h"
 #include "dawn_native/PassResourceUsage.h"
-#include "dawn_native/RefCounted.h"
 
 #include <memory>
 #include <set>
@@ -39,14 +39,9 @@
 
     class CommandBufferBuilder;
 
-    class CommandBufferBase : public RefCounted {
+    class CommandBufferBase : public ObjectBase {
       public:
         CommandBufferBase(CommandBufferBuilder* builder);
-
-        DeviceBase* GetDevice();
-
-      private:
-        DeviceBase* mDevice;
     };
 
     class CommandBufferBuilder : public Builder<CommandBufferBase> {
diff --git a/src/dawn_native/ComputePipeline.h b/src/dawn_native/ComputePipeline.h
index 0e9e02d..1cea676 100644
--- a/src/dawn_native/ComputePipeline.h
+++ b/src/dawn_native/ComputePipeline.h
@@ -24,7 +24,7 @@
     MaybeError ValidateComputePipelineDescriptor(DeviceBase* device,
                                                  const ComputePipelineDescriptor* descriptor);
 
-    class ComputePipelineBase : public RefCounted, public PipelineBase {
+    class ComputePipelineBase : public PipelineBase {
       public:
         ComputePipelineBase(DeviceBase* device, const ComputePipelineDescriptor* descriptor);
     };
diff --git a/src/dawn_native/DepthStencilState.cpp b/src/dawn_native/DepthStencilState.cpp
index 5647d9e..9405cfa 100644
--- a/src/dawn_native/DepthStencilState.cpp
+++ b/src/dawn_native/DepthStencilState.cpp
@@ -21,7 +21,9 @@
     // DepthStencilStateBase
 
     DepthStencilStateBase::DepthStencilStateBase(DepthStencilStateBuilder* builder)
-        : mDepthInfo(builder->mDepthInfo), mStencilInfo(builder->mStencilInfo) {
+        : ObjectBase(builder->GetDevice()),
+          mDepthInfo(builder->mDepthInfo),
+          mStencilInfo(builder->mStencilInfo) {
     }
 
     bool DepthStencilStateBase::StencilTestEnabled() const {
@@ -57,7 +59,7 @@
     }
 
     DepthStencilStateBase* DepthStencilStateBuilder::GetResultImpl() {
-        return mDevice->CreateDepthStencilState(this);
+        return GetDevice()->CreateDepthStencilState(this);
     }
 
     void DepthStencilStateBuilder::SetDepthCompareFunction(
diff --git a/src/dawn_native/DepthStencilState.h b/src/dawn_native/DepthStencilState.h
index cf687ba..87a8952 100644
--- a/src/dawn_native/DepthStencilState.h
+++ b/src/dawn_native/DepthStencilState.h
@@ -17,13 +17,13 @@
 
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
 namespace dawn_native {
 
-    class DepthStencilStateBase : public RefCounted {
+    class DepthStencilStateBase : public ObjectBase {
       public:
         DepthStencilStateBase(DepthStencilStateBuilder* builder);
 
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index 9ecd02a..dfa947a 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -17,7 +17,7 @@
 
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/DawnNative.h"
 #include "dawn_native/dawn_platform.h"
diff --git a/src/dawn_native/InputState.cpp b/src/dawn_native/InputState.cpp
index 54cbe97..6e818f9 100644
--- a/src/dawn_native/InputState.cpp
+++ b/src/dawn_native/InputState.cpp
@@ -84,7 +84,7 @@
 
     // InputStateBase
 
-    InputStateBase::InputStateBase(InputStateBuilder* builder) {
+    InputStateBase::InputStateBase(InputStateBuilder* builder) : ObjectBase(builder->GetDevice()) {
         mAttributesSetMask = builder->mAttributesSetMask;
         mAttributeInfos = builder->mAttributeInfos;
         mInputsSetMask = builder->mInputsSetMask;
@@ -123,7 +123,7 @@
             }
         }
 
-        return mDevice->CreateInputState(this);
+        return GetDevice()->CreateInputState(this);
     }
 
     void InputStateBuilder::SetAttribute(uint32_t shaderLocation,
diff --git a/src/dawn_native/InputState.h b/src/dawn_native/InputState.h
index 9c4b081..05519b2 100644
--- a/src/dawn_native/InputState.h
+++ b/src/dawn_native/InputState.h
@@ -18,7 +18,7 @@
 #include "common/Constants.h"
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -32,7 +32,7 @@
     size_t VertexFormatComponentSize(dawn::VertexFormat format);
     size_t VertexFormatSize(dawn::VertexFormat format);
 
-    class InputStateBase : public RefCounted {
+    class InputStateBase : public ObjectBase {
       public:
         InputStateBase(InputStateBuilder* builder);
 
diff --git a/src/dawn_native/ObjectBase.cpp b/src/dawn_native/ObjectBase.cpp
new file mode 100644
index 0000000..2d6b56f
--- /dev/null
+++ b/src/dawn_native/ObjectBase.cpp
@@ -0,0 +1,29 @@
+// Copyright 2018 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 "dawn_native/ObjectBase.h"
+
+namespace dawn_native {
+
+    ObjectBase::ObjectBase(DeviceBase* device) : mDevice(device) {
+    }
+
+    ObjectBase::~ObjectBase() {
+    }
+
+    DeviceBase* ObjectBase::GetDevice() const {
+        return mDevice;
+    }
+
+}  // namespace dawn_native
diff --git a/src/dawn_native/ObjectBase.h b/src/dawn_native/ObjectBase.h
new file mode 100644
index 0000000..019938a
--- /dev/null
+++ b/src/dawn_native/ObjectBase.h
@@ -0,0 +1,37 @@
+// Copyright 2018 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 DAWNNATIVE_OBJECTBASE_H_
+#define DAWNNATIVE_OBJECTBASE_H_
+
+#include "dawn_native/RefCounted.h"
+
+namespace dawn_native {
+
+    class DeviceBase;
+
+    class ObjectBase : public RefCounted {
+      public:
+        ObjectBase(DeviceBase* device);
+        virtual ~ObjectBase();
+
+        DeviceBase* GetDevice() const;
+
+      private:
+        DeviceBase* mDevice;
+    };
+
+}  // namespace dawn_native
+
+#endif  // DAWNNATIVE_OBJECTBASE_H_
diff --git a/src/dawn_native/Pipeline.cpp b/src/dawn_native/Pipeline.cpp
index d22b9f0..301ef0f 100644
--- a/src/dawn_native/Pipeline.cpp
+++ b/src/dawn_native/Pipeline.cpp
@@ -27,16 +27,19 @@
     PipelineBase::PipelineBase(DeviceBase* device,
                                PipelineLayoutBase* layout,
                                dawn::ShaderStageBit stages)
-        : mStageMask(stages), mLayout(layout), mDevice(device) {
+        : ObjectBase(device), mStageMask(stages), mLayout(layout), mDevice(device) {
     }
 
     PipelineBase::PipelineBase(DeviceBase* device, PipelineBuilder* builder)
-        : mStageMask(builder->mStageMask), mLayout(std::move(builder->mLayout)), mDevice(device) {
+        : ObjectBase(device),
+          mStageMask(builder->mStageMask),
+          mLayout(std::move(builder->mLayout)),
+          mDevice(device) {
         if (!mLayout) {
             PipelineLayoutDescriptor descriptor;
             descriptor.numBindGroupLayouts = 0;
             descriptor.bindGroupLayouts = nullptr;
-            mLayout = builder->GetParentBuilder()->GetDevice()->CreatePipelineLayout(&descriptor);
+            mLayout = device->CreatePipelineLayout(&descriptor);
             // Remove the external ref objects are created with
             mLayout->Release();
         }
diff --git a/src/dawn_native/Pipeline.h b/src/dawn_native/Pipeline.h
index 0453e8d..d91dc5b 100644
--- a/src/dawn_native/Pipeline.h
+++ b/src/dawn_native/Pipeline.h
@@ -17,9 +17,9 @@
 
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
+#include "dawn_native/ObjectBase.h"
 #include "dawn_native/PerStage.h"
 #include "dawn_native/PipelineLayout.h"
-#include "dawn_native/RefCounted.h"
 #include "dawn_native/ShaderModule.h"
 
 #include "dawn_native/dawn_platform.h"
@@ -37,7 +37,7 @@
 
     class PipelineBuilder;
 
-    class PipelineBase {
+    class PipelineBase : public ObjectBase {
       public:
         PipelineBase(DeviceBase* device, PipelineLayoutBase* layout, dawn::ShaderStageBit stages);
         PipelineBase(DeviceBase* device, PipelineBuilder* builder);
diff --git a/src/dawn_native/PipelineLayout.cpp b/src/dawn_native/PipelineLayout.cpp
index 3ade2fc..1ccb386 100644
--- a/src/dawn_native/PipelineLayout.cpp
+++ b/src/dawn_native/PipelineLayout.cpp
@@ -42,7 +42,7 @@
 
     PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
                                            const PipelineLayoutDescriptor* descriptor)
-        : mDevice(device) {
+        : ObjectBase(device) {
         ASSERT(descriptor->numBindGroupLayouts <= kMaxBindGroups);
         for (uint32_t group = 0; group < descriptor->numBindGroupLayouts; ++group) {
             mBindGroupLayouts[group] = descriptor->bindGroupLayouts[group];
@@ -73,8 +73,4 @@
         return kMaxBindGroups + 1;
     }
 
-    DeviceBase* PipelineLayoutBase::GetDevice() const {
-        return mDevice;
-    }
-
 }  // namespace dawn_native
diff --git a/src/dawn_native/PipelineLayout.h b/src/dawn_native/PipelineLayout.h
index 3d6b581..0d5e932 100644
--- a/src/dawn_native/PipelineLayout.h
+++ b/src/dawn_native/PipelineLayout.h
@@ -18,7 +18,7 @@
 #include "common/Constants.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -32,7 +32,7 @@
 
     using BindGroupLayoutArray = std::array<Ref<BindGroupLayoutBase>, kMaxBindGroups>;
 
-    class PipelineLayoutBase : public RefCounted {
+    class PipelineLayoutBase : public ObjectBase {
       public:
         PipelineLayoutBase(DeviceBase* device, const PipelineLayoutDescriptor* descriptor);
 
@@ -47,10 +47,7 @@
         // [1, kMaxBindGroups + 1]
         uint32_t GroupsInheritUpTo(const PipelineLayoutBase* other) const;
 
-        DeviceBase* GetDevice() const;
-
       protected:
-        DeviceBase* mDevice;
         BindGroupLayoutArray mBindGroupLayouts;
         std::bitset<kMaxBindGroups> mMask;
     };
diff --git a/src/dawn_native/ProgrammablePassEncoder.cpp b/src/dawn_native/ProgrammablePassEncoder.cpp
index 7b06146..86ec823 100644
--- a/src/dawn_native/ProgrammablePassEncoder.cpp
+++ b/src/dawn_native/ProgrammablePassEncoder.cpp
@@ -23,7 +23,7 @@
     ProgrammablePassEncoder::ProgrammablePassEncoder(DeviceBase* device,
                                                      CommandBufferBuilder* topLevelBuilder,
                                                      CommandAllocator* allocator)
-        : mDevice(device), mTopLevelBuilder(topLevelBuilder), mAllocator(allocator) {
+        : ObjectBase(device), mTopLevelBuilder(topLevelBuilder), mAllocator(allocator) {
     }
 
     void ProgrammablePassEncoder::EndPass() {
@@ -72,10 +72,6 @@
         memcpy(values, data, count * sizeof(uint32_t));
     }
 
-    DeviceBase* ProgrammablePassEncoder::GetDevice() const {
-        return mDevice;
-    }
-
     MaybeError ProgrammablePassEncoder::ValidateCanRecordCommands() const {
         if (mAllocator == nullptr) {
             return DAWN_VALIDATION_ERROR("Recording in an already ended computePassEncoder");
diff --git a/src/dawn_native/ProgrammablePassEncoder.h b/src/dawn_native/ProgrammablePassEncoder.h
index 8f59f7d..2606096 100644
--- a/src/dawn_native/ProgrammablePassEncoder.h
+++ b/src/dawn_native/ProgrammablePassEncoder.h
@@ -16,7 +16,7 @@
 #define DAWNNATIVE_PROGRAMMABLEPASSENCODER_H_
 
 #include "dawn_native/Error.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -26,7 +26,7 @@
     class DeviceBase;
 
     // Base class for shared functionality between ComputePassEncoder and RenderPassEncoder.
-    class ProgrammablePassEncoder : public RefCounted {
+    class ProgrammablePassEncoder : public ObjectBase {
       public:
         ProgrammablePassEncoder(DeviceBase* device,
                                 CommandBufferBuilder* topLevelBuilder,
@@ -40,13 +40,9 @@
                               uint32_t count,
                               const void* data);
 
-        DeviceBase* GetDevice() const;
-
       protected:
         MaybeError ValidateCanRecordCommands() const;
 
-        DeviceBase* mDevice;
-
         // The allocator is borrowed from the top level builder. Keep a reference to the builder
         // to make sure the allocator isn't freed.
         Ref<CommandBufferBuilder> mTopLevelBuilder = nullptr;
diff --git a/src/dawn_native/Queue.cpp b/src/dawn_native/Queue.cpp
index 384b1fe..46facf5 100644
--- a/src/dawn_native/Queue.cpp
+++ b/src/dawn_native/Queue.cpp
@@ -21,15 +21,11 @@
 
     // QueueBase
 
-    QueueBase::QueueBase(DeviceBase* device) : mDevice(device) {
-    }
-
-    DeviceBase* QueueBase::GetDevice() {
-        return mDevice;
+    QueueBase::QueueBase(DeviceBase* device) : ObjectBase(device) {
     }
 
     void QueueBase::Submit(uint32_t numCommands, CommandBufferBase* const* commands) {
-        if (mDevice->ConsumedError(ValidateSubmit(numCommands, commands))) {
+        if (GetDevice()->ConsumedError(ValidateSubmit(numCommands, commands))) {
             return;
         }
 
diff --git a/src/dawn_native/Queue.h b/src/dawn_native/Queue.h
index 6a356de..a9655f2 100644
--- a/src/dawn_native/Queue.h
+++ b/src/dawn_native/Queue.h
@@ -18,18 +18,16 @@
 #include "dawn_native/Builder.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
 namespace dawn_native {
 
-    class QueueBase : public RefCounted {
+    class QueueBase : public ObjectBase {
       public:
         QueueBase(DeviceBase* device);
 
-        DeviceBase* GetDevice();
-
         // Dawn API
         void Submit(uint32_t numCommands, CommandBufferBase* const* commands);
 
@@ -37,8 +35,6 @@
         virtual void SubmitImpl(uint32_t numCommands, CommandBufferBase* const* commands) = 0;
 
         MaybeError ValidateSubmit(uint32_t numCommands, CommandBufferBase* const* commands);
-
-        DeviceBase* mDevice;
     };
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/RenderPassDescriptor.cpp b/src/dawn_native/RenderPassDescriptor.cpp
index 8a3fd6a..6147d24 100644
--- a/src/dawn_native/RenderPassDescriptor.cpp
+++ b/src/dawn_native/RenderPassDescriptor.cpp
@@ -24,13 +24,13 @@
     // RenderPassDescriptor
 
     RenderPassDescriptorBase::RenderPassDescriptorBase(RenderPassDescriptorBuilder* builder)
-        : mColorAttachmentsSet(builder->mColorAttachmentsSet),
+        : ObjectBase(builder->GetDevice()),
+          mColorAttachmentsSet(builder->mColorAttachmentsSet),
           mColorAttachments(builder->mColorAttachments),
           mDepthStencilAttachmentSet(builder->mDepthStencilAttachmentSet),
           mDepthStencilAttachment(builder->mDepthStencilAttachment),
           mWidth(builder->mWidth),
-          mHeight(builder->mHeight),
-          mDevice(builder->GetDevice()) {
+          mHeight(builder->mHeight) {
     }
 
     std::bitset<kMaxColorAttachments> RenderPassDescriptorBase::GetColorAttachmentMask() const {
@@ -78,10 +78,6 @@
         return mHeight;
     }
 
-    DeviceBase* RenderPassDescriptorBase::GetDevice() const {
-        return mDevice;
-    }
-
     // RenderPassDescriptorBuilder
 
     RenderPassDescriptorBuilder::RenderPassDescriptorBuilder(DeviceBase* device) : Builder(device) {
@@ -126,7 +122,7 @@
             return nullptr;
         }
 
-        return mDevice->CreateRenderPassDescriptor(this);
+        return GetDevice()->CreateRenderPassDescriptor(this);
     }
 
     void RenderPassDescriptorBuilder::SetColorAttachment(uint32_t attachment,
diff --git a/src/dawn_native/RenderPassDescriptor.h b/src/dawn_native/RenderPassDescriptor.h
index 191f2ef..4079a15 100644
--- a/src/dawn_native/RenderPassDescriptor.h
+++ b/src/dawn_native/RenderPassDescriptor.h
@@ -18,7 +18,7 @@
 #include "common/Constants.h"
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -45,7 +45,7 @@
     // RenderPassDescriptor contains the list of attachments for a renderpass along with data such
     // as the load operation and the clear values for the attachments.
 
-    class RenderPassDescriptorBase : public RefCounted {
+    class RenderPassDescriptorBase : public ObjectBase {
       public:
         RenderPassDescriptorBase(RenderPassDescriptorBuilder* builder);
 
@@ -61,8 +61,6 @@
         uint32_t GetWidth() const;
         uint32_t GetHeight() const;
 
-        DeviceBase* GetDevice() const;
-
       private:
         std::bitset<kMaxColorAttachments> mColorAttachmentsSet;
         std::array<RenderPassColorAttachmentInfo, kMaxColorAttachments> mColorAttachments;
@@ -72,8 +70,6 @@
 
         uint32_t mWidth;
         uint32_t mHeight;
-
-        DeviceBase* mDevice;
     };
 
     class RenderPassDescriptorBuilder : public Builder<RenderPassDescriptorBase> {
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index 56b2c9d..047ad25 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -27,7 +27,7 @@
     // RenderPipelineBase
 
     RenderPipelineBase::RenderPipelineBase(RenderPipelineBuilder* builder)
-        : PipelineBase(builder->mDevice, builder),
+        : PipelineBase(builder->GetDevice(), builder),
           mDepthStencilState(std::move(builder->mDepthStencilState)),
           mIndexFormat(builder->mIndexFormat),
           mInputState(std::move(builder->mInputState)),
@@ -138,17 +138,18 @@
     }
 
     RenderPipelineBase* RenderPipelineBuilder::GetResultImpl() {
+        DeviceBase* device = GetDevice();
         // TODO(cwallez@chromium.org): the layout should be required, and put the default objects in
         // the device
         if (!mInputState) {
-            auto builder = mDevice->CreateInputStateBuilder();
+            auto builder = device->CreateInputStateBuilder();
             mInputState = builder->GetResult();
             // Remove the external ref objects are created with
             mInputState->Release();
             builder->Release();
         }
         if (!mDepthStencilState) {
-            auto builder = mDevice->CreateDepthStencilStateBuilder();
+            auto builder = device->CreateDepthStencilStateBuilder();
             mDepthStencilState = builder->GetResult();
             // Remove the external ref objects are created with
             mDepthStencilState->Release();
@@ -163,12 +164,12 @@
         // Assign all color attachments without a blend state the default state
         // TODO(enga@google.com): Put the default objects in the device
         for (uint32_t attachmentSlot : IterateBitSet(mColorAttachmentsSet & ~mBlendStatesSet)) {
-            mBlendStates[attachmentSlot] = mDevice->CreateBlendStateBuilder()->GetResult();
+            mBlendStates[attachmentSlot] = device->CreateBlendStateBuilder()->GetResult();
             // Remove the external ref objects are created with
             mBlendStates[attachmentSlot]->Release();
         }
 
-        return mDevice->CreateRenderPipeline(this);
+        return device->CreateRenderPipeline(this);
     }
 
     void RenderPipelineBuilder::SetColorAttachmentFormat(uint32_t attachmentSlot,
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index a192d61..73362e7 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -27,7 +27,7 @@
 
 namespace dawn_native {
 
-    class RenderPipelineBase : public RefCounted, public PipelineBase {
+    class RenderPipelineBase : public PipelineBase {
       public:
         RenderPipelineBase(RenderPipelineBuilder* builder);
 
diff --git a/src/dawn_native/Sampler.cpp b/src/dawn_native/Sampler.cpp
index 1c3c76b..71cca99 100644
--- a/src/dawn_native/Sampler.cpp
+++ b/src/dawn_native/Sampler.cpp
@@ -34,7 +34,7 @@
 
     // SamplerBase
 
-    SamplerBase::SamplerBase(DeviceBase*, const SamplerDescriptor*) {
+    SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor*) : ObjectBase(device) {
     }
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/Sampler.h b/src/dawn_native/Sampler.h
index 5134bb3..a9d547a 100644
--- a/src/dawn_native/Sampler.h
+++ b/src/dawn_native/Sampler.h
@@ -16,7 +16,7 @@
 #define DAWNNATIVE_SAMPLER_H_
 
 #include "dawn_native/Error.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -26,7 +26,7 @@
 
     MaybeError ValidateSamplerDescriptor(DeviceBase* device, const SamplerDescriptor* descriptor);
 
-    class SamplerBase : public RefCounted {
+    class SamplerBase : public ObjectBase {
       public:
         SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor);
     };
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 21ce155..d125409 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -66,14 +66,11 @@
     // ShaderModuleBase
 
     ShaderModuleBase::ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor*)
-        : mDevice(device) {
-    }
-
-    DeviceBase* ShaderModuleBase::GetDevice() const {
-        return mDevice;
+        : ObjectBase(device) {
     }
 
     void ShaderModuleBase::ExtractSpirvInfo(const spirv_cross::Compiler& compiler) {
+        DeviceBase* device = GetDevice();
         // TODO(cwallez@chromium.org): make errors here builder-level
         // currently errors here do not prevent the shadermodule from being used
         const auto& resources = compiler.get_shader_resources();
@@ -132,7 +129,7 @@
                 }
 
                 if (offset + size > kMaxPushConstants) {
-                    mDevice->HandleError("Push constant block too big in the SPIRV");
+                    device->HandleError("Push constant block too big in the SPIRV");
                     return;
                 }
 
@@ -157,7 +154,7 @@
                 uint32_t set = compiler.get_decoration(resource.id, spv::DecorationDescriptorSet);
 
                 if (binding >= kMaxBindingsPerGroup || set >= kMaxBindGroups) {
-                    mDevice->HandleError("Binding over limits in the SPIRV");
+                    GetDevice()->HandleError("Binding over limits in the SPIRV");
                     continue;
                 }
 
@@ -184,7 +181,7 @@
                 uint32_t location = compiler.get_decoration(attrib.id, spv::DecorationLocation);
 
                 if (location >= kMaxVertexAttributes) {
-                    mDevice->HandleError("Attribute location over limits in the SPIRV");
+                    device->HandleError("Attribute location over limits in the SPIRV");
                     return;
                 }
 
@@ -195,7 +192,7 @@
             // all the location 0, causing a compile error.
             for (const auto& attrib : resources.stage_outputs) {
                 if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
-                    mDevice->HandleError("Need location qualifier on vertex output");
+                    device->HandleError("Need location qualifier on vertex output");
                     return;
                 }
             }
@@ -206,7 +203,7 @@
             // all the location 0, causing a compile error.
             for (const auto& attrib : resources.stage_inputs) {
                 if (!compiler.get_decoration_bitset(attrib.id).get(spv::DecorationLocation)) {
-                    mDevice->HandleError("Need location qualifier on fragment input");
+                    device->HandleError("Need location qualifier on fragment input");
                     return;
                 }
             }
diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h
index c9a6085..1d0fcf1 100644
--- a/src/dawn_native/ShaderModule.h
+++ b/src/dawn_native/ShaderModule.h
@@ -19,7 +19,7 @@
 #include "dawn_native/Builder.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -36,12 +36,10 @@
     MaybeError ValidateShaderModuleDescriptor(DeviceBase* device,
                                               const ShaderModuleDescriptor* descriptor);
 
-    class ShaderModuleBase : public RefCounted {
+    class ShaderModuleBase : public ObjectBase {
       public:
         ShaderModuleBase(DeviceBase* device, const ShaderModuleDescriptor* descriptor);
 
-        DeviceBase* GetDevice() const;
-
         void ExtractSpirvInfo(const spirv_cross::Compiler& compiler);
 
         struct PushConstantInfo {
@@ -72,7 +70,6 @@
       private:
         bool IsCompatibleWithBindGroupLayout(size_t group, const BindGroupLayoutBase* layout);
 
-        DeviceBase* mDevice;
         PushConstantInfo mPushConstants = {};
         ModuleBindingInfo mBindingInfo;
         std::bitset<kMaxVertexAttributes> mUsedVertexAttributes;
diff --git a/src/dawn_native/SwapChain.cpp b/src/dawn_native/SwapChain.cpp
index 05f79b6..4323455 100644
--- a/src/dawn_native/SwapChain.cpp
+++ b/src/dawn_native/SwapChain.cpp
@@ -22,7 +22,7 @@
     // SwapChain
 
     SwapChainBase::SwapChainBase(SwapChainBuilder* builder)
-        : mDevice(builder->mDevice), mImplementation(builder->mImplementation) {
+        : ObjectBase(builder->GetDevice()), mImplementation(builder->mImplementation) {
     }
 
     SwapChainBase::~SwapChainBase() {
@@ -30,16 +30,12 @@
         im.Destroy(im.userData);
     }
 
-    DeviceBase* SwapChainBase::GetDevice() {
-        return mDevice;
-    }
-
     void SwapChainBase::Configure(dawn::TextureFormat format,
                                   dawn::TextureUsageBit allowedUsage,
                                   uint32_t width,
                                   uint32_t height) {
         if (width == 0 || height == 0) {
-            mDevice->HandleError("Swap chain cannot be configured to zero size");
+            GetDevice()->HandleError("Swap chain cannot be configured to zero size");
             return;
         }
         allowedUsage |= dawn::TextureUsageBit::Present;
@@ -55,7 +51,7 @@
     TextureBase* SwapChainBase::GetNextTexture() {
         if (mWidth == 0) {
             // If width is 0, it implies swap chain has never been configured
-            mDevice->HandleError("Swap chain needs to be configured before GetNextTexture");
+            GetDevice()->HandleError("Swap chain needs to be configured before GetNextTexture");
             return nullptr;
         }
 
@@ -76,7 +72,7 @@
 
     void SwapChainBase::Present(TextureBase* texture) {
         if (texture != mLastNextTexture) {
-            mDevice->HandleError("Tried to present something other than the last NextTexture");
+            GetDevice()->HandleError("Tried to present something other than the last NextTexture");
             return;
         }
 
@@ -99,7 +95,7 @@
             HandleError("Implementation not set");
             return nullptr;
         }
-        return mDevice->CreateSwapChain(this);
+        return GetDevice()->CreateSwapChain(this);
     }
 
     void SwapChainBuilder::SetImplementation(uint64_t implementation) {
diff --git a/src/dawn_native/SwapChain.h b/src/dawn_native/SwapChain.h
index 02110bf..de51a0a 100644
--- a/src/dawn_native/SwapChain.h
+++ b/src/dawn_native/SwapChain.h
@@ -17,20 +17,18 @@
 
 #include "dawn_native/Builder.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn/dawn_wsi.h"
 #include "dawn_native/dawn_platform.h"
 
 namespace dawn_native {
 
-    class SwapChainBase : public RefCounted {
+    class SwapChainBase : public ObjectBase {
       public:
         SwapChainBase(SwapChainBuilder* builder);
         ~SwapChainBase();
 
-        DeviceBase* GetDevice();
-
         // Dawn API
         void Configure(dawn::TextureFormat format,
                        dawn::TextureUsageBit allowedUsage,
@@ -45,7 +43,6 @@
         virtual void OnBeforePresent(TextureBase* texture) = 0;
 
       private:
-        DeviceBase* mDevice = nullptr;
         dawnSwapChainImplementation mImplementation = {};
         dawn::TextureFormat mFormat = {};
         dawn::TextureUsageBit mAllowedUsage;
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index 952fcd4..eeb4aa2 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -180,7 +180,7 @@
     // TextureBase
 
     TextureBase::TextureBase(DeviceBase* device, const TextureDescriptor* descriptor)
-        : mDevice(device),
+        : ObjectBase(device),
           mDimension(descriptor->dimension),
           mFormat(descriptor->format),
           mSize(descriptor->size),
@@ -189,10 +189,6 @@
           mUsage(descriptor->usage) {
     }
 
-    DeviceBase* TextureBase::GetDevice() const {
-        return mDevice;
-    }
-
     dawn::TextureDimension TextureBase::GetDimension() const {
         return mDimension;
     }
@@ -216,16 +212,17 @@
         // TODO(jiawei.shao@intel.com): remove Device->CreateDefaultTextureView in all back-ends
         // and implement this function by creating a TextureViewDescriptor based on the texture
         // and calling CreateTextureView(&descriptor) instead.
-        return mDevice->CreateDefaultTextureView(this);
+        return GetDevice()->CreateDefaultTextureView(this);
     }
 
     TextureViewBase* TextureBase::CreateTextureView(const TextureViewDescriptor* descriptor) {
-        return mDevice->CreateTextureView(this, descriptor);
+        return GetDevice()->CreateTextureView(this, descriptor);
     }
 
     // TextureViewBase
 
-    TextureViewBase::TextureViewBase(TextureBase* texture) : mTexture(texture) {
+    TextureViewBase::TextureViewBase(TextureBase* texture)
+        : ObjectBase(texture->GetDevice()), mTexture(texture) {
     }
 
     const TextureBase* TextureViewBase::GetTexture() const {
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index 326c178..337f1ba 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -18,7 +18,7 @@
 #include "dawn_native/Builder.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
-#include "dawn_native/RefCounted.h"
+#include "dawn_native/ObjectBase.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -41,7 +41,7 @@
         dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Storage |
         dawn::TextureUsageBit::OutputAttachment;
 
-    class TextureBase : public RefCounted {
+    class TextureBase : public ObjectBase {
       public:
         TextureBase(DeviceBase* device, const TextureDescriptor* descriptor);
 
@@ -51,15 +51,12 @@
         uint32_t GetArrayLayers() const;
         uint32_t GetNumMipLevels() const;
         dawn::TextureUsageBit GetUsage() const;
-        DeviceBase* GetDevice() const;
 
         // Dawn API
         TextureViewBase* CreateDefaultTextureView();
         TextureViewBase* CreateTextureView(const TextureViewDescriptor* descriptor);
 
       private:
-        DeviceBase* mDevice;
-
         dawn::TextureDimension mDimension;
         dawn::TextureFormat mFormat;
         Extent3D mSize;
@@ -68,7 +65,7 @@
         dawn::TextureUsageBit mUsage = dawn::TextureUsageBit::None;
     };
 
-    class TextureViewBase : public RefCounted {
+    class TextureViewBase : public ObjectBase {
       public:
         TextureViewBase(TextureBase* texture);