vkcube: Improve GPU auto-selection
Instead of selecting GPU 0, prefer dGPU, iGPU, vGPU, CPU, OTHER.
In that order.
If user selects specific gpu_number (including 0), use only
that and don't fallback to anything else, even when incorrect.
diff --git a/cube/cube.cpp b/cube/cube.cpp
index 252f880..8efea2a 100644
--- a/cube/cube.cpp
+++ b/cube/cube.cpp
@@ -311,7 +311,7 @@
bool use_staging_buffer;
bool use_xlib;
bool separate_present_queue;
- uint32_t gpu_number;
+ int32_t gpu_number;
vk::Instance inst;
vk::PhysicalDevice gpu;
@@ -940,8 +940,8 @@
presentMode = vk::PresentModeKHR::eFifo;
frameCount = UINT32_MAX;
use_xlib = false;
- /* For cube demo we just grab the first physical device by default */
- gpu_number = 0;
+ /* Autodetect suitable / best GPU by default */
+ gpu_number = -1;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--use_staging") == 0) {
@@ -976,6 +976,7 @@
}
if ((strcmp(argv[i], "--gpu_number") == 0) && (i < argc - 1)) {
gpu_number = atoi(argv[i + 1]);
+ assert(gpu_number >= 0);
i++;
continue;
}
@@ -988,7 +989,7 @@
<< "\t\tVK_PRESENT_MODE_IMMEDIATE_KHR = " << VK_PRESENT_MODE_IMMEDIATE_KHR << "\n"
<< "\t\tVK_PRESENT_MODE_MAILBOX_KHR = " << VK_PRESENT_MODE_MAILBOX_KHR << "\n"
<< "\t\tVK_PRESENT_MODE_FIFO_KHR = " << VK_PRESENT_MODE_FIFO_KHR << "\n"
- << "\t\tVK_PRESENT_MODE_FIFO_RELAXED_KHR = " << VK_PRESENT_MODE_FIFO_RELAXED_KHR;
+ << "\t\tVK_PRESENT_MODE_FIFO_RELAXED_KHR = " << VK_PRESENT_MODE_FIFO_RELAXED_KHR << "\n";
#if defined(_WIN32)
if (!suppress_popups) MessageBox(NULL, usage.str().c_str(), "Usage Error", MB_OK);
@@ -1243,22 +1244,12 @@
"vkCreateInstance Failure");
}
- /* Make initial call to query gpu_count, then second call for gpu info*/
- uint32_t gpu_count;
+ /* Make initial call to query gpu_count, then second call for gpu info */
+ uint32_t gpu_count = 0;
result = inst.enumeratePhysicalDevices(&gpu_count, static_cast<vk::PhysicalDevice *>(nullptr));
VERIFY(result == vk::Result::eSuccess);
- if (gpu_count > 0) {
- std::unique_ptr<vk::PhysicalDevice[]> physical_devices(new vk::PhysicalDevice[gpu_count]);
- result = inst.enumeratePhysicalDevices(&gpu_count, physical_devices.get());
- VERIFY(result == vk::Result::eSuccess);
- if (gpu_number > gpu_count - 1) {
- fprintf(stderr, "Gpu %u specified is not present, gpu count = %u\n", gpu_number, gpu_count);
- fprintf(stderr, "Continuing with gpu 0\n");
- gpu_number = 0;
- }
- gpu = physical_devices[gpu_number];
- } else {
+ if (gpu_count <= 0) {
ERR_EXIT(
"vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
"Do you have a compatible Vulkan installable client driver (ICD) installed?\n"
@@ -1266,6 +1257,54 @@
"vkEnumeratePhysicalDevices Failure");
}
+ std::unique_ptr<vk::PhysicalDevice[]> physical_devices(new vk::PhysicalDevice[gpu_count]);
+ result = inst.enumeratePhysicalDevices(&gpu_count, physical_devices.get());
+ VERIFY(result == vk::Result::eSuccess);
+
+ if (gpu_number >= 0 && !((uint32_t)gpu_number < gpu_count)) {
+ fprintf(stderr, "GPU %d specified is not present, GPU count = %u\n", gpu_number, gpu_count);
+ ERR_EXIT("Specified GPU number is not present", "User Error");
+ }
+
+ /* Try to auto select most suitable device */
+ if (gpu_number == -1) {
+ uint32_t count_device_type[VK_PHYSICAL_DEVICE_TYPE_CPU + 1];
+ memset(count_device_type, 0, sizeof(count_device_type));
+
+ for (uint32_t i = 0; i < gpu_count; i++) {
+ const auto physicalDeviceProperties = physical_devices[i].getProperties();
+ assert(static_cast<int>(physicalDeviceProperties.deviceType) <= VK_PHYSICAL_DEVICE_TYPE_CPU);
+ count_device_type[static_cast<int>(physicalDeviceProperties.deviceType)]++;
+ }
+
+ const vk::PhysicalDeviceType device_type_preference[] = {
+ vk::PhysicalDeviceType::eDiscreteGpu, vk::PhysicalDeviceType::eIntegratedGpu, vk::PhysicalDeviceType::eVirtualGpu,
+ vk::PhysicalDeviceType::eCpu, vk::PhysicalDeviceType::eOther};
+ vk::PhysicalDeviceType search_for_device_type = vk::PhysicalDeviceType::eDiscreteGpu;
+ for (uint32_t i = 0; i < sizeof(device_type_preference) / sizeof(vk::PhysicalDeviceType); i++) {
+ if (count_device_type[static_cast<int>(device_type_preference[i])]) {
+ search_for_device_type = device_type_preference[i];
+ break;
+ }
+ }
+
+ for (uint32_t i = 0; i < gpu_count; i++) {
+ const auto physicalDeviceProperties = physical_devices[i].getProperties();
+ if (physicalDeviceProperties.deviceType == search_for_device_type) {
+ gpu_number = i;
+ break;
+ }
+ }
+ }
+ assert(gpu_number >= 0);
+ gpu = physical_devices[gpu_number];
+ {
+ auto physicalDeviceProperties = gpu.getProperties();
+ fprintf(stderr, "Selected GPU %d: %s, type: %s\n", gpu_number, physicalDeviceProperties.deviceName.data(),
+ to_string(physicalDeviceProperties.deviceType).c_str());
+ }
+ physical_devices.reset();
+
/* Look for device extensions */
uint32_t device_extension_count = 0;
vk::Bool32 swapchainExtFound = VK_FALSE;