[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>
This commit is contained in:
David 'Digit' Turner 2019-09-10 10:07:28 +00:00 committed by Commit Bot service account
parent 86e74e0dc1
commit fa00c69506
9 changed files with 304 additions and 1 deletions

View File

@ -446,6 +446,11 @@ source_set("libdawn_native_sources") {
"src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp", "src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp",
"src/dawn_native/vulkan/external_semaphore/SemaphoreServiceOpaqueFD.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 { } else {
sources += [ sources += [
"src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp", "src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp",

View File

@ -360,6 +360,10 @@ namespace dawn_native { namespace vulkan {
extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryFD); extensionsToRequest.push_back(kExtensionNameKhrExternalMemoryFD);
usedKnobs.externalMemoryFD = true; usedKnobs.externalMemoryFD = true;
} }
if (mDeviceInfo.externalMemoryZirconHandle) {
extensionsToRequest.push_back(kExtensionNameFuchsiaExternalMemory);
usedKnobs.externalMemoryZirconHandle = true;
}
if (mDeviceInfo.externalSemaphore) { if (mDeviceInfo.externalSemaphore) {
extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphore); extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphore);
usedKnobs.externalSemaphore = true; usedKnobs.externalSemaphore = true;
@ -368,6 +372,10 @@ namespace dawn_native { namespace vulkan {
extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreFD); extensionsToRequest.push_back(kExtensionNameKhrExternalSemaphoreFD);
usedKnobs.externalSemaphoreFD = true; usedKnobs.externalSemaphoreFD = true;
} }
if (mDeviceInfo.externalSemaphoreZirconHandle) {
extensionsToRequest.push_back(kExtensionNameFuchsiaExternalSemaphore);
usedKnobs.externalSemaphoreZirconHandle = true;
}
if (mDeviceInfo.swapchain) { if (mDeviceInfo.swapchain) {
extensionsToRequest.push_back(kExtensionNameKhrSwapchain); extensionsToRequest.push_back(kExtensionNameKhrSwapchain);
usedKnobs.swapchain = true; usedKnobs.swapchain = true;

View File

@ -1,13 +1,20 @@
#ifndef DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_ #ifndef DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
#define DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_ #define DAWNNATIVE_VULKAN_EXTERNALHANDLE_H_
#include "common/vulkan_platform.h"
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
#ifdef DAWN_PLATFORM_LINUX #if DAWN_PLATFORM_LINUX
// File descriptor // File descriptor
using ExternalMemoryHandle = int; using ExternalMemoryHandle = int;
// File descriptor // File descriptor
using ExternalSemaphoreHandle = int; 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 #else
// Generic types so that the Null service can compile, not used for real handles // Generic types so that the Null service can compile, not used for real handles
using ExternalMemoryHandle = void*; using ExternalMemoryHandle = void*;

View File

@ -256,6 +256,18 @@ namespace dawn_native { namespace vulkan {
GET_DEVICE_PROC(GetSemaphoreFdKHR); 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) { if (usedKnobs.swapchain) {
GET_DEVICE_PROC(CreateSwapchainKHR); GET_DEVICE_PROC(CreateSwapchainKHR);
GET_DEVICE_PROC(DestroySwapchainKHR); GET_DEVICE_PROC(DestroySwapchainKHR);

View File

@ -253,6 +253,17 @@ namespace dawn_native { namespace vulkan {
// VK_KHR_external_semaphore_fd // VK_KHR_external_semaphore_fd
PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR = nullptr; PFN_vkImportSemaphoreFdKHR ImportSemaphoreFdKHR = nullptr;
PFN_vkGetSemaphoreFdKHR GetSemaphoreFdKHR = 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 }} // namespace dawn_native::vulkan

View File

@ -59,10 +59,12 @@ namespace dawn_native { namespace vulkan {
const char kExtensionNameKhrExternalMemoryCapabilities[] = const char kExtensionNameKhrExternalMemoryCapabilities[] =
"VK_KHR_external_memory_capabilities"; "VK_KHR_external_memory_capabilities";
const char kExtensionNameKhrExternalMemoryFD[] = "VK_KHR_external_memory_fd"; const char kExtensionNameKhrExternalMemoryFD[] = "VK_KHR_external_memory_fd";
const char kExtensionNameFuchsiaExternalMemory[] = "VK_FUCHSIA_external_memory";
const char kExtensionNameKhrExternalSemaphore[] = "VK_KHR_external_semaphore"; const char kExtensionNameKhrExternalSemaphore[] = "VK_KHR_external_semaphore";
const char kExtensionNameKhrExternalSemaphoreCapabilities[] = const char kExtensionNameKhrExternalSemaphoreCapabilities[] =
"VK_KHR_external_semaphore_capabilities"; "VK_KHR_external_semaphore_capabilities";
const char kExtensionNameKhrExternalSemaphoreFD[] = "VK_KHR_external_semaphore_fd"; const char kExtensionNameKhrExternalSemaphoreFD[] = "VK_KHR_external_semaphore_fd";
const char kExtensionNameFuchsiaExternalSemaphore[] = "VK_FUCHSIA_external_semaphore";
const char kExtensionNameKhrGetPhysicalDeviceProperties2[] = const char kExtensionNameKhrGetPhysicalDeviceProperties2[] =
"VK_KHR_get_physical_device_properties2"; "VK_KHR_get_physical_device_properties2";
const char kExtensionNameKhrSurface[] = "VK_KHR_surface"; const char kExtensionNameKhrSurface[] = "VK_KHR_surface";
@ -284,12 +286,18 @@ namespace dawn_native { namespace vulkan {
if (IsExtensionName(extension, kExtensionNameKhrExternalMemoryFD)) { if (IsExtensionName(extension, kExtensionNameKhrExternalMemoryFD)) {
info.externalMemoryFD = true; info.externalMemoryFD = true;
} }
if (IsExtensionName(extension, kExtensionNameFuchsiaExternalMemory)) {
info.externalMemoryZirconHandle = true;
}
if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphore)) { if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphore)) {
info.externalSemaphore = true; info.externalSemaphore = true;
} }
if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphoreFD)) { if (IsExtensionName(extension, kExtensionNameKhrExternalSemaphoreFD)) {
info.externalSemaphoreFD = true; info.externalSemaphoreFD = true;
} }
if (IsExtensionName(extension, kExtensionNameFuchsiaExternalSemaphore)) {
info.externalSemaphoreZirconHandle = true;
}
if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) { if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) {
info.swapchain = true; info.swapchain = true;
} }

View File

@ -36,9 +36,11 @@ namespace dawn_native { namespace vulkan {
extern const char kExtensionNameKhrExternalMemory[]; extern const char kExtensionNameKhrExternalMemory[];
extern const char kExtensionNameKhrExternalMemoryCapabilities[]; extern const char kExtensionNameKhrExternalMemoryCapabilities[];
extern const char kExtensionNameKhrExternalMemoryFD[]; extern const char kExtensionNameKhrExternalMemoryFD[];
extern const char kExtensionNameFuchsiaExternalMemory[];
extern const char kExtensionNameKhrExternalSemaphore[]; extern const char kExtensionNameKhrExternalSemaphore[];
extern const char kExtensionNameKhrExternalSemaphoreCapabilities[]; extern const char kExtensionNameKhrExternalSemaphoreCapabilities[];
extern const char kExtensionNameKhrExternalSemaphoreFD[]; extern const char kExtensionNameKhrExternalSemaphoreFD[];
extern const char kExtensionNameFuchsiaExternalSemaphore[];
extern const char kExtensionNameKhrGetPhysicalDeviceProperties2[]; extern const char kExtensionNameKhrGetPhysicalDeviceProperties2[];
extern const char kExtensionNameKhrSurface[]; extern const char kExtensionNameKhrSurface[];
extern const char kExtensionNameKhrSwapchain[]; extern const char kExtensionNameKhrSwapchain[];
@ -85,8 +87,10 @@ namespace dawn_native { namespace vulkan {
bool debugMarker = false; bool debugMarker = false;
bool externalMemory = false; bool externalMemory = false;
bool externalMemoryFD = false; bool externalMemoryFD = false;
bool externalMemoryZirconHandle = false;
bool externalSemaphore = false; bool externalSemaphore = false;
bool externalSemaphoreFD = false; bool externalSemaphoreFD = false;
bool externalSemaphoreZirconHandle = false;
bool swapchain = false; bool swapchain = false;
}; };

View File

@ -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

View File

@ -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