Break Instance->Backend->PhysicalDevice->Instance refcycle

Simplifies the ref hierarchy to minimize ref cycles to make
Dawn less prone to leaking backend objects.

Previously we had:
 Instance->Backend->PhysicalDevice->Instance
 Adapter->PhysicalDevice->Instance

Now, we have:
 Instance->Backend->PhysicalDevice
 Adapter->PhysicalDevice
 Adapter->Instance

Bug: none
Change-Id: I7882eb3b8580146c0ccc56bcba36eefda060fafc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/170560
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/include/dawn/native/DawnNative.h b/include/dawn/native/DawnNative.h
index 4b5e9e3..4a0ec7d 100644
--- a/include/dawn/native/DawnNative.h
+++ b/include/dawn/native/DawnNative.h
@@ -203,9 +203,6 @@
 // Backdoor to get the number of deprecation warnings for testing
 DAWN_NATIVE_EXPORT size_t GetDeprecationWarningCountForTesting(WGPUDevice device);
 
-// Backdoor to get the number of physical devices an instance knows about for testing
-DAWN_NATIVE_EXPORT size_t GetPhysicalDeviceCountForTesting(WGPUInstance instance);
-
 //  Query if texture has been initialized
 DAWN_NATIVE_EXPORT bool IsTextureSubresourceInitialized(
     WGPUTexture texture,
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 6a03657..41324f4 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -46,11 +46,13 @@
 static constexpr DeviceDescriptor kDefaultDeviceDesc = {};
 }  // anonymous namespace
 
