Skip to content

Commit 939643c

Browse files
committed
Fix to enumerate render-only adapters
1 parent b71e006 commit 939643c

File tree

2 files changed

+102
-25
lines changed

2 files changed

+102
-25
lines changed

Tools/DXGIAdapterRemovalSupportTest/src/main.cpp

+98-22
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,14 @@ HANDLE GetProcessFromID(DWORD processID, std::wstring& outAppProcessName)
192192
#pragma endregion
193193

194194
#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+
195203
std::wstring GetDeviceIdFromDeviceInterface(std::wstring DeviceInterface)
196204
{
197205
std::vector<WCHAR> DeviceId;
@@ -204,8 +212,9 @@ std::wstring GetDeviceIdFromDeviceInterface(std::wstring DeviceInterface)
204212
if (Return != CR_BUFFER_SMALL)
205213
{
206214
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;
209218
}
210219

211220
DeviceId.resize(BufferSize / sizeof(WCHAR));
@@ -216,33 +225,97 @@ std::wstring GetDeviceIdFromDeviceInterface(std::wstring DeviceInterface)
216225
return std::wstring(DeviceId.begin(), DeviceId.end());
217226
}
218227

219-
DEVINST FindAdapterDevInst(LUID AdapterLuid, std::wstring& DeviceIdString)
228+
std::vector<AdapterDeviceInfo> EnumerateAdapterDeviceInfo()
220229
{
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
227234
{
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+
}
231266
}
232267

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);
234286

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)
239297
{
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+
}
243313
}
244314

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;
246319
}
247320
#pragma endregion
248321

@@ -510,6 +583,9 @@ int _cdecl wmain(int argc, _In_reads_z_(argc) WCHAR** argv)
510583
return 1;
511584
}
512585

586+
// Init adapter enumeration information
587+
std::vector<AdapterDeviceInfo> adapterInfos = EnumerateAdapterDeviceInfo();
588+
513589
bool bSupportAdapterRemoval = true; // if the app truly supports adapter removal
514590

515591
// For each graphics adapter
@@ -518,7 +594,7 @@ int _cdecl wmain(int argc, _In_reads_z_(argc) WCHAR** argv)
518594
std::wcout << L"[" << i << L"], Targeting " << adapterDescs[i].Description << L" adapter." << std::endl;
519595

520596
std::wstring DeviceId;
521-
DEVINST gpuDevNode = FindAdapterDevInst(adapterDescs[i].AdapterLuid, DeviceId);
597+
DEVINST gpuDevNode = FindAdapterDevInst(adapterDescs[i].AdapterLuid, DeviceId, adapterInfos);
522598
if (gpuDevNode == 0)
523599
{
524600
return 1; // FindAdapterDevInst would have reported an error message

Tools/DXGIAdapterRemovalSupportTest/src/pch.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers.
2020
#endif
2121

22-
//#include <nt.h>
23-
//#include <ntrtl.h>
24-
//#include <nturtl.h>
22+
#include <nt.h>
23+
#include <ntrtl.h>
24+
#include <nturtl.h>
2525
#include <windows.h>
2626
#include <atlbase.h>
2727

28+
#include <d3dkmthk.h>
2829
#include <dxgi1_6.h>
2930
#include <psapi.h>
3031
#include <cfgmgr32.h>

0 commit comments

Comments
 (0)