Define an interface to import dma-bufs

This CL adds an API to import a dma-buf into Dawn as a WGPUTexture.

We also add a descriptor type enum to the base
ExternalImageDescriptor struct. This is because all memory import
code (e.g. MemoryService, Texture::CreateFromExternal) takes the
a base ExternalImageDescriptor as a parameter. The dma-buf external
memory and image services, however, will need to downcast to
ExternalImageDescriptorDmaBuf to access import parameters like
stride. Explicitly adding a type enum will let us more safely verify
the type before downcasting.

BUG=chromium:996470

Change-Id: I2d9883a15e9059a91f2c7bdb7a96d74373e18c56
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/13782
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brian Ho <hob@chromium.org>
This commit is contained in:
Brian Ho 2019-11-20 23:57:03 +00:00 committed by Commit Bot service account
parent ae687f5b83
commit 98ba76af00
5 changed files with 107 additions and 12 deletions

View File

@ -518,11 +518,6 @@ namespace dawn_native { namespace vulkan {
VkDeviceMemory externalMemoryAllocation, VkDeviceMemory externalMemoryAllocation,
std::vector<VkSemaphore> waitSemaphores) { std::vector<VkSemaphore> waitSemaphores) {
Device* device = ToBackend(GetDevice()); Device* device = ToBackend(GetDevice());
VkMemoryRequirements requirements;
device->fn.GetImageMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);
ASSERT(requirements.size <= descriptor->allocationSize);
DAWN_TRY(CheckVkSuccess( DAWN_TRY(CheckVkSuccess(
device->fn.BindImageMemory(device->GetVkDevice(), mHandle, externalMemoryAllocation, 0), device->fn.BindImageMemory(device->GetVkDevice(), mHandle, externalMemoryAllocation, 0),
"BindImageMemory (external)")); "BindImageMemory (external)"));

View File

@ -60,6 +60,23 @@ namespace dawn_native { namespace vulkan {
} }
#ifdef DAWN_PLATFORM_LINUX #ifdef DAWN_PLATFORM_LINUX
ExternalImageDescriptor::ExternalImageDescriptor(ExternalImageDescriptorType type)
: type(type) {
}
ExternalImageDescriptorFD::ExternalImageDescriptorFD(ExternalImageDescriptorType type)
: ExternalImageDescriptor(type) {
}
ExternalImageDescriptorOpaqueFD::ExternalImageDescriptorOpaqueFD()
: ExternalImageDescriptorFD(ExternalImageDescriptorType::OpaqueFD) {
}
ExternalImageDescriptorDmaBuf::ExternalImageDescriptorDmaBuf()
: ExternalImageDescriptorFD(ExternalImageDescriptorType::DmaBuf) {
}
// TODO(hob): Remove this once we switch over to WrapVulkanImage in Chromium.
WGPUTexture WrapVulkanImageOpaqueFD(WGPUDevice cDevice, WGPUTexture WrapVulkanImageOpaqueFD(WGPUDevice cDevice,
const ExternalImageDescriptorOpaqueFD* descriptor) { const ExternalImageDescriptorOpaqueFD* descriptor) {
Device* device = reinterpret_cast<Device*>(cDevice); Device* device = reinterpret_cast<Device*>(cDevice);
@ -85,6 +102,23 @@ namespace dawn_native { namespace vulkan {
return outHandle; return outHandle;
} }
WGPUTexture WrapVulkanImage(WGPUDevice cDevice, const ExternalImageDescriptor* descriptor) {
Device* device = reinterpret_cast<Device*>(cDevice);
switch (descriptor->type) {
case ExternalImageDescriptorType::OpaqueFD:
case ExternalImageDescriptorType::DmaBuf: {
const ExternalImageDescriptorFD* fdDescriptor =
static_cast<const ExternalImageDescriptorFD*>(descriptor);
TextureBase* texture = device->CreateTextureWrappingVulkanImage(
descriptor, fdDescriptor->memoryFD, fdDescriptor->waitFDs);
return reinterpret_cast<WGPUTexture>(texture);
}
default:
return nullptr;
}
}
#endif #endif
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan

View File

@ -88,7 +88,14 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams( ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
const ExternalImageDescriptor* descriptor, const ExternalImageDescriptor* descriptor,
VkImage image) { VkImage image) {
MemoryImportParams params = {descriptor->allocationSize, descriptor->memoryTypeIndex}; if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) {
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
}
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
static_cast<const ExternalImageDescriptorOpaqueFD*>(descriptor);
MemoryImportParams params = {opaqueFDDescriptor->allocationSize,
opaqueFDDescriptor->memoryTypeIndex};
return params; return params;
} }
@ -99,6 +106,12 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle"); return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
} }
VkMemoryRequirements requirements;
mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements);
if (requirements.size > importParams.allocationSize) {
return DAWN_VALIDATION_ERROR("Requested allocation size is too small for image");
}
VkImportMemoryFdInfoKHR importMemoryFdInfo; VkImportMemoryFdInfoKHR importMemoryFdInfo;
importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR; importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
importMemoryFdInfo.pNext = nullptr; importMemoryFdInfo.pNext = nullptr;

