From 69cc6272fbc1991d83b9e739acf5d464e8e905c6 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Fri, 1 Mar 2019 13:15:31 -0800 Subject: [PATCH] anv: Implement VK_EXT_external_memory_host v2: Ignore the import if handleType == 0. (Jason) Reviewed-by: Lionel Landwerlin Reviewed-by: Jason Ekstrand --- src/intel/vulkan/anv_allocator.c | 60 +++++++++++++++++++++++++++ src/intel/vulkan/anv_device.c | 66 +++++++++++++++++++++++++++++- src/intel/vulkan/anv_extensions.py | 1 + src/intel/vulkan/anv_private.h | 7 ++++ 4 files changed, 133 insertions(+), 1 deletion(-) diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index 6ed5634002c..dd967165bbb 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -1711,6 +1711,66 @@ anv_bo_cache_alloc(struct anv_device *device, return VK_SUCCESS; } +VkResult +anv_bo_cache_import_host_ptr(struct anv_device *device, + struct anv_bo_cache *cache, + void *host_ptr, uint32_t size, + uint64_t bo_flags, struct anv_bo **bo_out) +{ + assert(bo_flags == (bo_flags & ANV_BO_CACHE_SUPPORTED_FLAGS)); + assert((bo_flags & ANV_BO_EXTERNAL) == 0); + + uint32_t gem_handle = anv_gem_userptr(device, host_ptr, size); + if (!gem_handle) + return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE); + + pthread_mutex_lock(&cache->mutex); + + struct anv_cached_bo *bo = anv_bo_cache_lookup_locked(cache, gem_handle); + if (bo) { + /* VK_EXT_external_memory_host doesn't require handling importing the + * same pointer twice at the same time, but we don't get in the way. If + * kernel gives us the same gem_handle, only succeed if the flags match. + */ + if (bo_flags != bo->bo.flags) { + pthread_mutex_unlock(&cache->mutex); + return vk_errorf(device->instance, NULL, + VK_ERROR_INVALID_EXTERNAL_HANDLE, + "same host pointer imported two different ways"); + } + __sync_fetch_and_add(&bo->refcount, 1); + } else { + bo = vk_alloc(&device->alloc, sizeof(struct anv_cached_bo), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (!bo) { + anv_gem_close(device, gem_handle); + pthread_mutex_unlock(&cache->mutex); + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + } + + bo->refcount = 1; + + anv_bo_init(&bo->bo, gem_handle, size); + bo->bo.flags = bo_flags; + + if (!anv_vma_alloc(device, &bo->bo)) { + anv_gem_close(device, bo->bo.gem_handle); + pthread_mutex_unlock(&cache->mutex); + vk_free(&device->alloc, bo); + return vk_errorf(device->instance, NULL, + VK_ERROR_OUT_OF_DEVICE_MEMORY, + "failed to allocate virtual address for BO"); + } + + _mesa_hash_table_insert(cache->bo_map, (void *)(uintptr_t)gem_handle, bo); + } + + pthread_mutex_unlock(&cache->mutex); + *bo_out = &bo->bo; + + return VK_SUCCESS; +} + VkResult anv_bo_cache_import(struct anv_device *device, struct anv_bo_cache *cache, diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 7beb70f9e6b..aee795cbdbb 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -1238,6 +1238,14 @@ void anv_GetPhysicalDeviceProperties2( break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: { + VkPhysicalDeviceExternalMemoryHostPropertiesEXT *props = + (VkPhysicalDeviceExternalMemoryHostPropertiesEXT *) ext; + /* Userptr needs page aligned memory. */ + props->minImportedHostPointerAlignment = 4096; + break; + } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: { VkPhysicalDeviceIDProperties *id_props = (VkPhysicalDeviceIDProperties *)ext; @@ -2463,6 +2471,7 @@ VkResult anv_AllocateMemory( mem->map = NULL; mem->map_size = 0; mem->ahw = NULL; + mem->host_ptr = NULL; uint64_t bo_flags = 0; @@ -2575,6 +2584,30 @@ VkResult anv_AllocateMemory( goto success; } + const VkImportMemoryHostPointerInfoEXT *host_ptr_info = + vk_find_struct_const(pAllocateInfo->pNext, + IMPORT_MEMORY_HOST_POINTER_INFO_EXT); + if (host_ptr_info && host_ptr_info->handleType) { + if (host_ptr_info->handleType == + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT) { + result = vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE); + goto fail; + } + + assert(host_ptr_info->handleType == + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT); + + result = anv_bo_cache_import_host_ptr( + device, &device->bo_cache, host_ptr_info->pHostPointer, + pAllocateInfo->allocationSize, bo_flags, &mem->bo); + + if (result != VK_SUCCESS) + goto fail; + + mem->host_ptr = host_ptr_info->pHostPointer; + goto success; + } + /* Regular allocate (not importing memory). */ if (export_info && export_info->handleTypes) @@ -2664,6 +2697,32 @@ VkResult anv_GetMemoryFdPropertiesKHR( } } +VkResult anv_GetMemoryHostPointerPropertiesEXT( + VkDevice _device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHostPointer, + VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties) +{ + ANV_FROM_HANDLE(anv_device, device, _device); + + assert(pMemoryHostPointerProperties->sType == + VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT); + + switch (handleType) { + case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: { + struct anv_physical_device *pdevice = &device->instance->physicalDevice; + + /* Host memory can be imported as any memory type. */ + pMemoryHostPointerProperties->memoryTypeBits = + (1ull << pdevice->memory.type_count) - 1; + + return VK_SUCCESS; + } + default: + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } +} + void anv_FreeMemory( VkDevice _device, VkDeviceMemory _mem, @@ -2704,6 +2763,11 @@ VkResult anv_MapMemory( return VK_SUCCESS; } + if (mem->host_ptr) { + *ppData = mem->host_ptr + offset; + return VK_SUCCESS; + } + if (size == VK_WHOLE_SIZE) size = mem->bo->size - offset; @@ -2756,7 +2820,7 @@ void anv_UnmapMemory( { ANV_FROM_HANDLE(anv_device_memory, mem, _memory); - if (mem == NULL) + if (mem == NULL || mem->host_ptr) return; anv_gem_munmap(mem->map, mem->map_size); diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index 34500e65e4d..6fff293dee4 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -123,6 +123,7 @@ EXTENSIONS = [ Extension('VK_EXT_display_control', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), Extension('VK_EXT_display_surface_counter', 1, 'VK_USE_PLATFORM_DISPLAY_KHR'), Extension('VK_EXT_external_memory_dma_buf', 1, True), + Extension('VK_EXT_external_memory_host', 1, True), Extension('VK_EXT_global_priority', 1, 'device->has_context_priority'), Extension('VK_EXT_inline_uniform_block', 1, True), diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 782122b378c..d7934f81d75 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -871,6 +871,10 @@ VkResult anv_bo_cache_alloc(struct anv_device *device, struct anv_bo_cache *cache, uint64_t size, uint64_t bo_flags, struct anv_bo **bo); +VkResult anv_bo_cache_import_host_ptr(struct anv_device *device, + struct anv_bo_cache *cache, + void *host_ptr, uint32_t size, + uint64_t bo_flags, struct anv_bo **bo_out); VkResult anv_bo_cache_import(struct anv_device *device, struct anv_bo_cache *cache, int fd, uint64_t bo_flags, @@ -1488,6 +1492,9 @@ struct anv_device_memory { * which we must release when memory is freed. */ struct AHardwareBuffer * ahw; + + /* If set, this memory comes from a host pointer. */ + void * host_ptr; }; /** -- 2.30.2