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 <luoyonggang@gmail.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15857>
This commit is contained in:
Mike Blumenkrantz
2022-04-11 11:04:45 -04:00
committed by Marge Bot
parent 0c0ff57c61
commit c3ad1331be

View File

@@ -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;
}