Replace reinterpret_cast with FromAPI/ToAPI where possible

This brings more type safety to the code and is marginally more
readable.

Bug: None
Change-Id: I0330a8a8e95cd9b8b531af266acd8fdc50c50460
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/71606
Reviewed-by: Brandon Jones <bajones@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
Auto-Submit: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/templates/dawn_native/ProcTable.cpp b/generator/templates/dawn_native/ProcTable.cpp
index 7e0091b..f2a4c55 100644
--- a/generator/templates/dawn_native/ProcTable.cpp
+++ b/generator/templates/dawn_native/ProcTable.cpp
@@ -39,7 +39,7 @@
                     {%- endfor -%}
                 ) {
                     //* Perform conversion between C types and frontend types
-                    auto self = reinterpret_cast<{{as_frontendType(type)}}>(cSelf);
+                    auto self = FromAPI(cSelf);
 
                     {% for arg in method.arguments %}
                         {% set varName = as_varName(arg.name) %}
@@ -63,7 +63,7 @@
                     );
                     {% if method.return_type.name.canonical_case() != "void" %}
                         {% if method.return_type.category == "object" %}
-                            return reinterpret_cast<{{as_cType(method.return_type.name)}}>(result);
+                            return ToAPI(result);
                         {% else %}
                             return result;
                         {% endif %}
@@ -84,10 +84,8 @@
         static constexpr size_t sProcMapSize = sizeof(sProcMap) / sizeof(sProcMap[0]);
     }
 
