d3d: Use EnumAdapterByGpuPreference when available
Dawn currently uses EnumAdapters1 to enumerate IDXGIAdapters, and then
uses various properties of the adapter to infer the power preference.
This change uses the IDXGIFactory6::EnumAdapterByGpuPreference to
correctly return the most accurate power preference order, in
IDXGIFactory6 is available. EnumAdapters1 is used as a fallback. The
order of adapters returned by either API should take priority, so the
manual sorting is Dawn is bypassed for D3D backends.
Bug: 342299155
Change-Id: I5e27fbe6bb301cb393aafbc9468015818407044c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/189641
Commit-Queue: Patrick To <patrto@microsoft.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Rafael Cintron <rafael.cintron@microsoft.com>
diff --git a/src/dawn/native/Instance.cpp b/src/dawn/native/Instance.cpp
index efd7dfd..58d4fad 100644
--- a/src/dawn/native/Instance.cpp
+++ b/src/dawn/native/Instance.cpp
@@ -377,6 +377,14 @@
adapters.push_back(
CreateAdapter(physicalDevice, featureLevel, togglesDesc, unpacked->powerPreference));
}
+
+ if (options->backendType == wgpu::BackendType::D3D11 ||
+ options->backendType == wgpu::BackendType::D3D12) {
+ // If a D3D backend was requested, the order of the adapters returned by DXGI should be
+ // preserved instead of sorting by whether they are integrated vs. discrete. DXGI
+ // returns the correct order based on system settings and configuration.
+ return adapters;
+ }
return SortAdapters(std::move(adapters), options);
}
diff --git a/src/dawn/native/d3d/BackendD3D.cpp b/src/dawn/native/d3d/BackendD3D.cpp
index 478d60f..9b323af 100644
--- a/src/dawn/native/d3d/BackendD3D.cpp
+++ b/src/dawn/native/d3d/BackendD3D.cpp
@@ -61,6 +61,17 @@
return std::move(factory);
}
+DXGI_GPU_PREFERENCE ToDXGIPowerPreference(wgpu::PowerPreference powerPreference) {
+ switch (powerPreference) {
+ case wgpu::PowerPreference::Undefined:
+ return DXGI_GPU_PREFERENCE_UNSPECIFIED;
+ case wgpu::PowerPreference::LowPower:
+ return DXGI_GPU_PREFERENCE_MINIMUM_POWER;
+ case wgpu::PowerPreference::HighPerformance:
+ return DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE;
+ }
+}
+
} // anonymous namespace
Backend::Backend(InstanceBase* instance, wgpu::BackendType type)
@@ -261,7 +272,7 @@
return it->second;
}
- ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
+ ComPtr<IDXGIAdapter1> dxgiAdapter;
DAWN_TRY(CheckHRESULT(GetFactory()->EnumAdapterByLuid(luid, IID_PPV_ARGS(&dxgiAdapter)),
"EnumAdapterByLuid"));
@@ -308,11 +319,29 @@
return {std::move(physicalDevice)};
}
+ std::function<HRESULT(uint32_t, ComPtr<IDXGIAdapter1>&)> enumAdapters;
+ DXGI_GPU_PREFERENCE gpuPreference = ToDXGIPowerPreference(options->powerPreference);
+
+ ComPtr<IDXGIFactory6> factory6;
+ HRESULT hr = GetFactory()->QueryInterface(IID_PPV_ARGS(&factory6));
+ if (SUCCEEDED(hr)) {
+ // IDXGIFactory6 is not available on all versions of Windows 10. If it is available, use it
+ // to enumerate the adapters based on the desired power preference.
+ enumAdapters = [&](uint32_t adapterIndex, ComPtr<IDXGIAdapter1>& dxgiAdapter) -> HRESULT {
+ return factory6->EnumAdapterByGpuPreference(adapterIndex, gpuPreference,
+ IID_PPV_ARGS(&dxgiAdapter));
+ };
+ } else {
+ enumAdapters = [&](uint32_t adapterIndex, ComPtr<IDXGIAdapter1>& dxgiAdapter) -> HRESULT {
+ return GetFactory()->EnumAdapters1(adapterIndex, &dxgiAdapter);
+ };
+ }
+
// Enumerate and discover all available physicalDevices.
std::vector<Ref<PhysicalDeviceBase>> physicalDevices;
for (uint32_t adapterIndex = 0;; ++adapterIndex) {
- ComPtr<IDXGIAdapter1> dxgiAdapter = nullptr;
- if (GetFactory()->EnumAdapters1(adapterIndex, &dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
+ ComPtr<IDXGIAdapter1> dxgiAdapter;
+ if (enumAdapters(adapterIndex, dxgiAdapter) == DXGI_ERROR_NOT_FOUND) {
break; // No more physicalDevices to enumerate.
}