@@ -192,6 +192,14 @@ HANDLE GetProcessFromID(DWORD processID, std::wstring& outAppProcessName)
192
192
#pragma endregion
193
193
194
194
#pragma region DeviceHelperFunctions
195
+ struct AdapterDeviceInfo
196
+ {
197
+ std::wstring m_deviceInterface;
198
+ std::wstring m_deviceId;
199
+ LUID m_Luid = {};
200
+ DEVINST m_devInst = 0 ;
201
+ };
202
+
195
203
std::wstring GetDeviceIdFromDeviceInterface (std::wstring DeviceInterface)
196
204
{
197
205
std::vector<WCHAR> DeviceId;
@@ -204,8 +212,9 @@ std::wstring GetDeviceIdFromDeviceInterface(std::wstring DeviceInterface)
204
212
if (Return != CR_BUFFER_SMALL)
205
213
{
206
214
ScopedOutputColor outClr (ScopedOutputColor::COLOR_RED);
207
- std::wcout << L" Error: when calling CM_Get_Device_Interface_PropertyW" << std::endl;
208
- return 0 ;
215
+ std::wcout << L" Error (" << (UINT)Return << L" ): when calling CM_Get_Device_Interface_PropertyW for " << DeviceInterface.c_str () << std::endl;
216
+ DeviceId.clear ();
217
+ break ;
209
218
}
210
219
211
220
DeviceId.resize (BufferSize / sizeof (WCHAR));
@@ -216,33 +225,97 @@ std::wstring GetDeviceIdFromDeviceInterface(std::wstring DeviceInterface)
216
225
return std::wstring (DeviceId.begin (), DeviceId.end ());
217
226
}
218
227
219
- DEVINST FindAdapterDevInst (LUID AdapterLuid, std::wstring& DeviceIdString )
228
+ std::vector<AdapterDeviceInfo> EnumerateAdapterDeviceInfo ( )
220
229
{
221
- // Find the device path
222
- DISPLAYCONFIG_ADAPTER_NAME AdapterName = {};
223
- AdapterName.header .size = sizeof (AdapterName);
224
- AdapterName.header .type = DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME;
225
- AdapterName.header .adapterId = AdapterLuid;
226
- if (DisplayConfigGetDeviceInfo (&AdapterName.header ) != ERROR_SUCCESS)
230
+ // List out all the AdapterDevicePath of all graphics adapters, display or render
231
+ std::vector<WCHAR> devicesStringBuffer;
232
+ CONFIGRET Return;
233
+ do
227
234
{
228
- ScopedOutputColor outClr (ScopedOutputColor::COLOR_RED);
229
- std::wcout << L" Error: when calling DisplayConfigGetDeviceInfo for DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME." << std::endl;
230
- return 0 ;
235
+ // Get the buffer size
236
+ ULONG BufferSize = 0 ;
237
+ Return = CM_Get_Device_Interface_List_SizeW (&BufferSize, const_cast <LPGUID>(&GUID_DISPLAY_DEVICE_ARRIVAL), nullptr , CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
238
+ if (Return != CR_SUCCESS)
239
+ {
240
+ break ;
241
+ }
242
+
243
+ // Read the buffer
244
+ devicesStringBuffer.resize (BufferSize);
245
+ Return = CM_Get_Device_Interface_ListW (const_cast <LPGUID>(&GUID_DISPLAY_DEVICE_ARRIVAL), nullptr , devicesStringBuffer.data (), (ULONG)devicesStringBuffer.size (), CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
246
+ } while (Return == CR_BUFFER_SMALL);
247
+
248
+ // Parse the buffer into each adapter string
249
+ std::vector<AdapterDeviceInfo> adapterInfos;
250
+ auto startIt = devicesStringBuffer.begin ();
251
+ for (auto it = devicesStringBuffer.begin (); it != devicesStringBuffer.end (); ++it)
252
+ {
253
+ if (*it == L' \0 ' )
254
+ {
255
+ // Only save strings if they are not empty
256
+ if (it - startIt > 1 )
257
+ {
258
+ adapterInfos.push_back (AdapterDeviceInfo ());
259
+ adapterInfos.back ().m_deviceInterface = std::wstring (startIt, it);
260
+ }
261
+
262
+ // Continue to search for next string with one-past-this-null as the start
263
+ startIt = it;
264
+ ++startIt;
265
+ }
231
266
}
232
267
233
- DeviceIdString = GetDeviceIdFromDeviceInterface (AdapterName.adapterDevicePath );
268
+ // Retrieve respective adapter information
269
+ bool bError = false ;
270
+ for (auto & adapterInfo : adapterInfos)
271
+ {
272
+ D3DKMT_OPENADAPTERFROMDEVICENAME OpenAdapterFromDeviceName = {};
273
+ OpenAdapterFromDeviceName.pDeviceName = adapterInfo.m_deviceInterface .c_str ();
274
+ NTSTATUS Status = D3DKMTOpenAdapterFromDeviceName (&OpenAdapterFromDeviceName);
275
+ if (!NT_SUCCESS (Status))
276
+ {
277
+ bError = true ;
278
+ continue ;
279
+ }
280
+ adapterInfo.m_Luid = OpenAdapterFromDeviceName.AdapterLuid ;
281
+
282
+ D3DKMT_CLOSEADAPTER CloseAdapter = { OpenAdapterFromDeviceName.hAdapter };
283
+ D3DKMTCloseAdapter (&CloseAdapter);
284
+
285
+ adapterInfo.m_deviceId = GetDeviceIdFromDeviceInterface (adapterInfo.m_deviceInterface );
234
286
235
- // Locate the device node by path
236
- DEVINST AdapterDevInst = 0 ;
237
- CONFIGRET Return = CM_Locate_DevNodeW (&AdapterDevInst, const_cast <DEVINSTID_W>(DeviceIdString.c_str ()), CM_LOCATE_DEVNODE_NORMAL);
238
- if (Return != CR_SUCCESS)
287
+ // Locate the device node by path
288
+ CONFIGRET Return = CM_Locate_DevNodeW (&adapterInfo.m_devInst , const_cast <DEVINSTID_W>(adapterInfo.m_deviceId .c_str ()), CM_LOCATE_DEVNODE_NORMAL);
289
+ if (Return != CR_SUCCESS)
290
+ {
291
+ bError = true ;
292
+ continue ;
293
+ }
294
+ }
295
+
296
+ if (bError)
239
297
{
240
- ScopedOutputColor outClr (ScopedOutputColor::COLOR_RED);
241
- std::wcout << L" Error: Unable to locate device " << DeviceIdString.c_str () << std::endl;
242
- return 0 ;
298
+ ScopedOutputColor outClr (ScopedOutputColor::COLOR_YELLOW);
299
+ std::wcout << L" Warning: Some adapter info were unable to be enumerated." << std::endl;
300
+ }
301
+ return adapterInfos;
302
+ }
303
+
304
+ DEVINST FindAdapterDevInst (LUID AdapterLuid, std::wstring& DeviceIdString, const std::vector<AdapterDeviceInfo>& adapterInfos)
305
+ {
306
+ for (const auto & adapterInfo : adapterInfos)
307
+ {
308
+ if (RtlEqualLuid (&AdapterLuid, &adapterInfo.m_Luid ))
309
+ {
310
+ DeviceIdString = adapterInfo.m_deviceId ;
311
+ return adapterInfo.m_devInst ;
312
+ }
243
313
}
244
314
245
- return AdapterDevInst;
315
+ ScopedOutputColor outClr (ScopedOutputColor::COLOR_RED);
316
+ std::wcout << L" Error: Unable to locate device " << DeviceIdString.c_str () << L" from luid ("
317
+ << AdapterLuid.HighPart << L" ," << AdapterLuid.LowPart << L" )" << std::endl;
318
+ return 0 ;
246
319
}
247
320
#pragma endregion
248
321
@@ -510,6 +583,9 @@ int _cdecl wmain(int argc, _In_reads_z_(argc) WCHAR** argv)
510
583
return 1 ;
511
584
}
512
585
586
+ // Init adapter enumeration information
587
+ std::vector<AdapterDeviceInfo> adapterInfos = EnumerateAdapterDeviceInfo ();
588
+
513
589
bool bSupportAdapterRemoval = true ; // if the app truly supports adapter removal
514
590
515
591
// For each graphics adapter
@@ -518,7 +594,7 @@ int _cdecl wmain(int argc, _In_reads_z_(argc) WCHAR** argv)
518
594
std::wcout << L" [" << i << L" ], Targeting " << adapterDescs[i].Description << L" adapter." << std::endl;
519
595
520
596
std::wstring DeviceId;
521
- DEVINST gpuDevNode = FindAdapterDevInst (adapterDescs[i].AdapterLuid , DeviceId);
597
+ DEVINST gpuDevNode = FindAdapterDevInst (adapterDescs[i].AdapterLuid , DeviceId, adapterInfos );
522
598
if (gpuDevNode == 0 )
523
599
{
524
600
return 1 ; // FindAdapterDevInst would have reported an error message
0 commit comments