diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp index ed85121e5a..f317588d1f 100644 --- a/src/dawn_native/vulkan/DeviceVk.cpp +++ b/src/dawn_native/vulkan/DeviceVk.cpp @@ -615,7 +615,7 @@ namespace dawn_native { namespace vulkan { if (!mExternalSemaphoreService->Supported()) { return DAWN_VALIDATION_ERROR("External semaphore usage not supported"); } - if (!mExternalMemoryService->Supported( + if (!mExternalMemoryService->SupportsImportMemory( VulkanImageFormat(textureDescriptor->format), VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VulkanImageUsage(textureDescriptor->usage, @@ -683,7 +683,8 @@ namespace dawn_native { namespace vulkan { // if a failure happems. Texture* result = nullptr; // TODO(crbug.com/1026480): Consolidate this into a single CreateFromExternal call. - if (ConsumedError(Texture::CreateFromExternal(this, descriptor, textureDescriptor), + if (ConsumedError(Texture::CreateFromExternal(this, descriptor, textureDescriptor, + mExternalMemoryService.get()), &result) || ConsumedError(ImportExternalImage(descriptor, memoryHandle, result->GetHandle(), waitHandles, &signalSemaphore, &allocation, diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp index 211719db38..86104bbaf7 100644 --- a/src/dawn_native/vulkan/TextureVk.cpp +++ b/src/dawn_native/vulkan/TextureVk.cpp @@ -200,22 +200,6 @@ namespace dawn_native { namespace vulkan { return {extent.width, extent.height, extent.depth}; } - bool IsSampleCountSupported(const dawn_native::vulkan::Device* device, - const VkImageCreateInfo& imageCreateInfo) { - ASSERT(device); - - VkPhysicalDevice physicalDevice = ToBackend(device->GetAdapter())->GetPhysicalDevice(); - VkImageFormatProperties properties; - if (device->fn.GetPhysicalDeviceImageFormatProperties( - physicalDevice, imageCreateInfo.format, imageCreateInfo.imageType, - imageCreateInfo.tiling, imageCreateInfo.usage, imageCreateInfo.flags, - &properties) != VK_SUCCESS) { - UNREACHABLE(); - } - - return properties.sampleCounts & imageCreateInfo.samples; - } - } // namespace // Converts Dawn texture format to Vulkan formats. @@ -397,6 +381,22 @@ namespace dawn_native { namespace vulkan { return {}; } + bool IsSampleCountSupported(const dawn_native::vulkan::Device* device, + const VkImageCreateInfo& imageCreateInfo) { + ASSERT(device); + + VkPhysicalDevice physicalDevice = ToBackend(device->GetAdapter())->GetPhysicalDevice(); + VkImageFormatProperties properties; + if (device->fn.GetPhysicalDeviceImageFormatProperties( + physicalDevice, imageCreateInfo.format, imageCreateInfo.imageType, + imageCreateInfo.tiling, imageCreateInfo.usage, imageCreateInfo.flags, + &properties) != VK_SUCCESS) { + UNREACHABLE(); + } + + return properties.sampleCounts & imageCreateInfo.samples; + } + // static ResultOrError Texture::Create(Device* device, const TextureDescriptor* descriptor) { std::unique_ptr texture = @@ -409,10 +409,11 @@ namespace dawn_native { namespace vulkan { ResultOrError Texture::CreateFromExternal( Device* device, const ExternalImageDescriptor* descriptor, - const TextureDescriptor* textureDescriptor) { + const TextureDescriptor* textureDescriptor, + external_memory::Service* externalMemoryService) { std::unique_ptr texture = std::make_unique(device, textureDescriptor, TextureState::OwnedInternal); - DAWN_TRY(texture->InitializeFromExternal(descriptor)); + DAWN_TRY(texture->InitializeFromExternal(descriptor, externalMemoryService)); return texture.release(); } @@ -481,38 +482,34 @@ namespace dawn_native { namespace vulkan { } // Internally managed, but imported from external handle - MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptor* descriptor) { + MaybeError Texture::InitializeFromExternal(const ExternalImageDescriptor* descriptor, + external_memory::Service* externalMemoryService) { + VkFormat format = VulkanImageFormat(GetFormat().format); + if (!externalMemoryService->SupportsCreateImage(descriptor, format)) { + return DAWN_VALIDATION_ERROR("Creating an image from external memory is not supported"); + } + mExternalState = ExternalState::PendingAcquire; - Device* device = ToBackend(GetDevice()); - - VkImageCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR; - createInfo.imageType = VulkanImageType(GetDimension()); - createInfo.format = VulkanImageFormat(GetFormat().format); - createInfo.extent = VulkanExtent3D(GetSize()); - createInfo.mipLevels = GetNumMipLevels(); - createInfo.arrayLayers = GetArrayLayers(); - createInfo.samples = VulkanSampleCount(GetSampleCount()); - createInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - createInfo.usage = VulkanImageUsage(GetUsage(), GetFormat()); - createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.queueFamilyIndexCount = 0; - createInfo.pQueueFamilyIndices = nullptr; - createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - - ASSERT(IsSampleCountSupported(device, createInfo)); + VkImageCreateInfo baseCreateInfo = {}; + baseCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + baseCreateInfo.pNext = nullptr; + baseCreateInfo.imageType = VulkanImageType(GetDimension()); + baseCreateInfo.format = format; + baseCreateInfo.extent = VulkanExtent3D(GetSize()); + baseCreateInfo.mipLevels = GetNumMipLevels(); + baseCreateInfo.arrayLayers = GetArrayLayers(); + baseCreateInfo.samples = VulkanSampleCount(GetSampleCount()); + baseCreateInfo.usage = VulkanImageUsage(GetUsage(), GetFormat()); + baseCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + baseCreateInfo.queueFamilyIndexCount = 0; + baseCreateInfo.pQueueFamilyIndices = nullptr; // We always set VK_IMAGE_USAGE_TRANSFER_DST_BIT unconditionally beause the Vulkan images // that are used in vkCmdClearColorImage() must have been created with this flag, which is // also required for the implementation of robust resource initialization. - createInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; - - DAWN_TRY(CheckVkSuccess( - device->fn.CreateImage(device->GetVkDevice(), &createInfo, nullptr, &mHandle), - "CreateImage")); + baseCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT; + DAWN_TRY_ASSIGN(mHandle, externalMemoryService->CreateImage(descriptor, baseCreateInfo)); return {}; } diff --git a/src/dawn_native/vulkan/TextureVk.h b/src/dawn_native/vulkan/TextureVk.h index 5174292ce2..82366ae0ef 100644 --- a/src/dawn_native/vulkan/TextureVk.h +++ b/src/dawn_native/vulkan/TextureVk.h @@ -20,6 +20,7 @@ #include "common/vulkan_platform.h" #include "dawn_native/ResourceMemoryAllocation.h" #include "dawn_native/vulkan/ExternalHandle.h" +#include "dawn_native/vulkan/external_memory/MemoryService.h" namespace dawn_native { namespace vulkan { @@ -34,6 +35,9 @@ namespace dawn_native { namespace vulkan { MaybeError ValidateVulkanImageCanBeWrapped(const DeviceBase* device, const TextureDescriptor* descriptor); + bool IsSampleCountSupported(const dawn_native::vulkan::Device* device, + const VkImageCreateInfo& imageCreateInfo); + class Texture : public TextureBase { public: // Used to create a regular texture from a descriptor. @@ -45,7 +49,8 @@ namespace dawn_native { namespace vulkan { static ResultOrError CreateFromExternal( Device* device, const ExternalImageDescriptor* descriptor, - const TextureDescriptor* textureDescriptor); + const TextureDescriptor* textureDescriptor, + external_memory::Service* externalMemoryService); Texture(Device* device, const TextureDescriptor* descriptor, VkImage nativeImage); ~Texture(); @@ -76,7 +81,8 @@ namespace dawn_native { namespace vulkan { using TextureBase::TextureBase; MaybeError InitializeAsInternalTexture(); - MaybeError InitializeFromExternal(const ExternalImageDescriptor* descriptor); + MaybeError InitializeFromExternal(const ExternalImageDescriptor* descriptor, + external_memory::Service* externalMemoryService); void DestroyImpl() override; MaybeError ClearTexture(CommandRecordingContext* recordingContext, diff --git a/src/dawn_native/vulkan/external_memory/MemoryService.h b/src/dawn_native/vulkan/external_memory/MemoryService.h index bcd3ea4f4b..1d0d475eca 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryService.h +++ b/src/dawn_native/vulkan/external_memory/MemoryService.h @@ -36,12 +36,15 @@ namespace dawn_native { namespace vulkan { namespace external_memory { explicit Service(Device* device); ~Service(); - // True if the device reports it supports this feature - bool Supported(VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags); + // True if the device reports it supports importing external memory. + bool SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags); + + // True if the device reports it supports creating VkImages from external memory. + bool SupportsCreateImage(const ExternalImageDescriptor* descriptor, VkFormat format); // Returns the parameters required for importing memory ResultOrError GetMemoryImportParams( @@ -53,6 +56,10 @@ namespace dawn_native { namespace vulkan { namespace external_memory { const MemoryImportParams& importParams, VkImage image); + // Create a VkImage for the given handle type + ResultOrError CreateImage(const ExternalImageDescriptor* descriptor, + const VkImageCreateInfo& baseCreateInfo); + private: Device* mDevice = nullptr; diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp index c7417d7958..78144d6e0e 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceNull.cpp @@ -24,11 +24,15 @@ namespace dawn_native { namespace vulkan { namespace external_memory { Service::~Service() = default; - bool Service::Supported(VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags) { + bool Service::SupportsImportMemory(VkFormat format, + VkImageType type, + VkImageTiling tiling, + VkImageUsageFlags usage, + VkImageCreateFlags flags) { + return false; + } + + bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, VkFormat format) { return false; } @@ -44,4 +48,9 @@ namespace dawn_native { namespace vulkan { namespace external_memory { 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 diff --git a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp index 64cd3a5bba..00cb4464a3 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp @@ -16,6 +16,7 @@ #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" @@ -33,11 +34,11 @@ namespace dawn_native { namespace vulkan { namespace external_memory { Service::~Service() = default; - bool Service::Supported(VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags) { + 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; @@ -80,6 +81,10 @@ namespace dawn_native { namespace vulkan { namespace external_memory { !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR); } + bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, VkFormat format) { + return mSupported; + } + ResultOrError Service::GetMemoryImportParams( const ExternalImageDescriptor* descriptor, VkImage image) { @@ -113,4 +118,20 @@ namespace dawn_native { namespace vulkan { namespace external_memory { 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; + + 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/MemoryServiceZirconHandle.cpp b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp index d461d44cd4..0a72205375 100644 --- a/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp +++ b/src/dawn_native/vulkan/external_memory/MemoryServiceZirconHandle.cpp @@ -16,6 +16,7 @@ #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" @@ -33,11 +34,11 @@ namespace dawn_native { namespace vulkan { namespace external_memory { Service::~Service() = default; - bool Service::Supported(VkFormat format, - VkImageType type, - VkImageTiling tiling, - VkImageUsageFlags usage, - VkImageCreateFlags flags) { + 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; @@ -80,6 +81,10 @@ namespace dawn_native { namespace vulkan { namespace external_memory { !(memoryFlags & VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR); } + bool Service::SupportsCreateImage(const ExternalImageDescriptor* descriptor, VkFormat format) { + return mSupported; + } + ResultOrError Service::GetMemoryImportParams( const ExternalImageDescriptor* descriptor, VkImage image) { @@ -115,4 +120,20 @@ namespace dawn_native { namespace vulkan { namespace external_memory { 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; + + 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