diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c index 9839c6041d321..0a081495a2fd3 100644 --- a/src/gallium/frontends/lavapipe/lvp_device.c +++ b/src/gallium/frontends/lavapipe/lvp_device.c @@ -250,6 +250,7 @@ assert_memhandle_type(VkExternalMemoryHandleTypeFlags type) { switch (type) { case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: break; default: mesa_loge("lavapipe: unimplemented external memory type %u", type); @@ -1787,32 +1788,39 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory( mem->memory_type = LVP_DEVICE_MEMORY_TYPE_USER_PTR; } #ifdef PIPE_MEMORY_FD - else if(import_info) { + else if(import_info && import_info->handleType) { + bool dmabuf = import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; uint64_t size; - if(!device->pscreen->import_memory_fd(device->pscreen, import_info->fd, &mem->pmem, &size, false)) { + if(!device->pscreen->import_memory_fd(device->pscreen, import_info->fd, (struct pipe_memory_allocation**)&mem->alloc, &size, dmabuf)) { close(import_info->fd); error = VK_ERROR_INVALID_EXTERNAL_HANDLE; goto fail; } if(size < pAllocateInfo->allocationSize) { - device->pscreen->free_memory_fd(device->pscreen, mem->pmem); + device->pscreen->free_memory_fd(device->pscreen, (struct pipe_memory_allocation*)mem->alloc); close(import_info->fd); goto fail; } - if (export_info && export_info->handleTypes) { + if (export_info && export_info->handleTypes == import_info->handleType) { mem->backed_fd = import_info->fd; } else { close(import_info->fd); } - mem->memory_type = LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD; + + mem->size = size; + mem->pmem = mem->alloc->data; + mem->memory_type = dmabuf ? LVP_DEVICE_MEMORY_TYPE_DMA_BUF : LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD; } else if (export_info && export_info->handleTypes) { - mem->pmem = device->pscreen->allocate_memory_fd(device->pscreen, pAllocateInfo->allocationSize, &mem->backed_fd, false); - if (!mem->pmem || mem->backed_fd < 0) { - goto fail; + bool dmabuf = export_info->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + mem->alloc = (struct llvmpipe_memory_fd_alloc*)device->pscreen->allocate_memory_fd(device->pscreen, pAllocateInfo->allocationSize, &mem->backed_fd, dmabuf); + if (!mem->alloc || mem->backed_fd < 0) { + goto fail; } - mem->memory_type = LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD; + + mem->pmem = mem->alloc->data; + mem->memory_type = dmabuf ? LVP_DEVICE_MEMORY_TYPE_DMA_BUF : LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD; } #endif else { @@ -1853,8 +1861,9 @@ VKAPI_ATTR void VKAPI_CALL lvp_FreeMemory( device->pscreen->free_memory(device->pscreen, mem->pmem); break; #ifdef PIPE_MEMORY_FD + case LVP_DEVICE_MEMORY_TYPE_DMA_BUF: case LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD: - device->pscreen->free_memory_fd(device->pscreen, mem->pmem); + device->pscreen->free_memory_fd(device->pscreen, (struct pipe_memory_allocation*)mem->alloc); if(mem->backed_fd >= 0) close(mem->backed_fd); break; @@ -2207,7 +2216,7 @@ lvp_GetMemoryFdPropertiesKHR(VkDevice _device, assert(pMemoryFdProperties->sType == VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR); - if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) { + if (assert_memhandle_type(handleType)) { // There is only one memoryType so select this one pMemoryFdProperties->memoryTypeBits = 1; } diff --git a/src/gallium/frontends/lavapipe/lvp_formats.c b/src/gallium/frontends/lavapipe/lvp_formats.c index a22ef4b68aed8..47ccc8a9284d8 100644 --- a/src/gallium/frontends/lavapipe/lvp_formats.c +++ b/src/gallium/frontends/lavapipe/lvp_formats.c @@ -443,6 +443,18 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_GetPhysicalDeviceImageFormatProperties2( VkExternalMemoryHandleTypeFlags compat_flags = 0; switch (external_info->handleType) { +#ifdef HAVE_LIBDRM + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: { + int params = physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_DMABUF); + flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + if (params & DRM_PRIME_CAP_EXPORT) + flags |= VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + + export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + break; + } +#endif #ifdef PIPE_MEMORY_FD case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; @@ -501,6 +513,19 @@ VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalBufferProperties( VkExternalMemoryHandleTypeFlags export_flags = 0; VkExternalMemoryHandleTypeFlags compat_flags = 0; switch (pExternalBufferInfo->handleType) { +#ifdef HAVE_LIBDRM + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: { + LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice); + int params = physical_device->pscreen->get_param(physical_device->pscreen, PIPE_CAP_DMABUF); + flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; + if (params & DRM_PRIME_CAP_EXPORT) + flags |= VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; + + export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + break; + } +#endif #ifdef PIPE_MEMORY_FD case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: flags = VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT; diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h index 16751ab1cd86f..6e440d2f47ef0 100644 --- a/src/gallium/frontends/lavapipe/lvp_private.h +++ b/src/gallium/frontends/lavapipe/lvp_private.h @@ -216,6 +216,7 @@ enum lvp_device_memory_type { LVP_DEVICE_MEMORY_TYPE_DEFAULT, LVP_DEVICE_MEMORY_TYPE_USER_PTR, LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD, + LVP_DEVICE_MEMORY_TYPE_DMA_BUF, }; struct lvp_device_memory { @@ -227,6 +228,9 @@ struct lvp_device_memory { void * map; enum lvp_device_memory_type memory_type; int backed_fd; +#ifdef PIPE_MEMORY_FD + struct llvmpipe_memory_fd_alloc *alloc; +#endif }; struct lvp_pipe_sync { @@ -706,6 +710,10 @@ static inline uint8_t lvp_image_aspects_to_plane(ASSERTED const struct lvp_image *image, VkImageAspectFlags aspectMask) { + /* If we are requesting the first plane of image with only one plane, return that */ + if (image->vk.aspects == VK_IMAGE_ASPECT_COLOR_BIT && aspectMask == VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT) + return 0; + /* Verify that the aspects are actually in the image */ assert(!(aspectMask & ~image->vk.aspects));