From 8e5a1383d04755e1954e89619d4e97615d048a8b Mon Sep 17 00:00:00 2001 From: IgorAlexey Date: Wed, 18 Mar 2026 21:35:47 -0300 Subject: [PATCH 1/2] Vulkan: do not replace hardware GPU with software renderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When no discrete GPU is present, SelectPhysicalDevice iterates all physical devices and keeps overwriting SelectedPhysicalDevice without breaking, because the break only fires for VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU. On Linux with Mesa, a CPU-type software renderer (llvmpipe) is always enumerated alongside the real hardware device. On a system with only an integrated GPU the loop would iterate past the iGPU, land on llvmpipe as the last entry, and silently return it as the selected device—making the application run entirely on software rendering with no warning. Fix this by skipping CPU-type devices when a hardware device has already been selected. A CPU-type device is still accepted as a last resort when no hardware GPU is found at all, so the fallback behavior is preserved. Tested on an Intel Core Ultra 7 258V (Lunar Lake, Arc 130V/140V iGPU) running Fedora 43 with Mesa 25.3.6. --- .../GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp index c3a52ed5a8..f9bf4759ae 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp @@ -717,6 +717,13 @@ VkPhysicalDevice Instance::SelectPhysicalDevice(uint32_t AdapterId) const noexce if (IsGraphicsAndComputeQueueSupported(Device)) { + // 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; From 931a30409a89f18aa7cf265baf56282361c6c087 Mon Sep 17 00:00:00 2001 From: IgorAlexey Date: Thu, 19 Mar 2026 16:12:27 -0300 Subject: [PATCH 2/2] Vulkan: pick best device by type, require gfx+compute queue --- .../src/VulkanUtilities/Instance.cpp | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp index f9bf4759ae..27fd6d1a72 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/Instance.cpp @@ -706,16 +706,32 @@ 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 @@ -725,8 +741,7 @@ VkPhysicalDevice Instance::SelectPhysicalDevice(uint32_t AdapterId) const noexce continue; SelectedPhysicalDevice = Device; - if (DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) - break; + BestPriority = Priority; } } }