v3dv: implement VK_KHR_external_memory{_fd,_dma_buf}

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Iago Toral Quiroga 2020-01-15 11:32:09 +01:00 committed by Marge Bot
parent 0fd434d977
commit beee18103e
3 changed files with 135 additions and 3 deletions

View 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;
}

View 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

View 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 */