-    WGPUInstance NativeCreateInstance(WGPUInstanceDescriptor const* cDescriptor) {
-        const dawn_native::InstanceDescriptor* descriptor =
-            reinterpret_cast<const dawn_native::InstanceDescriptor*>(cDescriptor);
-        return reinterpret_cast<WGPUInstance>(InstanceBase::Create(descriptor));
+    WGPUInstance NativeCreateInstance(WGPUInstanceDescriptor const* descriptor) {
+        return ToAPI(InstanceBase::Create(FromAPI(descriptor)));
     }
 
     WGPUProc NativeGetProcAddress(WGPUDevice, const char* procName) {
diff --git a/src/dawn_native/Adapter.cpp b/src/dawn_native/Adapter.cpp
index e5b5f2b..77082d7 100644
--- a/src/dawn_native/Adapter.cpp
+++ b/src/dawn_native/Adapter.cpp
@@ -119,7 +119,7 @@
         // to store them (ex. by calling GetLimits directly instead). Currently,
         // we keep this function as it's only used internally in Chromium to
         // send the adapter properties across the wire.
-        GetLimits(reinterpret_cast<SupportedLimits*>(&adapterProperties.limits));
+        GetLimits(FromAPI(&adapterProperties.limits));
         return adapterProperties;
     }
 
@@ -149,19 +149,18 @@
     void AdapterBase::RequestDevice(const DawnDeviceDescriptor* descriptor,
                                     WGPURequestDeviceCallback callback,
                                     void* userdata) {
-        DeviceBase* result = nullptr;
-        MaybeError err = CreateDeviceInternal(&result, descriptor);
-        WGPUDevice device = reinterpret_cast<WGPUDevice>(result);
+        DeviceBase* device = nullptr;
+        MaybeError err = CreateDeviceInternal(&device, descriptor);
 
         if (err.IsError()) {
             std::unique_ptr<ErrorData> errorData = err.AcquireError();
-            callback(WGPURequestDeviceStatus_Error, device,
+            callback(WGPURequestDeviceStatus_Error, ToAPI(device),
                      errorData->GetFormattedMessage().c_str(), userdata);
             return;
         }
         WGPURequestDeviceStatus status =
             device == nullptr ? WGPURequestDeviceStatus_Unknown : WGPURequestDeviceStatus_Success;
-        callback(status, device, nullptr, userdata);
+        callback(status, ToAPI(device), nullptr, userdata);
     }
 
     MaybeError AdapterBase::CreateDeviceInternal(DeviceBase** result,
@@ -178,9 +177,8 @@
 
         if (descriptor != nullptr && descriptor->requiredLimits != nullptr) {
             DAWN_TRY_CONTEXT(
-                ValidateLimits(
-                    mUseTieredLimits ? ApplyLimitTiers(mLimits.v1) : mLimits.v1,
-                    reinterpret_cast<const RequiredLimits*>(descriptor->requiredLimits)->limits),
+                ValidateLimits(mUseTieredLimits ? ApplyLimitTiers(mLimits.v1) : mLimits.v1,
+                               FromAPI(descriptor->requiredLimits)->limits),
                 "validating required limits");
 
             DAWN_INVALID_IF(descriptor->requiredLimits->nextInChain != nullptr,
diff --git a/src/dawn_native/CreatePipelineAsyncTask.cpp b/src/dawn_native/CreatePipelineAsyncTask.cpp
index e241235..a266988 100644
--- a/src/dawn_native/CreatePipelineAsyncTask.cpp
+++ b/src/dawn_native/CreatePipelineAsyncTask.cpp
@@ -44,9 +44,8 @@
         ASSERT(mCreateComputePipelineAsyncCallback != nullptr);
 
         if (mPipeline.Get() != nullptr) {
-            mCreateComputePipelineAsyncCallback(
-                WGPUCreatePipelineAsyncStatus_Success,
-                reinterpret_cast<WGPUComputePipeline>(mPipeline.Detach()), "", mUserData);
+            mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Success,
+                                                ToAPI(mPipeline.Detach()), "", mUserData);
         } else {
             mCreateComputePipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Error, nullptr,
                                                 mErrorMessage.c_str(), mUserData);
@@ -81,9 +80,8 @@
         ASSERT(mCreateRenderPipelineAsyncCallback != nullptr);
 
         if (mPipeline.Get() != nullptr) {
-            mCreateRenderPipelineAsyncCallback(
-                WGPUCreatePipelineAsyncStatus_Success,
-                reinterpret_cast<WGPURenderPipeline>(mPipeline.Detach()), "", mUserData);
+            mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Success,
+                                               ToAPI(mPipeline.Detach()), "", mUserData);
         } else {
             mCreateRenderPipelineAsyncCallback(WGPUCreatePipelineAsyncStatus_Error, nullptr,
                                                mErrorMessage.c_str(), mUserData);
diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp
index 80dfc72..c10fe00 100644
--- a/src/dawn_native/DawnNative.cpp
+++ b/src/dawn_native/DawnNative.cpp
@@ -32,9 +32,7 @@
     }
 
     std::vector<const char*> GetTogglesUsed(WGPUDevice device) {
-        const dawn_native::DeviceBase* deviceBase =
-            reinterpret_cast<const dawn_native::DeviceBase*>(device);
-        return deviceBase->GetTogglesUsed();
+        return FromAPI(device)->GetTogglesUsed();
     }
 
     // Adapter
@@ -110,7 +108,7 @@
     }
 
     bool Adapter::GetLimits(WGPUSupportedLimits* limits) const {
-        return mImpl->GetLimits(reinterpret_cast<SupportedLimits*>(limits));
+        return mImpl->GetLimits(FromAPI(limits));
     }
 
     void Adapter::SetUseTieredLimits(bool useTieredLimits) {
@@ -126,7 +124,7 @@
     }
 
     WGPUDevice Adapter::CreateDevice(const DawnDeviceDescriptor* deviceDescriptor) {
-        return reinterpret_cast<WGPUDevice>(mImpl->CreateDevice(deviceDescriptor));
+        return ToAPI(mImpl->CreateDevice(deviceDescriptor));
     }
 
     void Adapter::RequestDevice(const DawnDeviceDescriptor* descriptor,
@@ -197,31 +195,29 @@
     }
 
     WGPUInstance Instance::Get() const {
-        return reinterpret_cast<WGPUInstance>(mImpl);
+        return ToAPI(mImpl);
     }
 
     size_t GetLazyClearCountForTesting(WGPUDevice device) {
-        dawn_native::DeviceBase* deviceBase = reinterpret_cast<dawn_native::DeviceBase*>(device);
-        return deviceBase->GetLazyClearCountForTesting();
+        return FromAPI(device)->GetLazyClearCountForTesting();
     }
 
     size_t GetDeprecationWarningCountForTesting(WGPUDevice device) {
-        dawn_native::DeviceBase* deviceBase = reinterpret_cast<dawn_native::DeviceBase*>(device);
-        return deviceBase->GetDeprecationWarningCountForTesting();
+        return FromAPI(device)->GetDeprecationWarningCountForTesting();
     }
 
-    bool IsTextureSubresourceInitialized(WGPUTexture cTexture,
+    bool IsTextureSubresourceInitialized(WGPUTexture texture,
                                          uint32_t baseMipLevel,
                                          uint32_t levelCount,
                                          uint32_t baseArrayLayer,
                                          uint32_t layerCount,
                                          WGPUTextureAspect cAspect) {
-        dawn_native::TextureBase* texture = reinterpret_cast<dawn_native::TextureBase*>(cTexture);
+        TextureBase* textureBase = FromAPI(texture);
 
         Aspect aspect =
-            ConvertAspect(texture->GetFormat(), static_cast<wgpu::TextureAspect>(cAspect));
+            ConvertAspect(textureBase->GetFormat(), static_cast<wgpu::TextureAspect>(cAspect));
         SubresourceRange range(aspect, {baseArrayLayer, layerCount}, {baseMipLevel, levelCount});
-        return texture->IsSubresourceContentInitialized(range);
+        return textureBase->IsSubresourceContentInitialized(range);
     }
 
     std::vector<const char*> GetProcMapNamesForTestingInternal();
@@ -231,8 +227,7 @@
     }
 
     DAWN_NATIVE_EXPORT bool DeviceTick(WGPUDevice device) {
-        dawn_native::DeviceBase* deviceBase = reinterpret_cast<dawn_native::DeviceBase*>(device);
-        return deviceBase->APITick();
+        return FromAPI(device)->APITick();
     }
 
     // ExternalImageDescriptor
@@ -251,14 +246,12 @@
     }
 
     uint64_t GetAllocatedSizeForTesting(WGPUBuffer buffer) {
-        return reinterpret_cast<const BufferBase*>(buffer)->GetAllocatedSize();
+        return FromAPI(buffer)->GetAllocatedSize();
     }
 
     bool BindGroupLayoutBindingsEqualForTesting(WGPUBindGroupLayout a, WGPUBindGroupLayout b) {
-        BindGroupLayoutBase* aBase = reinterpret_cast<BindGroupLayoutBase*>(a);
-        BindGroupLayoutBase* bBase = reinterpret_cast<BindGroupLayoutBase*>(b);
         bool excludePipelineCompatibiltyToken = true;
-        return aBase->IsLayoutEqual(bBase, excludePipelineCompatibiltyToken);
+        return FromAPI(a)->IsLayoutEqual(FromAPI(b), excludePipelineCompatibiltyToken);
     }
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index df06f8b..35b5101 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -180,8 +180,7 @@
         }
 
         if (descriptor != nullptr && descriptor->requiredLimits != nullptr) {
-            mLimits.v1 = ReifyDefaultLimits(
-                reinterpret_cast<const RequiredLimits*>(descriptor->requiredLimits)->limits);
+            mLimits.v1 = ReifyDefaultLimits(FromAPI(descriptor->requiredLimits)->limits);
         } else {
             GetDefaultLimits(&mLimits.v1);
         }
