diff --git a/include/private/vkd3d_debug.h b/include/private/vkd3d_debug.h index 8b4c77db..42e5903d 100644 --- a/include/private/vkd3d_debug.h +++ b/include/private/vkd3d_debug.h @@ -70,4 +70,6 @@ static inline const char *debugstr_guid(const GUID *guid) guid->Data4[5], guid->Data4[6], guid->Data4[7]); } +unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value) DECLSPEC_HIDDEN; + #endif /* __VKD3D_DEBUG_H */ diff --git a/libs/vkd3d-common/debug.c b/libs/vkd3d-common/debug.c index ee23ab0f..9d10c286 100644 --- a/libs/vkd3d-common/debug.c +++ b/libs/vkd3d-common/debug.c @@ -20,10 +20,11 @@ #include #include +#include +#include #include #include #include -#include #define VKD3D_DEBUG_BUFFER_COUNT 64 #define VKD3D_DEBUG_BUFFER_SIZE 512 @@ -297,3 +298,20 @@ const char *debugstr_w(const WCHAR *wstr, size_t wchar_size) return debugstr_w16((const uint16_t *)wstr); return debugstr_w32((const uint32_t *)wstr); } + +unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value) +{ + const char *value = getenv(name); + unsigned long r; + char *end_ptr; + + if (value) + { + errno = 0; + r = strtoul(value, &end_ptr, 0); + if (!errno && end_ptr != value) + return r; + } + + return default_value; +} diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 204489c2..f809a00b 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -1061,12 +1061,13 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, } static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance, - VkPhysicalDevice *selected_device) + unsigned int device_index, VkPhysicalDevice *selected_device) { VkPhysicalDevice dgpu_device = VK_NULL_HANDLE, igpu_device = VK_NULL_HANDLE; const struct vkd3d_vk_instance_procs *vk_procs = &instance->vk_procs; VkInstance vk_instance = instance->vk_instance; VkPhysicalDeviceProperties device_properties; + VkPhysicalDevice device = VK_NULL_HANDLE; VkPhysicalDevice *physical_devices; uint32_t count; unsigned int i; @@ -1094,27 +1095,36 @@ static HRESULT vkd3d_select_physical_device(struct vkd3d_instance *instance, return hresult_from_vk_result(vr); } + if (device_index != ~0u && device_index >= count) + WARN("Device index %u is out of range.\n", device_index); + for (i = 0; i < count; ++i) { VK_CALL(vkGetPhysicalDeviceProperties(physical_devices[i], &device_properties)); vkd3d_trace_physical_device(physical_devices[i], &device_properties, vk_procs); + if (i == device_index) + device = physical_devices[i]; + if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && !dgpu_device) dgpu_device = physical_devices[i]; else if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && !igpu_device) igpu_device = physical_devices[i]; } - *selected_device = dgpu_device ? dgpu_device : igpu_device; - if (!*selected_device) - *selected_device = physical_devices[0]; + if (!device) + device = dgpu_device ? dgpu_device : igpu_device; + if (!device) + device = physical_devices[0]; vkd3d_free(physical_devices); - VK_CALL(vkGetPhysicalDeviceProperties(*selected_device, &device_properties)); + VK_CALL(vkGetPhysicalDeviceProperties(device, &device_properties)); TRACE("Using device: %s, %#x:%#x.\n", device_properties.deviceName, device_properties.vendorID, device_properties.deviceID); + *selected_device = device; + return S_OK; } @@ -1285,6 +1295,7 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, VkPhysicalDeviceFeatures2 features2; VkPhysicalDevice physical_device; VkDeviceCreateInfo device_info; + unsigned int device_index; uint32_t extension_count; const char **extensions; VkDevice vk_device; @@ -1294,8 +1305,9 @@ static HRESULT vkd3d_create_vk_device(struct d3d12_device *device, TRACE("device %p, create_info %p.\n", device, create_info); physical_device = create_info->vk_physical_device; - if (!physical_device - && FAILED(hr = vkd3d_select_physical_device(device->vkd3d_instance, &physical_device))) + device_index = vkd3d_env_var_as_uint("VKD3D_VULKAN_DEVICE", ~0u); + if ((!physical_device || device_index != ~0u) + && FAILED(hr = vkd3d_select_physical_device(device->vkd3d_instance, device_index, &physical_device))) return hr; device->vk_physical_device = physical_device;