| // 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 "common/Assert.h" |
| #include "dawn_native/vulkan/AdapterVk.h" |
| #include "dawn_native/vulkan/BackendVk.h" |
| #include "dawn_native/vulkan/DeviceVk.h" |
| #include "dawn_native/vulkan/TextureVk.h" |
| #include "dawn_native/vulkan/VulkanError.h" |
| #include "dawn_native/vulkan/external_memory/MemoryService.h" |
| |
| namespace dawn::native { namespace vulkan::external_memory { |
| |
| Service::Service(Device* device) |
| : mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) { |
| } |
| |
| Service::~Service() = default; |
| |
| // static |
| bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) { |
| return deviceInfo.HasExt(DeviceExt::ExternalMemoryZirconHandle); |
| } |
| |
| bool Service::SupportsImportMemory(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_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.GetPhysicalDeviceImageFormatProperties2( |
| 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) != 0; |
| } |
| |
| bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, |
| VkFormat format, |
| VkImageUsageFlags usage, |
| bool* supportsDisjoint) { |
| *supportsDisjoint = false; |
| return mSupported; |
| } |
| |
| ResultOrError<MemoryImportParams> Service::GetMemoryImportParams( |
| const ExternalImageDescriptor* descriptor, |
| VkImage image) { |
| DAWN_INVALID_IF(descriptor->type != ExternalImageType::OpaqueFD, |
| "ExternalImageDescriptor is not an OpaqueFD descriptor."); |
| |
| const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = |
| static_cast<const ExternalImageDescriptorOpaqueFD*>(descriptor); |
| |
| MemoryImportParams params = {opaqueFDDescriptor->allocationSize, |
| opaqueFDDescriptor->memoryTypeIndex}; |
| return params; |
| } |
| |
| ResultOrError<VkDeviceMemory> Service::ImportMemory(ExternalMemoryHandle handle, |
| const MemoryImportParams& importParams, |
| VkImage image) { |
| DAWN_INVALID_IF(handle == ZX_HANDLE_INVALID, "Importing memory with an invalid handle."); |
| |
| VkMemoryRequirements requirements; |
| mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements); |
| DAWN_INVALID_IF( |
| requirements.size > importParams.allocationSize, |
| "Requested allocation size (%u) is smaller than the required image size (%u).", |
| importParams.allocationSize, requirements.size); |
| |
| VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo; |
| importMemoryHandleInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA; |
| importMemoryHandleInfo.pNext = nullptr; |
| importMemoryHandleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; |
| importMemoryHandleInfo.handle = handle; |
| |
| VkMemoryAllocateInfo allocateInfo; |
| allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; |
| allocateInfo.pNext = &importMemoryHandleInfo; |
| allocateInfo.allocationSize = importParams.allocationSize; |
| allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; |
| |
| VkDeviceMemory allocatedMemory = VK_NULL_HANDLE; |
| DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo, |
| nullptr, &*allocatedMemory), |
| "vkAllocateMemory")); |
| return allocatedMemory; |
| } |
| |
| ResultOrError<VkImage> Service::CreateImage(const ExternalImageDescriptor* descriptor, |
| const VkImageCreateInfo& baseCreateInfo) { |
| VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo; |
| externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; |
| externalMemoryImageCreateInfo.pNext = nullptr; |
| externalMemoryImageCreateInfo.handleTypes = |
| VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; |
| |
| VkImageCreateInfo createInfo = baseCreateInfo; |
| createInfo.pNext = &externalMemoryImageCreateInfo; |
| createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR; |
| createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; |
| createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; |
| |
| ASSERT(IsSampleCountSupported(mDevice, createInfo)); |
| |
| VkImage image; |
| DAWN_TRY(CheckVkSuccess( |
| mDevice->fn.CreateImage(mDevice->GetVkDevice(), &createInfo, nullptr, &*image), |
| "CreateImage")); |
| return image; |
| } |
| |
| }} // namespace dawn::native::vulkan::external_memory |