Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions src/rendervulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,15 @@ bool CVulkanDevice::selectPhysDev(VkSurfaceKHR surface)
bTryComputeOnly = false;
}

// Track whether the currently-selected device is discrete, so that when no
// device is explicitly preferred we upgrade from an integrated GPU to a
// discrete one. Without this, on hybrid systems (e.g. an AMD iGPU alongside
// a discrete NVIDIA/AMD GPU) the headless/standalone path with no surface to
// filter against would pick whichever device enumerates first — frequently
// the iGPU — and composite on the wrong, slower GPU.
const bool bHavePreferredDevice = ( g_preferVendorID != 0 || g_preferDeviceID != 0 );
bool bSelectedIsDiscrete = false;

for (auto cphysDev : physDevs)
{
VkPhysicalDeviceProperties deviceProperties;
Expand All @@ -370,9 +379,16 @@ bool CVulkanDevice::selectPhysDev(VkSurfaceKHR surface)

if (generalIndex != ~0u || computeOnlyIndex != ~0u)
{
// Select the device if it's the first one or the preferred one
if (!m_physDev ||
(g_preferVendorID == deviceProperties.vendorID && g_preferDeviceID == deviceProperties.deviceID))
const bool bIsPreferred = bHavePreferredDevice &&
g_preferVendorID == deviceProperties.vendorID &&
g_preferDeviceID == deviceProperties.deviceID;
Comment on lines +382 to +384

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a mismatch between how bIsPreferred is computed, and how bHavePreferredDevice is set: both vendor ID and device ID have to match, whereas the latter needs either to be set.

Do we expect to be able to specify only a vendor ID that would match all devices by this vendor? Does it even make sense? Even so, the device ID would never match the default value (0).

const bool bIsDiscrete = deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
// Upgrade integrated -> discrete only when the user hasn't pinned a device.
const bool bDiscreteUpgrade = !bHavePreferredDevice && m_physDev && !bSelectedIsDiscrete && bIsDiscrete;

// Select the device if it's the first one, the preferred one, or a
// discrete GPU superseding an integrated pick.
if (!m_physDev || bIsPreferred || bDiscreteUpgrade)
{
// if we have a surface, check that the queue family can actually present on it
if (surface) {
Expand All @@ -397,6 +413,7 @@ bool CVulkanDevice::selectPhysDev(VkSurfaceKHR surface)
m_queueFamily = computeOnlyIndex == ~0u ? generalIndex : computeOnlyIndex;
m_generalQueueFamily = generalIndex;
m_physDev = cphysDev;
bSelectedIsDiscrete = bIsDiscrete;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible optimization here: if the selected device is the preferred one (bIsPreferred), break out of the for loop.


/* When Intel uses compute-only queue for Gamescope composition, some games
* experience performance loss. Using the general queue alleviates the issue
Expand Down