diff options
| author | Witold Baryluk <witold.baryluk@gmail.com> | 2021-01-07 19:03:02 +0000 |
|---|---|---|
| committer | Tony Barbour <tony@lunarg.com> | 2021-01-12 15:51:58 -0700 |
| commit | a3b988fa55885a3da83e33724e7beaaaeeee297c (patch) | |
| tree | d20f59ce4c4fad5f72ab79e2bdb4640920c4d17f | |
| parent | be70e017bff5d1a1889cde1c09522b6ab24e5764 (diff) | |
| download | usermoji-a3b988fa55885a3da83e33724e7beaaaeeee297c.tar.xz | |
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.
| -rw-r--r-- | cube/cube.c | 76 | ||||
| -rw-r--r-- | cube/cube.cpp | 73 |
2 files changed, 114 insertions, 35 deletions
diff --git a/cube/cube.c b/cube/cube.c index 9516fca1..800a0694 100644 --- a/cube/cube.c +++ b/cube/cube.c @@ -343,7 +343,7 @@ struct demo { bool use_staging_buffer; bool separate_present_queue; bool is_minimized; - uint32_t gpu_number; + int32_t gpu_number; bool VK_KHR_incremental_present_enabled; @@ -3248,8 +3248,6 @@ static void demo_init_vk(struct demo *demo) { inst_info.pNext = &dbg_messenger_create_info; } - uint32_t gpu_count; - err = vkCreateInstance(&inst_info, NULL, &demo->inst); if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { ERR_EXIT( @@ -3269,22 +3267,12 @@ static void demo_init_vk(struct demo *demo) { "vkCreateInstance Failure"); } - /* Make initial call to query gpu_count, then second call for gpu info*/ + /* Make initial call to query gpu_count, then second call for gpu info */ + uint32_t gpu_count = 0; err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL); assert(!err); - if (gpu_count > 0) { - VkPhysicalDevice *physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count); - err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices); - assert(!err); - if (demo->gpu_number > gpu_count - 1) { - fprintf(stderr, "Gpu %u specified is not present, gpu count = %u\n", demo->gpu_number, gpu_count); - fprintf(stderr, "Continuing with gpu 0\n"); - demo->gpu_number = 0; - } - demo->gpu = physical_devices[demo->gpu_number]; - free(physical_devices); - } 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" @@ -3292,6 +3280,57 @@ static void demo_init_vk(struct demo *demo) { "vkEnumeratePhysicalDevices Failure"); } + VkPhysicalDevice *physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count); + err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices); + assert(!err); + if (demo->gpu_number >= 0 && !((uint32_t)demo->gpu_number < gpu_count)) { + fprintf(stderr, "GPU %d specified is not present, GPU count = %u\n", demo->gpu_number, gpu_count); + ERR_EXIT("Specified GPU number is not present", "User Error"); + } + + /* Try to auto select most suitable device */ + if (demo->gpu_number == -1) { + uint32_t count_device_type[VK_PHYSICAL_DEVICE_TYPE_CPU + 1]; + memset(count_device_type, 0, sizeof(count_device_type)); + + VkPhysicalDeviceProperties physicalDeviceProperties; + for (uint32_t i = 0; i < gpu_count; i++) { + vkGetPhysicalDeviceProperties(physical_devices[i], &physicalDeviceProperties); + assert(physicalDeviceProperties.deviceType <= VK_PHYSICAL_DEVICE_TYPE_CPU); + count_device_type[physicalDeviceProperties.deviceType]++; + } + + VkPhysicalDeviceType search_for_device_type = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; + if (count_device_type[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU]) { + search_for_device_type = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU; + } else if (count_device_type[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU]) { + search_for_device_type = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU; + } else if (count_device_type[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU]) { + search_for_device_type = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU; + } else if (count_device_type[VK_PHYSICAL_DEVICE_TYPE_CPU]) { + search_for_device_type = VK_PHYSICAL_DEVICE_TYPE_CPU; + } else if (count_device_type[VK_PHYSICAL_DEVICE_TYPE_OTHER]) { + search_for_device_type = VK_PHYSICAL_DEVICE_TYPE_OTHER; + } + + for (uint32_t i = 0; i < gpu_count; i++) { + vkGetPhysicalDeviceProperties(physical_devices[i], &physicalDeviceProperties); + if (physicalDeviceProperties.deviceType == search_for_device_type) { + demo->gpu_number = i; + break; + } + } + } + assert(demo->gpu_number >= 0); + demo->gpu = physical_devices[demo->gpu_number]; + { + VkPhysicalDeviceProperties physicalDeviceProperties; + vkGetPhysicalDeviceProperties(demo->gpu, &physicalDeviceProperties); + fprintf(stderr, "Selected GPU %d: %s, type: %u\n", demo->gpu_number, physicalDeviceProperties.deviceName, + physicalDeviceProperties.deviceType); + } + free(physical_devices); + /* Look for device extensions */ uint32_t device_extension_count = 0; VkBool32 swapchainExtFound = 0; @@ -3816,8 +3855,8 @@ static void demo_init(struct demo *demo, int argc, char **argv) { memset(demo, 0, sizeof(*demo)); demo->presentMode = VK_PRESENT_MODE_FIFO_KHR; demo->frameCount = INT32_MAX; - /* For cube demo we just grab the first physical device by default */ - demo->gpu_number = 0; + /* Autodetect suitable / best GPU by default */ + demo->gpu_number = -1; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--use_staging") == 0) { @@ -3865,6 +3904,7 @@ static void demo_init(struct demo *demo, int argc, char **argv) { } if ((strcmp(argv[i], "--gpu_number") == 0) && (i < argc - 1)) { demo->gpu_number = atoi(argv[i + 1]); + assert(demo->gpu_number >= 0); i++; continue; } diff --git a/cube/cube.cpp b/cube/cube.cpp index 252f880b..8efea2a2 100644 --- a/cube/cube.cpp +++ b/cube/cube.cpp @@ -311,7 +311,7 @@ struct Demo { 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 @@ void Demo::init(int argc, char **argv) { 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 @@ void Demo::init(int argc, char **argv) { } 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 @@ void Demo::init(int argc, char **argv) { << "\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 @@ void Demo::init_vk() { "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 @@ void Demo::init_vk() { "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; |