View File

@ -88,7 +88,14 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
ResultOrError<MemoryImportParams> Service::GetMemoryImportParams( ResultOrError<MemoryImportParams> Service::GetMemoryImportParams(
const ExternalImageDescriptor* descriptor, const ExternalImageDescriptor* descriptor,
VkImage image) { VkImage image) {
MemoryImportParams params = {descriptor->allocationSize, descriptor->memoryTypeIndex}; if (descriptor->type != ExternalImageDescriptorType::OpaqueFD) {
return DAWN_VALIDATION_ERROR("ExternalImageDescriptor is not an OpaqueFD descriptor");
}
const ExternalImageDescriptorOpaqueFD* opaqueFDDescriptor =
static_cast<const ExternalImageDescriptorOpaqueFD*>(descriptor);
MemoryImportParams params = {opaqueFDDescriptor->allocationSize,
opaqueFDDescriptor->memoryTypeIndex};
return params; return params;
} }
@ -99,6 +106,12 @@ namespace dawn_native { namespace vulkan { namespace external_memory {
return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle"); return DAWN_VALIDATION_ERROR("Trying to import memory with invalid handle");
} }
VkMemoryRequirements requirements;
mDevice->fn.GetImageMemoryRequirements(mDevice->GetVkDevice(), image, &requirements);
if (requirements.size > importParams.allocationSize) {
return DAWN_VALIDATION_ERROR("Requested allocation size is too small for image");
}
VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo; VkImportMemoryZirconHandleInfoFUCHSIA importMemoryHandleInfo;
importMemoryHandleInfo.sType = importMemoryHandleInfo.sType =
VK_STRUCTURE_TYPE_TEMP_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA; VK_STRUCTURE_TYPE_TEMP_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA;

View File

@ -24,12 +24,23 @@
namespace dawn_native { namespace vulkan { namespace dawn_native { namespace vulkan {
// The different types of ExternalImageDescriptors
enum ExternalImageDescriptorType {
#ifdef __linux__
OpaqueFD,
DmaBuf,
#endif // __linux__
};
// Common properties of external images // Common properties of external images
struct ExternalImageDescriptor { struct ExternalImageDescriptor {
public:
const ExternalImageDescriptorType type; // Must match the subclass
const WGPUTextureDescriptor* cTextureDescriptor; // Must match image creation params const WGPUTextureDescriptor* cTextureDescriptor; // Must match image creation params
bool isCleared; // Sets whether the texture will be cleared before use bool isCleared; // Sets whether the texture will be cleared before use
VkDeviceSize allocationSize; // Must match VkMemoryAllocateInfo from image creation
uint32_t memoryTypeIndex; // Must match VkMemoryAllocateInfo from image creation protected:
ExternalImageDescriptor(ExternalImageDescriptorType type);
}; };
DAWN_NATIVE_EXPORT VkInstance GetInstance(WGPUDevice device); DAWN_NATIVE_EXPORT VkInstance GetInstance(WGPUDevice device);
@ -43,10 +54,30 @@ namespace dawn_native { namespace vulkan {
// Can't use DAWN_PLATFORM_LINUX since header included in both dawn and chrome // Can't use DAWN_PLATFORM_LINUX since header included in both dawn and chrome
#ifdef __linux__ #ifdef __linux__
// Descriptor for opaque file descriptor image import // Common properties of external images represented by FDs
struct ExternalImageDescriptorOpaqueFD : ExternalImageDescriptor { struct ExternalImageDescriptorFD : ExternalImageDescriptor {
public:
int memoryFD; // A file descriptor from an export of the memory of the image int memoryFD; // A file descriptor from an export of the memory of the image
std::vector<int> waitFDs; // File descriptors of semaphores which will be waited on std::vector<int> waitFDs; // File descriptors of semaphores which will be waited on
protected:
ExternalImageDescriptorFD(ExternalImageDescriptorType type);
};
// Descriptor for opaque file descriptor image import
struct ExternalImageDescriptorOpaqueFD : ExternalImageDescriptorFD {
ExternalImageDescriptorOpaqueFD();
VkDeviceSize allocationSize; // Must match VkMemoryAllocateInfo from image creation
uint32_t memoryTypeIndex; // Must match VkMemoryAllocateInfo from image creation
};
// Descriptor for dma-buf file descriptor image import
struct ExternalImageDescriptorDmaBuf : ExternalImageDescriptorFD {
ExternalImageDescriptorDmaBuf();
uint32_t stride; // Stride of the buffer in bytes
uint64_t drmModifier; // DRM modifier of the buffer
}; };
// Imports an external vulkan image from an opaque file descriptor. Internally, this uses // Imports an external vulkan image from an opaque file descriptor. Internally, this uses
@ -54,6 +85,8 @@ namespace dawn_native { namespace vulkan {
// |descriptor->waitFDs| before the texture can be used. Finally, a signal semaphore // |descriptor->waitFDs| before the texture can be used. Finally, a signal semaphore
// can be exported, transferring control back to the caller. // can be exported, transferring control back to the caller.
// On failure, returns a nullptr // On failure, returns a nullptr
// NOTE: This is deprecated. Use WrapVulkanImage instead.
// TODO(hob): Remove this once Chromium has switched over to WrapVulkanImage.
DAWN_NATIVE_EXPORT WGPUTexture DAWN_NATIVE_EXPORT WGPUTexture
WrapVulkanImageOpaqueFD(WGPUDevice cDevice, WrapVulkanImageOpaqueFD(WGPUDevice cDevice,
const ExternalImageDescriptorOpaqueFD* descriptor); const ExternalImageDescriptorOpaqueFD* descriptor);
@ -62,6 +95,13 @@ namespace dawn_native { namespace vulkan {
// textures before they are destroyed. On failure, returns -1 // textures before they are destroyed. On failure, returns -1
DAWN_NATIVE_EXPORT int ExportSignalSemaphoreOpaqueFD(WGPUDevice cDevice, DAWN_NATIVE_EXPORT int ExportSignalSemaphoreOpaqueFD(WGPUDevice cDevice,
WGPUTexture cTexture); WGPUTexture cTexture);
// Imports external memory into a Vulkan image. Internally, this uses external memory /
// semaphore extensions to import the image and wait on the provided synchronizaton
// primitives before the texture can be used.
// On failure, returns a nullptr.
DAWN_NATIVE_EXPORT WGPUTexture WrapVulkanImage(WGPUDevice cDevice,
const ExternalImageDescriptor* descriptor);
#endif // __linux__ #endif // __linux__
}} // namespace dawn_native::vulkan }} // namespace dawn_native::vulkan