@@ -252,7 +251,7 @@
             ShaderModuleDescriptor descriptor;
             ShaderModuleWGSLDescriptor wgslDesc;
             wgslDesc.source = kEmptyFragmentShader;
-            descriptor.nextInChain = reinterpret_cast<ChainedStruct*>(&wgslDesc);
+            descriptor.nextInChain = &wgslDesc;
 
             DAWN_TRY_ASSIGN(mInternalPipelineStore->dummyFragmentShader,
                             CreateShaderModule(&descriptor));
@@ -1315,9 +1314,8 @@
         Ref<ComputePipelineBase> cachedComputePipeline =
             GetCachedComputePipeline(uninitializedComputePipeline.Get());
         if (cachedComputePipeline.Get() != nullptr) {
-            callback(WGPUCreatePipelineAsyncStatus_Success,
-                     reinterpret_cast<WGPUComputePipeline>(cachedComputePipeline.Detach()), "",
-                     userdata);
+            callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(cachedComputePipeline.Detach()),
+                     "", userdata);
         } else {
             // Otherwise we will create the pipeline object in InitializeComputePipelineAsyncImpl(),
             // where the pipeline object may be initialized asynchronously and the result will be
@@ -1462,9 +1460,8 @@
         Ref<RenderPipelineBase> cachedRenderPipeline =
             GetCachedRenderPipeline(uninitializedRenderPipeline.Get());
         if (cachedRenderPipeline != nullptr) {
-            callback(WGPUCreatePipelineAsyncStatus_Success,
-                     reinterpret_cast<WGPURenderPipeline>(cachedRenderPipeline.Detach()), "",
-                     userdata);
+            callback(WGPUCreatePipelineAsyncStatus_Success, ToAPI(cachedRenderPipeline.Detach()),
+                     "", userdata);
         } else {
             // Otherwise we will create the pipeline object in InitializeRenderPipelineAsyncImpl(),
             // where the pipeline object may be initialized asynchronously and the result will be
diff --git a/src/dawn_native/PersistentCache.cpp b/src/dawn_native/PersistentCache.cpp
index ce52a1e..944fd5c 100644
--- a/src/dawn_native/PersistentCache.cpp
+++ b/src/dawn_native/PersistentCache.cpp
@@ -30,13 +30,11 @@
             return blob;
         }
         std::lock_guard<std::mutex> lock(mMutex);
-        blob.bufferSize = mCache->LoadData(reinterpret_cast<WGPUDevice>(mDevice), key.data(),
-                                           key.size(), nullptr, 0);
+        blob.bufferSize = mCache->LoadData(ToAPI(mDevice), key.data(), key.size(), nullptr, 0);
         if (blob.bufferSize > 0) {
             blob.buffer.reset(new uint8_t[blob.bufferSize]);
-            const size_t bufferSize =
-                mCache->LoadData(reinterpret_cast<WGPUDevice>(mDevice), key.data(), key.size(),
-                                 blob.buffer.get(), blob.bufferSize);
+            const size_t bufferSize = mCache->LoadData(ToAPI(mDevice), key.data(), key.size(),
+                                                       blob.buffer.get(), blob.bufferSize);
             ASSERT(bufferSize == blob.bufferSize);
             return blob;
         }
@@ -50,8 +48,7 @@
         ASSERT(value != nullptr);
         ASSERT(size > 0);
         std::lock_guard<std::mutex> lock(mMutex);
-        mCache->StoreData(reinterpret_cast<WGPUDevice>(mDevice), key.data(), key.size(), value,
-                          size);
+        mCache->StoreData(ToAPI(mDevice), key.data(), key.size(), value, size);
     }
 
     dawn_platform::CachingInterface* PersistentCache::GetPlatformCache() {
diff --git a/src/dawn_native/d3d12/D3D12Backend.cpp b/src/dawn_native/d3d12/D3D12Backend.cpp
index 52c5099..f84b236 100644
--- a/src/dawn_native/d3d12/D3D12Backend.cpp
+++ b/src/dawn_native/d3d12/D3D12Backend.cpp
@@ -29,13 +29,11 @@
 namespace dawn_native { namespace d3d12 {
 
     ComPtr<ID3D12Device> GetD3D12Device(WGPUDevice device) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
-
-        return backendDevice->GetD3D12Device();
+        return ToBackend(FromAPI(device))->GetD3D12Device();
     }
 
     DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device, HWND window) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
 
         DawnSwapChainImplementation impl;
         impl = CreateSwapChainImplementation(new NativeSwapChainImpl(backendDevice, window));
@@ -78,7 +76,7 @@
     WGPUTexture ExternalImageDXGI::ProduceTexture(
         WGPUDevice device,
         const ExternalImageAccessDescriptorDXGIKeyedMutex* descriptor) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
 
         // Ensure the texture usage is allowed
         if (!IsSubset(descriptor->usage, mUsage)) {
@@ -114,14 +112,14 @@
             ExternalMutexSerial(descriptor->releaseMutexKey), descriptor->isSwapChainTexture,
             descriptor->isInitialized);
 
-        return reinterpret_cast<WGPUTexture>(texture.Detach());
+        return ToAPI(texture.Detach());
     }
 
     // static
     std::unique_ptr<ExternalImageDXGI> ExternalImageDXGI::Create(
         WGPUDevice device,
         const ExternalImageDescriptorDXGISharedHandle* descriptor) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
 
         Microsoft::WRL::ComPtr<ID3D12Resource> d3d12Resource;
         if (FAILED(backendDevice->GetD3D12Device()->OpenSharedHandle(
@@ -129,8 +127,7 @@
             return nullptr;
         }
 
-        const TextureDescriptor* textureDescriptor =
-            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
         if (backendDevice->ConsumedError(
                 ValidateTextureDescriptor(backendDevice, textureDescriptor))) {
@@ -168,7 +165,7 @@
     uint64_t SetExternalMemoryReservation(WGPUDevice device,
                                           uint64_t requestedReservationSize,
                                           MemorySegment memorySegment) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
 
         return backendDevice->GetResidencyManager()->SetExternalMemoryReservation(
             memorySegment, requestedReservationSize);
diff --git a/src/dawn_native/d3d12/SwapChainD3D12.cpp b/src/dawn_native/d3d12/SwapChainD3D12.cpp
index a3f2bad..4c2dd24 100644
--- a/src/dawn_native/d3d12/SwapChainD3D12.cpp
+++ b/src/dawn_native/d3d12/SwapChainD3D12.cpp
@@ -83,7 +83,7 @@
         : OldSwapChainBase(device, descriptor) {
         const auto& im = GetImplementation();
         DawnWSIContextD3D12 wsiContext = {};
-        wsiContext.device = reinterpret_cast<WGPUDevice>(GetDevice());
+        wsiContext.device = ToAPI(GetDevice());
         im.Init(im.userData, &wsiContext);
 
         ASSERT(im.textureUsage != WGPUTextureUsage_None);
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index db93279..c79cff4 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -433,8 +433,7 @@
     Ref<Texture> Device::CreateTextureWrappingIOSurface(const ExternalImageDescriptor* descriptor,
                                                         IOSurfaceRef ioSurface,
                                                         uint32_t plane) {
-        const TextureDescriptor* textureDescriptor =
-            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
         if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
             return nullptr;
diff --git a/src/dawn_native/metal/MetalBackend.mm b/src/dawn_native/metal/MetalBackend.mm
index b8fffaf..4d97fb8 100644
--- a/src/dawn_native/metal/MetalBackend.mm
+++ b/src/dawn_native/metal/MetalBackend.mm
@@ -22,26 +22,24 @@
 
 namespace dawn_native { namespace metal {
 
-    id<MTLDevice> GetMetalDevice(WGPUDevice cDevice) {
-        Device* device = reinterpret_cast<Device*>(cDevice);
-        return device->GetMTLDevice();
+    id<MTLDevice> GetMetalDevice(WGPUDevice device) {
+        return ToBackend(FromAPI(device))->GetMTLDevice();
     }
 
     ExternalImageDescriptorIOSurface::ExternalImageDescriptorIOSurface()
         : ExternalImageDescriptor(ExternalImageType::IOSurface) {
     }
 
-    WGPUTexture WrapIOSurface(WGPUDevice cDevice,
+    WGPUTexture WrapIOSurface(WGPUDevice device,
                               const ExternalImageDescriptorIOSurface* cDescriptor) {
-        Device* device = reinterpret_cast<Device*>(cDevice);
-        Ref<TextureBase> texture = device->CreateTextureWrappingIOSurface(
+        Device* backendDevice = ToBackend(FromAPI(device));
+        Ref<TextureBase> texture = backendDevice->CreateTextureWrappingIOSurface(
             cDescriptor, cDescriptor->ioSurface, cDescriptor->plane);
-        return reinterpret_cast<WGPUTexture>(texture.Detach());
+        return ToAPI(texture.Detach());
     }
 
-    void WaitForCommandsToBeScheduled(WGPUDevice cDevice) {
-        Device* device = reinterpret_cast<Device*>(cDevice);
-        device->WaitForCommandsToBeScheduled();
+    void WaitForCommandsToBeScheduled(WGPUDevice device) {
+        ToBackend(FromAPI(device))->WaitForCommandsToBeScheduled();
     }
 
 }}  // namespace dawn_native::metal
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index d8105af..37eb9bc 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -431,8 +431,7 @@
         const ExternalImageDescriptor* descriptor,
         IOSurfaceRef ioSurface,
         uint32_t plane) {
-        const TextureDescriptor* textureDescriptor =
-            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
         Ref<Texture> texture =
             AcquireRef(new Texture(device, textureDescriptor, TextureState::OwnedInternal));
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index a098dfb..89bd9f8 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -203,8 +203,7 @@
     }
     TextureBase* Device::CreateTextureWrappingEGLImage(const ExternalImageDescriptor* descriptor,
                                                        ::EGLImage image) {
-        const TextureDescriptor* textureDescriptor =
-            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
         if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
             return nullptr;
diff --git a/src/dawn_native/opengl/OpenGLBackend.cpp b/src/dawn_native/opengl/OpenGLBackend.cpp
index 3e089bb..560f3a0 100644
--- a/src/dawn_native/opengl/OpenGLBackend.cpp
+++ b/src/dawn_native/opengl/OpenGLBackend.cpp
@@ -34,7 +34,7 @@
     DawnSwapChainImplementation CreateNativeSwapChainImpl(WGPUDevice device,
                                                           PresentCallback present,
                                                           void* presentUserdata) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
 
         DawnSwapChainImplementation impl;
         impl = CreateSwapChainImplementation(
@@ -54,11 +54,12 @@
         : ExternalImageDescriptor(ExternalImageType::EGLImage) {
     }
 
-    WGPUTexture WrapExternalEGLImage(WGPUDevice cDevice,
+    WGPUTexture WrapExternalEGLImage(WGPUDevice device,
                                      const ExternalImageDescriptorEGLImage* descriptor) {
-        Device* device = reinterpret_cast<Device*>(cDevice);
-        TextureBase* texture = device->CreateTextureWrappingEGLImage(descriptor, descriptor->image);
-        return reinterpret_cast<WGPUTexture>(texture);
+        Device* backendDevice = ToBackend(FromAPI(device));
+        TextureBase* texture =
+            backendDevice->CreateTextureWrappingEGLImage(descriptor, descriptor->image);
+        return ToAPI(texture);
     }
 
 }}  // namespace dawn_native::opengl
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 02fc43b..bd53564 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -719,8 +719,7 @@
                                            VkSemaphore* outSignalSemaphore,
                                            VkDeviceMemory* outAllocation,
                                            std::vector<VkSemaphore>* outWaitSemaphores) {
-        const TextureDescriptor* textureDescriptor =
-            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
         const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
         FindInChain(textureDescriptor->nextInChain, &internalUsageDesc);
@@ -794,8 +793,7 @@
         const ExternalImageDescriptorVk* descriptor,
         ExternalMemoryHandle memoryHandle,
         const std::vector<ExternalSemaphoreHandle>& waitHandles) {
-        const TextureDescriptor* textureDescriptor =
-            reinterpret_cast<const TextureDescriptor*>(descriptor->cTextureDescriptor);
+        const TextureDescriptor* textureDescriptor = FromAPI(descriptor->cTextureDescriptor);
 
         // Initial validation
         if (ConsumedError(ValidateTextureDescriptor(this, textureDescriptor))) {
diff --git a/src/dawn_native/vulkan/VulkanBackend.cpp b/src/dawn_native/vulkan/VulkanBackend.cpp
index 30aa336..a2ac328 100644
--- a/src/dawn_native/vulkan/VulkanBackend.cpp
+++ b/src/dawn_native/vulkan/VulkanBackend.cpp
@@ -29,13 +29,13 @@
 namespace dawn_native { namespace vulkan {
 
     VkInstance GetInstance(WGPUDevice device) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
         return backendDevice->GetVkInstance();
     }
 
     DAWN_NATIVE_EXPORT PFN_vkVoidFunction GetInstanceProcAddr(WGPUDevice device,
                                                               const char* pName) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
         return (*backendDevice->fn.GetInstanceProcAddr)(backendDevice->GetVkInstance(), pName);
     }
 
@@ -43,7 +43,7 @@
     // header as seen in this file uses the wrapped type.
     DAWN_NATIVE_EXPORT DawnSwapChainImplementation
     CreateNativeSwapChainImpl(WGPUDevice device, ::VkSurfaceKHR surfaceNative) {
-        Device* backendDevice = reinterpret_cast<Device*>(device);
+        Device* backendDevice = ToBackend(FromAPI(device));
         VkSurfaceKHR surface = VkSurfaceKHR::CreateFromHandle(surfaceNative);
 
         DawnSwapChainImplementation impl;
@@ -77,17 +77,17 @@
     }
 #endif  // DAWN_PLATFORM_LINUX
 
-    WGPUTexture WrapVulkanImage(WGPUDevice cDevice, const ExternalImageDescriptorVk* descriptor) {
+    WGPUTexture WrapVulkanImage(WGPUDevice device, const ExternalImageDescriptorVk* descriptor) {
 #if defined(DAWN_PLATFORM_LINUX)
         switch (descriptor->type) {
             case ExternalImageType::OpaqueFD:
             case ExternalImageType::DmaBuf: {
+                Device* backendDevice = ToBackend(FromAPI(device));
                 const ExternalImageDescriptorFD* fdDescriptor =
                     static_cast<const ExternalImageDescriptorFD*>(descriptor);
-                Device* device = reinterpret_cast<Device*>(cDevice);
-                TextureBase* texture = device->CreateTextureWrappingVulkanImage(
-                    fdDescriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
-                return reinterpret_cast<WGPUTexture>(texture);
+
+                return ToAPI(backendDevice->CreateTextureWrappingVulkanImage(
+                    fdDescriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs));
             }
             default:
                 return nullptr;
@@ -97,20 +97,21 @@
 #endif  // DAWN_PLATFORM_LINUX
     }
 
-    bool ExportVulkanImage(WGPUTexture cTexture,
+    bool ExportVulkanImage(WGPUTexture texture,
                            VkImageLayout desiredLayout,
                            ExternalImageExportInfoVk* info) {
-        if (cTexture == nullptr) {
+        if (texture == nullptr) {
             return false;
         }
 #if defined(DAWN_PLATFORM_LINUX)
         switch (info->type) {
             case ExternalImageType::OpaqueFD:
             case ExternalImageType::DmaBuf: {
-                Texture* texture = reinterpret_cast<Texture*>(cTexture);
-                Device* device = ToBackend(texture->GetDevice());
+                Texture* backendTexture = ToBackend(FromAPI(texture));
+                Device* device = ToBackend(backendTexture->GetDevice());
                 ExternalImageExportInfoFD* fdInfo = static_cast<ExternalImageExportInfoFD*>(info);
-                return device->SignalAndExportExternalTexture(texture, desiredLayout, fdInfo,
+
+                return device->SignalAndExportExternalTexture(backendTexture, desiredLayout, fdInfo,
                                                               &fdInfo->semaphoreHandles);
             }
             default:
diff --git a/src/include/dawn_native/VulkanBackend.h b/src/include/dawn_native/VulkanBackend.h
index ce354b2..ff5feca 100644
--- a/src/include/dawn_native/VulkanBackend.h
+++ b/src/include/dawn_native/VulkanBackend.h
@@ -118,14 +118,14 @@
         // semaphore extensions to import the image and wait on the provided synchronizaton
         // primitives before the texture can be used.
         // On failure, returns a nullptr.
-        DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice cDevice,
+        DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice device,
                                                        const ExternalImageDescriptorVk* descriptor);
 
         // Exports external memory from a Vulkan image. This must be called on wrapped textures
         // before they are destroyed. It writes the semaphore to wait on and the old/new image
         // layouts to |info|. Pass VK_IMAGE_LAYOUT_UNDEFINED as |desiredLayout| if you don't want to
         // perform a layout transition.
-        DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture cTexture,
+        DAWN_NATIVE_EXPORT bool ExportVulkanImage(WGPUTexture texture,
                                                   VkImageLayout desiredLayout,
                                                   ExternalImageExportInfoVk* info);
 
diff --git a/src/tests/unittests/FeatureTests.cpp b/src/tests/unittests/FeatureTests.cpp
index 144b0e1..729dca6 100644
--- a/src/tests/unittests/FeatureTests.cpp
+++ b/src/tests/unittests/FeatureTests.cpp
@@ -73,7 +73,7 @@
         dawn_native::DawnDeviceDescriptor deviceDescriptor;
         deviceDescriptor.requiredFeatures = {featureName};
         dawn_native::DeviceBase* deviceBase =
-            reinterpret_cast<dawn_native::DeviceBase*>(adapter.CreateDevice(&deviceDescriptor));
+            dawn_native::FromAPI(adapter.CreateDevice(&deviceDescriptor));
         std::vector<const char*> enabledFeatures = deviceBase->GetEnabledFeatures();
         ASSERT_EQ(1u, enabledFeatures.size());
         ASSERT_EQ(0, std::strcmp(featureName, enabledFeatures[0]));
diff --git a/src/tests/unittests/validation/CommandBufferValidationTests.cpp b/src/tests/unittests/validation/CommandBufferValidationTests.cpp
index 944ecb3..7ec37af 100644
--- a/src/tests/unittests/validation/CommandBufferValidationTests.cpp
+++ b/src/tests/unittests/validation/CommandBufferValidationTests.cpp
@@ -318,7 +318,7 @@
         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&dummyRenderPass);
         pass.EndPass();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
         ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
     }
 
@@ -327,13 +327,13 @@
         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&dummyRenderPass);
         pass.EndPass();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
     }
 
     // Destroyed encoder should allow encoding, and emit error on finish.
     {
         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&dummyRenderPass);
         pass.EndPass();
         ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
@@ -342,7 +342,7 @@
     // Destroyed encoder should allow encoding and shouldn't emit an error if never finished.
     {
         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&dummyRenderPass);
         pass.EndPass();
     }
@@ -353,21 +353,21 @@
         wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&dummyRenderPass);
         pass.EndPass();
         encoder.Finish();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
     }
 
     // Destroying an encoder twice should not emit any errors.
     {
         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
     }
 
     // Destroying an encoder twice and then calling finish should fail.
     {
         wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
-        reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
+        dawn_native::FromAPI(encoder.Get())->Destroy();
         ASSERT_DEVICE_ERROR(encoder.Finish(), HasSubstr("Destroyed encoder cannot be finished."));
     }
 }
diff --git a/src/tests/unittests/validation/ShaderModuleValidationTests.cpp b/src/tests/unittests/validation/ShaderModuleValidationTests.cpp
index 5ea0128..fecb6dd3 100644
--- a/src/tests/unittests/validation/ShaderModuleValidationTests.cpp
+++ b/src/tests/unittests/validation/ShaderModuleValidationTests.cpp
@@ -167,8 +167,7 @@
             return vec4<f32>(0.0, 1.0, 0.0, 1.0);
         })");
 
-    dawn_native::ShaderModuleBase* shaderModuleBase =
-        reinterpret_cast<dawn_native::ShaderModuleBase*>(shaderModule.Get());
+    dawn_native::ShaderModuleBase* shaderModuleBase = dawn_native::FromAPI(shaderModule.Get());
     dawn_native::OwnedCompilationMessages* messages = shaderModuleBase->GetCompilationMessages();
     messages->ClearMessages();
     messages->AddMessageForTesting("Info Message");
diff --git a/src/tests/white_box/D3D12ResidencyTests.cpp b/src/tests/white_box/D3D12ResidencyTests.cpp
index 124cd44..ec60e79 100644
--- a/src/tests/white_box/D3D12ResidencyTests.cpp
+++ b/src/tests/white_box/D3D12ResidencyTests.cpp
@@ -42,7 +42,7 @@
 
         // Restrict Dawn's budget to create an artificial budget.
         dawn_native::d3d12::Device* d3dDevice =
-            reinterpret_cast<dawn_native::d3d12::Device*>(device.Get());
+            dawn_native::d3d12::ToBackend(dawn_native::FromAPI((device.Get())));
         d3dDevice->GetResidencyManager()->RestrictBudgetForTesting(kRestrictedBudgetSize);
 
         // Initialize a source buffer on the GPU to serve as a source to quickly copy data to other
@@ -94,18 +94,20 @@
     bool CheckAllocationMethod(wgpu::Buffer buffer,
                                dawn_native::AllocationMethod allocationMethod) const {
         dawn_native::d3d12::Buffer* d3dBuffer =
-            reinterpret_cast<dawn_native::d3d12::Buffer*>(buffer.Get());
+            dawn_native::d3d12::ToBackend(dawn_native::FromAPI((buffer.Get())));
         return d3dBuffer->CheckAllocationMethodForTesting(allocationMethod);
     }
 
     bool CheckIfBufferIsResident(wgpu::Buffer buffer) const {
         dawn_native::d3d12::Buffer* d3dBuffer =
-            reinterpret_cast<dawn_native::d3d12::Buffer*>(buffer.Get());
+            dawn_native::d3d12::ToBackend(dawn_native::FromAPI((buffer.Get())));
         return d3dBuffer->CheckIsResidentForTesting();
     }
 
     bool IsUMA() const {
-        return reinterpret_cast<dawn_native::d3d12::Device*>(device.Get())->GetDeviceInfo().isUMA;
+        return dawn_native::d3d12::ToBackend(dawn_native::FromAPI(device.Get()))
+            ->GetDeviceInfo()
+            .isUMA;
     }
 };
 
@@ -367,7 +369,7 @@
     wgpu::Sampler sampler = device.CreateSampler();
 
     dawn_native::d3d12::Device* d3dDevice =
-        reinterpret_cast<dawn_native::d3d12::Device*>(device.Get());
+        dawn_native::d3d12::ToBackend(dawn_native::FromAPI(device.Get()));
 
     dawn_native::d3d12::ShaderVisibleDescriptorAllocator* allocator =
         d3dDevice->GetViewShaderVisibleDescriptorAllocator();
diff --git a/src/tests/white_box/EGLImageWrappingTests.cpp b/src/tests/white_box/EGLImageWrappingTests.cpp
index 82eb738..be94756 100644
--- a/src/tests/white_box/EGLImageWrappingTests.cpp
+++ b/src/tests/white_box/EGLImageWrappingTests.cpp
@@ -128,7 +128,7 @@
                                   void* data,
                                   size_t size) {
         dawn_native::opengl::Device* openglDevice =
-            reinterpret_cast<dawn_native::opengl::Device*>(device.Get());
+            dawn_native::opengl::ToBackend(dawn_native::FromAPI(device.Get()));
         const dawn_native::opengl::OpenGLFunctions& gl = openglDevice->gl;
         GLuint tex;
         gl.GenTextures(1, &tex);
@@ -300,7 +300,7 @@
                      void* data,
                      size_t dataSize) {
         dawn_native::opengl::Device* openglDevice =
-            reinterpret_cast<dawn_native::opengl::Device*>(device.Get());
+            dawn_native::opengl::ToBackend(dawn_native::FromAPI(device.Get()));
         const dawn_native::opengl::OpenGLFunctions& gl = openglDevice->gl;
 
         // Get a texture view for the eglImage
diff --git a/src/tests/white_box/InternalStorageBufferBindingTests.cpp b/src/tests/white_box/InternalStorageBufferBindingTests.cpp
index 44c56c9..fc9c18f 100644
--- a/src/tests/white_box/InternalStorageBufferBindingTests.cpp
+++ b/src/tests/white_box/InternalStorageBufferBindingTests.cpp
@@ -53,14 +53,13 @@
         bglDesc.entryCount = 1;
         bglDesc.entries = &bglEntry;
 
-        dawn_native::DeviceBase* nativeDevice =
-            reinterpret_cast<dawn_native::DeviceBase*>(device.Get());
+        dawn_native::DeviceBase* nativeDevice = dawn_native::FromAPI(device.Get());
 
         Ref<dawn_native::BindGroupLayoutBase> bglRef =
             nativeDevice->CreateBindGroupLayout(&bglDesc, true).AcquireSuccess();
 
         wgpu::BindGroupLayout bgl =
-            wgpu::BindGroupLayout::Acquire(reinterpret_cast<WGPUBindGroupLayout>(bglRef.Detach()));
+            wgpu::BindGroupLayout::Acquire(dawn_native::ToAPI(bglRef.Detach()));
 
         // Create pipeline layout
         wgpu::PipelineLayoutDescriptor plDesc;
diff --git a/src/tests/white_box/QueryInternalShaderTests.cpp b/src/tests/white_box/QueryInternalShaderTests.cpp
index e488954..58d6a37 100644
--- a/src/tests/white_box/QueryInternalShaderTests.cpp
+++ b/src/tests/white_box/QueryInternalShaderTests.cpp
@@ -26,10 +26,10 @@
                                               wgpu::Buffer availability,
                                               wgpu::Buffer params) {
         ASSERT_TRUE(dawn_native::EncodeConvertTimestampsToNanoseconds(
-            reinterpret_cast<dawn_native::CommandEncoder*>(encoder.Get()),
-            reinterpret_cast<dawn_native::BufferBase*>(timestamps.Get()),
-            reinterpret_cast<dawn_native::BufferBase*>(availability.Get()),
-            reinterpret_cast<dawn_native::BufferBase*>(params.Get())).IsSuccess());
+                        dawn_native::FromAPI(encoder.Get()), dawn_native::FromAPI(timestamps.Get()),
+                        dawn_native::FromAPI(availability.Get()),
+                        dawn_native::FromAPI(params.Get()))
+                        .IsSuccess());
     }
 
     class InternalShaderExpectation : public detail::Expectation {
diff --git a/src/tests/white_box/VulkanErrorInjectorTests.cpp b/src/tests/white_box/VulkanErrorInjectorTests.cpp
index 8169331..2f3e33b 100644
--- a/src/tests/white_box/VulkanErrorInjectorTests.cpp
+++ b/src/tests/white_box/VulkanErrorInjectorTests.cpp
@@ -29,7 +29,7 @@
             DawnTest::SetUp();
             DAWN_TEST_UNSUPPORTED_IF(UsesWire());
 
-            mDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(device.Get());
+            mDeviceVk = dawn_native::vulkan::ToBackend(dawn_native::FromAPI(device.Get()));
         }
 
       protected:
diff --git a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp
index 60887fd..3b4fc07 100644
--- a/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp
+++ b/src/tests/white_box/VulkanImageWrappingTestsDmaBuf.cpp
@@ -44,7 +44,7 @@
                 DAWN_TEST_UNSUPPORTED_IF(UsesWire());
 
                 gbmDevice = CreateGbmDevice();
-                deviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(device.Get());
+                deviceVk = dawn_native::vulkan::ToBackend(dawn_native::FromAPI(device.Get()));
 
                 defaultGbmBo = CreateGbmBo(1, 1, true /* linear */);
                 defaultStride = gbm_bo_get_stride_for_plane(defaultGbmBo, 0);
@@ -311,14 +311,13 @@
             }
 
             // Create another device based on the original
-            backendAdapter =
-                reinterpret_cast<dawn_native::vulkan::Adapter*>(deviceVk->GetAdapter());
+            backendAdapter = dawn_native::vulkan::ToBackend(deviceVk->GetAdapter());
             deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds;
             deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds;
 
-            secondDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(
-                backendAdapter->CreateDevice(&deviceDescriptor));
-            secondDevice = wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(secondDeviceVk));
+            secondDeviceVk =
+                dawn_native::vullkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor));
+            secondDevice = wgpu::Device::Acquire(dawn_native::ToAPI(secondDeviceVk));
         }
 
       protected:
