11#pragma once
22
3- #include < wrl/client.h> // For ComPtr
4- #include < dxgi.h> // For IDXGIAdapter, IDXGIFactory1
5- #include < algorithm> // For sort
6- #include < d3dkmt.h> // For D3DKMT functions
7- #include < setupapi.h> // For SetupAPI
8- #include < devpkey.h> // For DEVPKEY
9- #include < cfgmgr32.h> // For CM_ functions
10- #include < fstream> // For file I/O
11- #include < string>
3+ #include < wrl/client.h> // For ComPtr
4+ #include < dxgi.h> // For IDXGIAdapter, IDXGIFactory1
5+ #include < algorithm> // For sort
126
137using namespace std ;
148using namespace Microsoft ::WRL;
159
16- // Structure to hold GPU information
10+ // Structure to vector gpus
1711struct GPUInfo {
18- wstring name; // GPU friendly name (from DXGI_ADAPTER_DESC)
12+ wstring name; // GPU name
1913 ComPtr<IDXGIAdapter> adapter;// COM pointer to the adapter
2014 DXGI_ADAPTER_DESC desc; // Adapter description
21- wstring deviceId; // Device Instance ID
22- wstring slotInfo; // PCI slot information (e.g., "PCI Slot 2")
2315};
2416
2517// Sort function for GPUs by dedicated video memory
2618bool CompareGPUs (const GPUInfo& a, const GPUInfo& b) {
2719 return a.desc .DedicatedVideoMemory > b.desc .DedicatedVideoMemory ;
2820}
2921
30- // Helper function to get Device Instance ID and PCI slot info from LUID
31- struct AdapterDeviceInfo {
32- wstring deviceId;
33- wstring slotInfo;
34- LUID luid;
35- };
36-
37- vector<AdapterDeviceInfo> GetAdapterDeviceInfos () {
38- vector<AdapterDeviceInfo> adapterInfos;
39-
40- // Enumerate display adapter interfaces
41- HDEVINFO devInfo = SetupDiGetClassDevsW (&GUID_DEVINTERFACE_DISPLAY_ADAPTER, nullptr , nullptr , DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
42- if (devInfo == INVALID_HANDLE_VALUE) {
43- return adapterInfos;
44- }
45-
46- SP_DEVICE_INTERFACE_DATA interfaceData = { sizeof (SP_DEVICE_INTERFACE_DATA) };
47- for (DWORD i = 0 ; SetupDiEnumDeviceInterfaces (devInfo, nullptr , &GUID_DEVINTERFACE_DISPLAY_ADAPTER, i, &interfaceData); ++i) {
48- // Get device interface path
49- DWORD requiredSize = 0 ;
50- SetupDiGetDeviceInterfaceDetailW (devInfo, &interfaceData, nullptr , 0 , &requiredSize, nullptr );
51- vector<WCHAR> buffer (requiredSize / sizeof (WCHAR));
52- PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail = reinterpret_cast <PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buffer.data ());
53- detail->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA_W);
54- if (!SetupDiGetDeviceInterfaceDetailW (devInfo, &interfaceData, detail, requiredSize, nullptr , nullptr )) {
55- continue ;
56- }
57-
58- // Get LUID
59- D3DKMT_OPENADAPTERFROMDEVICENAME openAdapter = {};
60- openAdapter.pDeviceName = detail->DevicePath ;
61- NTSTATUS status = D3DKMTOpenAdapterFromDeviceName (&openAdapter);
62- if (!NT_SUCCESS (status)) {
63- continue ;
64- }
65-
66- // Get Device Instance ID
67- ULONG propSize = 0 ;
68- DEVPROPTYPE propType;
69- CM_Get_Device_Interface_PropertyW (detail->DevicePath , &DEVPKEY_Device_InstanceId, &propType, nullptr , &propSize, 0 );
70- vector<BYTE> propBuffer (propSize);
71- wstring deviceId;
72- if (CM_Get_Device_Interface_PropertyW (detail->DevicePath , &DEVPKEY_Device_InstanceId, &propType, propBuffer.data (), &propSize, 0 ) == CR_SUCCESS) {
73- deviceId = reinterpret_cast <PWCHAR>(propBuffer.data ());
74- }
75-
76- // Get PCI slot info
77- propSize = 0 ;
78- CM_Get_Device_Interface_PropertyW (detail->DevicePath , &DEVPKEY_Device_LocationInfo, &propType, nullptr , &propSize, 0 );
79- propBuffer.resize (propSize);
80- wstring slotInfo;
81- if (CM_Get_Device_Interface_PropertyW (detail->DevicePath , &DEVPKEY_Device_LocationInfo, &propType, propBuffer.data (), &propSize, 0 ) == CR_SUCCESS) {
82- slotInfo = reinterpret_cast <PWCHAR>(propBuffer.data ());
83- }
84-
85- adapterInfos.push_back ({ deviceId, slotInfo, openAdapter.AdapterLuid });
86-
87- D3DKMT_CLOSEADAPTER closeAdapter = { openAdapter.hAdapter };
88- D3DKMTCloseAdapter (&closeAdapter);
89- }
90-
91- SetupDiDestroyDeviceInfoList (devInfo);
92- return adapterInfos;
93- }
94-
95- // Get a list of available GPUs with Device Instance ID and PCI slot info
22+ // Get a enumerate list of available GPUs
9623vector<GPUInfo> getAvailableGPUs () {
97- vector<GPUInfo> gpus;
24+ vector<GPUInfo> gpus; // Vector to hold all GPU's information
9825
9926 ComPtr<IDXGIFactory1> factory;
10027 if (!SUCCEEDED (CreateDXGIFactory1 (IID_PPV_ARGS (&factory)))) {
10128 return gpus;
10229 }
10330
104- // Get Device Instance IDs and slot info
105- auto deviceInfos = GetAdapterDeviceInfos ();
106-
10731 // Enumerate all adapters (GPUs)
10832 for (UINT i = 0 ;; i++) {
10933 ComPtr<IDXGIAdapter> adapter;
@@ -112,22 +36,13 @@ vector<GPUInfo> getAvailableGPUs() {
11236 }
11337
11438 DXGI_ADAPTER_DESC desc;
39+
11540 if (!SUCCEEDED (adapter->GetDesc (&desc))) {
11641 continue ;
11742 }
11843
119- // Find matching Device Instance ID and slot info
120- wstring deviceId, slotInfo;
121- for (const auto & deviceInfo : deviceInfos) {
122- if (RtlEqualLuid (&desc.AdapterLuid , &deviceInfo.luid )) {
123- deviceId = deviceInfo.deviceId ;
124- slotInfo = deviceInfo.slotInfo ;
125- break ;
126- }
127- }
128-
12944 // Add the adapter information to the list
130- GPUInfo info{ desc.Description , adapter, desc, deviceId, slotInfo };
45+ GPUInfo info{ desc.Description , adapter, desc };
13146 gpus.push_back (info);
13247 }
13348
@@ -138,36 +53,26 @@ class AdapterOption {
13853public:
13954 bool hasTargetAdapter{}; // Indicates if a target adapter is selected
14055 LUID adapterLuid{}; // Adapter's unique identifier (LUID)
141- wstring target_name{}; // Target adapter name (friendlyname,slot)
142- wstring target_device_id{}; // Device Instance ID of selected adapter
56+ wstring target_name{}; // Target adapter name
14357
14458 // Select the best GPU based on dedicated video memory
14559 wstring selectBestGPU () {
14660 auto gpus = getAvailableGPUs ();
14761 if (gpus.empty ()) {
148- return L" " ; // Error check for headless/VM
62+ return L" " ; // Error check for headless / vm
14963 }
15064
15165 // Sort GPUs by dedicated video memory in descending order
15266 sort (gpus.begin (), gpus.end (), CompareGPUs);
15367 auto bestGPU = gpus.front (); // Get the GPU with the most memory
15468
155- // Return friendlyname,slot format
156- return bestGPU.name + (bestGPU.slotInfo .empty () ? L" " : L" ," + bestGPU.slotInfo );
69+ return bestGPU.name ;
15770 }
15871
159- // Parse friendlyname,pcislot input
160- pair<wstring, wstring> parseTarget (const wstring& input) {
161- auto pos = input.find (L' ,' );
162- if (pos == wstring::npos) {
163- return { input, L" " }; // No slot specified
164- }
165- return { input.substr (0 , pos), input.substr (pos + 1 ) }; // Friendly name, slot
166- }
167-
168- // Load friendlyname,slot from a file or select the best GPU
72+ // Load friendlyname from a file OR select the best GPU
16973 void load (const wchar_t * path) {
17074 ifstream ifs{ path };
75+
17176 if (!ifs.is_open ()) {
17277 target_name = selectBestGPU ();
17378 }
@@ -177,15 +82,15 @@ class AdapterOption {
17782 target_name.assign (line.begin (), line.end ());
17883 }
17984
180- // Find and set the adapter based on the target name and slot
85+ // Find and set the adapter based on the target name
18186 if (!findAndSetAdapter (target_name)) {
18287 // If the adapter is not found, select the best GPU and retry
18388 target_name = selectBestGPU ();
18489 findAndSetAdapter (target_name);
18590 }
18691 }
18792
188- // Set the target adapter from a given name and slot (e.g., "NVIDIA GeForce RTX 3080,PCI Slot 2")
93+ // Set the target adapter from a given name and validate it
18994 void xmlprovide (const wstring& xtarg) {
19095 target_name = xtarg;
19196 if (!findAndSetAdapter (target_name)) {
@@ -205,53 +110,20 @@ class AdapterOption {
205110 }
206111
207112private:
208- // Find and set the adapter by its friendly name and optional PCI slot
209- bool findAndSetAdapter (const wstring& target ) {
113+ // Find and set the adapter by its name
114+ bool findAndSetAdapter (const wstring& adapterName ) {
210115 auto gpus = getAvailableGPUs ();
211- if (gpus.empty ()) {
212- hasTargetAdapter = false ;
213- return false ;
214- }
215-
216- auto [targetName, targetSlot] = parseTarget (target);
217116
218- // Find all adapters matching the friendly name
219- vector<GPUInfo> matchingGPUs;
117+ // Iterate through all available GPUs
220118 for (const auto & gpu : gpus) {
221- if (_wcsicmp (gpu.name .c_str (), targetName.c_str ()) == 0 ) {
222- matchingGPUs.push_back (gpu);
223- }
224- }
225-
226- if (matchingGPUs.empty ()) {
227- hasTargetAdapter = false ;
228- return false ;
229- }
230-
231- // If only one match or no slot specified, use the first match
232- if (matchingGPUs.size () == 1 || targetSlot.empty ()) {
233- const auto & gpu = matchingGPUs.front ();
234- adapterLuid = gpu.desc .AdapterLuid ;
235- target_device_id = gpu.deviceId ;
236- hasTargetAdapter = true ;
237- return true ;
238- }
239-
240- // Multiple matches: use PCI slot to disambiguate
241- for (const auto & gpu : matchingGPUs) {
242- if (_wcsicmp (gpu.slotInfo .c_str (), targetSlot.c_str ()) == 0 ) {
243- adapterLuid = gpu.desc .AdapterLuid ;
244- target_device_id = gpu.deviceId ;
245- hasTargetAdapter = true ;
119+ if (_wcsicmp (gpu.name .c_str (), adapterName.c_str ()) == 0 ) {
120+ adapterLuid = gpu.desc .AdapterLuid ; // Set the adapter LUID
121+ hasTargetAdapter = true ; // Indicate that a target adapter is selected
246122 return true ;
247123 }
248124 }
249125
250- // No slot match found; fall back to first matching GPU
251- const auto & gpu = matchingGPUs.front ();
252- adapterLuid = gpu.desc .AdapterLuid ;
253- target_device_id = gpu.deviceId ;
254- hasTargetAdapter = true ;
255- return true ;
126+ hasTargetAdapter = false ; // Indicate that no target adapter is selected
127+ return false ;
256128 }
257129};
0 commit comments