device_select: add shortcut for MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE

MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE=1 is useful but it's tedious
to type. This commit extends slightly DRI_PRIME/MESA_VK_DEVICE_SELECT
syntax support: if "!" is appended at the end then only the selected GPU
will be made visible to the application.

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24750>
This commit is contained in:
Pierre-Eric Pelloux-Prayer 2023-08-17 12:41:42 +02:00 committed by Marge Bot
parent b935ce0131
commit af27ecb089
2 changed files with 47 additions and 10 deletions

View file

@ -395,7 +395,10 @@ Core Mesa environment variables
- ``DRI_PRIME=N``: selects the Nth non-default GPU (N > 0). - ``DRI_PRIME=N``: selects the Nth non-default GPU (N > 0).
- ``DRI_PRIME=pci-0000_02_00_0``: selects the GPU connected to this PCIe bus - ``DRI_PRIME=pci-0000_02_00_0``: selects the GPU connected to this PCIe bus
- ``DRI_PRIME=vendor_id:device_id``: selects the first GPU matching these ids - ``DRI_PRIME=vendor_id:device_id``: selects the first GPU matching these ids.
For Vulkan it's possible to append ``!``, in which case only the selected GPU
will be exposed to the application (eg: DRI_PRIME=1!).
.. note:: .. note::
@ -801,6 +804,8 @@ Vulkan mesa device select layer environment variables
when set to "vid:did" number from PCI device. That PCI device is when set to "vid:did" number from PCI device. That PCI device is
selected as default. The default device is returned as the first selected as default. The default device is returned as the first
device in vkEnumeratePhysicalDevices API. device in vkEnumeratePhysicalDevices API.
Using "vid:did!" will have the same effect as using the
``MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE`` variable.
.. envvar:: MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE .. envvar:: MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE

View file

