[Mesa-dev] [PATCH] radv: implement VK_EXT_external_memory_host
Fredrik Höglund
fredrik at kde.org
Fri Feb 2 23:47:15 UTC 2018
Ported from the radeonsi GL_AMD_pinned_memory implementation.
Signed-off-by: Fredrik Höglund <fredrik at 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
More information about the mesa-dev
mailing list