Vulkan: Add support for using dedicated allocation when importing images.
This is required to make importing images work on some systems. The ideal version would be detecting whether dedicated allocations are needed as Vulkan provides reflection for that. However this reflection doesn't work on Nvidia, so instead Dawn requires a NeedsDedicatedAllocation enum on import that's Yes/No/Detect so the application can force use of a specific code path. Support for this enum and toggling dedicated allocations on/off is added for all external memory service implementations. Vulkan image wrapping tests are modified to add test parameters so that the Yes/No/Detect code paths are covered by tests. This is technically post-V1 work, but gl_tests in Chromium fail on Nvidia workstations without this fix, which makes it hard to debug other issues. Bug: dawn:1552, dawn:206, dawn:1260 Change-Id: Iee4f7bb9dbec520432ec623551221ef9e4d3d984 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/103560 Reviewed-by: Austin Eng <enga@chromium.org> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
6ff74a6d3e
commit
324e446f9c
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -118,7 +118,10 @@ ResultOrError<MemoryImportParams> 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<VkDeviceMemory> 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),
|
||||
|
|
|
@ -252,7 +252,10 @@ ResultOrError<MemoryImportParams> 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<uint32_t>(memoryTypeIndex)};
|
||||
MemoryImportParams params;
|
||||
params.allocationSize = memoryRequirements.size;
|
||||
params.memoryTypeIndex = static_cast<uint32_t>(memoryTypeIndex);
|
||||
params.dedicatedAllocation = RequiresDedicatedAllocation(dmaBufDescriptor, image);
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -277,10 +280,12 @@ ResultOrError<VkDeviceMemory> 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,
|
||||
|
|
|
@ -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<MemoryImportParams> Service::GetMemoryImportParams(
|
|||
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
||||
static_cast<const ExternalImageDescriptorOpaqueFD*>(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<VkDeviceMemory> 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,
|
||||
|
|
|
@ -95,8 +95,10 @@ ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
|
|||
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
|
||||
static_cast<const ExternalImageDescriptorOpaqueFD*>(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<VkDeviceMemory> 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,
|
||||
|
|
|
@ -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<ImageWrappingParams> {
|
||||
protected:
|
||||
std::vector<wgpu::FeatureName> 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
|
||||
|
|
|
@ -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<ExternalTexture> 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 {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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<ExternalTexture> 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> VulkanImageWrappingTestBackend::
|
|||
backend->CreateGbmDevice();
|
||||
return backend;
|
||||
}
|
||||
|
||||
} // namespace dawn::native::vulkan
|
||||
|
|
|
@ -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<ExternalTexture> 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<uint32_t>(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;
|
||||
|
|
Loading…
Reference in New Issue