[d3d12] simplify enumerate_adapters() fn

Also fixes an issue where only high performance adapters would be enumerated if DXGI 1.6 is available.
This commit is contained in:
teoxoy 2024-08-21 15:37:43 +02:00 committed by Teodor Tanasoaia
parent 6c2f23c6a2
commit 912bdcd336
3 changed files with 11 additions and 78 deletions

View File

@ -47,75 +47,27 @@ fn should_keep_adapter(adapter: &Dxgi::IDXGIAdapter1) -> bool {
}
pub enum DxgiAdapter {
Adapter1(Dxgi::IDXGIAdapter1),
Adapter2(Dxgi::IDXGIAdapter2),
/// Provided by DXGI 1.4
Adapter3(Dxgi::IDXGIAdapter3),
/// Provided by DXGI 1.6
Adapter4(Dxgi::IDXGIAdapter4),
}
impl windows::core::Param<Dxgi::IDXGIAdapter> for &DxgiAdapter {
unsafe fn param(self) -> windows::core::ParamValue<Dxgi::IDXGIAdapter> {
unsafe { self.deref().param() }
}
}
impl Deref for DxgiAdapter {
type Target = Dxgi::IDXGIAdapter;
type Target = Dxgi::IDXGIAdapter3;
fn deref(&self) -> &Self::Target {
match self {
DxgiAdapter::Adapter1(a) => a,
DxgiAdapter::Adapter2(a) => a,
DxgiAdapter::Adapter3(a) => a,
DxgiAdapter::Adapter4(a) => a,
}
}
}
impl DxgiAdapter {
pub fn as_adapter2(&self) -> Option<&Dxgi::IDXGIAdapter2> {
match self {
Self::Adapter1(_) => None,
Self::Adapter2(f) => Some(f),
Self::Adapter3(f) => Some(f),
Self::Adapter4(f) => Some(f),
}
}
pub fn unwrap_adapter2(&self) -> &Dxgi::IDXGIAdapter2 {
self.as_adapter2().unwrap()
}
}
pub fn enumerate_adapters(factory: DxgiFactory) -> Vec<DxgiAdapter> {
let mut adapters = Vec::with_capacity(8);
for cur_index in 0.. {
if let DxgiFactory::Factory6(ref factory6) = factory {
profiling::scope!("IDXGIFactory6::EnumAdapterByGpuPreference");
// We're already at dxgi1.6, we can grab IDXGIAdapter4 directly
let adapter4: Dxgi::IDXGIAdapter4 = match unsafe {
factory6.EnumAdapterByGpuPreference(
cur_index,
Dxgi::DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
)
} {
Ok(a) => a,
Err(e) if e.code() == Dxgi::DXGI_ERROR_NOT_FOUND => break,
Err(e) => {
log::error!("Failed enumerating adapters: {}", e);
break;
}
};
if !should_keep_adapter(&adapter4) {
continue;
}
adapters.push(DxgiAdapter::Adapter4(adapter4));
continue;
}
profiling::scope!("IDXGIFactory1::EnumAdapters1");
let adapter1: Dxgi::IDXGIAdapter1 = match unsafe { factory.EnumAdapters1(cur_index) } {
Ok(a) => a,
@ -130,31 +82,12 @@ pub fn enumerate_adapters(factory: DxgiFactory) -> Vec<DxgiAdapter> {
continue;
}
// Do the most aggressive casts first, skipping Adapter4 as we definitely don't have dxgi1_6.
// Adapter1 -> Adapter3
match adapter1.cast::<Dxgi::IDXGIAdapter3>() {
Ok(adapter3) => {
if let Ok(adapter4) = adapter1.cast::<Dxgi::IDXGIAdapter4>() {
adapters.push(DxgiAdapter::Adapter4(adapter4));
} else {
let adapter3 = adapter1.cast::<Dxgi::IDXGIAdapter3>().unwrap();
adapters.push(DxgiAdapter::Adapter3(adapter3));
continue;
}
Err(err) => {
log::warn!("Failed casting Adapter1 to Adapter3: {}", err);
}
}
// Adapter1 -> Adapter2
match adapter1.cast::<Dxgi::IDXGIAdapter2>() {
Ok(adapter2) => {
adapters.push(DxgiAdapter::Adapter2(adapter2));
continue;
}
Err(err) => {
log::warn!("Failed casting Adapter1 to Adapter2: {}", err);
}
}
adapters.push(DxgiAdapter::Adapter1(adapter1));
}
adapters

View File

@ -95,7 +95,7 @@ impl super::Adapter {
// We have found a possible adapter.
// Acquire the device information.
let desc = unsafe { adapter.unwrap_adapter2().GetDesc2() }.unwrap();
let desc = unsafe { adapter.GetDesc2() }.unwrap();
let device_name = auxil::dxgi::conv::map_adapter_name(desc.Description);

View File

@ -49,7 +49,7 @@ use std::{ffi, fmt, mem, num::NonZeroU32, ops::Deref, sync::Arc};
use arrayvec::ArrayVec;
use parking_lot::{Mutex, RwLock};
use windows::{
core::{Free, Interface, Param as _},
core::{Free, Interface},
Win32::{
Foundation,
Graphics::{Direct3D, Direct3D12, DirectComposition, Dxgi},
@ -118,7 +118,7 @@ impl D3D12Lib {
let mut result__ = None;
(func)(
unsafe { adapter.param().abi() },
adapter.as_raw(),
feature_level,
// TODO: Generic?
&Direct3D12::ID3D12Device::IID,