@@ -691,10 +690,9 @@
         // device 1 = |device|
         // device 2 = |secondDevice|
         // Create device 3
-        dawn_native::vulkan::Device* thirdDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(
-            backendAdapter->CreateDevice(&deviceDescriptor));
-        wgpu::Device thirdDevice =
-            wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(thirdDeviceVk));
+        dawn_native::vulkan::Device* thirdDeviceVk =
+            dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor));
+        wgpu::Device thirdDevice = wgpu::Device::Acquire(dawn_native::ToAPI(thirdDeviceVk));
 
         // Make queue for device 2 and 3
         wgpu::Queue secondDeviceQueue = secondDevice.GetQueue();
diff --git a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp
index 6c252e0..196c1b0 100644
--- a/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp
+++ b/src/tests/white_box/VulkanImageWrappingTestsOpaqueFD.cpp
@@ -40,7 +40,7 @@
                 DawnTest::SetUp();
                 DAWN_TEST_UNSUPPORTED_IF(UsesWire());
 
-                deviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(device.Get());
+                deviceVk = dawn_native::vulkan::ToBackend(dawn_native::FromAPI(device.Get()));
             }
 
             // Creates a VkImage with external memory
@@ -382,14 +382,13 @@
             DAWN_TEST_UNSUPPORTED_IF(UsesWire());
 
             // Create another device based on the original
