From c3ad1331be6939aadb8365d995778f797c0db5ab Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 11 Apr 2022 11:04:45 -0400 Subject: [PATCH] zink: rework choose_pdev to (finally) be competent now zink will init using a priority system if multiple devices are available multiple devices will ONLY be available if: * the user does not specify VK_ICD_FILENAMES as they should * the user does not specify LIBGL_ALWAYS_SOFTWARE * multiple drivers exist I've prioritized the virtualized gpu here with the assumption that if such a thing is detected, the environment is most likely virtualized Reviewed-by: Yonggang Luo Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_screen.c | 56 ++++++++++++++++++-------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index ca7a6635ecb..04a58facf1c 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -1279,30 +1279,52 @@ choose_pdev(struct zink_screen *screen) assert(result == VK_SUCCESS); assert(pdev_count > 0); - VkPhysicalDeviceProperties *props = &screen->info.props; + VkPhysicalDeviceProperties props; bool cpu = debug_get_bool_option("LIBGL_ALWAYS_SOFTWARE", false); + /* priority when multiple drivers are available (highest to lowest): + VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU + VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU + VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU + VK_PHYSICAL_DEVICE_TYPE_CPU + VK_PHYSICAL_DEVICE_TYPE_OTHER + + * users should specify VK_ICD_FILENAMES since this is a standardized variable + * used by all vulkan applications + */ + unsigned prio_map[] = { + [VK_PHYSICAL_DEVICE_TYPE_OTHER] = 0, + [VK_PHYSICAL_DEVICE_TYPE_CPU] = 1, + [VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU] = 2, + [VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU] = 3, + [VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU] = 4, + }; + unsigned idx = 0; + int cur_prio = 0; for (i = 0; i < pdev_count; ++i) { - vkGetPhysicalDeviceProperties(pdevs[i], props); + vkGetPhysicalDeviceProperties(pdevs[i], &props); if (cpu) { - if (props->deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) { - screen->pdev = pdevs[i]; - screen->info.device_version = props->apiVersion; - is_cpu = true; + /* if user wants cpu, only give them cpu */ + if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) { + idx = i; + cur_prio = prio_map[props.deviceType]; break; } - continue; - } - - if (props->deviceType != VK_PHYSICAL_DEVICE_TYPE_CPU) { - screen->pdev = pdevs[i]; - screen->info.device_version = props->apiVersion; - break; + } else { + assert(props.deviceType <= VK_PHYSICAL_DEVICE_TYPE_CPU); + if (prio_map[props.deviceType] > cur_prio) { + idx = i; + cur_prio = prio_map[props.deviceType]; + } } } - free(pdevs); - if (cpu && !screen->pdev) - return true; + is_cpu = cur_prio == prio_map[VK_PHYSICAL_DEVICE_TYPE_CPU]; + if (cpu && !is_cpu) + goto out; + + screen->pdev = pdevs[idx]; + vkGetPhysicalDeviceProperties(screen->pdev, &screen->info.props); + screen->info.device_version = screen->info.props.apiVersion; /* runtime version is the lesser of the instance version and device version */ screen->vk_version = MIN2(screen->info.device_version, screen->instance_info.loader_version); @@ -1314,6 +1336,8 @@ choose_pdev(struct zink_screen *screen) screen->spirv_version = SPIRV_VERSION(1, 3); else screen->spirv_version = SPIRV_VERSION(1, 0); +out: + free(pdevs); return is_cpu; }