242: Add logic to pick highest performance GPU on DirectX 12 r=kvark a=AndrewGaspar

I was having an issue on my Surface Book where my Intel's integrated GPU is always selected instead of my Nvidia discrete GPU when querying for `HighPerformance`. It turns out the Intel GPU is reported as a `DistcreteGPU` by `gfx` (in fact `gfx` has no logic for reporting `IntegratedGPU`s for DX12). However, it also turns out that `dx12::Instance::enumerate_adapters` returns adapters in descending order of performance, at least on Windows 10 > 1803. Therefore, we should use the _first_ GPU in each category, at least for `HighPerformance`. With this fix, `LowPower` selects my Intel GPU and `HighPerformance` and `Default` select my Nvidia GPU.

I'm not so sure `LowPower` = `IntegratedGPU` and `HighPerformance` = `DiscreteGPU` is the quite correct mapping, so I filed an issue on gfx to improve the ability for querying for power/performance preference: https://github.com/gfx-rs/gfx/issues/2879

Anyway, let me know if you have a different fix you'd prefer.

Co-authored-by: Andrew Gaspar <andrew.gaspar@outlook.com>
This commit is contained in:
bors[bot] 2019-07-02 17:16:19 +00:00
commit 662f9567d7

View File

@ -200,22 +200,40 @@ pub fn instance_get_adapter(instance_id: InstanceId, desc: &AdapterDescriptor) -
surface.raw.enumerate_adapters()
};
let (mut low, mut high, mut other) = (None, None, None);
for adapter in adapters {
let (mut integrated_first, mut discrete_first, mut discrete_last, mut alternative) =
(None, None, None, None);
// On Windows > 1803, dx12 enumerate_adapters returns the adapters in order from highest to
// lowest performance. Therefore, the first found adapter in each category is selected.
//
// TODO: move power/performance policy querying into gfx, which has more context into
// performance policy than wgpu
for (i, adapter) in adapters.iter().enumerate() {
match adapter.info.device_type {
hal::adapter::DeviceType::IntegratedGpu => low = Some(adapter),
hal::adapter::DeviceType::DiscreteGpu => high = Some(adapter),
_ => other = Some(adapter),
hal::adapter::DeviceType::IntegratedGpu => {
integrated_first = integrated_first.or(Some(i));
}
hal::adapter::DeviceType::DiscreteGpu => {
discrete_first = discrete_first.or(Some(i));
discrete_last = Some(i);
}
_ => alternative = Some(i),
}
}
let some = match desc.power_preference {
PowerPreference::LowPower => low.or(high),
PowerPreference::HighPerformance | PowerPreference::Default => high.or(low),
let preferred_gpu = match desc.power_preference {
// If `LowPower`, prefer lowest power `DiscreteGPU`
PowerPreference::LowPower => integrated_first.or(discrete_last),
PowerPreference::HighPerformance | PowerPreference::Default => {
discrete_first.or(integrated_first)
}
};
some
.or(other)
.expect("No adapters found. Please enable the feature for one of the graphics backends: vulkan, metal, dx12, dx11, gl")
let selected = preferred_gpu
.or(alternative)
.expect("No adapters found. Please enable the feature for one of the graphics backends: vulkan, metal, dx12, dx11, gl");
adapters.into_iter().nth(selected).unwrap()
}
#[cfg(feature = "local")]