diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp index c3a52ed5a8..27fd6d1a72 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp @@ -706,20 +706,42 @@ VkPhysicalDevice Instance::SelectPhysicalDevice(uint32_t AdapterId) const noexce SelectedPhysicalDevice = m_PhysicalDevices[AdapterId]; } - // Select a device that exposes a queue family that supports both compute and graphics operations. - // Prefer discrete GPU. + // Select a device that exposes a queue family that supports both compute and graphics operations + // DISCRETE > INTEGRATED > everything else. if (SelectedPhysicalDevice == VK_NULL_HANDLE) { + // Returns a priority value for the device type (higher is better). + const auto GetDeviceTypePriority = [](VkPhysicalDeviceType Type) -> int { + switch (Type) + { + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return 3; + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return 2; + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return 1; + default: return 0; + } + }; + + int BestPriority = -1; for (VkPhysicalDevice Device : m_PhysicalDevices) { + if (!IsGraphicsAndComputeQueueSupported(Device)) + continue; + VkPhysicalDeviceProperties DeviceProps; vkGetPhysicalDeviceProperties(Device, &DeviceProps); - if (IsGraphicsAndComputeQueueSupported(Device)) + const int Priority = GetDeviceTypePriority(DeviceProps.deviceType); + if (Priority > BestPriority) { + // Don't replace a hardware device with a software renderer (e.g. llvmpipe). + // On systems without a discrete GPU the loop would otherwise overwrite an + // integrated GPU with the last CPU-type device in the list. + if (SelectedPhysicalDevice != VK_NULL_HANDLE && + DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) + continue; + SelectedPhysicalDevice = Device; - if (DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) - break; + BestPriority = Priority; } } }