From 34c8621c3b372f8cd2ae2a684ac21460129d5bfb Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 17 Jan 2020 23:52:50 -0600 Subject: [PATCH] anv: Allow enumerating multiple physical devices Instead of having a single physical device in anv_instance, have a linked list of them. What we have now works today because we our GPUs are build into the CPU and so you're guaranteed to only ever have one of them. One day, that will change and we want ANV to be ready. Reviewed-by: Lionel Landwerlin Tested-by: Marge Bot Part-of: --- src/intel/vulkan/anv_device.c | 140 ++++++++++++++++----------------- src/intel/vulkan/anv_private.h | 7 +- 2 files changed, 75 insertions(+), 72 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 509f92a5034..50b0a01debf 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -329,9 +329,9 @@ get_available_system_memory() } static VkResult -anv_physical_device_init(struct anv_physical_device *device, - struct anv_instance *instance, - drmDevicePtr drm_device) +anv_physical_device_try_create(struct anv_instance *instance, + drmDevicePtr drm_device, + struct anv_physical_device **device_out) { const char *primary_path = drm_device->nodes[DRM_NODE_PRIMARY]; const char *path = drm_device->nodes[DRM_NODE_RENDER]; @@ -348,7 +348,7 @@ anv_physical_device_init(struct anv_physical_device *device, struct gen_device_info devinfo; if (!gen_get_device_info_from_fd(fd, &devinfo)) { result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER); - goto fail; + goto fail_fd; } const char *device_name = gen_get_device_name(devinfo.chipset_id); @@ -366,7 +366,15 @@ anv_physical_device_init(struct anv_physical_device *device, } else { result = vk_errorfi(instance, NULL, VK_ERROR_INCOMPATIBLE_DRIVER, "Vulkan not yet supported on %s", device_name); - goto fail; + goto fail_fd; + } + + struct anv_physical_device *device = + vk_alloc(&instance->alloc, sizeof(*device), 8, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (device == NULL) { + result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + goto fail_fd; } device->_loader_data.loaderMagic = ICD_LOADER_MAGIC; @@ -395,7 +403,7 @@ anv_physical_device_init(struct anv_physical_device *device, result = vk_errorfi(device->instance, NULL, VK_ERROR_INITIALIZATION_FAILED, "failed to get command parser version"); - goto fail; + goto fail_alloc; } } @@ -403,14 +411,14 @@ anv_physical_device_init(struct anv_physical_device *device, result = vk_errorfi(device->instance, NULL, VK_ERROR_INITIALIZATION_FAILED, "kernel missing gem wait"); - goto fail; + goto fail_alloc; } if (!anv_gem_get_param(fd, I915_PARAM_HAS_EXECBUF2)) { result = vk_errorfi(device->instance, NULL, VK_ERROR_INITIALIZATION_FAILED, "kernel missing execbuf2"); - goto fail; + goto fail_alloc; } if (!device->info.has_llc && @@ -418,7 +426,7 @@ anv_physical_device_init(struct anv_physical_device *device, result = vk_errorfi(device->instance, NULL, VK_ERROR_INITIALIZATION_FAILED, "kernel missing wc mmap"); - goto fail; + goto fail_alloc; } device->has_softpin = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_SOFTPIN); @@ -432,7 +440,7 @@ anv_physical_device_init(struct anv_physical_device *device, result = anv_physical_device_init_heaps(device, fd); if (result != VK_SUCCESS) - goto fail; + goto fail_alloc; device->use_softpin = device->has_softpin && device->supports_48bit_addresses; @@ -510,7 +518,7 @@ anv_physical_device_init(struct anv_physical_device *device, device->compiler = brw_compiler_create(NULL, &device->info); if (device->compiler == NULL) { result = vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); - goto fail; + goto fail_alloc; } device->compiler->shader_debug_log = compiler_debug_log; device->compiler->shader_perf_log = compiler_perf_log; @@ -538,7 +546,7 @@ anv_physical_device_init(struct anv_physical_device *device, result = anv_physical_device_init_uuids(device); if (result != VK_SUCCESS) - goto fail; + goto fail_compiler; anv_physical_device_init_disk_cache(device); @@ -557,11 +565,8 @@ anv_physical_device_init(struct anv_physical_device *device, device->master_fd = master_fd; result = anv_init_wsi(device); - if (result != VK_SUCCESS) { - ralloc_free(device->compiler); - anv_physical_device_free_disk_cache(device); - goto fail; - } + if (result != VK_SUCCESS) + goto fail_disk_cache; device->perf = anv_get_perf(&device->info, fd); @@ -571,9 +576,17 @@ anv_physical_device_init(struct anv_physical_device *device, device->local_fd = fd; + *device_out = device; + return VK_SUCCESS; -fail: +fail_disk_cache: + anv_physical_device_free_disk_cache(device); +fail_compiler: + ralloc_free(device->compiler); +fail_alloc: + vk_free(&instance->alloc, device); +fail_fd: close(fd); if (master_fd != -1) close(master_fd); @@ -581,7 +594,7 @@ fail: } static void -anv_physical_device_finish(struct anv_physical_device *device) +anv_physical_device_destroy(struct anv_physical_device *device) { anv_finish_wsi(device); anv_physical_device_free_disk_cache(device); @@ -590,6 +603,7 @@ anv_physical_device_finish(struct anv_physical_device *device) close(device->local_fd); if (device->master_fd >= 0) close(device->master_fd); + vk_free(&device->instance->alloc, device); } static void * @@ -738,7 +752,8 @@ VkResult anv_CreateInstance( } } - instance->physicalDeviceCount = -1; + instance->physical_devices_enumerated = false; + list_inithead(&instance->physical_devices); result = vk_debug_report_instance_init(&instance->debug_report_callbacks); if (result != VK_SUCCESS) { @@ -773,11 +788,9 @@ void anv_DestroyInstance( if (!instance) return; - if (instance->physicalDeviceCount > 0) { - /* We support at most one physical device. */ - assert(instance->physicalDeviceCount == 1); - anv_physical_device_finish(&instance->physicalDevice); - } + list_for_each_entry_safe(struct anv_physical_device, pdevice, + &instance->physical_devices, link) + anv_physical_device_destroy(pdevice); vk_free(&instance->alloc, (char *)instance->app_info.app_name); vk_free(&instance->alloc, (char *)instance->app_info.engine_name); @@ -795,15 +808,18 @@ void anv_DestroyInstance( } static VkResult -anv_enumerate_devices(struct anv_instance *instance) +anv_enumerate_physical_devices(struct anv_instance *instance) { + if (instance->physical_devices_enumerated) + return VK_SUCCESS; + + instance->physical_devices_enumerated = true; + /* TODO: Check for more devices ? */ drmDevicePtr devices[8]; VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER; int max_devices; - instance->physicalDeviceCount = 0; - max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); if (max_devices < 1) return VK_ERROR_INCOMPATIBLE_DRIVER; @@ -813,31 +829,19 @@ anv_enumerate_devices(struct anv_instance *instance) devices[i]->bustype == DRM_BUS_PCI && devices[i]->deviceinfo.pci->vendor_id == 0x8086) { - result = anv_physical_device_init(&instance->physicalDevice, - instance, devices[i]); - if (result != VK_ERROR_INCOMPATIBLE_DRIVER) - break; + struct anv_physical_device *pdevice; + result = anv_physical_device_try_create(instance, devices[i], + &pdevice); + if (result != VK_SUCCESS) + continue; + + list_addtail(&pdevice->link, &instance->physical_devices); } } drmFreeDevices(devices, max_devices); - if (result == VK_SUCCESS) - instance->physicalDeviceCount = 1; - - return result; -} - -static VkResult -anv_instance_ensure_physical_device(struct anv_instance *instance) -{ - if (instance->physicalDeviceCount < 0) { - VkResult result = anv_enumerate_devices(instance); - if (result != VK_SUCCESS && - result != VK_ERROR_INCOMPATIBLE_DRIVER) - return result; - } - - return VK_SUCCESS; + /* If we successfully enumerated any devices, call it success */ + return !list_is_empty(&instance->physical_devices) ? VK_SUCCESS : result; } VkResult anv_EnumeratePhysicalDevices( @@ -848,16 +852,15 @@ VkResult anv_EnumeratePhysicalDevices( ANV_FROM_HANDLE(anv_instance, instance, _instance); VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount); - VkResult result = anv_instance_ensure_physical_device(instance); + VkResult result = anv_enumerate_physical_devices(instance); if (result != VK_SUCCESS) return result; - if (instance->physicalDeviceCount == 0) - return VK_SUCCESS; - - assert(instance->physicalDeviceCount == 1); - vk_outarray_append(&out, i) { - *i = anv_physical_device_to_handle(&instance->physicalDevice); + list_for_each_entry(struct anv_physical_device, pdevice, + &instance->physical_devices, link) { + vk_outarray_append(&out, i) { + *i = anv_physical_device_to_handle(pdevice); + } } return vk_outarray_status(&out); @@ -872,24 +875,21 @@ VkResult anv_EnumeratePhysicalDeviceGroups( VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties, pPhysicalDeviceGroupCount); - VkResult result = anv_instance_ensure_physical_device(instance); + VkResult result = anv_enumerate_physical_devices(instance); if (result != VK_SUCCESS) return result; - if (instance->physicalDeviceCount == 0) - return VK_SUCCESS; + list_for_each_entry(struct anv_physical_device, pdevice, + &instance->physical_devices, link) { + vk_outarray_append(&out, p) { + p->physicalDeviceCount = 1; + memset(p->physicalDevices, 0, sizeof(p->physicalDevices)); + p->physicalDevices[0] = anv_physical_device_to_handle(pdevice); + p->subsetAllocation = false; - assert(instance->physicalDeviceCount == 1); - - vk_outarray_append(&out, p) { - p->physicalDeviceCount = 1; - memset(p->physicalDevices, 0, sizeof(p->physicalDevices)); - p->physicalDevices[0] = - anv_physical_device_to_handle(&instance->physicalDevice); - p->subsetAllocation = false; - - vk_foreach_struct(ext, p->pNext) - anv_debug_ignored_stype(ext->sType); + vk_foreach_struct(ext, p->pNext) + anv_debug_ignored_stype(ext->sType); + } } return vk_outarray_status(&out); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index c083f0b30ff..7c22a354ffd 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -965,6 +965,9 @@ struct anv_memory_heap { struct anv_physical_device { VK_LOADER_DATA _loader_data; + /* Link in anv_instance::physical_devices */ + struct list_head link; + struct anv_instance * instance; bool no_hw; char path[20]; @@ -1056,8 +1059,8 @@ struct anv_instance { struct anv_physical_device_dispatch_table physical_device_dispatch; struct anv_device_dispatch_table device_dispatch; - int physicalDeviceCount; - struct anv_physical_device physicalDevice; + bool physical_devices_enumerated; + struct list_head physical_devices; bool pipeline_cache_enabled;