v3dv: implement VK_KHR_external_memory{_fd,_dma_buf}
authorIago Toral Quiroga <itoral@igalia.com>
Wed, 15 Jan 2020 10:32:09 +0000 (11:32 +0100)
committerMarge Bot <eric+marge@anholt.net>
Tue, 13 Oct 2020 21:21:26 +0000 (21:21 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>

src/broadcom/vulkan/v3dv_device.c
src/broadcom/vulkan/v3dv_extensions.py
src/broadcom/vulkan/v3dv_formats.c

index a349114..fef0100 100644 (file)
@@ -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;
+}
index 0e9bfdc..3a51951 100644 (file)
@@ -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
index 61b822f..740318e 100644 (file)
@@ -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 */