From 5a38d8f1036b949e442359f691956b48b32b0e30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Thu, 25 Jan 2018 18:12:14 +0100 Subject: [PATCH] radv: implement VK_EXT_external_memory_host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ported from the radeonsi GL_AMD_pinned_memory implementation. Signed-off-by: Fredrik Höglund Reviewed-by: Bas Nieuwenhuizen --- 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;