diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index bc8abb8f0b..0a8b9174d4 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -696,8 +696,11 @@ source_set("sources") { "vulkan/VulkanFunctions.h", "vulkan/VulkanInfo.cpp", "vulkan/VulkanInfo.h", + "vulkan/external_memory/MemoryImportParams.h", "vulkan/external_memory/MemoryService.cpp", "vulkan/external_memory/MemoryService.h", + "vulkan/external_memory/MemoryServiceImplementation.cpp", + "vulkan/external_memory/MemoryServiceImplementation.h", "vulkan/external_semaphore/SemaphoreService.cpp", "vulkan/external_semaphore/SemaphoreService.h", "vulkan/external_semaphore/SemaphoreServiceImplementation.cpp", diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index 51368114d1..fe39ea4454 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -569,8 +569,11 @@ if (DAWN_ENABLE_VULKAN) "vulkan/VulkanFunctions.h" "vulkan/VulkanInfo.cpp" "vulkan/VulkanInfo.h" + "vulkan/external_memory/MemoryImportParams.h" "vulkan/external_memory/MemoryService.cpp" "vulkan/external_memory/MemoryService.h" + "vulkan/external_memory/MemoryServiceImplementation.cpp" + "vulkan/external_memory/MemoryServiceImplementation.h" "vulkan/external_semaphore/SemaphoreService.cpp" "vulkan/external_semaphore/SemaphoreService.h" "vulkan/external_semaphore/SemaphoreServiceImplementation.cpp" diff --git a/src/dawn/native/vulkan/external_memory/MemoryImportParams.h b/src/dawn/native/vulkan/external_memory/MemoryImportParams.h new file mode 100644 index 0000000000..8f9c666b86 --- /dev/null +++ b/src/dawn/native/vulkan/external_memory/MemoryImportParams.h @@ -0,0 +1,30 @@ +// Copyright 2023 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. + +#ifndef SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_MEMORYIMPORTPARAMS_H_ +#define SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_MEMORYIMPORTPARAMS_H_ + +#include "dawn/native/VulkanBackend.h" + +namespace dawn::native::vulkan::external_memory { + +struct MemoryImportParams { + VkDeviceSize allocationSize; + uint32_t memoryTypeIndex; + bool dedicatedAllocation = false; +}; + +} // namespace dawn::native::vulkan::external_memory + +#endif // SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_MEMORYIMPORTPARAMS_H_ diff --git a/src/dawn/native/vulkan/external_memory/MemoryService.cpp b/src/dawn/native/vulkan/external_memory/MemoryService.cpp index 02361e21c3..1f74778098 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryService.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryService.cpp @@ -13,46 +13,46 @@ // limitations under the License. #include "dawn/native/vulkan/external_memory/MemoryService.h" - -#include "dawn/native/vulkan/DeviceVk.h" +#include "dawn/native/vulkan/external_memory/MemoryServiceImplementation.h" namespace dawn::native::vulkan::external_memory { -bool Service::RequiresDedicatedAllocation(const ExternalImageDescriptorVk* descriptor, - VkImage image) { - switch (descriptor->dedicatedAllocation) { - case NeedsDedicatedAllocation::Yes: - return true; +Service::~Service() = default; - case NeedsDedicatedAllocation::No: - return false; +bool Service::SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) { + return mImpl->SupportsImportMemory(format, type, tiling, usage, flags); +} - case NeedsDedicatedAllocation::Detect: - if (!mDevice->GetDeviceInfo().HasExt(DeviceExt::DedicatedAllocation)) { - return false; - } +bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) { + return mImpl->SupportsCreateImage(descriptor, format, usage, supportsDisjoint); +} - VkMemoryDedicatedRequirements dedicatedRequirements; - dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; - dedicatedRequirements.pNext = nullptr; +ResultOrError Service::GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) { + return mImpl->GetMemoryImportParams(descriptor, image); +} - VkMemoryRequirements2 baseRequirements; - baseRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; - baseRequirements.pNext = &dedicatedRequirements; +uint32_t Service::GetQueueFamilyIndex() { + return mImpl->GetQueueFamilyIndex(); +} - VkImageMemoryRequirementsInfo2 imageInfo; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; - imageInfo.pNext = nullptr; - imageInfo.image = image; +ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) { + return mImpl->ImportMemory(handle, importParams, image); +} - mDevice->fn.GetImageMemoryRequirements2(mDevice->GetVkDevice(), &imageInfo, - &baseRequirements); - - // The Vulkan spec requires that prefersDA is set if requiresDA is, so we can just check - // for prefersDA. - return dedicatedRequirements.prefersDedicatedAllocation; - } - DAWN_UNREACHABLE(); +ResultOrError Service::CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) { + return mImpl->CreateImage(descriptor, baseCreateInfo); } } // namespace dawn::native::vulkan::external_memory diff --git a/src/dawn/native/vulkan/external_memory/MemoryService.h b/src/dawn/native/vulkan/external_memory/MemoryService.h index 0800bf21c1..adafd40dae 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryService.h +++ b/src/dawn/native/vulkan/external_memory/MemoryService.h @@ -15,10 +15,11 @@ #ifndef SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_MEMORYSERVICE_H_ #define SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_MEMORYSERVICE_H_ -#include "dawn/common/vulkan_platform.h" +#include + #include "dawn/native/Error.h" -#include "dawn/native/VulkanBackend.h" #include "dawn/native/vulkan/ExternalHandle.h" +#include "dawn/native/vulkan/external_memory/MemoryImportParams.h" namespace dawn::native::vulkan { class Device; @@ -27,11 +28,7 @@ struct VulkanDeviceInfo; namespace dawn::native::vulkan::external_memory { -struct MemoryImportParams { - VkDeviceSize allocationSize; - uint32_t memoryTypeIndex; - bool dedicatedAllocation = false; -}; +class ServiceImplementation; class Service { public: @@ -71,12 +68,7 @@ class Service { const VkImageCreateInfo& baseCreateInfo); private: - bool RequiresDedicatedAllocation(const ExternalImageDescriptorVk* descriptor, VkImage image); - - Device* mDevice = nullptr; - - // True if early checks pass that determine if the service is supported - bool mSupported = false; + std::unique_ptr mImpl; }; } // namespace dawn::native::vulkan::external_memory diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.cpp new file mode 100644 index 0000000000..ec907f5d6c --- /dev/null +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.cpp @@ -0,0 +1,60 @@ +// Copyright 2023 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/external_memory/MemoryServiceImplementation.h" +#include "dawn/native/vulkan/DeviceVk.h" + +namespace dawn::native::vulkan::external_memory { + +ServiceImplementation::ServiceImplementation(Device* device) : mDevice(device) {} +ServiceImplementation::~ServiceImplementation() = default; + +bool ServiceImplementation::RequiresDedicatedAllocation(const ExternalImageDescriptorVk* descriptor, + VkImage image) const { + switch (descriptor->dedicatedAllocation) { + case NeedsDedicatedAllocation::Yes: + return true; + + case NeedsDedicatedAllocation::No: + return false; + + case NeedsDedicatedAllocation::Detect: + if (!mDevice->GetDeviceInfo().HasExt(DeviceExt::DedicatedAllocation)) { + return false; + } + + VkMemoryDedicatedRequirements dedicatedRequirements; + dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; + dedicatedRequirements.pNext = nullptr; + + VkMemoryRequirements2 baseRequirements; + baseRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + baseRequirements.pNext = &dedicatedRequirements; + + VkImageMemoryRequirementsInfo2 imageInfo; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2; + imageInfo.pNext = nullptr; + imageInfo.image = image; + + mDevice->fn.GetImageMemoryRequirements2(mDevice->GetVkDevice(), &imageInfo, + &baseRequirements); + + // The Vulkan spec requires that prefersDA is set if requiresDA is, so we can just check + // for prefersDA. + return dedicatedRequirements.prefersDedicatedAllocation; + } + DAWN_UNREACHABLE(); +} + +} // namespace dawn::native::vulkan::external_memory diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.h b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.h new file mode 100644 index 0000000000..e129c2fa38 --- /dev/null +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementation.h @@ -0,0 +1,78 @@ +// Copyright 2023 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. + +#ifndef SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_SERVICEIMPLEMENTATION_H_ +#define SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_SERVICEIMPLEMENTATION_H_ + +#include "dawn/common/vulkan_platform.h" +#include "dawn/native/Error.h" +#include "dawn/native/VulkanBackend.h" +#include "dawn/native/vulkan/ExternalHandle.h" +#include "dawn/native/vulkan/external_memory/MemoryImportParams.h" + +namespace dawn::native::vulkan { +class Device; +struct VulkanDeviceInfo; +} // namespace dawn::native::vulkan + +namespace dawn::native::vulkan::external_memory { + +class ServiceImplementation { + public: + explicit ServiceImplementation(Device* device); + virtual ~ServiceImplementation(); + + // True if the device reports it supports importing external memory. + virtual bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) = 0; + + // True if the device reports it supports creating VkImages from external memory. + virtual bool SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) = 0; + + // Returns the parameters required for importing memory + virtual ResultOrError GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) = 0; + + // Returns the index of the queue memory from this services should be exported with. + virtual uint32_t GetQueueFamilyIndex() = 0; + + // Given an external handle pointing to memory, import it into a VkDeviceMemory + virtual ResultOrError ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) = 0; + + // Create a VkImage for the given handle type + virtual ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) = 0; + + // True if the device reports it supports this feature + virtual bool Supported() const = 0; + + protected: + bool RequiresDedicatedAllocation(const ExternalImageDescriptorVk* descriptor, + VkImage image) const; + + Device* mDevice = nullptr; +}; + +} // namespace dawn::native::vulkan::external_memory + +#endif // SRC_DAWN_NATIVE_VULKAN_EXTERNAL_MEMORY_SERVICEIMPLEMENTATION_H_ diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationAHardwareBuffer.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationAHardwareBuffer.cpp index 203136540f..2ecd4ee61a 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationAHardwareBuffer.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationAHardwareBuffer.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "dawn/common/Assert.h" #include "dawn/native/vulkan/AdapterVk.h" #include "dawn/native/vulkan/BackendVk.h" @@ -20,178 +22,194 @@ #include "dawn/native/vulkan/UtilsVulkan.h" #include "dawn/native/vulkan/VulkanError.h" #include "dawn/native/vulkan/external_memory/MemoryService.h" +#include "dawn/native/vulkan/external_memory/MemoryServiceImplementation.h" namespace dawn::native::vulkan::external_memory { -Service::Service(Device* device) - : mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} +class ServiceImplementationAHardwareBuffer : public ServiceImplementation { + public: + explicit ServiceImplementationAHardwareBuffer(Device* device) + : ServiceImplementation(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} + ~ServiceImplementationAHardwareBuffer() override = default; -Service::~Service() = default; + static bool CheckSupport(const VulkanDeviceInfo& deviceInfo) { + return deviceInfo.HasExt(DeviceExt::ExternalMemoryAndroidHardwareBuffer); + } + + bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) override { + // Early out before we try using extension functions + if (!mSupported) { + return false; + } + + VkPhysicalDeviceImageFormatInfo2 formatInfo = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR, + .pNext = nullptr, + .format = format, + .type = type, + .tiling = tiling, + .usage = usage, + .flags = flags, + }; + + PNextChainBuilder formatInfoChain(&formatInfo); + + VkPhysicalDeviceExternalImageFormatInfo externalFormatInfo = { + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, + }; + formatInfoChain.Add(&externalFormatInfo, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR); + + VkImageFormatProperties2 formatProperties = { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, + .pNext = nullptr, + }; + + PNextChainBuilder formatPropertiesChain(&formatProperties); + + VkExternalImageFormatProperties externalFormatProperties; + formatPropertiesChain.Add(&externalFormatProperties, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR); + + VkResult result = VkResult::WrapUnsafe(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 SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) override { + *supportsDisjoint = false; + return mSupported; + } + + ResultOrError GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) override { + DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::AHardwareBuffer, + "ExternalImageDescriptor is not an AHardwareBuffer descriptor."); + + const ExternalImageDescriptorAHardwareBuffer* aHardwareBufferDescriptor = + static_cast(descriptor); + + VkAndroidHardwareBufferPropertiesANDROID bufferProperties = { + .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, + .pNext = nullptr, + }; + + PNextChainBuilder bufferPropertiesChain(&bufferProperties); + + VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties; + bufferPropertiesChain.Add( + &bufferFormatProperties, + VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID); + + DAWN_TRY(CheckVkSuccess( + mDevice->fn.GetAndroidHardwareBufferPropertiesANDROID( + mDevice->GetVkDevice(), aHardwareBufferDescriptor->handle, &bufferProperties), + "vkGetAndroidHardwareBufferPropertiesANDROID")); + + MemoryImportParams params; + params.allocationSize = bufferProperties.allocationSize; + params.memoryTypeIndex = bufferProperties.memoryTypeBits; + params.dedicatedAllocation = RequiresDedicatedAllocation(aHardwareBufferDescriptor, image); + return params; + } + + uint32_t GetQueueFamilyIndex() override { return VK_QUEUE_FAMILY_FOREIGN_EXT; } + + ResultOrError ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) override { + DAWN_INVALID_IF(handle == nullptr, "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 image requires (%u).", + importParams.allocationSize, requirements.size); + + VkMemoryAllocateInfo allocateInfo = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = nullptr, + .allocationSize = importParams.allocationSize, + .memoryTypeIndex = importParams.memoryTypeIndex, + }; + + PNextChainBuilder allocateInfoChain(&allocateInfo); + + VkImportAndroidHardwareBufferInfoANDROID importMemoryAHBInfo = { + .buffer = handle, + }; + allocateInfoChain.Add(&importMemoryAHBInfo, + VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); + + VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo; + if (importParams.dedicatedAllocation) { + dedicatedAllocateInfo.image = image; + dedicatedAllocateInfo.buffer = VkBuffer{}; + allocateInfoChain.Add(&dedicatedAllocateInfo, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + } + + VkDeviceMemory allocatedMemory = VK_NULL_HANDLE; + DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo, + nullptr, &*allocatedMemory), + "vkAllocateMemory")); + return allocatedMemory; + } + + ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) override { + VkImageCreateInfo createInfo = baseCreateInfo; + createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR; + createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + PNextChainBuilder createInfoChain(&createInfo); + + VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = { + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, + }; + createInfoChain.Add(&externalMemoryImageCreateInfo, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); + + ASSERT(IsSampleCountSupported(mDevice, createInfo)); + + VkImage image; + DAWN_TRY(CheckVkSuccess( + mDevice->fn.CreateImage(mDevice->GetVkDevice(), &createInfo, nullptr, &*image), + "CreateImage")); + return image; + } + + bool Supported() const override { return mSupported; } + + private: + bool mSupported = false; +}; + +Service::Service(Device* device) { + mImpl = std::make_unique(device); +} // static bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) { return deviceInfo.HasExt(DeviceExt::ExternalMemoryAndroidHardwareBuffer); } -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; - } - - VkPhysicalDeviceImageFormatInfo2 formatInfo = { - .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR, - .pNext = nullptr, - .format = format, - .type = type, - .tiling = tiling, - .usage = usage, - .flags = flags, - }; - - PNextChainBuilder formatInfoChain(&formatInfo); - - VkPhysicalDeviceExternalImageFormatInfo externalFormatInfo = { - .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, - }; - formatInfoChain.Add(&externalFormatInfo, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO_KHR); - - VkImageFormatProperties2 formatProperties = { - .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR, - .pNext = nullptr, - }; - - PNextChainBuilder formatPropertiesChain(&formatProperties); - - VkExternalImageFormatProperties externalFormatProperties; - formatPropertiesChain.Add(&externalFormatProperties, - VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR); - - VkResult result = VkResult::WrapUnsafe(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 Service::GetMemoryImportParams( - const ExternalImageDescriptor* descriptor, - VkImage image) { - DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::AHardwareBuffer, - "ExternalImageDescriptor is not an AHardwareBuffer descriptor."); - - const ExternalImageDescriptorAHardwareBuffer* aHardwareBufferDescriptor = - static_cast(descriptor); - - VkAndroidHardwareBufferPropertiesANDROID bufferProperties = { - .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, - .pNext = nullptr, - }; - - PNextChainBuilder bufferPropertiesChain(&bufferProperties); - - VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties; - bufferPropertiesChain.Add(&bufferFormatProperties, - VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID); - - DAWN_TRY(CheckVkSuccess( - mDevice->fn.GetAndroidHardwareBufferPropertiesANDROID( - mDevice->GetVkDevice(), aHardwareBufferDescriptor->handle, &bufferProperties), - "vkGetAndroidHardwareBufferPropertiesANDROID")); - - MemoryImportParams params; - params.allocationSize = bufferProperties.allocationSize; - params.memoryTypeIndex = bufferProperties.memoryTypeBits; - params.dedicatedAllocation = RequiresDedicatedAllocation(aHardwareBufferDescriptor, image); - return params; -} - -uint32_t Service::GetQueueFamilyIndex() { - return VK_QUEUE_FAMILY_FOREIGN_EXT; -} - -ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, - const MemoryImportParams& importParams, - VkImage image) { - DAWN_INVALID_IF(handle == nullptr, "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 image requires (%u).", - importParams.allocationSize, requirements.size); - - VkMemoryAllocateInfo allocateInfo = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = nullptr, - .allocationSize = importParams.allocationSize, - .memoryTypeIndex = importParams.memoryTypeIndex, - }; - - PNextChainBuilder allocateInfoChain(&allocateInfo); - - VkImportAndroidHardwareBufferInfoANDROID importMemoryAHBInfo = { - .buffer = handle, - }; - allocateInfoChain.Add(&importMemoryAHBInfo, - VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID); - - VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo; - if (importParams.dedicatedAllocation) { - dedicatedAllocateInfo.image = image; - dedicatedAllocateInfo.buffer = VkBuffer{}; - allocateInfoChain.Add(&dedicatedAllocateInfo, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); - } - - 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) { - VkImageCreateInfo createInfo = baseCreateInfo; - createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR; - createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - PNextChainBuilder createInfoChain(&createInfo); - - VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = { - .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID, - }; - createInfoChain.Add(&externalMemoryImageCreateInfo, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); - - 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 diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationDmaBuf.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationDmaBuf.cpp index fc6a1e3ea3..f46106067c 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationDmaBuf.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationDmaBuf.cpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include #include #include "dawn/common/Assert.h" @@ -22,6 +23,7 @@ #include "dawn/native/vulkan/UtilsVulkan.h" #include "dawn/native/vulkan/VulkanError.h" #include "dawn/native/vulkan/external_memory/MemoryService.h" +#include "dawn/native/vulkan/external_memory/MemoryServiceImplementation.h" namespace dawn::native::vulkan::external_memory { @@ -115,10 +117,250 @@ bool SupportsDisjoint(const VulkanFunctions& fn, } // namespace -Service::Service(Device* device) - : mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} +class ServiceImplementationDmaBuf : public ServiceImplementation { + public: + explicit ServiceImplementationDmaBuf(Device* device) + : ServiceImplementation(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} + ~ServiceImplementationDmaBuf() override = default; -Service::~Service() = default; + static bool CheckSupport(const VulkanDeviceInfo& deviceInfo) { + return deviceInfo.HasExt(DeviceExt::ExternalMemoryFD) && + deviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier); + } + + bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) override { + return mSupported && (!IsMultiPlanarVkFormat(format) || + (format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM && + mDevice->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList))); + } + + bool SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) override { + *supportsDisjoint = false; + // Early out before we try using extension functions + if (!mSupported) { + return false; + } + if (descriptor->GetType() != ExternalImageType::DmaBuf) { + return false; + } + const ExternalImageDescriptorDmaBuf* dmaBufDescriptor = + static_cast(descriptor); + + // Verify plane count for the modifier. + VkPhysicalDevice physicalDevice = ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(); + uint32_t planeCount = 0; + if (mDevice->ConsumedError(GetModifierPlaneCount(mDevice->fn, physicalDevice, format, + dmaBufDescriptor->drmModifier), + &planeCount)) { + return false; + } + if (planeCount == 0) { + return false; + } + // Only support the NV12 multi-planar format for now. + if (planeCount > 1 && format != VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) { + return false; + } + *supportsDisjoint = + SupportsDisjoint(mDevice->fn, physicalDevice, format, dmaBufDescriptor->drmModifier); + + // Verify that the format modifier of the external memory and the requested Vulkan format + // are actually supported together in a dma-buf import. + VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {}; + imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; + imageFormatInfo.format = format; + imageFormatInfo.type = VK_IMAGE_TYPE_2D; + imageFormatInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + imageFormatInfo.usage = usage; + imageFormatInfo.flags = 0; + PNextChainBuilder imageFormatInfoChain(&imageFormatInfo); + + VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo = {}; + externalImageFormatInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + imageFormatInfoChain.Add(&externalImageFormatInfo, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO); + + VkPhysicalDeviceImageDrmFormatModifierInfoEXT drmModifierInfo = {}; + drmModifierInfo.drmFormatModifier = dmaBufDescriptor->drmModifier; + drmModifierInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + imageFormatInfoChain.Add( + &drmModifierInfo, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); + + // For mutable vkimage of multi-planar format, we also need to make sure the each + // plane's view format can be supported. + std::array viewFormats; + VkImageFormatListCreateInfo imageFormatListInfo = {}; + + if (planeCount > 1) { + ASSERT(format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); + viewFormats = {VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM}; + imageFormatListInfo.viewFormatCount = 2; + imageFormatListInfo.pViewFormats = viewFormats.data(); + imageFormatInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + imageFormatInfoChain.Add(&imageFormatListInfo, + VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO); + } + + VkImageFormatProperties2 imageFormatProps = {}; + imageFormatProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; + PNextChainBuilder imageFormatPropsChain(&imageFormatProps); + + VkExternalImageFormatProperties externalImageFormatProps = {}; + imageFormatPropsChain.Add(&externalImageFormatProps, + VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES); + + VkResult result = VkResult::WrapUnsafe(mDevice->fn.GetPhysicalDeviceImageFormatProperties2( + physicalDevice, &imageFormatInfo, &imageFormatProps)); + if (result != VK_SUCCESS) { + return false; + } + VkExternalMemoryFeatureFlags featureFlags = + externalImageFormatProps.externalMemoryProperties.externalMemoryFeatures; + return featureFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + } + + ResultOrError GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) override { + DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::DmaBuf, + "ExternalImageDescriptor is not a ExternalImageDescriptorDmaBuf."); + + const ExternalImageDescriptorDmaBuf* dmaBufDescriptor = + static_cast(descriptor); + VkDevice device = mDevice->GetVkDevice(); + + // Get the valid memory types for the VkImage. + VkMemoryRequirements memoryRequirements; + mDevice->fn.GetImageMemoryRequirements(device, image, &memoryRequirements); + + VkMemoryFdPropertiesKHR fdProperties; + fdProperties.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR; + fdProperties.pNext = nullptr; + + // Get the valid memory types that the external memory can be imported as. + mDevice->fn.GetMemoryFdPropertiesKHR(device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + dmaBufDescriptor->memoryFD, &fdProperties); + // Choose the best memory type that satisfies both the image's constraint and the + // import's constraint. + memoryRequirements.memoryTypeBits &= fdProperties.memoryTypeBits; + int memoryTypeIndex = mDevice->GetResourceMemoryAllocator()->FindBestTypeIndex( + memoryRequirements, MemoryKind::Opaque); + DAWN_INVALID_IF(memoryTypeIndex == -1, + "Unable to find an appropriate memory type for import."); + + MemoryImportParams params; + params.allocationSize = memoryRequirements.size; + params.memoryTypeIndex = static_cast(memoryTypeIndex); + params.dedicatedAllocation = RequiresDedicatedAllocation(dmaBufDescriptor, image); + return params; + } + + uint32_t GetQueueFamilyIndex() override { return VK_QUEUE_FAMILY_EXTERNAL_KHR; } + + ResultOrError ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) override { + DAWN_INVALID_IF(handle < 0, "Importing memory with an invalid handle."); + + VkMemoryAllocateInfo memoryAllocateInfo = {}; + memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memoryAllocateInfo.allocationSize = importParams.allocationSize; + memoryAllocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; + PNextChainBuilder memoryAllocateInfoChain(&memoryAllocateInfo); + + VkImportMemoryFdInfoKHR importMemoryFdInfo; + importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, + importMemoryFdInfo.fd = handle; + memoryAllocateInfoChain.Add(&importMemoryFdInfo, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR); + + VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo; + if (importParams.dedicatedAllocation) { + memoryDedicatedAllocateInfo.image = image; + memoryDedicatedAllocateInfo.buffer = VkBuffer{}; + memoryAllocateInfoChain.Add(&memoryDedicatedAllocateInfo, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + } + + VkDeviceMemory allocatedMemory = VK_NULL_HANDLE; + DAWN_TRY( + CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &memoryAllocateInfo, + nullptr, &*allocatedMemory), + "vkAllocateMemory")); + return allocatedMemory; + } + + ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) override { + DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::DmaBuf, + "ExternalImageDescriptor is not a dma-buf descriptor."); + + const ExternalImageDescriptorDmaBuf* dmaBufDescriptor = + static_cast(descriptor); + VkPhysicalDevice physicalDevice = ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(); + VkDevice device = mDevice->GetVkDevice(); + + uint32_t planeCount; + DAWN_TRY_ASSIGN(planeCount, + GetModifierPlaneCount(mDevice->fn, physicalDevice, baseCreateInfo.format, + dmaBufDescriptor->drmModifier)); + + VkImageCreateInfo createInfo = baseCreateInfo; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + createInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; + + PNextChainBuilder createInfoChain(&createInfo); + + VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {}; + externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + createInfoChain.Add(&externalMemoryImageCreateInfo, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); + + VkSubresourceLayout planeLayouts[ExternalImageDescriptorDmaBuf::kMaxPlanes]; + for (uint32_t plane = 0u; plane < planeCount; ++plane) { + planeLayouts[plane].offset = dmaBufDescriptor->planeLayouts[plane].offset; + planeLayouts[plane].size = 0; // VK_EXT_image_drm_format_modifier mandates size = 0. + planeLayouts[plane].rowPitch = dmaBufDescriptor->planeLayouts[plane].stride; + planeLayouts[plane].arrayPitch = 0; // Not an array texture + planeLayouts[plane].depthPitch = 0; // Not a depth texture + } + + VkImageDrmFormatModifierExplicitCreateInfoEXT explicitCreateInfo = {}; + explicitCreateInfo.drmFormatModifier = dmaBufDescriptor->drmModifier; + explicitCreateInfo.drmFormatModifierPlaneCount = planeCount; + explicitCreateInfo.pPlaneLayouts = &planeLayouts[0]; + + if (planeCount > 1) { + // For multi-planar formats, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT specifies that a + // VkImageView can be plane's format which might differ from the image's format. + createInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; + } + createInfoChain.Add(&explicitCreateInfo, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); + + // Create a new VkImage with tiling equal to the DRM format modifier. + VkImage image; + DAWN_TRY(CheckVkSuccess(mDevice->fn.CreateImage(device, &createInfo, nullptr, &*image), + "CreateImage")); + return image; + } + + bool Supported() const override { return mSupported; } + + private: + bool mSupported = false; +}; + +Service::Service(Device* device) { + mImpl = std::make_unique(device); +} // static bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) { @@ -126,227 +368,4 @@ bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) { deviceInfo.HasExt(DeviceExt::ImageDrmFormatModifier); } -bool Service::SupportsImportMemory(VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags) { - return mSupported && (!IsMultiPlanarVkFormat(format) || - (format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM && - mDevice->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList))); -} - -bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, - VkFormat format, - VkImageUsageFlags usage, - bool* supportsDisjoint) { - *supportsDisjoint = false; - // Early out before we try using extension functions - if (!mSupported) { - return false; - } - if (descriptor->GetType() != ExternalImageType::DmaBuf) { - return false; - } - const ExternalImageDescriptorDmaBuf* dmaBufDescriptor = - static_cast(descriptor); - - // Verify plane count for the modifier. - VkPhysicalDevice physicalDevice = ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(); - uint32_t planeCount = 0; - if (mDevice->ConsumedError(GetModifierPlaneCount(mDevice->fn, physicalDevice, format, - dmaBufDescriptor->drmModifier), - &planeCount)) { - return false; - } - if (planeCount == 0) { - return false; - } - // Only support the NV12 multi-planar format for now. - if (planeCount > 1 && format != VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) { - return false; - } - *supportsDisjoint = - SupportsDisjoint(mDevice->fn, physicalDevice, format, dmaBufDescriptor->drmModifier); - - // Verify that the format modifier of the external memory and the requested Vulkan format - // are actually supported together in a dma-buf import. - VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {}; - imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2; - imageFormatInfo.format = format; - imageFormatInfo.type = VK_IMAGE_TYPE_2D; - imageFormatInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - imageFormatInfo.usage = usage; - imageFormatInfo.flags = 0; - PNextChainBuilder imageFormatInfoChain(&imageFormatInfo); - - VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo = {}; - externalImageFormatInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; - imageFormatInfoChain.Add(&externalImageFormatInfo, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO); - - VkPhysicalDeviceImageDrmFormatModifierInfoEXT drmModifierInfo = {}; - drmModifierInfo.drmFormatModifier = dmaBufDescriptor->drmModifier; - drmModifierInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - imageFormatInfoChain.Add(&drmModifierInfo, - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT); - - // For mutable vkimage of multi-planar format, we also need to make sure the each - // plane's view format can be supported. - std::array viewFormats; - VkImageFormatListCreateInfo imageFormatListInfo = {}; - - if (planeCount > 1) { - ASSERT(format == VK_FORMAT_G8_B8R8_2PLANE_420_UNORM); - viewFormats = {VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM}; - imageFormatListInfo.viewFormatCount = 2; - imageFormatListInfo.pViewFormats = viewFormats.data(); - imageFormatInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; - imageFormatInfoChain.Add(&imageFormatListInfo, - VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO); - } - - VkImageFormatProperties2 imageFormatProps = {}; - imageFormatProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2; - PNextChainBuilder imageFormatPropsChain(&imageFormatProps); - - VkExternalImageFormatProperties externalImageFormatProps = {}; - imageFormatPropsChain.Add(&externalImageFormatProps, - VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES); - - VkResult result = VkResult::WrapUnsafe(mDevice->fn.GetPhysicalDeviceImageFormatProperties2( - physicalDevice, &imageFormatInfo, &imageFormatProps)); - if (result != VK_SUCCESS) { - return false; - } - VkExternalMemoryFeatureFlags featureFlags = - externalImageFormatProps.externalMemoryProperties.externalMemoryFeatures; - return featureFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; -} - -ResultOrError Service::GetMemoryImportParams( - const ExternalImageDescriptor* descriptor, - VkImage image) { - DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::DmaBuf, - "ExternalImageDescriptor is not a ExternalImageDescriptorDmaBuf."); - - const ExternalImageDescriptorDmaBuf* dmaBufDescriptor = - static_cast(descriptor); - VkDevice device = mDevice->GetVkDevice(); - - // Get the valid memory types for the VkImage. - VkMemoryRequirements memoryRequirements; - mDevice->fn.GetImageMemoryRequirements(device, image, &memoryRequirements); - - VkMemoryFdPropertiesKHR fdProperties; - fdProperties.sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR; - fdProperties.pNext = nullptr; - - // Get the valid memory types that the external memory can be imported as. - mDevice->fn.GetMemoryFdPropertiesKHR(device, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, - dmaBufDescriptor->memoryFD, &fdProperties); - // Choose the best memory type that satisfies both the image's constraint and the - // import's constraint. - memoryRequirements.memoryTypeBits &= fdProperties.memoryTypeBits; - int memoryTypeIndex = mDevice->GetResourceMemoryAllocator()->FindBestTypeIndex( - memoryRequirements, MemoryKind::Opaque); - DAWN_INVALID_IF(memoryTypeIndex == -1, "Unable to find an appropriate memory type for import."); - - MemoryImportParams params; - params.allocationSize = memoryRequirements.size; - params.memoryTypeIndex = static_cast(memoryTypeIndex); - params.dedicatedAllocation = RequiresDedicatedAllocation(dmaBufDescriptor, image); - return params; -} - -uint32_t Service::GetQueueFamilyIndex() { - return VK_QUEUE_FAMILY_EXTERNAL_KHR; -} - -ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, - const MemoryImportParams& importParams, - VkImage image) { - DAWN_INVALID_IF(handle < 0, "Importing memory with an invalid handle."); - - VkMemoryAllocateInfo memoryAllocateInfo = {}; - memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - memoryAllocateInfo.allocationSize = importParams.allocationSize; - memoryAllocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; - PNextChainBuilder memoryAllocateInfoChain(&memoryAllocateInfo); - - VkImportMemoryFdInfoKHR importMemoryFdInfo; - importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, - importMemoryFdInfo.fd = handle; - memoryAllocateInfoChain.Add(&importMemoryFdInfo, VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR); - - VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo; - if (importParams.dedicatedAllocation) { - memoryDedicatedAllocateInfo.image = image; - memoryDedicatedAllocateInfo.buffer = VkBuffer{}; - memoryAllocateInfoChain.Add(&memoryDedicatedAllocateInfo, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); - } - - VkDeviceMemory allocatedMemory = VK_NULL_HANDLE; - DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &memoryAllocateInfo, - nullptr, &*allocatedMemory), - "vkAllocateMemory")); - return allocatedMemory; -} - -ResultOrError Service::CreateImage(const ExternalImageDescriptor* descriptor, - const VkImageCreateInfo& baseCreateInfo) { - DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::DmaBuf, - "ExternalImageDescriptor is not a dma-buf descriptor."); - - const ExternalImageDescriptorDmaBuf* dmaBufDescriptor = - static_cast(descriptor); - VkPhysicalDevice physicalDevice = ToBackend(mDevice->GetAdapter())->GetPhysicalDevice(); - VkDevice device = mDevice->GetVkDevice(); - - uint32_t planeCount; - DAWN_TRY_ASSIGN(planeCount, - GetModifierPlaneCount(mDevice->fn, physicalDevice, baseCreateInfo.format, - dmaBufDescriptor->drmModifier)); - - VkImageCreateInfo createInfo = baseCreateInfo; - createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - createInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - - PNextChainBuilder createInfoChain(&createInfo); - - VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {}; - externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; - createInfoChain.Add(&externalMemoryImageCreateInfo, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); - - VkSubresourceLayout planeLayouts[ExternalImageDescriptorDmaBuf::kMaxPlanes]; - for (uint32_t plane = 0u; plane < planeCount; ++plane) { - planeLayouts[plane].offset = dmaBufDescriptor->planeLayouts[plane].offset; - planeLayouts[plane].size = 0; // VK_EXT_image_drm_format_modifier mandates size = 0. - planeLayouts[plane].rowPitch = dmaBufDescriptor->planeLayouts[plane].stride; - planeLayouts[plane].arrayPitch = 0; // Not an array texture - planeLayouts[plane].depthPitch = 0; // Not a depth texture - } - - VkImageDrmFormatModifierExplicitCreateInfoEXT explicitCreateInfo = {}; - explicitCreateInfo.drmFormatModifier = dmaBufDescriptor->drmModifier; - explicitCreateInfo.drmFormatModifierPlaneCount = planeCount; - explicitCreateInfo.pPlaneLayouts = &planeLayouts[0]; - - if (planeCount > 1) { - // For multi-planar formats, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT specifies that a - // VkImageView can be plane's format which might differ from the image's format. - createInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; - } - createInfoChain.Add(&explicitCreateInfo, - VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT); - - // Create a new VkImage with tiling equal to the DRM format modifier. - VkImage image; - DAWN_TRY(CheckVkSuccess(mDevice->fn.CreateImage(device, &createInfo, nullptr, &*image), - "CreateImage")); - return image; -} - } // namespace dawn::native::vulkan::external_memory diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationOpaqueFD.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationOpaqueFD.cpp index 1ad48f1c34..9eb13ebf8c 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationOpaqueFD.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationOpaqueFD.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "dawn/common/Assert.h" #include "dawn/native/vulkan/AdapterVk.h" #include "dawn/native/vulkan/BackendVk.h" @@ -20,152 +22,167 @@ #include "dawn/native/vulkan/UtilsVulkan.h" #include "dawn/native/vulkan/VulkanError.h" #include "dawn/native/vulkan/external_memory/MemoryService.h" +#include "dawn/native/vulkan/external_memory/MemoryServiceImplementation.h" namespace dawn::native::vulkan::external_memory { -Service::Service(Device* device) - : mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} +class ServiceImplementationOpaqueFD : public ServiceImplementation { + public: + explicit ServiceImplementationOpaqueFD(Device* device) + : ServiceImplementation(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} + ~ServiceImplementationOpaqueFD() override = default; -Service::~Service() = default; + static bool CheckSupport(const VulkanDeviceInfo& deviceInfo) { + return deviceInfo.HasExt(DeviceExt::ExternalMemoryFD); + } + + bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) override { + // 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_OPAQUE_FD_BIT_KHR; + + 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 = VkResult::WrapUnsafe(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; + } + + VkFlags memoryFlags = + externalFormatProperties.externalMemoryProperties.externalMemoryFeatures; + return (memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR) != 0; + } + + bool SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) override { + *supportsDisjoint = false; + return mSupported; + } + + ResultOrError GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) override { + DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::OpaqueFD, + "ExternalImageDescriptor is not an OpaqueFD descriptor."); + + const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = + static_cast(descriptor); + + MemoryImportParams params; + params.allocationSize = opaqueFDDescriptor->allocationSize; + params.memoryTypeIndex = opaqueFDDescriptor->memoryTypeIndex; + params.dedicatedAllocation = RequiresDedicatedAllocation(opaqueFDDescriptor, image); + return params; + } + + uint32_t GetQueueFamilyIndex() override { return VK_QUEUE_FAMILY_EXTERNAL_KHR; } + + ResultOrError ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) override { + DAWN_INVALID_IF(handle < 0, "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 image requires (%u).", + importParams.allocationSize, requirements.size); + + VkMemoryAllocateInfo allocateInfo; + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.pNext = nullptr; + allocateInfo.allocationSize = importParams.allocationSize; + allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; + PNextChainBuilder allocateInfoChain(&allocateInfo); + + VkImportMemoryFdInfoKHR importMemoryFdInfo; + importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + importMemoryFdInfo.fd = handle; + allocateInfoChain.Add(&importMemoryFdInfo, VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR); + + VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo; + if (importParams.dedicatedAllocation) { + dedicatedAllocateInfo.image = image; + dedicatedAllocateInfo.buffer = VkBuffer{}; + allocateInfoChain.Add(&dedicatedAllocateInfo, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + } + + VkDeviceMemory allocatedMemory = VK_NULL_HANDLE; + DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo, + nullptr, &*allocatedMemory), + "vkAllocateMemory")); + return allocatedMemory; + } + + ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) override { + VkImageCreateInfo createInfo = baseCreateInfo; + createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR; + createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo; + externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + externalMemoryImageCreateInfo.pNext = nullptr; + externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; + + PNextChainBuilder createInfoChain(&createInfo); + createInfoChain.Add(&externalMemoryImageCreateInfo, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); + + ASSERT(IsSampleCountSupported(mDevice, createInfo)); + + VkImage image; + DAWN_TRY(CheckVkSuccess( + mDevice->fn.CreateImage(mDevice->GetVkDevice(), &createInfo, nullptr, &*image), + "CreateImage")); + return image; + } + + bool Supported() const override { return mSupported; } + + private: + bool mSupported = false; +}; + +Service::Service(Device* device) { + mImpl = std::make_unique(device); +} // static bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) { return deviceInfo.HasExt(DeviceExt::ExternalMemoryFD); } -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_OPAQUE_FD_BIT_KHR; - - 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 = VkResult::WrapUnsafe(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; - } - - 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 Service::GetMemoryImportParams( - const ExternalImageDescriptor* descriptor, - VkImage image) { - DAWN_INVALID_IF(descriptor->GetType() != ExternalImageType::OpaqueFD, - "ExternalImageDescriptor is not an OpaqueFD descriptor."); - - const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = - static_cast(descriptor); - - MemoryImportParams params; - params.allocationSize = opaqueFDDescriptor->allocationSize; - params.memoryTypeIndex = opaqueFDDescriptor->memoryTypeIndex; - params.dedicatedAllocation = RequiresDedicatedAllocation(opaqueFDDescriptor, image); - return params; -} - -uint32_t Service::GetQueueFamilyIndex() { - return VK_QUEUE_FAMILY_EXTERNAL_KHR; -} - -ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, - const MemoryImportParams& importParams, - VkImage image) { - DAWN_INVALID_IF(handle < 0, "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 image requires (%u).", - importParams.allocationSize, requirements.size); - - VkMemoryAllocateInfo allocateInfo; - allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocateInfo.pNext = nullptr; - allocateInfo.allocationSize = importParams.allocationSize; - allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; - PNextChainBuilder allocateInfoChain(&allocateInfo); - - VkImportMemoryFdInfoKHR importMemoryFdInfo; - importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; - importMemoryFdInfo.fd = handle; - allocateInfoChain.Add(&importMemoryFdInfo, VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR); - - VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo; - if (importParams.dedicatedAllocation) { - dedicatedAllocateInfo.image = image; - dedicatedAllocateInfo.buffer = VkBuffer{}; - allocateInfoChain.Add(&dedicatedAllocateInfo, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); - } - - 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) { - VkImageCreateInfo createInfo = baseCreateInfo; - createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR; - createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo; - externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; - externalMemoryImageCreateInfo.pNext = nullptr; - externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; - - PNextChainBuilder createInfoChain(&createInfo); - createInfoChain.Add(&externalMemoryImageCreateInfo, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); - - 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 diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationZirconHandle.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationZirconHandle.cpp index 2f0dd3b56b..383b96af03 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationZirconHandle.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceImplementationZirconHandle.cpp @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "dawn/common/Assert.h" #include "dawn/native/vulkan/AdapterVk.h" #include "dawn/native/vulkan/BackendVk.h" @@ -20,155 +22,171 @@ #include "dawn/native/vulkan/UtilsVulkan.h" #include "dawn/native/vulkan/VulkanError.h" #include "dawn/native/vulkan/external_memory/MemoryService.h" +#include "dawn/native/vulkan/external_memory/MemoryServiceImplementation.h" namespace dawn::native::vulkan::external_memory { -Service::Service(Device* device) - : mDevice(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} +class ServiceImplementationZicronHandle : public ServiceImplementation { + public: + explicit ServiceImplementationZicronHandle(Device* device) + : ServiceImplementation(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} + ~ServiceImplementationZicronHandle() override = default; -Service::~Service() = default; + static bool CheckSupport(const VulkanDeviceInfo& deviceInfo) { + return deviceInfo.HasExt(DeviceExt::ExternalMemoryZirconHandle); + } + + bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) override { + // 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 SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) override { + *supportsDisjoint = false; + return mSupported; + } + + ResultOrError GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) override { + DAWN_INVALID_IF(descriptor->type != ExternalImageType::OpaqueFD, + "ExternalImageDescriptor is not an OpaqueFD descriptor."); + + const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = + static_cast(descriptor); + + MemoryImportParams params; + params.allocationSize = opaqueFDDescriptor->allocationSize; + params.memoryTypeIndex = opaqueFDDescriptor->memoryTypeIndex; + params.dedicatedAllocation = RequiresDedicatedAllocation(opaqueFDDescriptor, image); + return params; + } + + uint32_t GetQueueFamilyIndex() override { return VK_QUEUE_FAMILY_EXTERNAL_KHR; } + + ResultOrError ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) override { + 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); + + VkMemoryAllocateInfo allocateInfo; + allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocateInfo.pNext = nullptr; + allocateInfo.allocationSize = importParams.allocationSize; + allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; + PNextChainBuilder allocateInfoChain(&allocateInfo); + + VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo; + importMemoryHandleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; + importMemoryHandleInfo.handle = handle; + allocateInfoChain.Add(&importMemoryHandleInfo, + VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA); + + VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo; + if (importParams.dedicatedAllocation) { + dedicatedAllocateInfo.image = image; + dedicatedAllocateInfo.buffer = VkBuffer{}; + allocateInfoChain.Add(&dedicatedAllocateInfo, + VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + } + + VkDeviceMemory allocatedMemory = VK_NULL_HANDLE; + DAWN_TRY(CheckVkSuccess(mDevice->fn.AllocateMemory(mDevice->GetVkDevice(), &allocateInfo, + nullptr, &*allocatedMemory), + "vkAllocateMemory")); + return allocatedMemory; + } + + ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) override { + VkImageCreateInfo createInfo = baseCreateInfo; + createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR; + createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + + 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; + + PNextChainBuilder createInfoChain(&createInfo); + createInfoChain.Add(&externalMemoryImageCreateInfo, + VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); + + ASSERT(IsSampleCountSupported(mDevice, createInfo)); + + VkImage image; + DAWN_TRY(CheckVkSuccess( + mDevice->fn.CreateImage(mDevice->GetVkDevice(), &createInfo, nullptr, &*image), + "CreateImage")); + return image; + } + + bool Supported() const override { return mSupported; } + + private: + bool mSupported = false; +}; + +Service::Service(Device* device) { + mImpl = std::make_unique(device); +} // 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 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(descriptor); - - MemoryImportParams params; - params.allocationSize = opaqueFDDescriptor->allocationSize; - params.memoryTypeIndex = opaqueFDDescriptor->memoryTypeIndex; - params.dedicatedAllocation = RequiresDedicatedAllocation(opaqueFDDescriptor, image); - return params; -} - -uint32_t Service::GetQueueFamilyIndex() { - return VK_QUEUE_FAMILY_EXTERNAL_KHR; -} - -ResultOrError 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); - - VkMemoryAllocateInfo allocateInfo; - allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocateInfo.pNext = nullptr; - allocateInfo.allocationSize = importParams.allocationSize; - allocateInfo.memoryTypeIndex = importParams.memoryTypeIndex; - PNextChainBuilder allocateInfoChain(&allocateInfo); - - VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo; - importMemoryHandleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; - importMemoryHandleInfo.handle = handle; - allocateInfoChain.Add(&importMemoryHandleInfo, - VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA); - - VkMemoryDedicatedAllocateInfo dedicatedAllocateInfo; - if (importParams.dedicatedAllocation) { - dedicatedAllocateInfo.image = image; - dedicatedAllocateInfo.buffer = VkBuffer{}; - allocateInfoChain.Add(&dedicatedAllocateInfo, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); - } - - 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) { - VkImageCreateInfo createInfo = baseCreateInfo; - createInfo.flags |= VK_IMAGE_CREATE_ALIAS_BIT_KHR; - createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - 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; - - PNextChainBuilder createInfoChain(&createInfo); - createInfoChain.Add(&externalMemoryImageCreateInfo, - VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO); - - 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 diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceNull.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceNull.cpp index 328265d8a2..5f7de1e27b 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceNull.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceNull.cpp @@ -12,58 +12,70 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "dawn/native/vulkan/DeviceVk.h" #include "dawn/native/vulkan/external_memory/MemoryService.h" +#include "dawn/native/vulkan/external_memory/MemoryServiceImplementation.h" namespace dawn::native::vulkan::external_memory { -Service::Service(Device* device) : mDevice(device) { - DAWN_UNUSED(mDevice); - DAWN_UNUSED(mSupported); -} +class ServiceImplementationNull : public ServiceImplementation { + public: + explicit ServiceImplementationNull(Device* device) + : ServiceImplementation(device), mSupported(CheckSupport(device->GetDeviceInfo())) {} + ~ServiceImplementationNull() override = default; -Service::~Service() = default; + static bool CheckSupport(const VulkanDeviceInfo& deviceInfo) { return false; } + + bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) override { + return false; + } + + bool SupportsCreateImage(const ExternalImageDescriptor* descriptor, + VkFormat format, + VkImageUsageFlags usage, + bool* supportsDisjoint) override { + *supportsDisjoint = false; + return false; + } + + ResultOrError GetMemoryImportParams( + const ExternalImageDescriptor* descriptor, + VkImage image) override { + return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan"); + } + + uint32_t GetQueueFamilyIndex() override { return VK_QUEUE_FAMILY_EXTERNAL_KHR; } + + ResultOrError ImportMemory(ExternalMemoryHandle handle, + const MemoryImportParams& importParams, + VkImage image) override { + return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan"); + } + + ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo) override { + return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan"); + } + + bool Supported() const override { return false; } + + private: + bool mSupported = false; +}; + +Service::Service(Device* device) { + mImpl = std::make_unique(device); +} // static bool Service::CheckSupport(const VulkanDeviceInfo& deviceInfo) { return false; } -bool Service::SupportsImportMemory(VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags) { - return false; -} - -bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, - VkFormat format, - VkImageUsageFlags usage, - bool* supportsDisjoint) { - *supportsDisjoint = false; - return false; -} - -ResultOrError Service::GetMemoryImportParams( - const ExternalImageDescriptor* descriptor, - VkImage image) { - return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan"); -} - -uint32_t Service::GetQueueFamilyIndex() { - return VK_QUEUE_FAMILY_EXTERNAL_KHR; -} - -ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, - const MemoryImportParams& importParams, - VkImage image) { - return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan"); -} - -ResultOrError Service::CreateImage(const ExternalImageDescriptor* descriptor, - const VkImageCreateInfo& baseCreateInfo) { - return DAWN_UNIMPLEMENTED_ERROR("Using null memory service to interop inside Vulkan"); -} - } // namespace dawn::native::vulkan::external_memory