Why does EnumDisplayDevices ignore my second gpu? - windows

I've got a call like this:
while(EnumDisplayDevices(NULL, index, &displayDevice, 0)) {
// do stuff
}
My understanding is that this is supposed to report all graphics devices as displayDevice but it only reports one, multiple times. I've got an Intel card as my primary adapter and and NVidia card as secondary -- I'm hoping to be able to not only get the names and info of both cards but also to determine which the app is run with (ie the app defaults to the Intel but I can change the default in the NVidia control panel or even with the context menu in Windows Explorer). However, the call always reports three devices... and all three are the Intel. It reports Intel as \.\DISPLAY1, \.\DISPLAY2 and \.\DISPLAY3.
I can confirm that my code runs with the correct graphics card by looking at the DLLs that it uses. (Indeed, I needed to connect a second monitor to get it to use the NVidia card at all -- otherwise, the app would launch on the Intel no matter what card I chose. Either way, the Intel card always comes back as DISPLAY_DEVICE_ACTIVE.

This is because flag in DISPLAY_DEVICE structure, DISPLAY_DEVICE_PRIMARY_DEVICE --The primary desktop is on the device. For a system with a single display card, this is always set. For a system with multiple display cards, only one device can have this set.
To fetch active display devices from second GPU use following flag condition
while (EnumDisplayDevices(NULL, index, &dd, 0))
{
if(((dd.StateFlags & DISPLAY_DEVICE_ACTIVE) && ((dd.StateFlags & DISPLAY_DEVICE_ACTIVE) || (!(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE))) &&(!(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))))
{
activeDispCount++;
}
index++;
}

Related

A driver has enumerated two child PDO's that returned identical Device ID's

I have a kmdf bus driver PCI\VEN_XXXX&DEV_XXXX that creates two statically enumerated PDOs with serial numbers: 217 and 218; one for each Ethernet port. The PDO hardware id is ROOT\MY_NIC_PORT so I can install a NDIS Miniport driver on them.
The bus driver passes SDV and Verifier; but, on reboot two more PDOs get enumerated. On the next reboot I get a duplicate pdo crash.
The toaster example used the device class guid as part of the hardware id. When I tried that my NIC ports no longer showed up in device manager.
Any debug suggestion or work around idea would be appreciated?
pnpCaps.LockSupported = WdfFalse;
pnpCaps.EjectSupported = WdfTrue;
pnpCaps.Removable = WdfTrue;
pnpCaps.DockDevice = WdfFalse;
pnpCaps.UniqueID = WdfTrue;
pnpCaps.SilentInstall = WdfTrue;
pnpCaps.SurpriseRemovalOK = WdfTrue;
pnpCaps.HardwareDisabled = WdfFalse;
pnpCaps.NoDisplayInUI = WdfFalse;
pnpCaps.Address = SerialNo;
pnpCaps.UINumber = SerialNo;
************************************************************
Driver Verifier detected violation:
A driver has enumerated two child PDO's that returned identical Device
ID's.
CulpritAddress = FFFFF8025ED309C4, DeviceObject1 = FFFFE3882FB2F300,
DeviceObject2 = FFFFE3882EBF88D0.
************************************************************
There are a few versions of the toaster bus sample -- assuming you started with this one, then note that it saves its list of child PDOs in the registry. My guess is that your driver is both loading PDOs from the registry, and trying to dynamically create some too.
Set a breakpoint on your driver's version of Bus_PlugInDevice, and see how often it's getting called. Make sure it's never getting called 2x with the same Instance ID.
To clear up a bit of the naming thing: a device setup class is a GUID that is totally unrelated to its hardware ID. For NICs that want to interoperate with the OS's networking stack, you must use the NET setup class, {4d36e972-e325-11ce-bfc1-08002be10318}. You can put anything you want into your hardware ID. I don't really encourage you to put "ROOT\" in there, since that could be confused with a root-enumerated device (which your devices are not). Instead, you can use "yourcompany_yourdevice\port1" as a hardware ID.
While you're thinking about naming things, there are a few things to note about hardware IDs:
Once you assign a HWID, it's rather difficult to change it in a future driver update, without breaking customers who had already installed your device. So get it right the first time.
Once you assign an Instance ID, don't change or reuse it for the lifetime of the device. Otherwise you'll cause this bugcheck, or cause IP addresses to bounce around / get reset. The OS ultimately uses the Instance ID to figure out which NIC port to bind an IP address to.
Think about what happens if someone plugs 2 of your device into a system. Make sure your Instance ID is unique across all ports. You can do this by encoding into the Instance ID the PCI device serial number (if it has one) or by falling back to the PCI bus:device:function.
Don't lump together different types of hardware under the same hardware ID. For example, if the deluxe version of your device supports checksum offload, but the regular version does not -- you should use 2 different hardware IDs for these two different devices. Otherwise it gets difficult to write a single INF that has keywords for both.

Programmatically determine NUMA node or PCI bus, device, function number of Direct3D9Ex device

I'm looking for a way to programmatically determine which NUMA node a particular Direct3D9Ex display adapter is connected to so that I can allocate memory for host to device transfers on that node.
I can use IDirect3D9Ex::GetAdapterIdentifier() to obtain a DeviceName of the form "\.\DISPLAY1".
I can use EnumDisplayDevices() to enumerate the display devices and match this DeviceName to a DeviceKey of the form "\Registry\Machine\System\CurrentControlSet\Control\Video{62E184AC-2614-4AA8-844C-47454B92C142}\0000".
I can use SetupDiEnumDeviceInfo() to enumerate devices and SetupDiGetDeviceProperty() to query properties including DEVPKEY_NAME (e.g. "NVIDIA GeForce GTX TITAN X"), DEVPKEY_Device_LocationInfo (e.g. "PCI bus 2, device 0, function 0") and DEVPKEY_Device_Numa_Node (e.g. 0) but I can't find anything to link one of these devices to either the DeviceName or DeviceKey in EnumDisplayDevices().
I can do equivalent thing is CUDA because cudaDeviceGetPCIBusId() provides the PCI bus, device and function information but I also need to do it in Direct3D9Ex (when CUDA is unavailable).
The other thing I've noticed is that in the registry under "HKLM\SYSTEM\CurrentControlSet\Enum\PCI\VEN_10DE&DEV_17C2&SUBSYS_113210DE&REV_A1" there is a key for each of my display devices and each one contains another key called "Device Parameters" with a value called "VideoID" of the form "{62E184AC-2614-4AA8-844C-47454B92C142}". Unfortunately applications are not supposed to read this part of the registry directly and I don't know how to obtain the same information through the SETUPAPI.

How to pick the right Metal Device for GPU processing on a Mac Pro

When creating a new CIContext with Metal device one has to provide which device (a GPU) to use:
let context = CIContext(
mtlDevice: device
)
On my MacBook Pro for the development purposes I always pick the device associated with the screen with MTLCreateSystemDefaultDevice() method:
guard
let device:MTLDevice = MTLCreateSystemDefaultDevice()
else {
exit(EXIT_FAILURE)
}
However on a Mac Pro which will be used in production in a headless mode there are two GPU cards that I can target. In order to get all available devices one can use MTLCopyAllDevices() method which gives the following output on my Mac Pro:
[
<MTLDebugDevice: 0x103305450> -> <BronzeMtlDevice: 0x10480a200>
name = AMD Radeon HD - FirePro D700
<MTLDebugDevice: 0x103307730> -> <BronzeMtlDevice: 0x104814800>
name = AMD Radeon HD - FirePro D700
]
This Mac Pro will be utilised heavily with hundreds of small tasks per second and every time the new task comes in I need to select a GPU device on which the task will be processed.
Now the question is - is picking a random device from the above array a good idea:
let devices = MTLCopyAllDevices() // get all available devices
let rand = Int(arc4random_uniform(UInt32(devices.count))) // random index
let device = devices[rand] // randomly selected GPU to use
let context = CIContext(
mtlDevice: device
)
Since there are two equal GPU devices on a Mac Pro, targeting always one will be a waste of resources. Logic tells me that with the above code both GPUs will be utilised equally but maybe I'm wrong and MacOS offer some kind of abstraction layer that will intelligently pick the GPU which is less utilised at the time of execution?
Thank you in advance.
Why not just alternate between them? Even if you're committing command buffers from multiple threads, the work should be spread roughly evenly:
device = devices[taskIndex % devices.count]
Also, make sure to avoid creating CIContexts for every operation; those are expensive, so you should keep a list of contexts (one per device) instead.
Note that if you're doing any of your own Metal work (as opposed to just Core Image filtering), you'll need to have a command queue for each device, and any resources you want to use will need to be allocated by their respective device (resources can't be shared by MTLDevices).

How to scan Bluetooth Low energy (BLE) devices which are available/present?

I am working on a windows phone app that can scan BLE devices. I have implemented the logic which is showing the desired devices.
But the problem is that if I remove those devices or switch them off, even then my application returns their names in scan result. I think it is returning cached result. How I can make sure it will show only those devices which are available/present.
I have tried using the additional properties i.e. System.Devices.Aep.IsPresent etc in scan but they are coming as null in result no matter ble devices available or not.
Here is code snippet I am using -
string[] requestedProperties = new string[] { "System.Devices.Aep.IsPresent"
, "System.Devices.Present"
, "System.Devices.Connected"
, "System.Devices.Paired"
, "System.Devices.Aep.IsConnected"
, "System.Devices.AepContainer.IsPresent"
};
diCollection = await DeviceInformation.FindAllAsync(GattDeviceService.GetDeviceSelectorFromUuid(serviceUuid)
, requestedProperties
);
foreach (var diItem in diCollection)
{
Debug.WriteLine("Discovered Device name - " + diItem.Name);
Debug.WriteLine("Discovered Device Additional Properties Below");
foreach (var item in diItem.Properties)
{
Debug.WriteLine("Key-{0} Value-{1}", item.Key, item.Value);
}
}
Here is the Package.appxmanifest capabilities used -
<Capabilities>
<Capability Name="internetClientServer" />
<DeviceCapability Name="bluetooth" />
</Capabilities>
Please help me resolve this small issue. Am I missing something trivial here?
Thanks in advance.
-Jitender
I tried every single one of the properties below with 2 PCs, where both were paired to the Handheld and only one was turned on and a Windows Handheld 8.1.
https://learn.microsoft.com/en-us/windows/uwp/devices-sensors/device-information-properties
The ones needed were AssociationEndpoint related properties, none of which are supported in windows phone 8.1 (even the enumeration is not available) - so basically the api does not provide any way for us to be able to query the connections from cache for whether they are presently available or not.
I tested with every combinations and they do not provide sufficient information (the PC that is turned on is indistinguishable from the one that was not).
The only workaround was to connect to every paired computer on the cache and see if each connection was successful to add this to the list displayed if succeeeded. Every failed connection takes ~4-5 seconds. So this can take some significant amount of delay in showing the list if there are multiple paired computers via in the past. Yet I could not find any other feasible way of checking this, at least this resolves the issue.

How to identify PC (motherboard) in win32 api? [duplicate]

How to uniquely identify computer (mainboard) using C#(.Net/Mono, local application)?
Edition. We can identify mainboard in .Net using something like this (see Get Unique System Identifiers in C#):
using System.Management;
...
ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_MotherboardDevice");
...
But unfortunately Mono does not support System.Management. How to do it under Mono for Linux? - I don't know :(
Write a function that takes a few unique hardware parameters as input and generates a hash out of them.
For example, Windows activation looks at the following hardware characteristics:
Display Adapter
SCSI Adapter
IDE Adapter (effectively the motherboard)
Network Adapter (NIC) and its MAC Address
RAM Amount Range (i.e., 0-64mb, 64-128mb, etc.)
Processor Type
Processor Serial Number
Hard Drive Device
Hard Drive Volume Serial Number (VSN)
CD-ROM / CD-RW / DVD-ROM
You can pick up a few of them to generate your unique computer identifier.
Please see: Get Unique System Identifiers in C#
You realistically have MotherboardID, CPUID, Disk Serial and MAC address, from experience none of them are 100%.
Our stats show
Disk serial Is missing 0.1 %
MAC Is missing 1.3 %
Motherboard ID Is missing 30 %
CPUID Is missing 99 %
0.04% of machines tested yielded no information, we couldn't even read the computer name. It maybe that these were some kind of virtual PC, HyperV or VMWare instance, or maybe just very locked down? In any case your design has to be able to cope with these cases.
Disk serial is the most reliable, but easy to change, mac can be changed and depending on the filtering applied when reading it can change if device drivers are added (hyperv, wireshark etc).
Motherboard and CPUID sometimes return values that are invalid "NONE", "AAAA..", "XXXX..." etc.
You should also note that these functions can be very slow to call (they may take a few seconds even on a fast PC), so it may be worth kicking them off on a background thread as early as possible, you ideally don't want to be blocking on them.
Try this:
http://carso-owen.blogspot.com/2007/02/how-to-get-my-motherboard-serial-number.html
Personally though, I'd go with hard drive serial number. If a mainboard dies and is replaced, that PC isn't valid any more. If the HDD drive is replaced, it doesn't matter too much because the software was on it.
Of course, on the other hand, if the HDD is just moved elsewhere, the information goes with it, so you might want to look at a combination of serial numbers, depending what you want it for.
How about the MAC address of the network card?

Resources