Ported from the radeonsi GL_AMD_pinned_memory implementation.

Signed-off-by: Fredrik Höglund <fred...@kde.org>
---

Tested using a version of the cube demo modified to use host memory
allocations for buffers and staging images.

 src/amd/vulkan/radv_device.c                  | 60 ++++++++++++++++++++++++++-
 src/amd/vulkan/radv_extensions.py             |  1 +
 src/amd/vulkan/radv_formats.c                 | 30 +++++++++++---
 src/amd/vulkan/radv_private.h                 |  1 +
 src/amd/vulkan/radv_radeon_winsys.h           |  4 ++
 src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c | 49 ++++++++++++++++++++++
 6 files changed, 137 insertions(+), 8 deletions(-)

diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index 9fda419d584..09bb382eeb8 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -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(
diff --git a/src/amd/vulkan/radv_extensions.py 
b/src/amd/vulkan/radv_extensions.py
index e6c6e636277..d761895d3a0 100644
--- a/src/amd/vulkan/radv_extensions.py
+++ b/src/amd/vulkan/radv_extensions.py
@@ -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'),
diff --git a/src/amd/vulkan/radv_formats.c b/src/amd/vulkan/radv_formats.c
index 19cd2b1a916..a150f8c64f8 100644
--- a/src/amd/vulkan/radv_formats.c
+++ b/src/amd/vulkan/radv_formats.c
@@ -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;
        }
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 42f23a3cd66..be9e8f43964 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -646,6 +646,7 @@ struct radv_device_memory {
        uint32_t                                     type_index;
        VkDeviceSize                                 map_size;
        void *                                       map;
+       void *                                       user_ptr;
 };
 
 
diff --git a/src/amd/vulkan/radv_radeon_winsys.h 
b/src/amd/vulkan/radv_radeon_winsys.h
index 341e40505ca..4c306692e55 100644
--- a/src/amd/vulkan/radv_radeon_winsys.h
+++ b/src/amd/vulkan/radv_radeon_winsys.h
@@ -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);
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c 
b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
index 603111d2ebc..9e83390568a 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
@@ -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;
-- 
2.15.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to