-            backendAdapter =
-                reinterpret_cast<dawn_native::vulkan::Adapter*>(deviceVk->GetAdapter());
+            backendAdapter = dawn_native::vulkan::ToBackend(deviceVk->GetAdapter());
             deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds;
             deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds;
 
-            secondDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(
-                backendAdapter->CreateDevice(&deviceDescriptor));
-            secondDevice = wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(secondDeviceVk));
+            secondDeviceVk =
+                dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor));
+            secondDevice = wgpu::Device::Acquire(dawn_native::ToAPI(secondDeviceVk));
 
             CreateBindExportImage(deviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &defaultImage,
                                   &defaultAllocation, &defaultAllocationSize,
@@ -797,10 +796,9 @@
         // device 1 = |device|
         // device 2 = |secondDevice|
         // Create device 3
-        dawn_native::vulkan::Device* thirdDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(
-            backendAdapter->CreateDevice(&deviceDescriptor));
-        wgpu::Device thirdDevice =
-            wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(thirdDeviceVk));
+        dawn_native::vulkan::Device* thirdDeviceVk =
+            dawn_native::vulkan::ToBackend(backendAdapter->CreateDevice(&deviceDescriptor));
+        wgpu::Device thirdDevice = wgpu::Device::Acquire(dawn_native::ToAPI(thirdDeviceVk));
 
         // Make queue for device 2 and 3
         wgpu::Queue secondDeviceQueue = secondDevice.GetQueue();