radv: implement VK_EXT_external_memory_host
authorFredrik Höglund <fredrik@kde.org>
Thu, 25 Jan 2018 17:12:14 +0000 (18:12 +0100)
committerFredrik Höglund <fredrik@kde.org>
Wed, 7 Feb 2018 23:46:07 +0000 (00:46 +0100)
Ported from the radeonsi GL_AMD_pinned_memory implementation.

Signed-off-by: Fredrik Höglund <fredrik@kde.org>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_extensions.py
src/amd/vulkan/radv_formats.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_radeon_winsys.h
src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c

index 9fda419d5849816a59c627b6b196cff3ff410b7e..09bb382eeb8783faaa872be83bc9b91d58d24aac 100644 (file)
@@ -810,6 +810,12 @@ void radv_GetPhysicalDeviceProperties2KHR(
                        properties->maxDiscardRectangles = MAX_DISCARD_RECTANGLES;
                        break;
                }
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: {
+                       VkPhysicalDeviceExternalMemoryHostPropertiesEXT *properties =
+                           (VkPhysicalDeviceExternalMemoryHostPropertiesEXT *) ext;
+                       properties->minImportedHostPointerAlignment = 4096;
+                       break;
+               }
                default:
                        break;
                }
@@ -923,6 +929,33 @@ void radv_GetPhysicalDeviceMemoryProperties2KHR(
                                                      &pMemoryProperties->memoryProperties);
 }
 
+VkResult radv_GetMemoryHostPointerPropertiesEXT(
+       VkDevice                                    _device,
+       VkExternalMemoryHandleTypeFlagBitsKHR       handleType,
+       const void                                 *pHostPointer,
+       VkMemoryHostPointerPropertiesEXT           *pMemoryHostPointerProperties)
+{
+       RADV_FROM_HANDLE(radv_device, device, _device);
+
+       switch (handleType)
+       {
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: {
+               const struct radv_physical_device *physical_device = device->physical_device;
+               uint32_t memoryTypeBits = 0;
+               for (int i = 0; i < physical_device->memory_properties.memoryTypeCount; i++) {
+                       if (physical_device->mem_type_indices[i] == RADV_MEM_TYPE_GTT_CACHED) {
+                               memoryTypeBits = (1 << i);
+                               break;
+                       }
+               }
+               pMemoryHostPointerProperties->memoryTypeBits = memoryTypeBits;
+               return VK_SUCCESS;
+       }
+       default:
+               return VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+       }
+}
+
 static enum radeon_ctx_priority
 radv_get_queue_global_priority(const VkDeviceQueueGlobalPriorityCreateInfoEXT *pObj)
 {
@@ -2246,6 +2279,8 @@ static VkResult radv_alloc_memory(struct radv_device *device,
                vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO_KHR);
        const VkExportMemoryAllocateInfoKHR *export_info =
                vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO_KHR);
+       const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
+               vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
 
        const struct wsi_memory_allocate_info *wsi_info =
                vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
@@ -2266,6 +2301,8 @@ static VkResult radv_alloc_memory(struct radv_device *device,
                mem->buffer = NULL;
        }
 
+       mem->user_ptr = NULL;
+
        if (import_info) {
                assert(import_info->handleType ==
                       VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR ||
@@ -2282,6 +2319,20 @@ static VkResult radv_alloc_memory(struct radv_device *device,
                }
        }
 
+       if (host_ptr_info) {
+               assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
+               assert(mem_type_index == RADV_MEM_TYPE_GTT_CACHED);
+               mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer,
+                                                     pAllocateInfo->allocationSize);
+               if (!mem->bo) {
+                       result = VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR;
+                       goto fail;
+               } else {
+                       mem->user_ptr = host_ptr_info->pHostPointer;
+                       goto out_success;
+               }
+       }
+
        uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
        if (mem_type_index == RADV_MEM_TYPE_GTT_WRITE_COMBINE ||
            mem_type_index == RADV_MEM_TYPE_GTT_CACHED)
@@ -2362,7 +2413,11 @@ VkResult radv_MapMemory(
                return VK_SUCCESS;
        }
 
