diff --git a/include/dawn/native/VulkanBackend.h b/include/dawn/native/VulkanBackend.h index 22adb0eac9..8fb8a7173a 100644 --- a/include/dawn/native/VulkanBackend.h +++ b/include/dawn/native/VulkanBackend.h @@ -40,6 +40,13 @@ struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptio bool forceSwiftShader = false; }; +enum class NeedsDedicatedAllocation { + Yes, + No, + // Use Vulkan reflection to detect whether a dedicated allocation is needed. + Detect, +}; + struct DAWN_NATIVE_EXPORT ExternalImageDescriptorVk : ExternalImageDescriptor { public: // The following members may be ignored if |ExternalImageDescriptor::isInitialized| is false @@ -54,6 +61,11 @@ struct DAWN_NATIVE_EXPORT ExternalImageDescriptorVk : ExternalImageDescriptor { VkImageLayout releasedOldLayout = VK_IMAGE_LAYOUT_GENERAL; VkImageLayout releasedNewLayout = VK_IMAGE_LAYOUT_GENERAL; + // Try to detect the need to use a dedicated allocation for imported images by default but let + // the application override this as drivers have bugs and forget to require a dedicated + // allocation. + NeedsDedicatedAllocation dedicatedAllocation = NeedsDedicatedAllocation::Detect; + protected: using ExternalImageDescriptor::ExternalImageDescriptor; }; diff --git a/src/dawn/native/BUILD.gn b/src/dawn/native/BUILD.gn index ac57e07437..85025fbc68 100644 --- a/src/dawn/native/BUILD.gn +++ b/src/dawn/native/BUILD.gn @@ -670,6 +670,7 @@ source_set("sources") { "vulkan/VulkanFunctions.h", "vulkan/VulkanInfo.cpp", "vulkan/VulkanInfo.h", + "vulkan/external_memory/MemoryService.cpp", "vulkan/external_memory/MemoryService.h", "vulkan/external_semaphore/SemaphoreService.h", ] diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt index 6eececf9fb..ec2e9906c3 100644 --- a/src/dawn/native/CMakeLists.txt +++ b/src/dawn/native/CMakeLists.txt @@ -552,6 +552,7 @@ if (DAWN_ENABLE_VULKAN) "vulkan/VulkanFunctions.h" "vulkan/VulkanInfo.cpp" "vulkan/VulkanInfo.h" + "vulkan/external_memory/MemoryService.cpp" "vulkan/external_memory/MemoryService.h" "vulkan/external_semaphore/SemaphoreService.h" ) diff --git a/src/dawn/native/vulkan/DeviceVk.cpp b/src/dawn/native/vulkan/DeviceVk.cpp index fec7cb51ad..826de69d24 100644 --- a/src/dawn/native/vulkan/DeviceVk.cpp +++ b/src/dawn/native/vulkan/DeviceVk.cpp @@ -14,7 +14,6 @@ #include "dawn/native/vulkan/DeviceVk.h" -#include "dawn/common/Log.h" #include "dawn/common/NonCopyable.h" #include "dawn/common/Platform.h" #include "dawn/native/BackendConnection.h" diff --git a/src/dawn/native/vulkan/external_memory/MemoryService.cpp b/src/dawn/native/vulkan/external_memory/MemoryService.cpp new file mode 100644 index 0000000000..0db58f4a86 --- /dev/null +++ b/src/dawn/native/vulkan/external_memory/MemoryService.cpp @@ -0,0 +1,57 @@ +// Copyright 2022 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/MemoryService.h" + +#include "dawn/native/vulkan/DeviceVk.h" + +namespace dawn::native::vulkan::external_memory { + +bool Service::RequiresDedicatedAllocation(const ExternalImageDescriptorVk* descriptor, + VkImage image) { + 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; + } +} + +} // 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 eee4e992d5..0800bf21c1 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryService.h +++ b/src/dawn/native/vulkan/external_memory/MemoryService.h @@ -30,6 +30,7 @@ namespace dawn::native::vulkan::external_memory { struct MemoryImportParams { VkDeviceSize allocationSize; uint32_t memoryTypeIndex; + bool dedicatedAllocation = false; }; class Service { @@ -70,6 +71,8 @@ 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 diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceAHardwareBuffer.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceAHardwareBuffer.cpp index cf379292b7..203136540f 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceAHardwareBuffer.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceAHardwareBuffer.cpp @@ -118,7 +118,10 @@ ResultOrError Service::GetMemoryImportParams( mDevice->GetVkDevice(), aHardwareBufferDescriptor->handle, &bufferProperties), "vkGetAndroidHardwareBufferPropertiesANDROID")); - MemoryImportParams params = {bufferProperties.allocationSize, bufferProperties.memoryTypeBits}; + MemoryImportParams params; + params.allocationSize = bufferProperties.allocationSize; + params.memoryTypeIndex = bufferProperties.memoryTypeBits; + params.dedicatedAllocation = RequiresDedicatedAllocation(aHardwareBufferDescriptor, image); return params; } @@ -152,6 +155,14 @@ ResultOrError Service::ImportMemory(ExternalMemoryHandle 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), diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceDmaBuf.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceDmaBuf.cpp index c712d7ea90..fc6a1e3ea3 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceDmaBuf.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceDmaBuf.cpp @@ -252,7 +252,10 @@ ResultOrError Service::GetMemoryImportParams( memoryRequirements, MemoryKind::Opaque); DAWN_INVALID_IF(memoryTypeIndex == -1, "Unable to find an appropriate memory type for import."); - MemoryImportParams params = {memoryRequirements.size, static_cast(memoryTypeIndex)}; + MemoryImportParams params; + params.allocationSize = memoryRequirements.size; + params.memoryTypeIndex = static_cast(memoryTypeIndex); + params.dedicatedAllocation = RequiresDedicatedAllocation(dmaBufDescriptor, image); return params; } @@ -277,10 +280,12 @@ ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, memoryAllocateInfoChain.Add(&importMemoryFdInfo, VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR); VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo; - memoryDedicatedAllocateInfo.image = image; - memoryDedicatedAllocateInfo.buffer = VkBuffer{}; - memoryAllocateInfoChain.Add(&memoryDedicatedAllocateInfo, - VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + 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, diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp index 00a74e4908..1ad48f1c34 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceOpaqueFD.cpp @@ -73,7 +73,6 @@ bool Service::SupportsImportMemory(VkFormat format, 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; } @@ -95,8 +94,10 @@ ResultOrError Service::GetMemoryImportParams( const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = static_cast(descriptor); - MemoryImportParams params = {opaqueFDDescriptor->allocationSize, - opaqueFDDescriptor->memoryTypeIndex}; + MemoryImportParams params; + params.allocationSize = opaqueFDDescriptor->allocationSize; + params.memoryTypeIndex = opaqueFDDescriptor->memoryTypeIndex; + params.dedicatedAllocation = RequiresDedicatedAllocation(opaqueFDDescriptor, image); return params; } @@ -115,17 +116,25 @@ ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, "Requested allocation size (%u) is smaller than the image requires (%u).", importParams.allocationSize, requirements.size); - VkImportMemoryFdInfoKHR importMemoryFdInfo; - importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR; - importMemoryFdInfo.pNext = nullptr; - importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT; - importMemoryFdInfo.fd = handle; - VkMemoryAllocateInfo allocateInfo; allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocateInfo.pNext = &importMemoryFdInfo; + 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, diff --git a/src/dawn/native/vulkan/external_memory/MemoryServiceZirconHandle.cpp b/src/dawn/native/vulkan/external_memory/MemoryServiceZirconHandle.cpp index 5836b87962..2f0dd3b56b 100644 --- a/src/dawn/native/vulkan/external_memory/MemoryServiceZirconHandle.cpp +++ b/src/dawn/native/vulkan/external_memory/MemoryServiceZirconHandle.cpp @@ -95,8 +95,10 @@ ResultOrError Service::GetMemoryImportParams( const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor = static_cast(descriptor); - MemoryImportParams params = {opaqueFDDescriptor->allocationSize, - opaqueFDDescriptor->memoryTypeIndex}; + MemoryImportParams params; + params.allocationSize = opaqueFDDescriptor->allocationSize; + params.memoryTypeIndex = opaqueFDDescriptor->memoryTypeIndex; + params.dedicatedAllocation = RequiresDedicatedAllocation(opaqueFDDescriptor, image); return params; } @@ -115,17 +117,26 @@ ResultOrError Service::ImportMemory(ExternalMemoryHandle handle, "Requested allocation size (%u) is smaller than the required image size (%u).", importParams.allocationSize, requirements.size); - VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo; - importMemoryHandleInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA; - importMemoryHandleInfo.pNext = nullptr; - importMemoryHandleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA; - importMemoryHandleInfo.handle = handle; - VkMemoryAllocateInfo allocateInfo; allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocateInfo.pNext = &importMemoryHandleInfo; + allocateInfo.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, diff --git a/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp b/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp index 6747a0465a..f98c6cbc04 100644 --- a/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp +++ b/src/dawn/tests/white_box/VulkanImageWrappingTests.cpp @@ -27,9 +27,22 @@ namespace dawn::native::vulkan { using ExternalTexture = VulkanImageWrappingTestBackend::ExternalTexture; using ExternalSemaphore = VulkanImageWrappingTestBackend::ExternalSemaphore; +void VulkanImageWrappingTestBackend::SetParam( + const VulkanImageWrappingTestBackend::TestParams& params) { + mParams = params; +} + +const VulkanImageWrappingTestBackend::TestParams& VulkanImageWrappingTestBackend::GetParam() const { + return mParams; +} + namespace { -class VulkanImageWrappingTestBase : public DawnTest { +using UseDedicatedAllocation = bool; +using DetectDedicatedAllocation = bool; +DAWN_TEST_PARAM_STRUCT(ImageWrappingParams, UseDedicatedAllocation, DetectDedicatedAllocation); + +class VulkanImageWrappingTestBase : public DawnTestWithParams { protected: std::vector GetRequiredFeatures() override { return {wgpu::FeatureName::DawnInternalUsages}; @@ -37,11 +50,22 @@ class VulkanImageWrappingTestBase : public DawnTest { public: void SetUp() override { - DawnTest::SetUp(); + DawnTestWithParams::SetUp(); DAWN_TEST_UNSUPPORTED_IF(UsesWire()); + // TODO(dawn:1552): Nvidia doesn't seem to correctly reflect whether an import requires a + // dedicated allocation. + DAWN_SUPPRESS_TEST_IF(IsLinux() && IsNvidia() && GetParam().mUseDedicatedAllocation && + GetParam().mDetectDedicatedAllocation); + mBackend = VulkanImageWrappingTestBackend::Create(device); + VulkanImageWrappingTestBackend::TestParams params; + params.useDedicatedAllocation = GetParam().mUseDedicatedAllocation; + params.detectDedicatedAllocation = GetParam().mDetectDedicatedAllocation; + DAWN_TEST_UNSUPPORTED_IF(!mBackend->SupportsTestParams(params)); + mBackend->SetParam(params); + defaultDescriptor.dimension = wgpu::TextureDimension::e2D; defaultDescriptor.format = wgpu::TextureFormat::RGBA8Unorm; defaultDescriptor.size = {1, 1, 1}; @@ -56,13 +80,13 @@ class VulkanImageWrappingTestBase : public DawnTest { void TearDown() override { if (UsesWire()) { - DawnTest::TearDown(); + DawnTestWithParams::TearDown(); return; } defaultTexture = nullptr; mBackend = nullptr; - DawnTest::TearDown(); + DawnTestWithParams::TearDown(); } wgpu::Texture WrapVulkanImage(wgpu::Device dawnDevice, @@ -868,7 +892,15 @@ TEST_P(VulkanImageWrappingUsageTests, SRGBReinterpretation) { IgnoreSignalSemaphore(texture); } -DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend()); -DAWN_INSTANTIATE_TEST(VulkanImageWrappingUsageTests, VulkanBackend()); +DAWN_INSTANTIATE_TEST_P(VulkanImageWrappingValidationTests, + {VulkanBackend()}, + {true, false}, // UseDedicatedAllocation + {true, false} // DetectDedicatedAllocation +); +DAWN_INSTANTIATE_TEST_P(VulkanImageWrappingUsageTests, + {VulkanBackend()}, + {true, false}, // UseDedicatedAllocation + {true, false} // DetectDedicatedAllocation +); } // namespace dawn::native::vulkan diff --git a/src/dawn/tests/white_box/VulkanImageWrappingTests.h b/src/dawn/tests/white_box/VulkanImageWrappingTests.h index dd7152b3dd..a430783113 100644 --- a/src/dawn/tests/white_box/VulkanImageWrappingTests.h +++ b/src/dawn/tests/white_box/VulkanImageWrappingTests.h @@ -45,6 +45,17 @@ class VulkanImageWrappingTestBackend { virtual ~ExternalSemaphore() = default; }; + // Test parameters passed from the wrapping tests so that they can be used by the test + // backends. The DAWN_TEST_PARAM_STRUCT is not declared here because it is unnecessary but also + // because it declares a bunch of functions that would cause ODR violations. + struct TestParams { + bool useDedicatedAllocation = false; + bool detectDedicatedAllocation = false; + }; + void SetParam(const TestParams& params); + const TestParams& GetParam() const; + virtual bool SupportsTestParams(const TestParams& params) const = 0; + virtual std::unique_ptr CreateTexture(uint32_t width, uint32_t height, wgpu::TextureFormat format, @@ -57,6 +68,9 @@ class VulkanImageWrappingTestBackend { virtual bool ExportImage(const wgpu::Texture& texture, VkImageLayout layout, ExternalImageExportInfoVkForTesting* exportInfo) = 0; + + private: + TestParams mParams; }; struct ExternalImageDescriptorVkForTesting : public ExternalImageDescriptorVk { diff --git a/src/dawn/tests/white_box/VulkanImageWrappingTests_DmaBuf.cpp b/src/dawn/tests/white_box/VulkanImageWrappingTests_DmaBuf.cpp index adb03e764a..d2be7ba7fe 100644 --- a/src/dawn/tests/white_box/VulkanImageWrappingTests_DmaBuf.cpp +++ b/src/dawn/tests/white_box/VulkanImageWrappingTests_DmaBuf.cpp @@ -22,6 +22,7 @@ #include #include +#include "dawn/native/vulkan/DeviceVk.h" #include "dawn/tests/white_box/VulkanImageWrappingTests.h" namespace dawn::native::vulkan { @@ -80,7 +81,9 @@ class ExternalTextureDmaBuf : public VulkanImageWrappingTestBackend::ExternalTex class VulkanImageWrappingTestBackendDmaBuf : public VulkanImageWrappingTestBackend { public: - explicit VulkanImageWrappingTestBackendDmaBuf(const wgpu::Device& device) {} + explicit VulkanImageWrappingTestBackendDmaBuf(const wgpu::Device& device) { + mDeviceVk = dawn::native::vulkan::ToBackend(dawn::native::FromAPI(device.Get())); + } ~VulkanImageWrappingTestBackendDmaBuf() { if (mGbmDevice != nullptr) { @@ -89,6 +92,14 @@ class VulkanImageWrappingTestBackendDmaBuf : public VulkanImageWrappingTestBacke } } + bool SupportsTestParams(const TestParams& params) const override { + // Even though this backend doesn't decide on creation whether the image should use + // dedicated allocation, it still supports all options of NeedsDedicatedAllocation so we + // test them. + return !params.useDedicatedAllocation || + mDeviceVk->GetDeviceInfo().HasExt(DeviceExt::DedicatedAllocation); + } + std::unique_ptr CreateTexture(uint32_t width, uint32_t height, wgpu::TextureFormat format, @@ -186,6 +197,7 @@ class VulkanImageWrappingTestBackendDmaBuf : public VulkanImageWrappingTestBacke } gbm_device* mGbmDevice = nullptr; + dawn::native::vulkan::Device* mDeviceVk; }; // static @@ -195,4 +207,5 @@ std::unique_ptr VulkanImageWrappingTestBackend:: backend->CreateGbmDevice(); return backend; } + } // namespace dawn::native::vulkan diff --git a/src/dawn/tests/white_box/VulkanImageWrappingTests_OpaqueFD.cpp b/src/dawn/tests/white_box/VulkanImageWrappingTests_OpaqueFD.cpp index e8e8a59333..8944deead5 100644 --- a/src/dawn/tests/white_box/VulkanImageWrappingTests_OpaqueFD.cpp +++ b/src/dawn/tests/white_box/VulkanImageWrappingTests_OpaqueFD.cpp @@ -21,6 +21,7 @@ #include "dawn/native/vulkan/DeviceVk.h" #include "dawn/native/vulkan/FencedDeleter.h" #include "dawn/native/vulkan/ResourceMemoryAllocatorVk.h" +#include "dawn/native/vulkan/UtilsVulkan.h" #include "dawn/tests/white_box/VulkanImageWrappingTests.h" #include "gtest/gtest.h" @@ -95,6 +96,11 @@ class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBac mDeviceVk = dawn::native::vulkan::ToBackend(dawn::native::FromAPI(device.Get())); } + bool SupportsTestParams(const TestParams& params) const override { + return !params.useDedicatedAllocation || + mDeviceVk->GetDeviceInfo().HasExt(DeviceExt::DedicatedAllocation); + } + std::unique_ptr CreateTexture(uint32_t width, uint32_t height, wgpu::TextureFormat format, @@ -141,6 +147,14 @@ class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBac descriptorOpaqueFD.memoryTypeIndex = textureOpaqueFD->memoryTypeIndex; descriptorOpaqueFD.waitFDs = std::move(waitFDs); + if (GetParam().detectDedicatedAllocation) { + descriptorOpaqueFD.dedicatedAllocation = NeedsDedicatedAllocation::Detect; + } else if (GetParam().useDedicatedAllocation) { + descriptorOpaqueFD.dedicatedAllocation = NeedsDedicatedAllocation::Yes; + } else { + descriptorOpaqueFD.dedicatedAllocation = NeedsDedicatedAllocation::No; + } + return wgpu::Texture::Acquire( dawn::native::vulkan::WrapVulkanImage(device.Get(), &descriptorOpaqueFD)); } @@ -167,17 +181,12 @@ class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBac uint32_t height, VkFormat format, VkImage* image) { - VkExternalMemoryImageCreateInfoKHR externalInfo; - externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR; - externalInfo.pNext = nullptr; - externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; - auto usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; VkImageCreateInfo createInfo; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - createInfo.pNext = &externalInfo; + createInfo.pNext = nullptr; createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR; createInfo.imageType = VK_IMAGE_TYPE_2D; createInfo.format = format; @@ -191,6 +200,11 @@ class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBac createInfo.queueFamilyIndexCount = 0; createInfo.pQueueFamilyIndices = nullptr; createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + PNextChainBuilder createChain(&createInfo); + + VkExternalMemoryImageCreateInfoKHR externalInfo; + externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + createChain.Add(&externalInfo, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR); return deviceVk->fn.CreateImage(deviceVk->GetVkDevice(), &createInfo, nullptr, &**image); } @@ -205,19 +219,28 @@ class VulkanImageWrappingTestBackendOpaqueFD : public VulkanImageWrappingTestBac VkMemoryRequirements requirements; deviceVk->fn.GetImageMemoryRequirements(deviceVk->GetVkDevice(), handle, &requirements); - // Import memory from file descriptor - VkExportMemoryAllocateInfoKHR externalInfo; - externalInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR; - externalInfo.pNext = nullptr; - externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; - int bestType = deviceVk->GetResourceMemoryAllocator()->FindBestTypeIndex( requirements, MemoryKind::Opaque); + VkMemoryAllocateInfo allocateInfo; allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocateInfo.pNext = &externalInfo; + allocateInfo.pNext = nullptr; allocateInfo.allocationSize = requirements.size; allocateInfo.memoryTypeIndex = static_cast(bestType); + PNextChainBuilder allocateChain(&allocateInfo); + + // Import memory from file descriptor + VkExportMemoryAllocateInfoKHR externalInfo; + externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; + allocateChain.Add(&externalInfo, VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR); + + // Use a dedicated memory allocation if testing that path. + VkMemoryDedicatedAllocateInfo dedicatedInfo; + if (GetParam().useDedicatedAllocation) { + dedicatedInfo.image = handle; + dedicatedInfo.buffer = VkBuffer{}; + allocateChain.Add(&dedicatedInfo, VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO); + } *allocationSize = allocateInfo.allocationSize; *memoryTypeIndex = allocateInfo.memoryTypeIndex;