From fa00c69506bc93f9eb45be3290d08e36997891ea Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Tue, 10 Sep 2019 10:07:28 +0000 Subject: [PATCH] [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 Commit-Queue: David Turner --- BUILD.gn | 5 + src/dawn_native/vulkan/DeviceVk.cpp | 8 + src/dawn_native/vulkan/ExternalHandle.h | 9 +- src/dawn_native/vulkan/VulkanFunctions.cpp | 12 ++ src/dawn_native/vulkan/VulkanFunctions.h | 11 ++ src/dawn_native/vulkan/VulkanInfo.cpp | 8 + src/dawn_native/vulkan/VulkanInfo.h | 4 + .../MemoryServiceZirconHandle.cpp | 110 ++++++++++++++ .../SemaphoreServiceZirconHandle.cpp | 138 ++++++++++++++++++ 9 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp create mode 100644 src/dawn_native/vulkan/external_semaphore/SemaphoreServiceZirconHandle.cpp diff --git a/BUILD.gn b/BUILD.gn index 9d290a0533..7876bf389e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -446,6 +446,11 @@ source_set("libdawn_native_sources") { "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 821445c44f..1a66e2b390 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -360,6 +360,10 @@ namespace dawn_native { namespace vulkan { 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 @@ namespace dawn_native { namespace vulkan { 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 37a2e21d1e..45206b36f6 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 c6647a0c37..d3bbe67d8e 100644 --- a/src/dawn_native/vulkan/VulkanFunctions.cpp +++ b/src/dawn_native/vulkan/VulkanFunctions.cpp @@ -256,6 +256,18 @@ namespace dawn_native { namespace vulkan { 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 8638a7bdb6..28e4096cbe 100644 --- a/src/dawn_native/vulkan/VulkanFunctions.h +++ b/src/dawn_native/vulkan/VulkanFunctions.h @@ -253,6 +253,17 @@ namespace dawn_native { namespace vulkan { // 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 0e21bb0792..675e132ad3 100644 --- a/src/dawn_native/vulkan/VulkanInfo.cpp +++ b/src/dawn_native/vulkan/VulkanInfo.cpp @@ -59,10 +59,12 @@ namespace dawn_native { namespace vulkan { 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 @@ namespace dawn_native { namespace vulkan { 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 69b9f1f8f1..9c61525f6d 100644 --- a/src/dawn_native/vulkan/VulkanInfo.h +++ b/src/dawn_native/vulkan/VulkanInfo.h @@ -36,9 +36,11 @@ namespace dawn_native { namespace vulkan { 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 @@ namespace dawn_native { namespace vulkan { 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 0000000000..1788f70cad --- /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 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 0000000000..81fb9fd5ec --- /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 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 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 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