@ -284,6 +284,15 @@ static int device_select_find_dri_prime_tag_default(struct device_pci_info *pci_
const char *dri_prime) const char *dri_prime)
{ {
int default_idx = -1; int default_idx = -1;
/* Drop the trailing '!' if present. */
int ref = strlen("pci-xxxx_yy_zz_w");
int n = strlen(dri_prime);
if (n < ref)
return default_idx;
if (n == ref + 1 && dri_prime[n - 1] == '!')
n--;
for (unsigned i = 0; i < device_count; ++i) { for (unsigned i = 0; i < device_count; ++i) {
char *tag = NULL; char *tag = NULL;
if (asprintf(&tag, "pci-%04x_%02x_%02x_%1u", if (asprintf(&tag, "pci-%04x_%02x_%02x_%1u",
@ -291,7 +300,7 @@ static int device_select_find_dri_prime_tag_default(struct device_pci_info *pci_
pci_infos[i].bus_info.bus, pci_infos[i].bus_info.bus,
pci_infos[i].bus_info.dev, pci_infos[i].bus_info.dev,
pci_infos[i].bus_info.func) >= 0) { pci_infos[i].bus_info.func) >= 0) {
if (strcmp(dri_prime, tag) == 0) if (strncmp(dri_prime, tag, n) == 0)
default_idx = i; default_idx = i;
} }
free(tag); free(tag);
@ -419,10 +428,16 @@ static bool should_debug_device_selection() {
debug_get_bool_option("DRI_PRIME_DEBUG", false); debug_get_bool_option("DRI_PRIME_DEBUG", false);
} }
static bool ends_with_exclamation_mark(const char *str) {
size_t n = strlen(str);
return n > 1 && str[n - 1] == '!';
}
static uint32_t get_default_device(const struct instance_info *info, static uint32_t get_default_device(const struct instance_info *info,
const char *selection, const char *selection,
uint32_t physical_device_count, uint32_t physical_device_count,
VkPhysicalDevice *pPhysicalDevices) VkPhysicalDevice *pPhysicalDevices,
bool *expose_only_one_dev)
{ {
int default_idx = -1; int default_idx = -1;
const char *dri_prime = getenv("DRI_PRIME"); const char *dri_prime = getenv("DRI_PRIME");
@ -447,12 +462,18 @@ static uint32_t get_default_device(const struct instance_info *info,
if (selection) if (selection)
default_idx = device_select_find_explicit_default(pci_infos, physical_device_count, selection); default_idx = device_select_find_explicit_default(pci_infos, physical_device_count, selection);
if (default_idx != -1) {
*expose_only_one_dev = ends_with_exclamation_mark(selection);
}
if (default_idx == -1 && dri_prime && dri_prime_as_int == 0) { if (default_idx == -1 && dri_prime && dri_prime_as_int == 0) {
/* Try DRI_PRIME=vendor_id:device_id */ /* Try DRI_PRIME=vendor_id:device_id */
default_idx = device_select_find_explicit_default(pci_infos, physical_device_count, dri_prime); default_idx = device_select_find_explicit_default(pci_infos, physical_device_count, dri_prime);
if (debug && default_idx != -1) if (default_idx != -1) {
fprintf(stderr, "device-select: device_select_find_explicit_default selected %i\n", default_idx); if (debug)
fprintf(stderr, "device-select: device_select_find_explicit_default selected %i\n", default_idx);
*expose_only_one_dev = ends_with_exclamation_mark(dri_prime);
}
if (default_idx == -1) { if (default_idx == -1) {
/* Try DRI_PRIME=pci-xxxx_yy_zz_w */ /* Try DRI_PRIME=pci-xxxx_yy_zz_w */
@ -461,8 +482,11 @@ static uint32_t get_default_device(const struct instance_info *info,
else else
default_idx = device_select_find_dri_prime_tag_default(pci_infos, physical_device_count, dri_prime); default_idx = device_select_find_dri_prime_tag_default(pci_infos, physical_device_count, dri_prime);
if (debug && default_idx != -1) if (default_idx != -1) {
fprintf(stderr, "device-select: device_select_find_dri_prime_tag_default selected %i\n", default_idx); if (debug)
fprintf(stderr, "device-select: device_select_find_dri_prime_tag_default selected %i\n", default_idx);
*expose_only_one_dev = ends_with_exclamation_mark(dri_prime);
}
} }
} }
if (default_idx == -1 && info->has_wayland) { if (default_idx == -1 && info->has_wayland) {
@ -506,8 +530,11 @@ static uint32_t get_default_device(const struct instance_info *info,
if (dri_prime_as_int > 0 && physical_device_count > (cpu_count + 1)) { if (dri_prime_as_int > 0 && physical_device_count > (cpu_count + 1)) {
if (default_idx == 0 || default_idx == 1) { if (default_idx == 0 || default_idx == 1) {
default_idx = find_non_cpu_skip(pci_infos, physical_device_count, default_idx, dri_prime_as_int); default_idx = find_non_cpu_skip(pci_infos, physical_device_count, default_idx, dri_prime_as_int);
if (debug && default_idx != -1) if (default_idx != -1) {
fprintf(stderr, "device-select: find_non_cpu_skip selected %i\n", default_idx); if (debug)
fprintf(stderr, "device-select: find_non_cpu_skip selected %i\n", default_idx);
*expose_only_one_dev = ends_with_exclamation_mark(dri_prime);
}
} }
} }
free(pci_infos); free(pci_infos);
@ -522,6 +549,7 @@ static VkResult device_select_EnumeratePhysicalDevices(VkInstance instance,
uint32_t physical_device_count = 0; uint32_t physical_device_count = 0;
uint32_t selected_physical_device_count = 0; uint32_t selected_physical_device_count = 0;
const char* selection = getenv("MESA_VK_DEVICE_SELECT"); const char* selection = getenv("MESA_VK_DEVICE_SELECT");
bool expose_only_one_dev = false;
VkResult result = info->EnumeratePhysicalDevices(instance, &physical_device_count, NULL); VkResult result = info->EnumeratePhysicalDevices(instance, &physical_device_count, NULL);
VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices, pPhysicalDeviceCount); VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices, pPhysicalDeviceCount);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
@ -563,7 +591,8 @@ static VkResult device_select_EnumeratePhysicalDevices(VkInstance instance,
exit(0); exit(0);
} }
unsigned selected_index = get_default_device(info, selection, physical_device_count, physical_devices); unsigned selected_index = get_default_device(info, selection, physical_device_count,
physical_devices, &expose_only_one_dev);
selected_physical_device_count = physical_device_count; selected_physical_device_count = physical_device_count;
selected_physical_devices[0] = physical_devices[selected_index]; selected_physical_devices[0] = physical_devices[selected_index];
for (unsigned i = 0; i < physical_device_count - 1; ++i) { for (unsigned i = 0; i < physical_device_count - 1; ++i) {
@ -580,6 +609,9 @@ static VkResult device_select_EnumeratePhysicalDevices(VkInstance instance,
/* do not give multiple device option to app if force default device */ /* do not give multiple device option to app if force default device */
const char *force_default_device = getenv("MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE"); const char *force_default_device = getenv("MESA_VK_DEVICE_SELECT_FORCE_DEFAULT_DEVICE");
if (force_default_device && !strcmp(force_default_device, "1") && selected_physical_device_count != 0) if (force_default_device && !strcmp(force_default_device, "1") && selected_physical_device_count != 0)
expose_only_one_dev = true;
if (expose_only_one_dev)
selected_physical_device_count = 1; selected_physical_device_count = 1;
for (unsigned i = 0; i < selected_physical_device_count; i++) { for (unsigned i = 0; i < selected_physical_device_count; i++) {