[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