From beee18103e5198ebbf2f0c58111e7cc42a1c6fba Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Wed, 15 Jan 2020 11:32:09 +0100 Subject: [PATCH] v3dv: implement VK_KHR_external_memory{_fd,_dma_buf} Part-of: --- src/broadcom/vulkan/v3dv_device.c | 127 ++++++++++++++++++++++++++++++++- src/broadcom/vulkan/v3dv_extensions.py | 3 + src/broadcom/vulkan/v3dv_formats.c | 8 ++- 3 files changed, 135 insertions(+), 3 deletions(-) diff --git a/src/broadcom/vulkan/v3dv_device.c b/src/broadcom/vulkan/v3dv_device.c index a349114..fef0100 100644 --- a/src/broadcom/vulkan/v3dv_device.c +++ b/src/broadcom/vulkan/v3dv_device.c @@ -1152,6 +1152,62 @@ device_unmap(struct v3dv_device *device, struct v3dv_device_memory *mem) v3dv_bo_unmap(device, mem->bo); } +static VkResult +device_import_bo(struct v3dv_device *device, + const VkAllocationCallbacks *pAllocator, + int fd, uint64_t size, + struct v3dv_bo **bo) +{ + VkResult result; + + *bo = vk_alloc2(&device->alloc, pAllocator, sizeof(struct v3dv_bo), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (*bo == NULL) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto fail; + } + + off_t real_size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + if (real_size < 0 || (uint64_t) real_size < size) { + result = VK_ERROR_INVALID_EXTERNAL_HANDLE; + goto fail; + } + + int ret; + uint32_t handle; + ret = drmPrimeFDToHandle(device->fd, fd, &handle); + if (ret) { + result = VK_ERROR_INVALID_EXTERNAL_HANDLE; + goto fail; + } + + struct drm_v3d_get_bo_offset get_offset = { + .handle = handle, + }; + ret = v3dv_ioctl(device->fd, DRM_IOCTL_V3D_GET_BO_OFFSET, &get_offset); + if (ret) { + result = VK_ERROR_INVALID_EXTERNAL_HANDLE; + goto fail; + } + assert(get_offset.offset != 0); + + (*bo)->handle = handle; + (*bo)->size = size; + (*bo)->offset = get_offset.offset; + (*bo)->map = NULL; + (*bo)->map_size = 0; + + return VK_SUCCESS; + +fail: + if (*bo) { + vk_free2(&device->alloc, pAllocator, *bo); + *bo = NULL; + } + return result; +} + VkResult v3dv_AllocateMemory(VkDevice _device, const VkMemoryAllocateInfo *pAllocateInfo, @@ -1175,7 +1231,35 @@ v3dv_AllocateMemory(VkDevice _device, assert(pAllocateInfo->memoryTypeIndex < pdevice->memory.memoryTypeCount); mem->type = &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex]; - VkResult result = device_alloc(device, mem, pAllocateInfo->allocationSize); + const VkImportMemoryFdInfoKHR *fd_info = NULL; + vk_foreach_struct_const(ext, pAllocateInfo->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: + fd_info = (void *)ext; + break; + default: + v3dv_debug_ignored_stype(ext->sType); + break; + } + } + + VkResult result = VK_SUCCESS; + if (fd_info && fd_info->handleType) { + assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || + fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + result = device_import_bo(device, pAllocator, + fd_info->fd, pAllocateInfo->allocationSize, + &mem->bo); + if (result == VK_SUCCESS) + close(fd_info->fd); + } else { + result = device_alloc(device, mem, pAllocateInfo->allocationSize); + } + + if (result != VK_SUCCESS) { + vk_free2(&device->alloc, pAllocator, mem); + return vk_error(device->instance, result); + } *pMem = v3dv_device_memory_to_handle(mem); return result; @@ -1503,3 +1587,44 @@ v3dv_DestroyFramebuffer(VkDevice _device, vk_free2(&device->alloc, pAllocator, fb); } + +VkResult +v3dv_GetMemoryFdPropertiesKHR(VkDevice _device, + VkExternalMemoryHandleTypeFlagBits handleType, + int fd, + VkMemoryFdPropertiesKHR *pMemoryFdProperties) +{ + V3DV_FROM_HANDLE(v3dv_device, device, _device); + struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; + + switch (handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: + pMemoryFdProperties->memoryTypeBits = + (1 << pdevice->memory.memoryTypeCount) - 1; + return VK_SUCCESS; + default: + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); + } +} + +VkResult +v3dv_GetMemoryFdKHR(VkDevice _device, + const VkMemoryGetFdInfoKHR *pGetFdInfo, + int *pFd) +{ + V3DV_FROM_HANDLE(v3dv_device, device, _device); + V3DV_FROM_HANDLE(v3dv_device_memory, mem, pGetFdInfo->memory); + + assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR); + assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || + pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + + int fd, ret; + ret = drmPrimeHandleToFD(device->fd, mem->bo->handle, DRM_CLOEXEC, &fd); + if (ret) + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + + *pFd = fd; + + return VK_SUCCESS; +} diff --git a/src/broadcom/vulkan/v3dv_extensions.py b/src/broadcom/vulkan/v3dv_extensions.py index 0e9bfdc..3a51951 100644 --- a/src/broadcom/vulkan/v3dv_extensions.py +++ b/src/broadcom/vulkan/v3dv_extensions.py @@ -59,9 +59,12 @@ API_VERSIONS = [ MAX_API_VERSION = None # Computed later EXTENSIONS = [ + Extension('VK_KHR_external_memory', 1, True), Extension('VK_KHR_external_memory_capabilities', 1, True), + Extension('VK_KHR_external_memory_fd', 1, True), Extension('VK_KHR_get_physical_device_properties2', 1, True), Extension('VK_EXT_debug_report', 9, True), + Extension('VK_EXT_external_memory_dma_buf', 1, True), ] # Sort the extension list the way we expect: KHR, then EXT, then vendors diff --git a/src/broadcom/vulkan/v3dv_formats.c b/src/broadcom/vulkan/v3dv_formats.c index 61b822f..740318e 100644 --- a/src/broadcom/vulkan/v3dv_formats.c +++ b/src/broadcom/vulkan/v3dv_formats.c @@ -392,9 +392,11 @@ static const VkExternalMemoryProperties prime_fd_props = { .externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT, .exportFromImportedHandleTypes = - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, .compatibleHandleTypes = - VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; VkResult @@ -465,6 +467,7 @@ v3dv_GetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, if (external_info && external_info->handleType != 0) { switch (external_info->handleType) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: if (external_props) external_props->externalMemoryProperties = prime_fd_props; break; @@ -510,6 +513,7 @@ v3dv_GetPhysicalDeviceExternalBufferProperties( { switch (pExternalBufferInfo->handleType) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: pExternalBufferProperties->externalMemoryProperties = prime_fd_props; return; default: /* Unsupported */ -- 2.7.4