-AdapterBase::AdapterBase(Ref<PhysicalDeviceBase> physicalDevice,
+AdapterBase::AdapterBase(InstanceBase* instance,
+                         Ref<PhysicalDeviceBase> physicalDevice,
                          FeatureLevel featureLevel,
                          const TogglesState& requiredAdapterToggles,
                          wgpu::PowerPreference powerPreference)
-    : mPhysicalDevice(std::move(physicalDevice)),
+    : mInstance(instance),
+      mPhysicalDevice(std::move(physicalDevice)),
       mFeatureLevel(featureLevel),
       mTogglesState(requiredAdapterToggles),
       mPowerPreference(powerPreference) {
@@ -79,8 +81,12 @@
     return mPhysicalDevice.Get();
 }
 
+InstanceBase* AdapterBase::GetInstance() const {
+    return mInstance.Get();
+}
+
 InstanceBase* AdapterBase::APIGetInstance() const {
-    InstanceBase* instance = mPhysicalDevice->GetInstance();
+    InstanceBase* instance = mInstance.Get();
     DAWN_ASSERT(instance != nullptr);
     instance->APIAddRef();
     return instance;
@@ -88,10 +94,8 @@
 
 bool AdapterBase::APIGetLimits(SupportedLimits* limits) const {
     DAWN_ASSERT(limits != nullptr);
-    InstanceBase* instance = mPhysicalDevice->GetInstance();
-
     UnpackedPtr<SupportedLimits> unpacked;
-    if (instance->ConsumedError(ValidateAndUnpack(limits), &unpacked)) {
+    if (mInstance->ConsumedError(ValidateAndUnpack(limits), &unpacked)) {
         return false;
     }
 
@@ -117,26 +121,24 @@
 
 void AdapterBase::APIGetProperties(AdapterProperties* properties) const {
     DAWN_ASSERT(properties != nullptr);
-    InstanceBase* instance = mPhysicalDevice->GetInstance();
-
     UnpackedPtr<AdapterProperties> unpacked;
-    if (instance->ConsumedError(ValidateAndUnpack(properties), &unpacked)) {
+    if (mInstance->ConsumedError(ValidateAndUnpack(properties), &unpacked)) {
         return;
     }
 
     if (unpacked.Get<AdapterPropertiesMemoryHeaps>() != nullptr &&
         !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesMemoryHeaps)) {
-        [[maybe_unused]] bool hadError = instance->ConsumedError(
+        [[maybe_unused]] bool hadError = mInstance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature AdapterPropertiesMemoryHeaps is not available."));
     }
     if (unpacked.Get<AdapterPropertiesD3D>() != nullptr &&
         !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesD3D)) {
-        [[maybe_unused]] bool hadError = instance->ConsumedError(
+        [[maybe_unused]] bool hadError = mInstance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature AdapterPropertiesD3D is not available."));
     }
     if (unpacked.Get<AdapterPropertiesVk>() != nullptr &&
         !mSupportedFeatures.IsEnabled(wgpu::FeatureName::AdapterPropertiesVk)) {
-        [[maybe_unused]] bool hadError = instance->ConsumedError(
+        [[maybe_unused]] bool hadError = mInstance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature AdapterPropertiesVk is not available."));
     }
 
@@ -207,9 +209,9 @@
     }
 
     auto [lostEvent, result] = CreateDevice(descriptor);
-    mPhysicalDevice->GetInstance()->GetEventManager()->TrackEvent(lostEvent);
+    mInstance->GetEventManager()->TrackEvent(lostEvent);
     Ref<DeviceBase> device;
-    if (mPhysicalDevice->GetInstance()->ConsumedError(std::move(result), &device)) {
+    if (mInstance->ConsumedError(std::move(result), &device)) {
         return nullptr;
     }
     return ReturnToAPI(std::move(device));
@@ -233,12 +235,12 @@
     // Default toggles for all backend
     deviceToggles.Default(Toggle::LazyClearResourceOnFirstUse, true);
     deviceToggles.Default(Toggle::TimestampQuantization, true);
-    if (mPhysicalDevice->GetInstance()->IsBackendValidationEnabled()) {
+    if (mInstance->IsBackendValidationEnabled()) {
         deviceToggles.Default(Toggle::UseUserDefinedLabelsInBackend, true);
     }
 
     // Backend-specific forced and default device toggles
-    mPhysicalDevice->SetupBackendDeviceToggles(&deviceToggles);
+    mPhysicalDevice->SetupBackendDeviceToggles(mInstance->GetPlatform(), &deviceToggles);
 
     // Validate all required features are supported by the adapter and suitable under device
     // toggles. Note that certain toggles in device toggles state may be overriden by user and
@@ -281,7 +283,7 @@
     if (result.IsError()) {
         lostEvent->mReason = wgpu::DeviceLostReason::FailedCreation;
         lostEvent->mMessage = "Failed to create device.";
-        mPhysicalDevice->GetInstance()->GetEventManager()->SetFutureReady(lostEvent.Get());
+        mInstance->GetEventManager()->SetFutureReady(lostEvent.Get());
     }
     return {lostEvent, std::move(result)};
 }
@@ -339,34 +341,33 @@
     FutureID futureID = kNullFutureID;
     auto [lostEvent, result] = CreateDevice(descriptor);
     if (result.IsSuccess()) {
-        futureID = mPhysicalDevice->GetInstance()->GetEventManager()->TrackEvent(
+        futureID = mInstance->GetEventManager()->TrackEvent(
             AcquireRef(new RequestDeviceEvent(callbackInfo, result.AcquireSuccess())));
     } else {
-        futureID = mPhysicalDevice->GetInstance()->GetEventManager()->TrackEvent(AcquireRef(
+        futureID = mInstance->GetEventManager()->TrackEvent(AcquireRef(
             new RequestDeviceEvent(callbackInfo, result.AcquireError()->GetFormattedMessage())));
     }
-    mPhysicalDevice->GetInstance()->GetEventManager()->TrackEvent(std::move(lostEvent));
+    mInstance->GetEventManager()->TrackEvent(std::move(lostEvent));
     return {futureID};
 }
 
 bool AdapterBase::APIGetFormatCapabilities(wgpu::TextureFormat format,
                                            FormatCapabilities* capabilities) {
-    InstanceBase* instance = mPhysicalDevice->GetInstance();
     if (!mSupportedFeatures.IsEnabled(wgpu::FeatureName::FormatCapabilities)) {
-        [[maybe_unused]] bool hadError = instance->ConsumedError(
+        [[maybe_unused]] bool hadError = mInstance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature FormatCapabilities is not available."));
         return false;
     }
     DAWN_ASSERT(capabilities != nullptr);
 
     UnpackedPtr<FormatCapabilities> unpacked;
-    if (instance->ConsumedError(ValidateAndUnpack(capabilities), &unpacked)) {
+    if (mInstance->ConsumedError(ValidateAndUnpack(capabilities), &unpacked)) {
         return false;
     }
 
     if (unpacked.Get<DrmFormatCapabilities>() != nullptr &&
         !mSupportedFeatures.IsEnabled(wgpu::FeatureName::DrmFormatCapabilities)) {
-        [[maybe_unused]] bool hadError = instance->ConsumedError(
+        [[maybe_unused]] bool hadError = mInstance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature DrmFormatCapabilities is not available."));
         return false;
     }
diff --git a/src/dawn/native/Adapter.h b/src/dawn/native/Adapter.h
index ed2797e..a800eba 100644
--- a/src/dawn/native/Adapter.h
+++ b/src/dawn/native/Adapter.h
@@ -48,12 +48,16 @@
 
 class AdapterBase : public RefCounted, public WeakRefSupport<AdapterBase> {
   public:
-    AdapterBase(Ref<PhysicalDeviceBase> physicalDevice,
+    AdapterBase(InstanceBase* instance,
+                Ref<PhysicalDeviceBase> physicalDevice,
                 FeatureLevel featureLevel,
                 const TogglesState& requiredAdapterToggles,
                 wgpu::PowerPreference powerPreference);
     ~AdapterBase() override;
 
+    // Gets the instance without adding a ref.
+    InstanceBase* GetInstance() const;
+
     // WebGPU API
     InstanceBase* APIGetInstance() const;
     bool APIGetLimits(SupportedLimits* limits) const;
@@ -90,6 +94,7 @@
     ResultOrError<Ref<DeviceBase>> CreateDeviceInternal(const DeviceDescriptor* rawDescriptor,
                                                         Ref<DeviceBase::DeviceLostEvent> lostEvent);
 
+    Ref<InstanceBase> mInstance;
     Ref<PhysicalDeviceBase> mPhysicalDevice;
     FeatureLevel mFeatureLevel;
     bool mUseTieredLimits = false;
diff --git a/src/dawn/native/BackendConnection.h b/src/dawn/native/BackendConnection.h
index 3f3d06a..627cf2f 100644
--- a/src/dawn/native/BackendConnection.h
+++ b/src/dawn/native/BackendConnection.h
@@ -55,12 +55,6 @@
     virtual std::vector<Ref<PhysicalDeviceBase>> DiscoverPhysicalDevices(
         const UnpackedPtr<RequestAdapterOptions>& options) = 0;
 
-    // Clear all internal refs to physical devices.
-    virtual void ClearPhysicalDevices() = 0;
-
-    // Get the number of internally-referenced physical devices, for testing.
-    virtual size_t GetPhysicalDeviceCountForTesting() const = 0;
-
   private:
     raw_ptr<InstanceBase> mInstance = nullptr;
     wgpu::BackendType mType;
diff --git a/src/dawn/native/DawnNative.cpp b/src/dawn/native/DawnNative.cpp
index 7f88beb..9be48d5 100644
--- a/src/dawn/native/DawnNative.cpp
+++ b/src/dawn/native/DawnNative.cpp
@@ -145,7 +145,8 @@
 }
 
 void Adapter::ResetInternalDeviceForTesting() {
-    mImpl->GetPhysicalDevice()->ResetInternalDeviceForTesting();
+    [[maybe_unused]] bool hadError = mImpl->GetInstance()->ConsumedError(
+        mImpl->GetPhysicalDevice()->ResetInternalDeviceForTesting());
 }
 
 // DawnInstanceDescriptor
@@ -227,10 +228,6 @@
     return FromAPI(device)->GetDeprecationWarningCountForTesting();
 }
 
-size_t GetPhysicalDeviceCountForTesting(WGPUInstance instance) {
-    return FromAPI(instance)->GetPhysicalDeviceCountForTesting();
-}
-
 bool IsTextureSubresourceInitialized(WGPUTexture texture,
                                      uint32_t baseMipLevel,
                                      uint32_t levelCount,
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index faf610e..531996c 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -465,7 +465,7 @@
     // mAdapter is not set for mock test devices.
     // TODO(crbug.com/dawn/1702): using a mock adapter could avoid the null checking.
     if (mAdapter != nullptr) {
-        mAdapter->GetPhysicalDevice()->GetInstance()->AddDevice(this);
+        mAdapter->GetInstance()->AddDevice(this);
     }
 
     return {};
@@ -515,12 +515,11 @@
     // mAdapter is not set for mock test devices.
     // TODO(crbug.com/dawn/1702): using a mock adapter could avoid the null checking.
     if (mAdapter != nullptr) {
-        mAdapter->GetPhysicalDevice()->GetInstance()->RemoveDevice(this);
+        mAdapter->GetInstance()->RemoveDevice(this);
 
         // Once last external ref dropped, all callbacks should be forwarded to Instance's callback
         // queue instead.
-        mCallbackTaskManager =
-            mAdapter->GetPhysicalDevice()->GetInstance()->GetCallbackTaskManager();
+        mCallbackTaskManager = mAdapter->GetInstance()->GetCallbackTaskManager();
     }
 }
 
@@ -956,7 +955,7 @@
 }
 
 InstanceBase* DeviceBase::GetInstance() const {
-    return mAdapter->GetPhysicalDevice()->GetInstance();
+    return mAdapter->GetInstance();
 }
 
 AdapterBase* DeviceBase::GetAdapter() const {
@@ -968,7 +967,7 @@
 }
 
 dawn::platform::Platform* DeviceBase::GetPlatform() const {
-    return GetPhysicalDevice()->GetInstance()->GetPlatform();
+    return GetAdapter()->GetInstance()->GetPlatform();
 }
 
 InternalPipelineStore* DeviceBase::GetInternalPipelineStore() {
@@ -1864,7 +1863,7 @@
 
 bool DeviceBase::APIGetLimits(SupportedLimits* limits) const {
     DAWN_ASSERT(limits != nullptr);
-    InstanceBase* instance = GetPhysicalDevice()->GetInstance();
+    InstanceBase* instance = GetAdapter()->GetInstance();
 
     UnpackedPtr<SupportedLimits> unpacked;
     if (instance->ConsumedError(ValidateAndUnpack(limits), &unpacked)) {
diff --git a/src/dawn/native/Instance.cpp b/src/dawn/native/Instance.cpp
index 543b133..29acf7d 100644
--- a/src/dawn/native/Instance.cpp
+++ b/src/dawn/native/Instance.cpp
@@ -65,10 +65,6 @@
 #include "dawn/native/X11Functions.h"
 #endif  // defined(DAWN_USE_X11)
 
-#if DAWN_PLATFORM_IS(ANDROID)
-#include "dawn/native/AHBFunctions.h"
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-
 namespace dawn::native {
 
 // Forward definitions of each backend's "Connect" function that creates new BackendConnection.
@@ -194,22 +190,8 @@
 }
 
 void InstanceBase::WillDropLastExternalRef() {
-    // InstanceBase uses RefCountedWithExternalCount to break refcycles.
-
     // Stop tracking events. See comment on ShutDown.
     mEventManager.ShutDown();
-
-    // InstanceBase holds backends which hold Refs to PhysicalDeviceBases discovered, which hold
-    // Refs back to the InstanceBase.
-    // In order to break this cycle and prevent leaks, when the application drops the last external
-    // ref and WillDropLastExternalRef is called, the instance clears out any member refs to
-    // physical devices that hold back-refs to the instance - thus breaking any reference cycles.
-    for (auto& backend : mBackends) {
-        if (backend != nullptr) {
-            backend->ClearPhysicalDevices();
-        }
-    }
-
     mLoggingCallback = nullptr;
     mLoggingCallbackUserdata = nullptr;
 }
@@ -342,17 +324,17 @@
 Ref<AdapterBase> InstanceBase::CreateAdapter(Ref<PhysicalDeviceBase> physicalDevice,
                                              FeatureLevel featureLevel,
                                              const DawnTogglesDescriptor* requiredAdapterToggles,
-                                             wgpu::PowerPreference powerPreference) const {
+                                             wgpu::PowerPreference powerPreference) {
     // Set up toggles state for default adapter from given toggles descriptor and inherit from
     // instance toggles.
     TogglesState adapterToggles =
         TogglesState::CreateFromTogglesDescriptor(requiredAdapterToggles, ToggleStage::Adapter);
     adapterToggles.InheritFrom(mToggles);
     // Set up forced and default adapter toggles for selected physical device.
-    physicalDevice->SetupBackendAdapterToggles(&adapterToggles);
+    physicalDevice->SetupBackendAdapterToggles(GetPlatform(), &adapterToggles);
 
-    return AcquireRef(
-        new AdapterBase(std::move(physicalDevice), featureLevel, adapterToggles, powerPreference));
+    return AcquireRef(new AdapterBase(this, std::move(physicalDevice), featureLevel, adapterToggles,
+                                      powerPreference));
 }
 
 const TogglesState& InstanceBase::GetTogglesState() const {
@@ -390,16 +372,6 @@
     return SortAdapters(std::move(adapters), options);
 }
 
-size_t InstanceBase::GetPhysicalDeviceCountForTesting() const {
-    size_t count = 0;
-    for (auto& backend : mBackends) {
-        if (backend != nullptr) {
-            count += backend->GetPhysicalDeviceCountForTesting();
-        }
-    }
-    return count;
-}
-
 BackendConnection* InstanceBase::GetBackendConnection(wgpu::BackendType backendType) {
     if (mBackendsTried[backendType]) {
         return mBackends[backendType].get();
@@ -614,17 +586,6 @@
 #endif  // defined(DAWN_USE_X11)
 }
 
-const AHBFunctions* InstanceBase::GetOrLoadAHBFunctions() {
-#if DAWN_PLATFORM_IS(ANDROID)
-    if (mAHBFunctions == nullptr) {
-        mAHBFunctions = std::make_unique<AHBFunctions>();
-    }
-    return mAHBFunctions.get();
-#else
-    DAWN_UNREACHABLE();
-#endif  // DAWN_PLATFORM_IS(ANDROID)
-}
-
 Surface* InstanceBase::APICreateSurface(const SurfaceDescriptor* descriptor) {
     UnpackedPtr<SurfaceDescriptor> unpacked;
     if (ConsumedError(ValidateSurfaceDescriptor(this, descriptor), &unpacked)) {
diff --git a/src/dawn/native/Instance.h b/src/dawn/native/Instance.h
index 5ad5858..1b4d894 100644
--- a/src/dawn/native/Instance.h
+++ b/src/dawn/native/Instance.h
@@ -57,7 +57,6 @@
 
 namespace dawn::native {
 
-class AHBFunctions;
 class CallbackTaskManager;
 class DeviceBase;
 class Surface;
@@ -138,7 +137,6 @@
 
     // Get backend-independent libraries that need to be loaded dynamically.
     const X11Functions* GetOrLoadX11Functions();
-    const AHBFunctions* GetOrLoadAHBFunctions();
 
     // TODO(dawn:752) Standardize webgpu.h to decide if we should return bool.
     //   Currently this is a backdoor for Chromium's process event loop.
@@ -183,7 +181,7 @@
     Ref<AdapterBase> CreateAdapter(Ref<PhysicalDeviceBase> physicalDevice,
                                    FeatureLevel featureLevel,
                                    const DawnTogglesDescriptor* requiredAdapterToggles,
-                                   wgpu::PowerPreference powerPreference) const;
+                                   wgpu::PowerPreference powerPreference);
 
     void GatherWGSLFeatures(const DawnWGSLBlocklist* wgslBlocklist);
 
@@ -216,9 +214,6 @@
 #if defined(DAWN_USE_X11)
     std::unique_ptr<X11Functions> mX11Functions;
 #endif  // defined(DAWN_USE_X11)
-#if DAWN_PLATFORM_IS(ANDROID)
-    std::unique_ptr<AHBFunctions> mAHBFunctions;
-#endif  // DAWN_PLATFORM_IS(ANDROID)
 
     Ref<CallbackTaskManager> mCallbackTaskManager;
     EventManager mEventManager;
diff --git a/src/dawn/native/ObjectBase.cpp b/src/dawn/native/ObjectBase.cpp
index 46be060..b6f086d 100644
--- a/src/dawn/native/ObjectBase.cpp
+++ b/src/dawn/native/ObjectBase.cpp
@@ -52,7 +52,7 @@
 ObjectBase::ObjectBase(DeviceBase* device, ErrorTag) : ErrorMonad(kError), mDevice(device) {}
 
 InstanceBase* ObjectBase::GetInstance() const {
-    return mDevice->GetAdapter()->GetPhysicalDevice()->GetInstance();
+    return mDevice->GetAdapter()->GetInstance();
 }
 
 DeviceBase* ObjectBase::GetDevice() const {
diff --git a/src/dawn/native/PhysicalDevice.cpp b/src/dawn/native/PhysicalDevice.cpp
index fa91398..c769be4 100644
--- a/src/dawn/native/PhysicalDevice.cpp
+++ b/src/dawn/native/PhysicalDevice.cpp
@@ -44,8 +44,7 @@
 FeatureValidationResult::FeatureValidationResult(std::string errorMsg)
     : success(false), errorMessage(errorMsg) {}
 
-PhysicalDeviceBase::PhysicalDeviceBase(InstanceBase* instance, wgpu::BackendType backend)
-    : mInstance(instance), mBackend(backend) {}
+PhysicalDeviceBase::PhysicalDeviceBase(wgpu::BackendType backend) : mBackend(backend) {}
 
 PhysicalDeviceBase::~PhysicalDeviceBase() = default;
 
@@ -119,10 +118,6 @@
     return mBackend;
 }
 
-InstanceBase* PhysicalDeviceBase::GetInstance() const {
-    return mInstance.Get();
-}
-
 bool PhysicalDeviceBase::IsFeatureSupportedWithToggles(wgpu::FeatureName feature,
                                                        const TogglesState& toggles) const {
     return ValidateFeatureSupportedWithToggles(feature, toggles).success;
@@ -201,8 +196,8 @@
     }
 }
 
-void PhysicalDeviceBase::ResetInternalDeviceForTesting() {
-    [[maybe_unused]] bool hadError = mInstance->ConsumedError(ResetInternalDeviceForTestingImpl());
+MaybeError PhysicalDeviceBase::ResetInternalDeviceForTesting() {
+    return ResetInternalDeviceForTestingImpl();
 }
 
 MaybeError PhysicalDeviceBase::ResetInternalDeviceForTestingImpl() {
diff --git a/src/dawn/native/PhysicalDevice.h b/src/dawn/native/PhysicalDevice.h
index 68494b7..b3e6852 100644
--- a/src/dawn/native/PhysicalDevice.h
+++ b/src/dawn/native/PhysicalDevice.h
@@ -68,7 +68,7 @@
 
 class PhysicalDeviceBase : public RefCounted {
   public:
-    PhysicalDeviceBase(InstanceBase* instance, wgpu::BackendType backend);
+    explicit PhysicalDeviceBase(wgpu::BackendType backend);
     ~PhysicalDeviceBase() override;
 
     MaybeError Initialize();
@@ -88,11 +88,7 @@
     wgpu::AdapterType GetAdapterType() const;
     wgpu::BackendType GetBackendType() const;
 
-    // This method differs from APIGetInstance() in that it won't increase the ref count of the
-    // instance.
-    InstanceBase* GetInstance() const;
-
-    void ResetInternalDeviceForTesting();
+    MaybeError ResetInternalDeviceForTesting();
 
     // Get all features supported by the physical device and suitable with given toggles.
     FeaturesSet GetSupportedFeatures(const TogglesState& toggles) const;
@@ -108,9 +104,11 @@
     virtual bool SupportsFeatureLevel(FeatureLevel featureLevel) const = 0;
 
     // Backend-specific force-setting and defaulting device toggles
-    virtual void SetupBackendAdapterToggles(TogglesState* adapterToggles) const = 0;
+    virtual void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                            TogglesState* adapterToggles) const = 0;
     // Backend-specific force-setting and defaulting device toggles
-    virtual void SetupBackendDeviceToggles(TogglesState* deviceToggles) const = 0;
+    virtual void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                           TogglesState* deviceToggles) const = 0;
 
     // Check if a feature os supported by this adapter AND suitable with given toggles.
     FeatureValidationResult ValidateFeatureSupportedWithToggles(wgpu::FeatureName feature,
@@ -126,6 +124,7 @@
         UnpackedPtr<FormatCapabilities>& capabilities) const;
 
     virtual ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
+        InstanceBase* instance,
         const Surface* surface) const = 0;
 
   protected:
@@ -171,7 +170,6 @@
         const TogglesState& toggles) const = 0;
 
     virtual MaybeError ResetInternalDeviceForTestingImpl();
-    Ref<InstanceBase> mInstance;
     wgpu::BackendType mBackend;
 
     // Features set that CAN be supported by devices of this adapter. Some features in this set may
diff --git a/src/dawn/native/Surface.cpp b/src/dawn/native/Surface.cpp
index 013b535..90aced4 100644
--- a/src/dawn/native/Surface.cpp
+++ b/src/dawn/native/Surface.cpp
@@ -275,7 +275,8 @@
     MaybeError WithAdapterCapabilities(AdapterBase* adapter, const Surface* surface, F f) {
         if (mCachedCapabilitiesAdapter.Promote().Get() != adapter) {
             const PhysicalDeviceBase* physicalDevice = adapter->GetPhysicalDevice();
-            DAWN_TRY_ASSIGN(mCachedCapabilities, physicalDevice->GetSurfaceCapabilities(surface));
+            DAWN_TRY_ASSIGN(mCachedCapabilities, physicalDevice->GetSurfaceCapabilities(
+                                                     adapter->GetInstance(), surface));
             mCachedCapabilitiesAdapter = GetWeakRef(adapter);
         }
         return f(mCachedCapabilities);
diff --git a/src/dawn/native/d3d/BackendD3D.cpp b/src/dawn/native/d3d/BackendD3D.cpp
index c99d703..478d60f 100644
--- a/src/dawn/native/d3d/BackendD3D.cpp
+++ b/src/dawn/native/d3d/BackendD3D.cpp
@@ -328,14 +328,6 @@
     return physicalDevices;
 }
 
-void Backend::ClearPhysicalDevices() {
-    mPhysicalDevices.clear();
-}
-
-size_t Backend::GetPhysicalDeviceCountForTesting() const {
-    return mPhysicalDevices.size();
-}
-
 size_t Backend::LUIDHashFunc::operator()(const LUID& luid) const {
     size_t hash = 0;
     dawn::HashCombine(&hash, luid.LowPart, luid.HighPart);
diff --git a/src/dawn/native/d3d/BackendD3D.h b/src/dawn/native/d3d/BackendD3D.h
index e8848fd..7ae6fdb 100644
--- a/src/dawn/native/d3d/BackendD3D.h
+++ b/src/dawn/native/d3d/BackendD3D.h
@@ -93,8 +93,6 @@
 
     std::vector<Ref<PhysicalDeviceBase>> DiscoverPhysicalDevices(
         const UnpackedPtr<RequestAdapterOptions>& options) override;
-    void ClearPhysicalDevices() override;
-    size_t GetPhysicalDeviceCountForTesting() const override;
 
   protected:
     virtual ResultOrError<Ref<PhysicalDeviceBase>> CreatePhysicalDeviceFromIDXGIAdapter(
diff --git a/src/dawn/native/d3d/PhysicalDeviceD3D.cpp b/src/dawn/native/d3d/PhysicalDeviceD3D.cpp
index ef89ac1..14d7f66 100644
--- a/src/dawn/native/d3d/PhysicalDeviceD3D.cpp
+++ b/src/dawn/native/d3d/PhysicalDeviceD3D.cpp
@@ -38,7 +38,7 @@
 PhysicalDevice::PhysicalDevice(Backend* backend,
                                ComPtr<IDXGIAdapter4> hardwareAdapter,
                                wgpu::BackendType backendType)
-    : PhysicalDeviceBase(backend->GetInstance(), backendType),
+    : PhysicalDeviceBase(backendType),
       mHardwareAdapter(std::move(hardwareAdapter)),
       mBackend(backend) {}
 
@@ -53,6 +53,7 @@
 }
 
 ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
+    InstanceBase*,
     const Surface*) const {
     PhysicalDeviceSurfaceCapabilities capabilities;
 
diff --git a/src/dawn/native/d3d/PhysicalDeviceD3D.h b/src/dawn/native/d3d/PhysicalDeviceD3D.h
index b0db8b5..00dbcab 100644
--- a/src/dawn/native/d3d/PhysicalDeviceD3D.h
+++ b/src/dawn/native/d3d/PhysicalDeviceD3D.h
@@ -48,6 +48,7 @@
     Backend* GetBackend() const;
 
     ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
+        InstanceBase* instance,
         const Surface* surface) const override;
 
   protected:
diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp
index f9907eb..9747f21 100644
--- a/src/dawn/native/d3d11/DeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/DeviceD3D11.cpp
@@ -120,7 +120,10 @@
 }
 
 MaybeError Device::Initialize(const UnpackedPtr<DeviceDescriptor>& descriptor) {
-    DAWN_TRY_ASSIGN(mD3d11Device, ToBackend(GetPhysicalDevice())->CreateD3D11Device());
+    DAWN_TRY_ASSIGN(
+        mD3d11Device,
+        ToBackend(GetPhysicalDevice())
+            ->CreateD3D11Device(GetAdapter()->GetInstance()->IsBackendValidationEnabled()));
     DAWN_ASSERT(mD3d11Device != nullptr);
 
     mIsDebugLayerEnabled = IsDebugLayerEnabled(mD3d11Device);
@@ -338,7 +341,7 @@
 }
 
 void Device::AppendDebugLayerMessages(ErrorData* error) {
-    if (!GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled()) {
+    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) {
         return;
     }
 
diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
index 3c62fc7..4da0c91 100644
--- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
@@ -108,7 +108,7 @@
     return mDeviceInfo;
 }
 
-ResultOrError<ComPtr<ID3D11Device>> PhysicalDevice::CreateD3D11Device() {
+ResultOrError<ComPtr<ID3D11Device>> PhysicalDevice::CreateD3D11Device(bool enableDebugLayer) {
     if (mIsSharedD3D11Device) {
         DAWN_ASSERT(mD3D11Device);
         // If the shared d3d11 device was created with debug layer, we have to initialize debug
@@ -121,9 +121,8 @@
 
     // If there mD3D11Device which is used for collecting GPU info is not null, try to use it.
     if (mD3D11Device) {
-        bool isDebugLayerEnabled = IsDebugLayerEnabled(mD3D11Device);
         // Backend validation level doesn't match, recreate the d3d11 device.
-        if (GetInstance()->IsBackendValidationEnabled() == isDebugLayerEnabled) {
+        if (enableDebugLayer == IsDebugLayerEnabled(mD3D11Device)) {
             return std::move(mD3D11Device);
         }
         mD3D11Device = nullptr;
@@ -134,7 +133,7 @@
 
     ComPtr<ID3D11Device> d3d11Device;
 
-    if (GetInstance()->IsBackendValidationEnabled()) {
+    if (enableDebugLayer) {
         // Try create d3d11 device with debug layer.
         HRESULT hr = functions->d3d11CreateDevice(
             GetHardwareAdapter(), D3D_DRIVER_TYPE_UNKNOWN,
@@ -165,7 +164,7 @@
     // Create the device to populate the adapter properties then reuse it when needed for actual
     // rendering.
     if (!mIsSharedD3D11Device) {
-        DAWN_TRY_ASSIGN(mD3D11Device, CreateD3D11Device());
+        DAWN_TRY_ASSIGN(mD3D11Device, CreateD3D11Device(/*enableDebugLayers=*/false));
     }
 
     mFeatureLevel = mD3D11Device->GetFeatureLevel();
@@ -309,12 +308,14 @@
     return {};
 }
 
-void PhysicalDevice::SetupBackendAdapterToggles(TogglesState* adpterToggles) const {
+void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                                TogglesState* adapterToggles) const {
     // D3D11 must use FXC, not DXC.
-    adpterToggles->ForceSet(Toggle::UseDXC, false);
+    adapterToggles->ForceSet(Toggle::UseDXC, false);
 }
 
-void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
+void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                               TogglesState* deviceToggles) const {
     // D3D11 can only clear RTV with float values.
     deviceToggles->Default(Toggle::ApplyClearBigIntegerColorValueWithDraw, true);
     deviceToggles->Default(Toggle::UseBlitForBufferToStencilTextureCopy, true);
diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.h b/src/dawn/native/d3d11/PhysicalDeviceD3D11.h
index 9e79240..de41bff 100644
--- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.h
+++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.h
@@ -50,7 +50,7 @@
     bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
 
     const DeviceInfo& GetDeviceInfo() const;
-    ResultOrError<ComPtr<ID3D11Device>> CreateD3D11Device();
+    ResultOrError<ComPtr<ID3D11Device>> CreateD3D11Device(bool enableDebugLayer);
 
     uint32_t GetUAVSlotCount() const { return mUAVSlotCount; }
     bool IsSharedD3D11Device() const { return mIsSharedD3D11Device; }
@@ -58,8 +58,10 @@
   private:
     using Base = d3d::PhysicalDevice;
 
-    void SetupBackendAdapterToggles(TogglesState* adapterToggles) const override;
-    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+    void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                    TogglesState* adapterToggles) const override;
+    void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                   TogglesState* deviceToggles) const override;
 
     ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
         AdapterBase* adapter,
diff --git a/src/dawn/native/d3d12/DeviceD3D12.cpp b/src/dawn/native/d3d12/DeviceD3D12.cpp
index 3fc0cc4..a46aad7 100644
--- a/src/dawn/native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/DeviceD3D12.cpp
@@ -654,7 +654,7 @@
 }
 
 MaybeError Device::CheckDebugLayerAndGenerateErrors() {
-    if (!GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled()) {
+    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) {
         return {};
     }
 
@@ -678,7 +678,7 @@
 }
 
 void Device::AppendDebugLayerMessages(ErrorData* error) {
-    if (!GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled()) {
+    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) {
         return;
     }
 
diff --git a/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp b/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
index cf1fb21..3fe92f1 100644
--- a/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
+++ b/src/dawn/native/d3d12/PhysicalDeviceD3D12.cpp
@@ -413,7 +413,9 @@
 }
 
 MaybeError PhysicalDevice::InitializeDebugLayerFilters() {
-    if (!GetInstance()->IsBackendValidationEnabled()) {
+    // If the debug layer is not installed, return immediately.
+    ComPtr<ID3D12InfoQueue> infoQueue;
+    if (FAILED(mD3d12Device.As(&infoQueue))) {
         return {};
     }
 
@@ -493,10 +495,6 @@
     filter.DenyList.NumIDs = ARRAYSIZE(denyIds);
     filter.DenyList.pIDList = denyIds;
 
-    ComPtr<ID3D12InfoQueue> infoQueue;
-    DAWN_TRY(CheckHRESULT(mD3d12Device.As(&infoQueue),
-                          "D3D12 QueryInterface ID3D12Device to ID3D12InfoQueue"));
-
     // To avoid flooding the console, a storage-filter is also used to
     // prevent messages from getting logged.
     DAWN_TRY(
@@ -509,10 +507,6 @@
 }
 
 void PhysicalDevice::CleanUpDebugLayerFilters() {
-    if (!GetInstance()->IsBackendValidationEnabled()) {
-        return;
-    }
-
     // The device may not exist if this adapter failed to initialize.
     if (mD3d12Device == nullptr) {
         return;
@@ -528,7 +522,8 @@
     infoQueue->PopStorageFilter();
 }
 
-void PhysicalDevice::SetupBackendAdapterToggles(TogglesState* adapterToggles) const {
+void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                                TogglesState* adapterToggles) const {
     // Check for use_dxc toggle
 #ifdef DAWN_USE_BUILT_DXC
     // Default to using DXC. If shader model < 6.0, though, we must use FXC.
@@ -536,8 +531,7 @@
         adapterToggles->ForceSet(Toggle::UseDXC, false);
     }
 
-    bool useDxc =
-        GetInstance()->GetPlatform()->IsFeatureEnabled(dawn::platform::Features::kWebGPUUseDXC);
+    bool useDxc = platform->IsFeatureEnabled(dawn::platform::Features::kWebGPUUseDXC);
     adapterToggles->Default(Toggle::UseDXC, useDxc);
 #else
     // Default to using FXC
@@ -571,7 +565,8 @@
     }
 }
 
-void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
+void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                               TogglesState* deviceToggles) const {
     const bool useResourceHeapTier2 = (GetDeviceInfo().resourceHeapTier >= 2);
     deviceToggles->Default(Toggle::UseD3D12ResourceHeapTier2, useResourceHeapTier2);
     deviceToggles->Default(Toggle::UseD3D12RenderPass, GetDeviceInfo().supportsRenderPass);
diff --git a/src/dawn/native/d3d12/PhysicalDeviceD3D12.h b/src/dawn/native/d3d12/PhysicalDeviceD3D12.h
index 3be26f3..8341a5b 100644
--- a/src/dawn/native/d3d12/PhysicalDeviceD3D12.h
+++ b/src/dawn/native/d3d12/PhysicalDeviceD3D12.h
@@ -58,8 +58,10 @@
   private:
     using Base = d3d::PhysicalDevice;
 
-    void SetupBackendAdapterToggles(TogglesState* adapterToggles) const override;
-    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+    void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                    TogglesState* adapterToggles) const override;
+    void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                   TogglesState* deviceToggles) const override;
 
     ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
         AdapterBase* adapter,
diff --git a/src/dawn/native/metal/BackendMTL.h b/src/dawn/native/metal/BackendMTL.h
index 2ffd340..19956e7 100644
--- a/src/dawn/native/metal/BackendMTL.h
+++ b/src/dawn/native/metal/BackendMTL.h
@@ -41,8 +41,6 @@
 
     std::vector<Ref<PhysicalDeviceBase>> DiscoverPhysicalDevices(
         const UnpackedPtr<RequestAdapterOptions>& options) override;
-    void ClearPhysicalDevices() override;
-    size_t GetPhysicalDeviceCountForTesting() const override;
 
   private:
     std::vector<Ref<PhysicalDeviceBase>> mPhysicalDevices;
diff --git a/src/dawn/native/metal/BackendMTL.mm b/src/dawn/native/metal/BackendMTL.mm
index db0f3f0..2261b30 100644
--- a/src/dawn/native/metal/BackendMTL.mm
+++ b/src/dawn/native/metal/BackendMTL.mm
@@ -99,14 +99,6 @@
     return std::vector<Ref<PhysicalDeviceBase>>{mPhysicalDevices};
 }
 
-void Backend::ClearPhysicalDevices() {
-    mPhysicalDevices.clear();
-}
-
-size_t Backend::GetPhysicalDeviceCountForTesting() const {
-    return mPhysicalDevices.size();
-}
-
 BackendConnection* Connect(InstanceBase* instance) {
     return new Backend(instance);
 }
diff --git a/src/dawn/native/metal/PhysicalDeviceMTL.h b/src/dawn/native/metal/PhysicalDeviceMTL.h
index d6eef36..c18c7e3 100644
--- a/src/dawn/native/metal/PhysicalDeviceMTL.h
+++ b/src/dawn/native/metal/PhysicalDeviceMTL.h
@@ -48,6 +48,7 @@
     bool SupportsExternalImages() const override;
     bool SupportsFeatureLevel(FeatureLevel) const override;
     ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
+        InstanceBase* instance,
         const Surface*) const override;
 
   private:
@@ -57,8 +58,10 @@
         const TogglesState& deviceToggles,
         Ref<DeviceBase::DeviceLostEvent>&& lostEvent) override;
 
-    void SetupBackendAdapterToggles(TogglesState* adapterToggles) const override;
-    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+    void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                    TogglesState* adapterToggles) const override;
+    void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                   TogglesState* deviceToggles) const override;
 
     MaybeError InitializeImpl() override;
 
diff --git a/src/dawn/native/metal/PhysicalDeviceMTL.mm b/src/dawn/native/metal/PhysicalDeviceMTL.mm
index 7902ce0..6dd2920 100644
--- a/src/dawn/native/metal/PhysicalDeviceMTL.mm
+++ b/src/dawn/native/metal/PhysicalDeviceMTL.mm
@@ -316,7 +316,7 @@
 PhysicalDevice::PhysicalDevice(InstanceBase* instance,
                                NSPRef<id<MTLDevice>> device,
                                bool metalValidationEnabled)
-    : PhysicalDeviceBase(instance, wgpu::BackendType::Metal),
+    : PhysicalDeviceBase(wgpu::BackendType::Metal),
       mDevice(std::move(device)),
       mMetalValidationEnabled(metalValidationEnabled) {
     mName = std::string([[*mDevice name] UTF8String]);
@@ -360,6 +360,7 @@
 }
 
 ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
+    InstanceBase* instance,
     const Surface*) const {
     PhysicalDeviceSurfaceCapabilities capabilities;
 
@@ -401,9 +402,11 @@
     return Device::Create(adapter, mDevice, descriptor, deviceToggles, std::move(lostEvent));
 }
 
-void PhysicalDevice::SetupBackendAdapterToggles(TogglesState* adapterToggles) const {}
+void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                                TogglesState* adapterToggles) const {}
 
-void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
+void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                               TogglesState* deviceToggles) const {
     {
         bool haveStoreAndMSAAResolve = false;
 #if DAWN_PLATFORM_IS(MACOS)
diff --git a/src/dawn/native/null/DeviceNull.cpp b/src/dawn/native/null/DeviceNull.cpp
index 2bbd98b..bf4bf69 100644
--- a/src/dawn/native/null/DeviceNull.cpp
+++ b/src/dawn/native/null/DeviceNull.cpp
@@ -46,8 +46,7 @@
 // Implementation of pre-Device objects: the null physical device, null backend connection and
 // Connect()
 
-PhysicalDevice::PhysicalDevice(InstanceBase* instance)
-    : PhysicalDeviceBase(instance, wgpu::BackendType::Null) {
+PhysicalDevice::PhysicalDevice() : PhysicalDeviceBase(wgpu::BackendType::Null) {
     mVendorId = 0;
     mDeviceId = 0;
     mName = "Null backend";
@@ -67,6 +66,7 @@
 }
 
 ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
+    InstanceBase* instance,
     const Surface* surface) const {
     PhysicalDeviceSurfaceCapabilities capabilities;
     capabilities.formats = {wgpu::TextureFormat::BGRA8Unorm};
@@ -94,9 +94,11 @@
     return {};
 }
 
-void PhysicalDevice::SetupBackendAdapterToggles(TogglesState* adpterToggles) const {}
+void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                                TogglesState* adapterToggles) const {}
 
-void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {}
+void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                               TogglesState* deviceToggles) const {}
 
 ResultOrError<Ref<DeviceBase>> PhysicalDevice::CreateDeviceImpl(
     AdapterBase* adapter,
@@ -140,16 +142,11 @@
         // There is always a single Null physical device because it is purely CPU based
         // and doesn't depend on the system.
         if (mPhysicalDevice == nullptr) {
-            mPhysicalDevice = AcquireRef(new PhysicalDevice(GetInstance()));
+            mPhysicalDevice = AcquireRef(new PhysicalDevice());
         }
         return {mPhysicalDevice};
     }
 
-    void ClearPhysicalDevices() override { mPhysicalDevice = nullptr; }
-    size_t GetPhysicalDeviceCountForTesting() const override {
-        return mPhysicalDevice != nullptr ? 1 : 0;
-    }
-
   private:
     Ref<PhysicalDevice> mPhysicalDevice;
 };
diff --git a/src/dawn/native/null/DeviceNull.h b/src/dawn/native/null/DeviceNull.h
index 6997d2d..8991fff 100644
--- a/src/dawn/native/null/DeviceNull.h
+++ b/src/dawn/native/null/DeviceNull.h
@@ -185,9 +185,7 @@
 
 class PhysicalDevice : public PhysicalDeviceBase {
   public:
-    // Create null adapter without providing toggles state for testing, only inherit instance's
-    // toggles state
-    explicit PhysicalDevice(InstanceBase* instance);
+    PhysicalDevice();
     ~PhysicalDevice() override;
 
     // PhysicalDeviceBase Implementation
@@ -196,6 +194,7 @@
     bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
 
     ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
+        InstanceBase* instance,
         const Surface* surface) const override;
 
     // Used for the tests that intend to use an adapter without all features enabled.
@@ -210,8 +209,10 @@
         wgpu::FeatureName feature,
         const TogglesState& toggles) const override;
 
-    void SetupBackendAdapterToggles(TogglesState* adapterToggles) const override;
-    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+    void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                    TogglesState* adapterToggles) const override;
+    void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                   TogglesState* deviceToggles) const override;
     ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
         AdapterBase* adapter,
         const UnpackedPtr<DeviceDescriptor>& descriptor,
diff --git a/src/dawn/native/opengl/BackendGL.cpp b/src/dawn/native/opengl/BackendGL.cpp
index 34ea163..65e4d93 100644
--- a/src/dawn/native/opengl/BackendGL.cpp
+++ b/src/dawn/native/opengl/BackendGL.cpp
@@ -99,8 +99,7 @@
     }
     if (mPhysicalDevice == nullptr) {
         if (GetInstance()->ConsumedErrorAndWarnOnce(
-                PhysicalDevice::Create(GetInstance(), GetType(), getProc, display),
-                &mPhysicalDevice)) {
+                PhysicalDevice::Create(GetType(), getProc, display), &mPhysicalDevice)) {
             return {};
         }
         mGetProc = getProc;
@@ -109,14 +108,6 @@
     return {mPhysicalDevice};
 }
 
-void Backend::ClearPhysicalDevices() {
-    mPhysicalDevice = nullptr;
-}
-
-size_t Backend::GetPhysicalDeviceCountForTesting() const {
-    return mPhysicalDevice != nullptr ? 1 : 0;
-}
-
 BackendConnection* Connect(InstanceBase* instance, wgpu::BackendType backendType) {
     return new Backend(instance, backendType);
 }
diff --git a/src/dawn/native/opengl/BackendGL.h b/src/dawn/native/opengl/BackendGL.h
index 221a165..a9d2c5a 100644
--- a/src/dawn/native/opengl/BackendGL.h
+++ b/src/dawn/native/opengl/BackendGL.h
@@ -44,8 +44,6 @@
 
     std::vector<Ref<PhysicalDeviceBase>> DiscoverPhysicalDevices(
         const UnpackedPtr<RequestAdapterOptions>& options) override;
-    void ClearPhysicalDevices() override;
-    size_t GetPhysicalDeviceCountForTesting() const override;
 
   private:
     std::vector<Ref<PhysicalDeviceBase>> DiscoverPhysicalDevicesWithProcs(
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index b2f6234..726477e 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -158,7 +158,7 @@
     // extensions
     bool hasDebugOutput = gl.IsAtLeastGL(4, 3) || gl.IsAtLeastGLES(3, 2);
 
-    if (GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled() && hasDebugOutput) {
+    if (GetAdapter()->GetInstance()->IsBackendValidationEnabled() && hasDebugOutput) {
         gl.Enable(GL_DEBUG_OUTPUT);
         gl.Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
 
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.cpp b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
index 147c1a7..70e6e73 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.cpp
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.cpp
@@ -90,8 +90,7 @@
 }  // anonymous namespace
 
 // static
-ResultOrError<Ref<PhysicalDevice>> PhysicalDevice::Create(InstanceBase* instance,
-                                                          wgpu::BackendType backendType,
+ResultOrError<Ref<PhysicalDevice>> PhysicalDevice::Create(wgpu::BackendType backendType,
                                                           void* (*getProc)(const char*),
                                                           EGLDisplay display) {
     EGLFunctions egl;
@@ -116,8 +115,7 @@
 
     context->MakeCurrent();
 
-    Ref<PhysicalDevice> physicalDevice =
-        AcquireRef(new PhysicalDevice(instance, backendType, display));
+    Ref<PhysicalDevice> physicalDevice = AcquireRef(new PhysicalDevice(backendType, display));
     DAWN_TRY(physicalDevice->InitializeGLFunctions(getProc));
     DAWN_TRY(physicalDevice->Initialize());
 
@@ -125,10 +123,8 @@
     return physicalDevice;
 }
 
-PhysicalDevice::PhysicalDevice(InstanceBase* instance,
-                               wgpu::BackendType backendType,
-                               EGLDisplay display)
-    : PhysicalDeviceBase(instance, backendType), mDisplay(display) {}
+PhysicalDevice::PhysicalDevice(wgpu::BackendType backendType, EGLDisplay display)
+    : PhysicalDeviceBase(backendType), mDisplay(display) {}
 
 MaybeError PhysicalDevice::InitializeGLFunctions(void* (*getProc)(const char*)) {
     // Use getProc to populate the dispatch table
@@ -331,9 +327,11 @@
     return {};
 }
 
-void PhysicalDevice::SetupBackendAdapterToggles(TogglesState* adpterToggles) const {}
+void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                                TogglesState* adapterToggles) const {}
 
-void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
+void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                               TogglesState* deviceToggles) const {
     const OpenGLFunctions& gl = mFunctions;
 
     bool supportsBaseVertex = gl.IsAtLeastGLES(3, 2) || gl.IsAtLeastGL(3, 2);
@@ -453,6 +451,7 @@
 }
 
 ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
+    InstanceBase*,
     const Surface*) const {
     PhysicalDeviceSurfaceCapabilities capabilities;
 
diff --git a/src/dawn/native/opengl/PhysicalDeviceGL.h b/src/dawn/native/opengl/PhysicalDeviceGL.h
index ac0fa7a..1518af3 100644
--- a/src/dawn/native/opengl/PhysicalDeviceGL.h
+++ b/src/dawn/native/opengl/PhysicalDeviceGL.h
@@ -36,8 +36,7 @@
 
 class PhysicalDevice : public PhysicalDeviceBase {
   public:
-    static ResultOrError<Ref<PhysicalDevice>> Create(InstanceBase* instance,
-                                                     wgpu::BackendType backendType,
+    static ResultOrError<Ref<PhysicalDevice>> Create(wgpu::BackendType backendType,
                                                      void* (*getProc)(const char*),
                                                      EGLDisplay display);
 
@@ -47,10 +46,11 @@
     bool SupportsExternalImages() const override;
     bool SupportsFeatureLevel(FeatureLevel featureLevel) const override;
     ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
+        InstanceBase* instance,
         const Surface* surface) const override;
 
   private:
-    PhysicalDevice(InstanceBase* instance, wgpu::BackendType backendType, EGLDisplay display);
+    PhysicalDevice(wgpu::BackendType backendType, EGLDisplay display);
     MaybeError InitializeGLFunctions(void* (*getProc)(const char*));
 
     MaybeError InitializeImpl() override;
@@ -61,8 +61,10 @@
         wgpu::FeatureName feature,
         const TogglesState& toggles) const override;
 
-    void SetupBackendAdapterToggles(TogglesState* adapterToggles) const override;
-    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+    void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                    TogglesState* adapterToggles) const override;
+    void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                   TogglesState* deviceToggles) const override;
     ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
         AdapterBase* adapter,
         const UnpackedPtr<DeviceDescriptor>& descriptor,
diff --git a/src/dawn/native/vulkan/BackendVk.cpp b/src/dawn/native/vulkan/BackendVk.cpp
index d8feeb7..60a7bba 100644
--- a/src/dawn/native/vulkan/BackendVk.cpp
+++ b/src/dawn/native/vulkan/BackendVk.cpp
@@ -589,8 +589,8 @@
             const std::vector<VkPhysicalDevice>& vkPhysicalDevices =
                 mVulkanInstances[icd]->GetVkPhysicalDevices();
             for (VkPhysicalDevice vkPhysicalDevice : vkPhysicalDevices) {
-                Ref<PhysicalDevice> physicalDevice = AcquireRef(
-                    new PhysicalDevice(instance, mVulkanInstances[icd].Get(), vkPhysicalDevice));
+                Ref<PhysicalDevice> physicalDevice =
+                    AcquireRef(new PhysicalDevice(mVulkanInstances[icd].Get(), vkPhysicalDevice));
                 if (instance->ConsumedErrorAndWarnOnce(physicalDevice->Initialize())) {
                     continue;
                 }
@@ -603,20 +603,6 @@
     return physicalDevices;
 }
 
-void Backend::ClearPhysicalDevices() {
-    for (ICD icd : kICDs) {
-        mPhysicalDevices[icd].clear();
-    }
-}
-
-size_t Backend::GetPhysicalDeviceCountForTesting() const {
-    size_t count = 0;
-    for (ICD icd : kICDs) {
-        count += mPhysicalDevices[icd].size();
-    }
-    return count;
-}
-
 BackendConnection* Connect(InstanceBase* instance) {
     return new Backend(instance);
 }
diff --git a/src/dawn/native/vulkan/BackendVk.h b/src/dawn/native/vulkan/BackendVk.h
index 5e74098..5354ce3 100644
--- a/src/dawn/native/vulkan/BackendVk.h
+++ b/src/dawn/native/vulkan/BackendVk.h
@@ -109,8 +109,6 @@
 
     std::vector<Ref<PhysicalDeviceBase>> DiscoverPhysicalDevices(
         const UnpackedPtr<RequestAdapterOptions>& options) override;
-    void ClearPhysicalDevices() override;
-    size_t GetPhysicalDeviceCountForTesting() const override;
 
   private:
     ityp::bitset<ICD, kICDCount> mVulkanInstancesCreated = {};
diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp
index 8798ba0..b9e68ee 100644
--- a/src/dawn/native/vulkan/DeviceVk.cpp
+++ b/src/dawn/native/vulkan/DeviceVk.cpp
@@ -798,8 +798,7 @@
 }
 
 MaybeError Device::CheckDebugLayerAndGenerateErrors() {
-    if (!GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled() ||
-        mDebugMessages.empty()) {
+    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled() || mDebugMessages.empty()) {
         return {};
     }
 
@@ -811,7 +810,7 @@
 }
 
 void Device::AppendDebugLayerMessages(ErrorData* error) {
-    if (!GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled()) {
+    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled()) {
         return;
     }
 
@@ -822,8 +821,7 @@
 }
 
 void Device::CheckDebugMessagesAfterDestruction() const {
-    if (!GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled() ||
-        mDebugMessages.empty()) {
+    if (!GetAdapter()->GetInstance()->IsBackendValidationEnabled() || mDebugMessages.empty()) {
         return;
     }
 
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
index e6bd5a6..46a12a8 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp
@@ -81,10 +81,8 @@
 
 }  // anonymous namespace
 
-PhysicalDevice::PhysicalDevice(InstanceBase* instance,
-                               VulkanInstance* vulkanInstance,
-                               VkPhysicalDevice physicalDevice)
-    : PhysicalDeviceBase(instance, wgpu::BackendType::Vulkan),
+PhysicalDevice::PhysicalDevice(VulkanInstance* vulkanInstance, VkPhysicalDevice physicalDevice)
+    : PhysicalDeviceBase(wgpu::BackendType::Vulkan),
       mVkPhysicalDevice(physicalDevice),
       mVulkanInstance(vulkanInstance) {}
 
@@ -412,7 +410,7 @@
 
 #if DAWN_PLATFORM_IS(ANDROID)
     if (mDeviceInfo.HasExt(DeviceExt::ExternalMemoryAndroidHardwareBuffer)) {
-        if (GetInstance()->GetOrLoadAHBFunctions()->IsValid()) {
+        if (GetOrLoadAHBFunctions()->IsValid()) {
             EnableFeature(Feature::SharedTextureMemoryAHardwareBuffer);
         }
     }
@@ -625,9 +623,11 @@
     return true;
 }
 
-void PhysicalDevice::SetupBackendAdapterToggles(TogglesState* adpterToggles) const {}
+void PhysicalDevice::SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                                TogglesState* adapterToggles) const {}
 
-void PhysicalDevice::SetupBackendDeviceToggles(TogglesState* deviceToggles) const {
+void PhysicalDevice::SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                               TogglesState* deviceToggles) const {
     // TODO(crbug.com/dawn/857): tighten this workaround when this issue is fixed in both
     // Vulkan SPEC and drivers.
     deviceToggles->Default(Toggle::UseTemporaryBufferInCompressedTextureToTextureCopy, true);
@@ -637,8 +637,8 @@
     deviceToggles->Default(Toggle::UseTintIR, true);
 #else
     // All other platforms default to the value corresponding to the feature flag.
-    deviceToggles->Default(Toggle::UseTintIR, GetInstance()->GetPlatform()->IsFeatureEnabled(
-                                                  platform::Features::kWebGPUUseTintIR));
+    deviceToggles->Default(Toggle::UseTintIR,
+                           platform->IsFeatureEnabled(platform::Features::kWebGPUUseTintIR));
 #endif
 
     if (IsAndroidQualcomm()) {
@@ -867,6 +867,7 @@
 }
 
 ResultOrError<PhysicalDeviceSurfaceCapabilities> PhysicalDevice::GetSurfaceCapabilities(
+    InstanceBase* instance,
     const Surface* surface) const {
     PhysicalDeviceSurfaceCapabilities capabilities;
 
@@ -902,7 +903,7 @@
     capabilities.alphaModes.push_back(wgpu::CompositeAlphaMode::Opaque);
 #else
     VkSurfaceKHR vkSurface;
-    DAWN_TRY_ASSIGN(vkSurface, CreateVulkanSurface(this, surface));
+    DAWN_TRY_ASSIGN(vkSurface, CreateVulkanSurface(instance, this, surface));
 
     VkPhysicalDevice vkPhysicalDevice = GetVkPhysicalDevice();
     const VulkanFunctions& fn = GetVulkanInstance()->GetFunctions();
@@ -941,6 +942,17 @@
     return capabilities;
 }
 
+const AHBFunctions* PhysicalDevice::GetOrLoadAHBFunctions() {
+#if DAWN_PLATFORM_IS(ANDROID)
+    if (mAHBFunctions == nullptr) {
+        mAHBFunctions = std::make_unique<AHBFunctions>();
+    }
+    return mAHBFunctions.get();
+#else
+    DAWN_UNREACHABLE();
+#endif  // DAWN_PLATFORM_IS(ANDROID)
+}
+
 void PhysicalDevice::PopulateBackendProperties(UnpackedPtr<AdapterProperties>& properties) const {
     if (auto* memoryHeapProperties = properties.Get<AdapterPropertiesMemoryHeaps>()) {
         size_t count = mDeviceInfo.memoryHeaps.size();
diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.h b/src/dawn/native/vulkan/PhysicalDeviceVk.h
index d4fe78a..fb8d266 100644
--- a/src/dawn/native/vulkan/PhysicalDeviceVk.h
+++ b/src/dawn/native/vulkan/PhysicalDeviceVk.h
@@ -28,21 +28,24 @@
 #ifndef SRC_DAWN_NATIVE_VULKAN_ADAPTERVK_H_
 #define SRC_DAWN_NATIVE_VULKAN_ADAPTERVK_H_
 
-#include "dawn/native/PhysicalDevice.h"
+#include <memory>
 
 #include "dawn/common/Ref.h"
 #include "dawn/common/vulkan_platform.h"
+#include "dawn/native/PhysicalDevice.h"
 #include "dawn/native/vulkan/VulkanInfo.h"
 
+namespace dawn::native {
+class AHBFunctions;
+}  // namespace dawn::native
+
 namespace dawn::native::vulkan {
 
 class VulkanInstance;
 
 class PhysicalDevice : public PhysicalDeviceBase {
   public:
-    PhysicalDevice(InstanceBase* instance,
-                   VulkanInstance* vulkanInstance,
-                   VkPhysicalDevice physicalDevice);
+    PhysicalDevice(VulkanInstance* vulkanInstance, VkPhysicalDevice physicalDevice);
     ~PhysicalDevice() override;
 
     // PhysicalDeviceBase Implementation
@@ -62,7 +65,9 @@
     uint32_t GetDefaultComputeSubgroupSize() const;
 
     ResultOrError<PhysicalDeviceSurfaceCapabilities> GetSurfaceCapabilities(
+        InstanceBase* instance,
         const Surface* surface) const override;
+    const AHBFunctions* GetOrLoadAHBFunctions();
 
   private:
     MaybeError InitializeImpl() override;
@@ -73,8 +78,10 @@
         wgpu::FeatureName feature,
         const TogglesState& toggles) const override;
 
-    void SetupBackendAdapterToggles(TogglesState* adapterToggles) const override;
-    void SetupBackendDeviceToggles(TogglesState* deviceToggles) const override;
+    void SetupBackendAdapterToggles(dawn::platform::Platform* platform,
+                                    TogglesState* adapterToggles) const override;
+    void SetupBackendDeviceToggles(dawn::platform::Platform* platform,
+                                   TogglesState* deviceToggles) const override;
     ResultOrError<Ref<DeviceBase>> CreateDeviceImpl(
         AdapterBase* adapter,
         const UnpackedPtr<DeviceDescriptor>& descriptor,
@@ -95,6 +102,10 @@
     VulkanDeviceInfo mDeviceInfo = {};
 
     uint32_t mDefaultComputeSubgroupSize = 0;
+
+#if DAWN_PLATFORM_IS(ANDROID)
+    std::unique_ptr<AHBFunctions> mAHBFunctions;
+#endif  // DAWN_PLATFORM_IS(ANDROID)
 };
 
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/native/vulkan/SharedTextureMemoryVk.cpp b/src/dawn/native/vulkan/SharedTextureMemoryVk.cpp
index d6b5d2a..fb817c8 100644
--- a/src/dawn/native/vulkan/SharedTextureMemoryVk.cpp
+++ b/src/dawn/native/vulkan/SharedTextureMemoryVk.cpp
@@ -386,8 +386,7 @@
     // Don't add the view format if backend validation is enabled, otherwise most image creations
     // will fail with VVL. This view format is only needed for sRGB reinterpretation.
     // TODO(crbug.com/dawn/2304): Investigate if this is a bug in VVL.
-    if (addViewFormats &&
-        !device->GetPhysicalDevice()->GetInstance()->IsBackendValidationEnabled()) {
+    if (addViewFormats && !device->GetAdapter()->GetInstance()->IsBackendValidationEnabled()) {
         DAWN_ASSERT(compatibleViewFormats.size() == 1u);
         viewFormats[imageFormatListInfo.viewFormatCount++] =
             VulkanImageFormat(device, compatibleViewFormats[0]->format);
@@ -487,7 +486,8 @@
     const char* label,
     const SharedTextureMemoryAHardwareBufferDescriptor* descriptor) {
 #if DAWN_PLATFORM_IS(ANDROID)
-    const auto* ahbFunctions = device->GetInstance()->GetOrLoadAHBFunctions();
+    const auto* ahbFunctions =
+        ToBackend(device->GetAdapter()->GetPhysicalDevice())->GetOrLoadAHBFunctions();
     VkDevice vkDevice = device->GetVkDevice();
 
     auto* aHardwareBuffer = static_cast<struct AHardwareBuffer*>(descriptor->handle);
diff --git a/src/dawn/native/vulkan/SwapChainVk.cpp b/src/dawn/native/vulkan/SwapChainVk.cpp
index bf0ea02..360fff2 100644
--- a/src/dawn/native/vulkan/SwapChainVk.cpp
+++ b/src/dawn/native/vulkan/SwapChainVk.cpp
@@ -88,7 +88,7 @@
 
     VkSurfaceKHR surfaceVk;
     VkSurfaceCapabilitiesKHR surfaceCapsVk;
-    DAWN_TRY_ASSIGN(surfaceVk, CreateVulkanSurface(physicalDevice, surface));
+    DAWN_TRY_ASSIGN(surfaceVk, CreateVulkanSurface(device->GetInstance(), physicalDevice, surface));
 
     DAWN_TRY(CheckVkSuccess(
         fn.GetPhysicalDeviceSurfaceCapabilitiesKHR(vkPhysicalDevice, surfaceVk, &surfaceCapsVk),
@@ -182,7 +182,8 @@
     }
 
     if (mVkSurface == VK_NULL_HANDLE) {
-        DAWN_TRY_ASSIGN(mVkSurface, CreateVulkanSurface(physicalDevice, GetSurface()));
+        DAWN_TRY_ASSIGN(mVkSurface,
+                        CreateVulkanSurface(device->GetInstance(), physicalDevice, GetSurface()));
     }
 
     VulkanSurfaceInfo surfaceInfo;
@@ -616,14 +617,15 @@
     }
 }
 
-ResultOrError<VkSurfaceKHR> CreateVulkanSurface(const PhysicalDevice* physicalDevice,
+ResultOrError<VkSurfaceKHR> CreateVulkanSurface(InstanceBase* instance,
+                                                const PhysicalDevice* physicalDevice,
                                                 const Surface* surface) {
     // May not be used in the platform-specific switches below.
     [[maybe_unused]] const VulkanGlobalInfo& info =
         physicalDevice->GetVulkanInstance()->GetGlobalInfo();
     [[maybe_unused]] const VulkanFunctions& fn =
         physicalDevice->GetVulkanInstance()->GetFunctions();
-    [[maybe_unused]] VkInstance instance = physicalDevice->GetVulkanInstance()->GetVkInstance();
+    [[maybe_unused]] VkInstance vkInstance = physicalDevice->GetVulkanInstance()->GetVkInstance();
 
     switch (surface->GetType()) {
 #if defined(DAWN_ENABLE_BACKEND_METAL)
@@ -637,7 +639,7 @@
 
                 VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                 DAWN_TRY(CheckVkSuccess(
-                    fn.CreateMetalSurfaceEXT(instance, &createInfo, nullptr, &*vkSurface),
+                    fn.CreateMetalSurfaceEXT(vkInstance, &createInfo, nullptr, &*vkSurface),
                     "CreateMetalSurface"));
                 return vkSurface;
             }
@@ -656,7 +658,7 @@
 
                 VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                 DAWN_TRY(CheckVkSuccess(
-                    fn.CreateWin32SurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    fn.CreateWin32SurfaceKHR(vkInstance, &createInfo, nullptr, &*vkSurface),
                     "CreateWin32Surface"));
                 return vkSurface;
             }
@@ -677,7 +679,7 @@
 
                 VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                 DAWN_TRY(CheckVkSuccess(
-                    fn.CreateAndroidSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    fn.CreateAndroidSurfaceKHR(vkInstance, &createInfo, nullptr, &*vkSurface),
                     "CreateAndroidSurfaceKHR"));
                 return vkSurface;
             }
@@ -699,7 +701,7 @@
 
                 VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                 DAWN_TRY(CheckVkSuccess(
-                    fn.CreateWaylandSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    fn.CreateWaylandSurfaceKHR(vkInstance, &createInfo, nullptr, &*vkSurface),
                     "CreateWaylandSurface"));
                 return vkSurface;
             }
@@ -719,7 +721,7 @@
 
                 VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                 DAWN_TRY(CheckVkSuccess(
-                    fn.CreateXlibSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    fn.CreateXlibSurfaceKHR(vkInstance, &createInfo, nullptr, &*vkSurface),
                     "CreateXlibSurface"));
                 return vkSurface;
             }
@@ -727,7 +729,7 @@
             // Fall back to using XCB surfaces if the Xlib extension isn't available.
             // See https://xcb.freedesktop.org/MixingCalls/ for more information about
             // interoperability between Xlib and XCB
-            const X11Functions* x11 = physicalDevice->GetInstance()->GetOrLoadX11Functions();
+            const X11Functions* x11 = instance->GetOrLoadX11Functions();
             DAWN_ASSERT(x11 != nullptr);
 
             if (info.HasExt(InstanceExt::XcbSurface) && x11->IsX11XcbLoaded()) {
@@ -742,7 +744,7 @@
 
                 VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                 DAWN_TRY(CheckVkSuccess(
-                    fn.CreateXcbSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
+                    fn.CreateXcbSurfaceKHR(vkInstance, &createInfo, nullptr, &*vkSurface),
                     "CreateXcbSurfaceKHR"));
                 return vkSurface;
             }
diff --git a/src/dawn/native/vulkan/SwapChainVk.h b/src/dawn/native/vulkan/SwapChainVk.h
index da1f7ea..501841d 100644
--- a/src/dawn/native/vulkan/SwapChainVk.h
+++ b/src/dawn/native/vulkan/SwapChainVk.h
@@ -97,7 +97,8 @@
     Ref<Texture> mTexture;
 };
 
-ResultOrError<VkSurfaceKHR> CreateVulkanSurface(const PhysicalDevice* physicalDevice,
+ResultOrError<VkSurfaceKHR> CreateVulkanSurface(InstanceBase* instance,
+                                                const PhysicalDevice* physicalDevice,
                                                 const Surface* surface);
 
 }  // namespace dawn::native::vulkan
diff --git a/src/dawn/tests/end2end/DeviceInitializationTests.cpp b/src/dawn/tests/end2end/DeviceInitializationTests.cpp
index 1034ad7..fb1f443 100644
--- a/src/dawn/tests/end2end/DeviceInitializationTests.cpp
+++ b/src/dawn/tests/end2end/DeviceInitializationTests.cpp
@@ -150,10 +150,6 @@
         wgpu::Adapter adapter;
 
         auto instance = std::make_unique<native::Instance>();
-        // Save a pointer to the instance.
-        // It will only be valid as long as the instance is alive.
-        WGPUInstance unsafeInstancePtr = instance->Get();
-
         for (native::Adapter& nativeAdapter : instance->EnumerateAdapters()) {
             wgpu::AdapterProperties properties;
             nativeAdapter.GetProperties(&properties);
@@ -163,14 +159,8 @@
                 properties.adapterType == desiredProperties.adapterType &&
                 properties.backendType == desiredProperties.backendType) {
                 // Save the adapter, and reset the instance.
-                // Check that the number of adapters before the reset is > 0, and after the reset
-                // is 0. Unsafe, but we assume the pointer is still valid since the adapter is
-                // holding onto the instance. The instance should have cleared all internal
-                // references to adapters when the last external ref is dropped.
                 adapter = wgpu::Adapter(nativeAdapter.Get());
-                EXPECT_GT(native::GetPhysicalDeviceCountForTesting(unsafeInstancePtr), 0u);
                 instance.reset();
-                EXPECT_EQ(native::GetPhysicalDeviceCountForTesting(unsafeInstancePtr), 0u);
                 break;
             }
         }
diff --git a/src/dawn/tests/unittests/FeatureTests.cpp b/src/dawn/tests/unittests/FeatureTests.cpp
index c8f545a..45a79cd 100644
--- a/src/dawn/tests/unittests/FeatureTests.cpp
+++ b/src/dawn/tests/unittests/FeatureTests.cpp
@@ -41,13 +41,15 @@
     FeatureTests()
         : testing::Test(),
           mInstanceBase(native::APICreateInstance(nullptr)),
-          mPhysicalDevice(mInstanceBase.Get()),
-          mUnsafePhysicalDevice(mInstanceBase.Get()),
-          mAdapterBase(&mPhysicalDevice,
+          mPhysicalDevice(),
+          mUnsafePhysicalDevice(),
+          mAdapterBase(mInstanceBase.Get(),
+                       &mPhysicalDevice,
                        native::FeatureLevel::Core,
                        native::TogglesState(native::ToggleStage::Adapter),
                        wgpu::PowerPreference::Undefined),
-          mUnsafeAdapterBase(&mUnsafePhysicalDevice,
+          mUnsafeAdapterBase(mInstanceBase.Get(),
+                             &mUnsafePhysicalDevice,
                              native::FeatureLevel::Core,
                              native::TogglesState(native::ToggleStage::Adapter)
                                  .SetForTesting(native::Toggle::AllowUnsafeAPIs, true, true),
diff --git a/src/dawn/tests/unittests/GetProcAddressTests.cpp b/src/dawn/tests/unittests/GetProcAddressTests.cpp
index 73ebcc2..23706fc 100644
--- a/src/dawn/tests/unittests/GetProcAddressTests.cpp
+++ b/src/dawn/tests/unittests/GetProcAddressTests.cpp
@@ -70,7 +70,8 @@
     GetProcAddressTests()
         : testing::TestWithParam<DawnFlavor>(),
           mNativeInstance(native::APICreateInstance(nullptr)),
-          mAdapterBase(AcquireRef(new native::null::PhysicalDevice(mNativeInstance.Get())),
+          mAdapterBase(mNativeInstance.Get(),
+                       AcquireRef(new native::null::PhysicalDevice()),
                        native::FeatureLevel::Core,
                        native::TogglesState(native::ToggleStage::Adapter),
                        wgpu::PowerPreference::Undefined) {}
diff --git a/src/dawn/tests/unittests/PerThreadProcTests.cpp b/src/dawn/tests/unittests/PerThreadProcTests.cpp
index 942f417..5478480 100644
--- a/src/dawn/tests/unittests/PerThreadProcTests.cpp
+++ b/src/dawn/tests/unittests/PerThreadProcTests.cpp
@@ -43,7 +43,8 @@
   public:
     PerThreadProcTests()
         : mNativeInstance(native::APICreateInstance(nullptr)),
-          mAdapterBase(AcquireRef(new native::null::PhysicalDevice(mNativeInstance.Get())),
+          mAdapterBase(mNativeInstance.Get(),
+                       AcquireRef(new native::null::PhysicalDevice()),
                        native::FeatureLevel::Core,
                        native::TogglesState(native::ToggleStage::Adapter),
                        wgpu::PowerPreference::Undefined) {}
diff --git a/src/dawn/tests/unittests/ToggleTests.cpp b/src/dawn/tests/unittests/ToggleTests.cpp
index d45ea91..4026f10 100644
--- a/src/dawn/tests/unittests/ToggleTests.cpp
+++ b/src/dawn/tests/unittests/ToggleTests.cpp
@@ -434,17 +434,17 @@
 
     // Create null adapters with the AllowUnsafeAPIs toggle set/forced to enabled/disabled, using
     // the same physical device and feature level as the known null adapter.
-    auto CreateAdapterWithAllowUnsafeAPIsToggle = [&adapter, nullPhysicalDevice, featureLevel](
-                                                      bool isAllowUnsafeAPIsEnabled,
-                                                      bool isAllowUnsafeAPIsForced) {
+    auto CreateAdapterWithAllowUnsafeAPIsToggle = [&adapter, instanceBase, nullPhysicalDevice,
+                                                   featureLevel](bool isAllowUnsafeAPIsEnabled,
+                                                                 bool isAllowUnsafeAPIsForced) {
         native::TogglesState adapterTogglesState = adapter->GetTogglesState();
         adapterTogglesState.SetForTesting(native::Toggle::AllowUnsafeAPIs, isAllowUnsafeAPIsEnabled,
                                           isAllowUnsafeAPIsForced);
 
         Ref<native::AdapterBase> resultAdapter;
         resultAdapter = AcquireRef<native::AdapterBase>(
-            new native::AdapterBase(nullPhysicalDevice, featureLevel, adapterTogglesState,
-                                    wgpu::PowerPreference::Undefined));
+            new native::AdapterBase(instanceBase, nullPhysicalDevice, featureLevel,
+                                    adapterTogglesState, wgpu::PowerPreference::Undefined));
 
         // AllowUnsafeAPIs should be set as expected.
         EXPECT_TRUE(resultAdapter->GetTogglesState().IsSet(native::Toggle::AllowUnsafeAPIs));
@@ -558,15 +558,15 @@
 
     // Create null adapters with the UseDXC toggle set/forced to enabled/disabled, using the same
     // physical device and feature level as the known null adapter.
-    auto CreateAdapterWithDXCToggle = [&adapter, nullPhysicalDevice, featureLevel](
+    auto CreateAdapterWithDXCToggle = [&adapter, instanceBase, nullPhysicalDevice, featureLevel](
                                           bool isUseDXCEnabled, bool isUseDXCForced) {
         native::TogglesState adapterTogglesState = adapter->GetTogglesState();
         adapterTogglesState.SetForTesting(native::Toggle::UseDXC, isUseDXCEnabled, isUseDXCForced);
 
         Ref<native::AdapterBase> resultAdapter;
         resultAdapter = AcquireRef<native::AdapterBase>(
-            new native::AdapterBase(nullPhysicalDevice, featureLevel, adapterTogglesState,
-                                    wgpu::PowerPreference::Undefined));
+            new native::AdapterBase(instanceBase, nullPhysicalDevice, featureLevel,
+                                    adapterTogglesState, wgpu::PowerPreference::Undefined));
 
         // AllowUnsafeAPIs should be inherited disabled by default.
         EXPECT_TRUE(resultAdapter->GetTogglesState().IsSet(native::Toggle::AllowUnsafeAPIs));