// 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 { namespace external_memory { Service::Service(Device* device) : mDevice(device) { mSupported = device->GetDeviceInfo().HasExt(DeviceExt::ExternalMemoryZirconHandle); } Service::~Service() = default; 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_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.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) && !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR); } bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, VkFormat format, VkImageUsageFlags usage) { return mSupported; } ResultOrError Service::GetMemoryImportParams( const ExternalImageDescriptor* descriptor, VkImage image) { if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) { return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor"); } const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = static_cast(descriptor); MemoryImportParams params = {opaqueFDDescriptor->allocationSize, opaqueFDDescriptor->memoryTypeIndex}; return params; } ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, const MemoryImportParams& importParams, VkImage image) { if (handle == ZX_HANDLE_INVALID) { return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle"); } VkMemoryRequirements requirements; mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements); if (requirements.size > importParams.allocationSize) { return DAWN_VALIDATION_ERROR("Requested allocation size is too small for image"); } 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 = 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 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_TEMP_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