-       *ppData = device->ws->buffer_map(mem->bo);
+       if (mem->user_ptr)
+               *ppData = mem->user_ptr;
+       else
+               *ppData = device->ws->buffer_map(mem->bo);
+
        if (*ppData) {
                *ppData += offset;
                return VK_SUCCESS;
@@ -2381,7 +2436,8 @@ void radv_UnmapMemory(
        if (mem == NULL)
                return;
 
-       device->ws->buffer_unmap(mem->bo);
+       if (mem->user_ptr == NULL)
+               device->ws->buffer_unmap(mem->bo);
 }
 
 VkResult radv_FlushMappedMemoryRanges(
index e6c6e636277f845a1f80906756a751c2c20a0f1c..d761895d3a09a41a19302e8a50e17fab8a4a3113 100644 (file)
@@ -85,6 +85,7 @@ EXTENSIONS = [
     Extension('VK_EXT_debug_report',                      9, True),
     Extension('VK_EXT_discard_rectangles',                1, True),
     Extension('VK_EXT_external_memory_dma_buf',           1, True),
+    Extension('VK_EXT_external_memory_host',              1, 'device->rad_info.has_userptr'),
     Extension('VK_EXT_global_priority',                   1, 'device->rad_info.has_ctx_priority'),
     Extension('VK_AMD_draw_indirect_count',               1, True),
     Extension('VK_AMD_rasterization_order',               1, 'device->rad_info.chip_class >= VI && device->rad_info.max_se >= 2'),
index 19cd2b1a9161ec35d133f5ac55d45f5786a1cc3f..a150f8c64f82b661e810947f56f701616b4ac15c 100644 (file)
@@ -1177,16 +1177,28 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties(
 
 static void
 get_external_image_format_properties(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
+                                    VkExternalMemoryHandleTypeFlagBitsKHR handleType,
                                     VkExternalMemoryPropertiesKHR *external_properties)
 {
        VkExternalMemoryFeatureFlagBitsKHR flags = 0;
        VkExternalMemoryHandleTypeFlagsKHR export_flags = 0;
        VkExternalMemoryHandleTypeFlagsKHR compat_flags = 0;
-       switch (pImageFormatInfo->type) {
-       case VK_IMAGE_TYPE_2D:
-               flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
-               compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
-                                             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+       switch (handleType) {
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
+               switch (pImageFormatInfo->type) {
+               case VK_IMAGE_TYPE_2D:
+                       flags = VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_KHR|VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
+                       compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
+                                                     VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+               flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
+               compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
                break;
        default:
                break;
@@ -1246,7 +1258,9 @@ VkResult radv_GetPhysicalDeviceImageFormatProperties2KHR(
                switch (external_info->handleType) {
                case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
                case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
-                       get_external_image_format_properties(base_info, &external_props->externalMemoryProperties);
+               case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+                       get_external_image_format_properties(base_info, external_info->handleType,
+                                                            &external_props->externalMemoryProperties);
                        break;
                default:
                        /* From the Vulkan 1.0.42 spec:
@@ -1320,6 +1334,10 @@ void radv_GetPhysicalDeviceExternalBufferPropertiesKHR(
                compat_flags = export_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR |
                                              VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
                break;
+       case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT:
+               flags = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_KHR;
+               compat_flags = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT;
+               break;
        default:
                break;
        }
index 42f23a3cd66e0a00c3239a0666605593af62b2ce..be9e8f4396455628f62282f35b67d099e0209dd0 100644 (file)
@@ -646,6 +646,7 @@ struct radv_device_memory {
        uint32_t                                     type_index;
        VkDeviceSize                                 map_size;
        void *                                       map;
+       void *                                       user_ptr;
 };
 
 
index 341e40505ca4a0284397ddfe59b7bae7458b8bfc..4c306692e5594ede4a1809ddab3868633a325cd0 100644 (file)
@@ -200,6 +200,10 @@ struct radeon_winsys {
        void (*buffer_destroy)(struct radeon_winsys_bo *bo);
        void *(*buffer_map)(struct radeon_winsys_bo *bo);
 
+       struct radeon_winsys_bo *(*buffer_from_ptr)(struct radeon_winsys *ws,
+                                                   void *pointer,
+                                                   uint64_t size);
+
        struct radeon_winsys_bo *(*buffer_from_fd)(struct radeon_winsys *ws,
                                                   int fd,
                                                   unsigned *stride, unsigned *offset);
index 603111d2ebc03154d7526c9b84ac6f3dfb51db1f..9e83390568ac6a5e82deaa694e1503614351e400 100644 (file)
@@ -402,6 +402,54 @@ radv_amdgpu_winsys_bo_unmap(struct radeon_winsys_bo *_bo)
        amdgpu_bo_cpu_unmap(bo->bo);
 }
 
+static struct radeon_winsys_bo *
+radv_amdgpu_winsys_bo_from_ptr(struct radeon_winsys *_ws,
+                               void *pointer,
+                               uint64_t size)
+{
+       struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
+       amdgpu_bo_handle buf_handle;
+       struct radv_amdgpu_winsys_bo *bo;
+       uint64_t va;
+       amdgpu_va_handle va_handle;
+
+       bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo);
+       if (!bo)
+               return NULL;
+
+       if (amdgpu_create_bo_from_user_mem(ws->dev, pointer, size, &buf_handle))
+               goto error;
+
+       if (amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
+                                 size, 1 << 12, 0, &va, &va_handle, 0))
+               goto error_va_alloc;
+
+       if (amdgpu_bo_va_op(buf_handle, 0, size, va, 0, AMDGPU_VA_OP_MAP))
+               goto error_va_map;
+
+       /* Initialize it */
+       bo->base.va = va;
+       bo->va_handle = va_handle;
+       bo->size = size;
+       bo->ref_count = 1;
+       bo->ws = ws;
+       bo->bo = buf_handle;
+       bo->initial_domain = RADEON_DOMAIN_GTT;
+
+       radv_amdgpu_add_buffer_to_global_list(bo);
+       return (struct radeon_winsys_bo *)bo;
+
+error_va_map:
+       amdgpu_va_range_free(va_handle);
+
+error_va_alloc:
+       amdgpu_bo_free(buf_handle);
+
+error:
+       FREE(bo);
+       return NULL;
+}
+
 static struct radeon_winsys_bo *
 radv_amdgpu_winsys_bo_from_fd(struct radeon_winsys *_ws,
                              int fd, unsigned *stride,
@@ -540,6 +588,7 @@ void radv_amdgpu_bo_init_functions(struct radv_amdgpu_winsys *ws)
        ws->base.buffer_destroy = radv_amdgpu_winsys_bo_destroy;
        ws->base.buffer_map = radv_amdgpu_winsys_bo_map;
        ws->base.buffer_unmap = radv_amdgpu_winsys_bo_unmap;
+       ws->base.buffer_from_ptr = radv_amdgpu_winsys_bo_from_ptr;
        ws->base.buffer_from_fd = radv_amdgpu_winsys_bo_from_fd;
        ws->base.buffer_get_fd = radv_amdgpu_winsys_get_fd;
        ws->base.buffer_set_metadata = radv_amdgpu_winsys_bo_set_metadata;