[fuchsia] Implement external semaphore and memory support.

This CL adds Fuchsia-specific implementations to the following
classes:

  dawn_native::vulkan::external_memory::Service
  dawn_native::vulkan::external_semaphore::Service

The implementation is based on two Fuchsia Vulkan extensions
that are provides by the vulkan_fuchsia_extras.h header (i.e.
are not upstreamed to Khronos yet, but used/provided by the
Fuchsia platform):

  VK_FUCHSIA_external_memory
  VK_FUCHSIA_external_semaphore

Their details are similar to VK_KHR_external_XXXX_fd, but
uses Zircon handles instead of file decriptors.

BUG=dawn:221
Change-Id: I48238bcf3193433970cbe200a84b86a67103a2f2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10963
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: David Turner <digit@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 9d290a0..7876bf3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -446,6 +446,11 @@
         "src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp",
         "src/dawn_native/vulkan/external_semaphore/SemaphoreServiceOpaqueFD.cpp",
       ]
+    } else if (is_fuchsia) {
+      sources += [
+        "src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp",
+        "src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp",
+      ]
     } else {
       sources += [
         "src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp",
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 821445c..1a66e2b 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -360,6 +360,10 @@
             extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryFD);
             usedKnobs.externalMemoryFD = true;
         }
+        if (mDeviceInfo.externalMemoryZirconHandle) {
+            extensionsToRequest.push_back(kExtensionNameFuchsiaExternalMemory);
+            usedKnobs.externalMemoryZirconHandle = true;
+        }
         if (mDeviceInfo.externalSemaphore) {
             extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphore);
             usedKnobs.externalSemaphore = true;
@@ -368,6 +372,10 @@
             extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreFD);
             usedKnobs.externalSemaphoreFD = true;
         }
+        if (mDeviceInfo.externalSemaphoreZirconHandle) {
+            extensionsToRequest.push_back(kExtensionNameFuchsiaExternalSemaphore);
+            usedKnobs.externalSemaphoreZirconHandle = true;
+        }
         if (mDeviceInfo.swapchain) {
             extensionsToRequest.push_back(kExtensionNameKhrSwapchain);
             usedKnobs.swapchain = true;
diff --git a/src/dawn_native/vulkan/ExternalHandle.h b/src/dawn_native/vulkan/ExternalHandle.h
index 37a2e21..45206b3 100644
--- a/src/dawn_native/vulkan/ExternalHandle.h
+++ b/src/dawn_native/vulkan/ExternalHandle.h
@@ -1,13 +1,20 @@
 #ifndef DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
 #define DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
 
+#include "common/vulkan_platform.h"
+
 namespace dawn_native { namespace vulkan {
 
-#ifdef DAWN_PLATFORM_LINUX
+#if DAWN_PLATFORM_LINUX
     // File descriptor
     using ExternalMemoryHandle = int;
     // File descriptor
     using ExternalSemaphoreHandle = int;
+#elif DAWN_PLATFORM_FUCHSIA
+    // Really a Zircon vmo handle.
+    using ExternalMemoryHandle = zx_handle_t;
+    // Really a Zircon event handle.
+    using ExternalSemaphoreHandle = zx_handle_t;
 #else
     // Generic types so that the Null service can compile, not used for real handles
     using ExternalMemoryHandle = void*;
diff --git a/src/dawn_native/vulkan/VulkanFunctions.cpp b/src/dawn_native/vulkan/VulkanFunctions.cpp
index c6647a0..d3bbe67 100644
--- a/src/dawn_native/vulkan/VulkanFunctions.cpp
+++ b/src/dawn_native/vulkan/VulkanFunctions.cpp
@@ -256,6 +256,18 @@
             GET_DEVICE_PROC(GetSemaphoreFdKHR);
         }
 
+#if VK_USE_PLATFORM_FUCHSIA
+        if (usedKnobs.externalMemoryZirconHandle) {
+            GET_DEVICE_PROC(GetMemoryZirconHandleFUCHSIA);
+            GET_DEVICE_PROC(GetMemoryZirconHandlePropertiesFUCHSIA);
+        }
+
+        if (usedKnobs.externalSemaphoreZirconHandle) {
+            GET_DEVICE_PROC(ImportSemaphoreZirconHandleFUCHSIA);
+            GET_DEVICE_PROC(GetSemaphoreZirconHandleFUCHSIA);
+        }
+#endif
+
         if (usedKnobs.swapchain) {
             GET_DEVICE_PROC(CreateSwapchainKHR);
             GET_DEVICE_PROC(DestroySwapchainKHR);
diff --git a/src/dawn_native/vulkan/VulkanFunctions.h b/src/dawn_native/vulkan/VulkanFunctions.h
index 8638a7b..28e4096 100644
--- a/src/dawn_native/vulkan/VulkanFunctions.h
+++ b/src/dawn_native/vulkan/VulkanFunctions.h
@@ -253,6 +253,17 @@
         // VK_KHR_external_semaphore_fd
         PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR = nullptr;
         PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR = nullptr;
+
+#if VK_USE_PLATFORM_FUCHSIA
+        // VK_FUCHSIA_external_memory
+        PFN_vkGetMemoryZirconHandleFUCHSIA GetMemoryZirconHandleFUCHSIA = nullptr;
+        PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA GetMemoryZirconHandlePropertiesFUCHSIA =
+            nullptr;
+
+        // VK_FUCHSIA_external_semaphore
+        PFN_vkImportSemaphoreZirconHandleFUCHSIA ImportSemaphoreZirconHandleFUCHSIA = nullptr;
+        PFN_vkGetSemaphoreZirconHandleFUCHSIA GetSemaphoreZirconHandleFUCHSIA = nullptr;
+#endif
     };
 
 }}  // namespace dawn_native::vulkan
