anv: Implement VK_EXT_external_memory_host
v2: Ignore the import if handleType == 0. (Jason) Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
This commit is contained in:
parent
5c655c47db
commit
69cc6272fb
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue