While working on RealBench v2 I had to enumerate the physical display adapters available on the user's system. There are several ways of doing this. I only found one that works the way I wanted it to work though.
The most common suggested solution for this is EnumDisplayDevices(). The problem with this approach is that it returns one device per available output display port. So for my development system with reference design Geforce 680 2xSLI cards, it actually returned 4xGeforce 680 devices. You can filter devices that are connected to a screen but that doesn't help at all in enumerating physical display adapters for any user configuration.
The second most suggested method is using DirectX's DXGI IDXGIFactory::EnumAdapters(). This is very easy to implement even for programmers who have never touched DirectX before BUT it still doesn't work as I needed it to work. As in the case of SLI/Crossfire it returns a single adapter instead of the amount of adapters present in the SLI/Crossfire array.
The one I used is the Setup API method which includes SetupDiGetClassDevs(), SetupDiEnumDeviceInfo() and SetupDiGetDeviceRegistryProperty(). This one works exactly like I wanted it to. It will return exactly what I need it to. The actual physical display adapter devices. Here's sample code (it includes a couple of QStrings as I'm using Qt):
-------------------------------------------------------
HDEVINFO deviceInfoSet;
GUID *guidDev = (GUID*) &GUID_DEVCLASS_DISPLAY;
deviceInfoSet = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
DWORD DataT;
WCHAR *buffer[4000];
DWORD buffersize = 4000;
int memberIndex = 0;
while (true)
{
SP_DEVINFO_DATA deviceInfoData;
ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex, &deviceInfoData) == FALSE)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
break;
}
}
SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buffer, buffersize, NULL);
qDebug() << QString::fromWCharArray((WCHAR*)buffer);
gpuInfo.append(QString::fromWCharArray((WCHAR*)buffer));
memberIndex++;
}
if (deviceInfoSet)
{
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
-------------------------------------------------------
There are a couple of other ways suggested. Namely, WMI and CCD API. Truth be told I never looked into these ways as Setup API did exactly what I wanted it to do and frankly I hate WMI. The CCD QueryDisplayConfig() function looks interesting and would be the next to try out if Setup API did not apply to my needs. :)
The most common suggested solution for this is EnumDisplayDevices(). The problem with this approach is that it returns one device per available output display port. So for my development system with reference design Geforce 680 2xSLI cards, it actually returned 4xGeforce 680 devices. You can filter devices that are connected to a screen but that doesn't help at all in enumerating physical display adapters for any user configuration.
The second most suggested method is using DirectX's DXGI IDXGIFactory::EnumAdapters(). This is very easy to implement even for programmers who have never touched DirectX before BUT it still doesn't work as I needed it to work. As in the case of SLI/Crossfire it returns a single adapter instead of the amount of adapters present in the SLI/Crossfire array.
The one I used is the Setup API method which includes SetupDiGetClassDevs(), SetupDiEnumDeviceInfo() and SetupDiGetDeviceRegistryProperty(). This one works exactly like I wanted it to. It will return exactly what I need it to. The actual physical display adapter devices. Here's sample code (it includes a couple of QStrings as I'm using Qt):
-------------------------------------------------------
HDEVINFO deviceInfoSet;
GUID *guidDev = (GUID*) &GUID_DEVCLASS_DISPLAY;
deviceInfoSet = SetupDiGetClassDevs(guidDev, NULL, NULL, DIGCF_PRESENT | DIGCF_PROFILE);
DWORD DataT;
WCHAR *buffer[4000];
DWORD buffersize = 4000;
int memberIndex = 0;
while (true)
{
SP_DEVINFO_DATA deviceInfoData;
ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
if (SetupDiEnumDeviceInfo(deviceInfoSet, memberIndex, &deviceInfoData) == FALSE)
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
{
break;
}
}
SetupDiGetDeviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC, &DataT, (PBYTE)buffer, buffersize, NULL);
qDebug() << QString::fromWCharArray((WCHAR*)buffer);
gpuInfo.append(QString::fromWCharArray((WCHAR*)buffer));
memberIndex++;
}
if (deviceInfoSet)
{
SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
-------------------------------------------------------
There are a couple of other ways suggested. Namely, WMI and CCD API. Truth be told I never looked into these ways as Setup API did exactly what I wanted it to do and frankly I hate WMI. The CCD QueryDisplayConfig() function looks interesting and would be the next to try out if Setup API did not apply to my needs. :)