Skip to content

Commit 0810110

Browse files
authored
Add pci bus and device uuid to AdapterInfo (#8290)
1 parent 982a210 commit 0810110

File tree

10 files changed

+189
-0
lines changed

10 files changed

+189
-0
lines changed

wgpu-core/src/pipeline_cache.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ mod tests {
319319
vendor: 0x0002_FEED,
320320
device: 0xFEFE_FEFE,
321321
device_type: wgt::DeviceType::Other,
322+
device_pci_bus_id: String::new(),
322323
driver: String::new(),
323324
driver_info: String::new(),
324325
backend: wgt::Backend::Vulkan,

wgpu-hal/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ dx12 = [
143143
"dep:range-alloc",
144144
"dep:windows-core",
145145
"dep:gpu-allocator",
146+
"gpu-allocator/d3d12",
147+
"windows/Win32_Devices_DeviceAndDriverInstallation",
146148
"windows/Win32_Graphics_Direct3D_Fxc",
147149
"windows/Win32_Graphics_Direct3D_Dxc",
148150
"windows/Win32_Graphics_Direct3D",

wgpu-hal/src/dx12/adapter.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ use parking_lot::Mutex;
66
use windows::{
77
core::Interface as _,
88
Win32::{
9+
Devices::DeviceAndDriverInstallation::{
10+
SetupDiDestroyDeviceInfoList, SetupDiEnumDeviceInfo, SetupDiGetClassDevsW,
11+
SetupDiGetDeviceRegistryPropertyW, DIGCF_PRESENT, GUID_DEVCLASS_DISPLAY, HDEVINFO,
12+
SPDRP_ADDRESS, SPDRP_BUSNUMBER, SPDRP_HARDWAREID, SP_DEVINFO_DATA,
13+
},
14+
Foundation::{GetLastError, ERROR_NO_MORE_ITEMS},
915
Graphics::{Direct3D, Direct3D12, Dxgi},
1016
UI::WindowsAndMessaging,
1117
},
@@ -127,6 +133,7 @@ impl super::Adapter {
127133
} else {
128134
wgt::DeviceType::DiscreteGpu
129135
},
136+
device_pci_bus_id: get_adapter_pci_info(desc.VendorId, desc.DeviceId),
130137
driver: {
131138
if let Ok(i) = unsafe { adapter.CheckInterfaceSupport(&Dxgi::IDXGIDevice::IID) } {
132139
const MASK: i64 = 0xFFFF;
@@ -1024,3 +1031,147 @@ impl crate::Adapter for super::Adapter {
10241031
wgt::PresentationTimestamp(self.presentation_timer.get_timestamp_ns())
10251032
}
10261033
}
1034+
1035+
fn get_adapter_pci_info(vendor_id: u32, device_id: u32) -> String {
1036+
// SAFETY: SetupDiGetClassDevsW is called with valid parameters
1037+
let device_info_set = unsafe {
1038+
match SetupDiGetClassDevsW(Some(&GUID_DEVCLASS_DISPLAY), None, None, DIGCF_PRESENT) {
1039+
Ok(set) => set,
1040+
Err(_) => return String::new(),
1041+
}
1042+
};
1043+
1044+
struct DeviceInfoSetGuard(HDEVINFO);
1045+
impl Drop for DeviceInfoSetGuard {
1046+
fn drop(&mut self) {
1047+
// SAFETY: device_info_set is a valid HDEVINFO and is only dropped once via this guard
1048+
unsafe {
1049+
let _ = SetupDiDestroyDeviceInfoList(self.0);
1050+
}
1051+
}
1052+
}
1053+
let _guard = DeviceInfoSetGuard(device_info_set);
1054+
1055+
let mut device_index = 0u32;
1056+
loop {
1057+
let mut device_info_data = SP_DEVINFO_DATA {
1058+
cbSize: size_of::<SP_DEVINFO_DATA>() as u32,
1059+
..Default::default()
1060+
};
1061+
1062+
// SAFETY: device_info_set is a valid HDEVINFO, device_index starts at 0 and
1063+
// device_info_data is properly initialized above
1064+
unsafe {
1065+
if SetupDiEnumDeviceInfo(device_info_set, device_index, &mut device_info_data).is_err()
1066+
{
1067+
if GetLastError() == ERROR_NO_MORE_ITEMS {
1068+
break;
1069+
}
1070+
device_index += 1;
1071+
continue;
1072+
}
1073+
}
1074+
1075+
let mut hardware_id_size = 0u32;
1076+
// SAFETY: device_info_set and device_info_data are valid
1077+
unsafe {
1078+
let _ = SetupDiGetDeviceRegistryPropertyW(
1079+
device_info_set,
1080+
&device_info_data,
1081+
SPDRP_HARDWAREID,
1082+
None,
1083+
None,
1084+
Some(&mut hardware_id_size),
1085+
);
1086+
}
1087+
1088+
if hardware_id_size == 0 {
1089+
device_index += 1;
1090+
continue;
1091+
}
1092+
1093+
let mut hardware_id_buffer = vec![0u8; hardware_id_size as usize];
1094+
// SAFETY: device_info_set and device_info_data are valid
1095+
unsafe {
1096+
if SetupDiGetDeviceRegistryPropertyW(
1097+
device_info_set,
1098+
&device_info_data,
1099+
SPDRP_HARDWAREID,
1100+
None,
1101+
Some(&mut hardware_id_buffer),
1102+
Some(&mut hardware_id_size),
1103+
)
1104+
.is_err()
1105+
{
1106+
device_index += 1;
1107+
continue;
1108+
}
1109+
}
1110+
1111+
let hardware_id_u16: Vec<u16> = hardware_id_buffer
1112+
.chunks_exact(2)
1113+
.map(|chunk| u16::from_le_bytes([chunk[0], chunk[1]]))
1114+
.collect();
1115+
let hardware_ids: Vec<String> = hardware_id_u16
1116+
.split(|&c| c == 0)
1117+
.filter(|s| !s.is_empty())
1118+
.map(|s| String::from_utf16_lossy(s).to_uppercase())
1119+
.collect();
1120+
1121+
// https://learn.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices
1122+
let expected_id = format!("PCI\\VEN_{vendor_id:04X}&DEV_{device_id:04X}");
1123+
if !hardware_ids.iter().any(|id| id.contains(&expected_id)) {
1124+
device_index += 1;
1125+
continue;
1126+
}
1127+
1128+
let mut bus_buffer = [0u8; 4];
1129+
let mut data_size = bus_buffer.len() as u32;
1130+
// SAFETY: device_info_set and device_info_data are valid
1131+
let bus_number = unsafe {
1132+
if SetupDiGetDeviceRegistryPropertyW(
1133+
device_info_set,
1134+
&device_info_data,
1135+
SPDRP_BUSNUMBER,
1136+
None,
1137+
Some(&mut bus_buffer),
1138+
Some(&mut data_size),
1139+
)
1140+
.is_err()
1141+
{
1142+
device_index += 1;
1143+
continue;
1144+
}
1145+
u32::from_le_bytes(bus_buffer)
1146+
};
1147+
1148+
let mut addr_buffer = [0u8; 4];
1149+
let mut addr_size = addr_buffer.len() as u32;
1150+
// SAFETY: device_info_set and device_info_data are valid
1151+
unsafe {
1152+
if SetupDiGetDeviceRegistryPropertyW(
1153+
device_info_set,
1154+
&device_info_data,
1155+
SPDRP_ADDRESS,
1156+
None,
1157+
Some(&mut addr_buffer),
1158+
Some(&mut addr_size),
1159+
)
1160+
.is_err()
1161+
{
1162+
device_index += 1;
1163+
continue;
1164+
}
1165+
}
1166+
let address = u32::from_le_bytes(addr_buffer);
1167+
1168+
// https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/obtaining-device-configuration-information-at-irql---dispatch-level
1169+
let device = (address >> 16) & 0x0000FFFF;
1170+
let function = address & 0x0000FFFF;
1171+
1172+
// domain:bus:device.function
1173+
return format!("{:04x}:{:02x}:{:02x}.{:x}", 0, bus_number, device, function);
1174+
}
1175+
1176+
String::new()
1177+
}

wgpu-hal/src/gles/adapter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ impl super::Adapter {
187187
device: 0,
188188
device_type: inferred_device_type,
189189
driver: "".to_owned(),
190+
device_pci_bus_id: String::new(),
190191
driver_info: version,
191192
backend: wgt::Backend::Gl,
192193
transient_saves_memory: false,

wgpu-hal/src/metal/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ impl crate::Instance for Instance {
156156
vendor: 0,
157157
device: 0,
158158
device_type: shared.private_caps.device_type(),
159+
device_pci_bus_id: String::new(),
159160
driver: String::new(),
160161
driver_info: String::new(),
161162
backend: wgt::Backend::Metal,

wgpu-hal/src/noop/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ pub fn adapter_info() -> wgt::AdapterInfo {
137137
vendor: 0,
138138
device: 0,
139139
device_type: wgt::DeviceType::Cpu,
140+
device_pci_bus_id: String::new(),
140141
driver: String::from("wgpu"),
141142
driver_info: String::new(),
142143
backend: wgt::Backend::Noop,

wgpu-hal/src/vulkan/adapter.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,10 @@ pub struct PhysicalDeviceProperties {
962962
/// `VK_EXT_mesh_shader` extension.
963963
mesh_shader: Option<vk::PhysicalDeviceMeshShaderPropertiesEXT<'static>>,
964964

965+
/// Additional `vk::PhysicalDevice` properties from the
966+
/// `VK_EXT_pci_bus_info` extension.
967+
pci_bus_info: Option<vk::PhysicalDevicePCIBusInfoPropertiesEXT<'static>>,
968+
965969
/// The device API version.
966970
///
967971
/// Which is the version of Vulkan supported for device-level functionality.
@@ -1392,6 +1396,8 @@ impl super::InstanceShared {
13921396
>= vk::API_VERSION_1_3
13931397
|| capabilities.supports_extension(ext::subgroup_size_control::NAME);
13941398
let supports_robustness2 = capabilities.supports_extension(ext::robustness2::NAME);
1399+
let supports_pci_bus_info =
1400+
capabilities.supports_extension(ext::pci_bus_info::NAME);
13951401

13961402
let supports_acceleration_structure =
13971403
capabilities.supports_extension(khr::acceleration_structure::NAME);
@@ -1448,6 +1454,13 @@ impl super::InstanceShared {
14481454
properties2 = properties2.push_next(next);
14491455
}
14501456

1457+
if supports_pci_bus_info {
1458+
let next = capabilities
1459+
.pci_bus_info
1460+
.insert(vk::PhysicalDevicePCIBusInfoPropertiesEXT::default());
1461+
properties2 = properties2.push_next(next);
1462+
}
1463+
14511464
if supports_mesh_shader {
14521465
let next = capabilities
14531466
.mesh_shader
@@ -1672,6 +1685,16 @@ impl super::Instance {
16721685
vk::PhysicalDeviceType::CPU => wgt::DeviceType::Cpu,
16731686
_ => wgt::DeviceType::Other,
16741687
},
1688+
device_pci_bus_id: phd_capabilities
1689+
.pci_bus_info
1690+
.filter(|info| info.pci_bus != 0 || info.pci_device != 0)
1691+
.map(|info| {
1692+
format!(
1693+
"{:04x}:{:02x}:{:02x}.{}",
1694+
info.pci_domain, info.pci_bus, info.pci_device, info.pci_function
1695+
)
1696+
})
1697+
.unwrap_or_default(),
16751698
driver: {
16761699
phd_capabilities
16771700
.driver

wgpu-info/src/human.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ fn print_adapter(output: &mut impl io::Write, report: &AdapterReport, idx: usize
9999
writeln!(output, "\t Name: {}", info.name)?;
100100
writeln!(output, "\t VendorID: {:#X?}", info.vendor)?;
101101
writeln!(output, "\t DeviceID: {:#X?}", info.device)?;
102+
writeln!(output, "\t DevicePCIBusId: {}", print_empty_string(&info.device_pci_bus_id))?;
102103
writeln!(output, "\t Type: {:?}", info.device_type)?;
103104
writeln!(output, "\t Driver: {}", print_empty_string(&info.driver))?;
104105
writeln!(output, "\t DriverInfo: {}", print_empty_string(&info.driver_info))?;

wgpu-types/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,13 @@ pub struct AdapterInfo {
14091409
pub device: u32,
14101410
/// Type of device
14111411
pub device_type: DeviceType,
1412+
/// [`Backend`]-specific PCI bus ID of the adapter.
1413+
///
1414+
/// * For [`Backend::Vulkan`], [`VkPhysicalDevicePCIBusInfoPropertiesEXT`] is used,
1415+
/// if available, in the form `bus:device.function`, e.g. `0000:01:00.0`.
1416+
///
1417+
/// [`VkPhysicalDevicePCIBusInfoPropertiesEXT`]: https://registry.khronos.org/vulkan/specs/latest/man/html/VkPhysicalDevicePCIBusInfoPropertiesEXT.html
1418+
pub device_pci_bus_id: String,
14121419
/// Driver name
14131420
pub driver: String,
14141421
/// Driver info

wgpu/src/backend/webgpu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,7 @@ impl dispatch::AdapterInterface for WebAdapter {
17071707
vendor: 0,
17081708
device: 0,
17091709
device_type: wgt::DeviceType::Other,
1710+
device_pci_bus_id: String::new(),
17101711
driver: String::new(),
17111712
driver_info: String::new(),
17121713
backend: wgt::Backend::BrowserWebGpu,

0 commit comments

Comments
 (0)