diff --git a/src/dawn_native/vulkan/VulkanInfo.cpp b/src/dawn_native/vulkan/VulkanInfo.cpp
index 0e21bb0..675e132 100644
--- a/src/dawn_native/vulkan/VulkanInfo.cpp
+++ b/src/dawn_native/vulkan/VulkanInfo.cpp
@@ -59,10 +59,12 @@
     const char kExtensionNameKhrExternalMemoryCapabilities[] =
         "VK_KHR_external_memory_capabilities";
     const char kExtensionNameKhrExternalMemoryFD[] = "VK_KHR_external_memory_fd";
+    const char kExtensionNameFuchsiaExternalMemory[] = "VK_FUCHSIA_external_memory";
     const char kExtensionNameKhrExternalSemaphore[] = "VK_KHR_external_semaphore";
     const char kExtensionNameKhrExternalSemaphoreCapabilities[] =
         "VK_KHR_external_semaphore_capabilities";
     const char kExtensionNameKhrExternalSemaphoreFD[] = "VK_KHR_external_semaphore_fd";
+    const char kExtensionNameFuchsiaExternalSemaphore[] = "VK_FUCHSIA_external_semaphore";
     const char kExtensionNameKhrGetPhysicalDeviceProperties2[] =
         "VK_KHR_get_physical_device_properties2";
     const char kExtensionNameKhrSurface[] = "VK_KHR_surface";
@@ -284,12 +286,18 @@
                 if (IsExtensionName(extension, kExtensionNameKhrExternalMemoryFD)) {
                     info.externalMemoryFD = true;
                 }
+                if (IsExtensionName(extension, kExtensionNameFuchsiaExternalMemory)) {
+                    info.externalMemoryZirconHandle = true;
+                }
                 if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphore)) {
                     info.externalSemaphore = true;
                 }
                 if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphoreFD)) {
                     info.externalSemaphoreFD = true;
                 }
+                if (IsExtensionName(extension, kExtensionNameFuchsiaExternalSemaphore)) {
+                    info.externalSemaphoreZirconHandle = true;
+                }
                 if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) {
                     info.swapchain = true;
                 }
diff --git a/src/dawn_native/vulkan/VulkanInfo.h b/src/dawn_native/vulkan/VulkanInfo.h
index 69b9f1f..9c61525 100644
--- a/src/dawn_native/vulkan/VulkanInfo.h
+++ b/src/dawn_native/vulkan/VulkanInfo.h
@@ -36,9 +36,11 @@
     extern const char kExtensionNameKhrExternalMemory[];
     extern const char kExtensionNameKhrExternalMemoryCapabilities[];
     extern const char kExtensionNameKhrExternalMemoryFD[];
+    extern const char kExtensionNameFuchsiaExternalMemory[];
     extern const char kExtensionNameKhrExternalSemaphore[];
     extern const char kExtensionNameKhrExternalSemaphoreCapabilities[];
     extern const char kExtensionNameKhrExternalSemaphoreFD[];
+    extern const char kExtensionNameFuchsiaExternalSemaphore[];
     extern const char kExtensionNameKhrGetPhysicalDeviceProperties2[];
     extern const char kExtensionNameKhrSurface[];
     extern const char kExtensionNameKhrSwapchain[];
@@ -85,8 +87,10 @@
         bool debugMarker = false;
         bool externalMemory = false;
         bool externalMemoryFD = false;
+        bool externalMemoryZirconHandle = false;
         bool externalSemaphore = false;
         bool externalSemaphoreFD = false;
+        bool externalSemaphoreZirconHandle = false;
         bool swapchain = false;
     };
 
diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
new file mode 100644
index 0000000..1788f70
--- /dev/null
+++ b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp
@@ -0,0 +1,110 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/vulkan/AdapterVk.h"
+#include "dawn_native/vulkan/BackendVk.h"
+#include "dawn_native/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/VulkanError.h"
+#include "dawn_native/vulkan/external_memory/MemoryService.h"
+
+namespace dawn_native { namespace vulkan { namespace external_memory {
+
+    Service::Service(Device* device) : mDevice(device) {
+        const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo();
+        const VulkanGlobalInfo& globalInfo =
+            ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
+
+        mSupported = globalInfo.getPhysicalDeviceProperties2 &&
+                     globalInfo.externalMemoryCapabilities && deviceInfo.externalMemory &&
+                     deviceInfo.externalMemoryFD;
+    }
+
+    Service::~Service() = default;
+
+    bool Service::Supported(VkFormat format,
+                            VkImageType type,
+                            VkImageTiling tiling,
+                            VkImageUsageFlags usage,
+                            VkImageCreateFlags flags) {
+        // Early out before we try using extension functions
+        if (!mSupported) {
+            return false;
+        }
+
+        VkPhysicalDeviceExternalImageFormatInfo externalFormatInfo;
+        externalFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR;
+        externalFormatInfo.pNext = nullptr;
+        externalFormatInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
+
+        VkPhysicalDeviceImageFormatInfo2 formatInfo;
+        formatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR;
+        formatInfo.pNext = &externalFormatInfo;
+        formatInfo.format = format;
+        formatInfo.type = type;
+        formatInfo.tiling = tiling;
+        formatInfo.usage = usage;
+        formatInfo.flags = flags;
+
+        VkExternalImageFormatProperties externalFormatProperties;
+        externalFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR;
+        externalFormatProperties.pNext = nullptr;
+
+        VkImageFormatProperties2 formatProperties;
+        formatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
+        formatProperties.pNext = &externalFormatProperties;
+
+        VkResult result = mDevice->fn.GetPhysicalDeviceImageFormatProperties2KHR(
+            ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &formatInfo, &formatProperties);
+
+        // If handle not supported, result == VK_ERROR_FORMAT_NOT_SUPPORTED
+        if (result != VK_SUCCESS) {
+            return false;
+        }
+
+        // TODO(http://crbug.com/dawn/206): Investigate dedicated only images
+        VkFlags memoryFlags =
+            externalFormatProperties.externalMemoryProperties.externalMemoryFeatures;
+        return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) &&
+               !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR);
+    }
+
+    ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle,
+                                                        VkDeviceSize allocationSize,
+                                                        uint32_t memoryTypeIndex) {
+        if (handle == ZX_HANDLE_INVALID) {
+            return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
+        }
+
+        VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo;
+        importMemoryHandleInfo.sType =
+            VK_STRUCTURE_TYPE_TEMP_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA;
+        importMemoryHandleInfo.pNext = nullptr;
+        importMemoryHandleInfo.handleType =
+            VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
+        importMemoryHandleInfo.handle = handle;
+
+        VkMemoryAllocateInfo allocateInfo;
+        allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+        allocateInfo.pNext = &importMemoryHandleInfo;
+        allocateInfo.allocationSize = allocationSize;
+        allocateInfo.memoryTypeIndex = memoryTypeIndex;
+
+        VkDeviceMemory allocatedMemory = VK_NULL_HANDLE;
+        DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo,
+                                                           nullptr, &allocatedMemory),
+                                "vkAllocateMemory"));
+        return allocatedMemory;
+    }
+
+}}}  // namespace dawn_native::vulkan::external_memory
diff --git a/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp
new file mode 100644
index 0000000..81fb9fd
--- /dev/null
+++ b/src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp
@@ -0,0 +1,138 @@
+// Copyright 2019 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "dawn_native/vulkan/AdapterVk.h"
+#include "dawn_native/vulkan/BackendVk.h"
+#include "dawn_native/vulkan/DeviceVk.h"
+#include "dawn_native/vulkan/VulkanError.h"
+#include "dawn_native/vulkan/external_semaphore/SemaphoreService.h"
+
+namespace dawn_native { namespace vulkan { namespace external_semaphore {
+
+    Service::Service(Device* device) : mDevice(device) {
+        const VulkanDeviceInfo& deviceInfo = mDevice->GetDeviceInfo();
+        const VulkanGlobalInfo& globalInfo =
+            ToBackend(mDevice->GetAdapter())->GetBackend()->GetGlobalInfo();
+
+        mSupported = globalInfo.getPhysicalDeviceProperties2 &&
+                     globalInfo.externalSemaphoreCapabilities && deviceInfo.externalSemaphore &&
+                     deviceInfo.externalSemaphoreFD;
+
+        // Early out before we try using extension functions
+        if (!mSupported) {
+            return;
+        }
+
+        VkPhysicalDeviceExternalSemaphoreInfoKHR semaphoreInfo;
+        semaphoreInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO_KHR;
+        semaphoreInfo.pNext = nullptr;
+        semaphoreInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
+
+        VkExternalSemaphorePropertiesKHR semaphoreProperties;
+        semaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES_KHR;
+        semaphoreProperties.pNext = nullptr;
+
+        mDevice->fn.GetPhysicalDeviceExternalSemaphorePropertiesKHR(
+            ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(), &semaphoreInfo,
+            &semaphoreProperties);
+
+        VkFlags requiredFlags = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
+                                VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
+        mSupported =
+            mSupported &&
+            ((semaphoreProperties.externalSemaphoreFeatures & requiredFlags) == requiredFlags);
+    }
+
+    Service::~Service() = default;
+
+    bool Service::Supported() {
+        return mSupported;
+    }
+
+    ResultOrError<VkSemaphore> Service::ImportSemaphore(ExternalSemaphoreHandle handle) {
+        if (handle == ZX_HANDLE_INVALID) {
+            return DAWN_VALIDATION_ERROR("Trying to import semaphore with invalid handle");
+        }
+
+        VkSemaphore semaphore = VK_NULL_HANDLE;
+        VkSemaphoreCreateInfo info;
+        info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+        info.pNext = nullptr;
+        info.flags = 0;
+
+        DAWN_TRY(CheckVkSuccess(
+            mDevice->fn.CreateSemaphore(mDevice->GetVkDevice(), &info, nullptr, &semaphore),
+            "vkCreateSemaphore"));
+
+        VkImportSemaphoreZirconHandleInfoFUCHSIA importSempahoreHandleInfo;
+        importSempahoreHandleInfo.sType =
+            VK_STRUCTURE_TYPE_TEMP_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA;
+        importSempahoreHandleInfo.pNext = nullptr;
+        importSempahoreHandleInfo.semaphore = semaphore;
+        importSempahoreHandleInfo.flags = 0;
+        importSempahoreHandleInfo.handleType =
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
+        importSempahoreHandleInfo.handle = handle;
+
+        MaybeError status = CheckVkSuccess(mDevice->fn.ImportSemaphoreZirconHandleFUCHSIA(
+                                               mDevice->GetVkDevice(), &importSempahoreHandleInfo),
+                                           "vkImportSemaphoreZirconHandleFUCHSIA");
+
+        if (status.IsError()) {
+            mDevice->fn.DestroySemaphore(mDevice->GetVkDevice(), semaphore, nullptr);
+            DAWN_TRY(std::move(status));
+        }
+
+        return semaphore;
+    }
+
+    ResultOrError<VkSemaphore> Service::CreateExportableSemaphore() {
+        VkExportSemaphoreCreateInfoKHR exportSemaphoreInfo;
+        exportSemaphoreInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR;
+        exportSemaphoreInfo.pNext = nullptr;
+        exportSemaphoreInfo.handleTypes =
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
+
+        VkSemaphoreCreateInfo semaphoreCreateInfo;
+        semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+        semaphoreCreateInfo.pNext = &exportSemaphoreInfo;
+        semaphoreCreateInfo.flags = 0;
+
+        VkSemaphore signalSemaphore;
+        DAWN_TRY(
+            CheckVkSuccess(mDevice->fn.CreateSemaphore(mDevice->GetVkDevice(), &semaphoreCreateInfo,
+                                                       nullptr, &signalSemaphore),
+                           "vkCreateSemaphore"));
+        return signalSemaphore;
+    }
+
+    ResultOrError<ExternalSemaphoreHandle> Service::ExportSemaphore(VkSemaphore semaphore) {
+        VkSemaphoreGetZirconHandleInfoFUCHSIA semaphoreGetHandleInfo;
+        semaphoreGetHandleInfo.sType =
+            VK_STRUCTURE_TYPE_TEMP_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA;
+        semaphoreGetHandleInfo.pNext = nullptr;
+        semaphoreGetHandleInfo.semaphore = semaphore;
+        semaphoreGetHandleInfo.handleType =
+            VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
+
+        zx_handle_t handle = ZX_HANDLE_INVALID;
+        DAWN_TRY(CheckVkSuccess(mDevice->fn.GetSemaphoreZirconHandleFUCHSIA(
+                                    mDevice->GetVkDevice(), &semaphoreGetHandleInfo, &handle),
+                                "VkSemaphoreGetZirconHandleInfoFUCHSIA"));
+
+        ASSERT(handle != ZX_HANDLE_INVALID);
+        return handle;
+    }
+
+}}}  // namespace dawn_native::vulkan::external_semaphore