Find out the active graphics driver using SetupAPI - c++

I try to find out the version of the currently active graphics driver on Windows using C++ and SetupAPI. The solution roughly looks like
Call SetupDiGetClassDevs for GUID_DEVCLASS_DISPLAY.
Call SetupDiBuildDriverInfoList for the result set.
Call SetupDiEnumDriverInfo for the device set with SPDIT_COMPATDRIVER, which gives me all known drivers compatible with the GPU.
The result includes the fallback driver from Microsoft, which I can easily exclute, but it also includes all driver versions (from NVIDIA) that have been installed on the system.
The question is: How do I find out which of the drivers is actually running?
I know from the SP_DEVINFO_DATA returned in step 1 how the driver service is called and I also get some kind of registry key, but I do not see how I could relate this to the SP_DRVINFO_DATA. I also know that NVAPI provides driver management capabilities, but I would prefer a solution that works with GPUs of all kinds of vendors.

Just FYI, you can also query the SPDRP_DRIVER via SetupDiGetDeviceRegistryProperty and then lookup that registry value under Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\. That key contains all the driver info. Here is some sample code from WebKit that actually retrieves GPU info this way.

I found the solution in the meantime at Why does SetupDiEnumDriverInfo give two version numbers for my driver: You need to update the install parameters of the device information set with the DI_FLAGSEX_INSTALLEDDRIVER flag before step 3.

Related

Get the currently "Active" driver for a device in C++

I have used SetupAPI to enumerate all the drivers, build a list of its properties etc etc. But what i want is to enumerate only the "Active" drivers for any device.
Eg. For a Intel HD 5500, There are a couple of drivers installed in the System with different versions like
20.19.15.4531
20.19.15.4454
But the version shown in DeviceManager is 20.19.15.4531. I need to get only this version.
When I use SetupAPI, I Get both the drivers. I've tried the solution listed at This Post but I can confirm that the solution does not work for me.
SetupDiGetSelectedDriver() also does not work. i.e. It works only when we are installing a driver to the store using SetupAPI functions.
Any Help will be really appreciated.
Note : There is no problem in finding and Enumerating the drivers. I use SetupDiBuildDriverInfoList() and SetupDiEnumDrvInfo(), and they work as expected.
I Finally ended up building a list of current drivers using WMI in c++. Couldn't find a way out!

DirectX11 Desktop duplication not working with NVIDIA

I'm trying too use DirectX desktop duplication API.
I tried running exmaples from
http://www.codeproject.com/Tips/1116253/Desktop-Screen-Capture-on-Windows-via-Windows-Desk
And from
https://code.msdn.microsoft.com/windowsdesktop/Desktop-Duplication-Sample-da4c696a
Both of these are examples of screen capture using DXGI.
I have NVIDIA GeForce GTX 1060 with Windows 10 Pro on the machine. It has Intelâ„¢ Core i7-6700HQ processor.
These examples work perfectly fine when NVIDIA Control Panel > 3D Settings is selected to Auto select processor.
However if I set the setting manually to NVIDIA Graphics Card the samples stop working.
Error occurs at the following line.
//IDXGIOutput1* DxgiOutput1
hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl);
Error in hr(HRESULT) is DXGI_ERROR_UNSUPPORTED 0x887A0004
I'm new to DirectX and I don't know the issue here, is DirectX desktop duplication not supported on NVIDIA ?
If that's the case then is there a way to select a particular processor at the start of program so that program can run with any settings ?
#Edit
After looking around I asked the developer (Evgeny Pereguda) of the second sample project on codeproject.com
Here's a link to the discussion
https://www.codeproject.com/Tips/1116253/Desktop-Screen-Capture-on-Windows-via-Windows-Desk?msg=5319978#xx5319978xx
Posting the screenshot of the discussion on codeproject.com in case original link goes down
I also found an answer on stackoverflow which unequivocally suggested that it could not be done with the desktop duplication API referring to support ticket at microsoft's support site https://support.microsoft.com/en-us/help/3019314/error-generated-when-desktop-duplication-api-capable-application-is-ru
Quote from the ticket
This issue occurs because the DDA does not support being run against
the discrete GPU on a Microsoft Hybrid system. By design, the call
fails together with error code DXGI_ERROR_UNSUPPORTED in such a
scenario.
However there are some applications which are efficiently duplicating desktop on windows in both modes (integrated graphics and discrete) on my machine. (https://www.youtube.com/watch?v=bjE6qXd6Itw)
I have looked into the installation folder of the Virtual Desktop on my machine and can see following DLLs of interest
SharpDX.D3DCompiler.dll
SharpDX.Direct2D1.dll
SharpDX.Direct3D10.dll
SharpDX.Direct3D11.dll
SharpDX.Direct3D9.dll
SharpDX.dll
SharpDX.DXGI.dll
SharpDX.Mathematics.dll
Its probably an indication that this application is using DXGI to duplicate desktop, or may be the application is capable of selecting a specific processor before it starts.
Anyway the question remains, is there any other efficient method of duplicating desktop in both modes?
The likely cause is certain internal limitation for Desktop Duplication API, described in Error generated when Desktop Duplication API-capable application is run against discrete GPU:
... when the application tries to duplicate the desktop image against the discrete GPU on a Microsoft Hybrid system, the application may not run correctly, or it may generate one of the following errors:
Failed to create windows swapchain with 0x80070005
CDesktopCaptureDWM: IDXGIOutput1::DuplicateOutput failed: 0x887a0004
The article does not suggest any other workaround except use of a different GPU (without more specific detail as for whether it is at all achievable programmatically):
To work around this issue, run the application on the integrated GPU instead of on the discrete GPU on a Microsoft Hybrid system.
Microsoft introduced a registry value that can be set programmatically to control which GPU an application runs on. Full answer here.

Program to check CUDA presence needs CUDA?

I wrote a simple application that checks if NVIDIA CUDA is available on the computer. It simply displays true if a CUDA-capable device is found.
I send the app to a second PC, and the application didn't run - a dialog box showed up that cudart.dll was not found. I want to check if CUDA is present and it requires CUDA to do that :)
I am using CUDA 5.0, VS2012, VC++11, Windows 7.
Can I compile the application in a way, that all CUDA libraries are inside the executable?
So the scenario is:
My app is compiled & sent to a computer
The computer can:
be running windows, linux (my app is compatible with the system)
have a gpu or not
have an nvidia gpu or not
have CUDA installed or not
My app should return true only if 2.3 and 2.4 are positive (GPU with CUDA)
As an opening comment, I think the order and number of steps in your edit is incorrect. It should be:
Programs starts and attempts to load the runtime API library
If the runtime library is present, attempt to use it to enumerate devices.
If step 1 fails, you do not have the necessary runtime support, and CUDA cannot be used. If 2 fails, there is not a compatible driver and GPU present in the system and CUDA cannot be used. If they both pass, you are good to go.
In step 1 you want to use something like dlopen on Linux and handle the return status. On Windows, you probably want to use the DLL delay loading mechanism (Sorry, not a Windows programmer, can't tell you more than that).
In both cases, if the library loads, then fetch the address of cudaGetDeviceCount via the appropriate host OS API and call it. That tells you whether there are compatible GPUs which can be enumerated. What you do after you find an apparently usable GPU is up to you. I would check for compute status and try establishing a context on it. That will ensure that a fully functional runtime/driver combination is present and everything works.
Linking to a different post on stackoverflow: detecting-nvidia-gpus-without-cuda
This shows the whole sequence to check if the cuda api is available and accessible.
I think that using only the software there is no reliable way to ensure that a GPU is Cuda-capable or not, especially if we consider that Cuda is a driver-based technology and for the OS Cuda doesn't exist if the driver says that Cuda doesn't exist.
I think that the best way to do this is the old fashion way, consider checking this simple web page and you will get a much more reliable answer.
create a plugin for your application that dynamically links to the relevant CUDA-libraries and performs the check.
then try loading the plugin and run it's check.
if the plugin fails to load, then you don't have the CUDA-libraries installed, so you can assume False
if the plugin succeeds to load, then you have CUDA-libs installed and can perform the check, whether the hardware supports CUDA as well.
As a late andditional answer:
I am struggling with the same problem (detecting cuda installation without using it) and my solution so far is
ensuring LoadLibraryA("nvcuda.dll") != nullptr (tells you pretty much only if there is an nvidia card installed, though)
checking for environment variable CUDA_PATH (or in my case, CUDA_PATH_V8_0), since that seems to be set by the cuda installation: const char * szCuda8Path = std::getenv("CUDA_PATH_V8_0"); (must be != nullptr)
Use cudaGetDeviceCount() to know if the computer is CUDA-capable.
According to this thread, you cannot statically link cudart.dll.
There are workarounds: embed the CUDA runtime as a resource in your executable, then extract it when your program runs, then dynamically link.
You can also use nvidia-smi to see if CUDA is installed on a machine.

Accessing device via existing device driver

I'm looking to write an application that will allow me to control music, etc with a remote control. The infrared receiver I have is built into my MacBook Pro which is running Windows.
What I want to know is how can I go about this? Most of the information I can find online is specific to writing Windows device drivers and I'm having trouble finding out how to use drivers that already exist for a device.
Is it absolutely necessary for me to write my own drivers or is there a way to use the drivers provided by Apple?
On Windows you communicate with a driver by first opening it using CreateFile and subsequently sending commands to it using DeviceIoControl. You need documentation for the driver's API though to understand what functionality is available through which control codes and what parameters they expect. Digging up that information is probably the hard part.

Can EnumDisplayDevices detect a device if it's drivers are not installed?

I need to deploy a hard drive image to a customer which on the first boot detects the graphics card type and installs the appropriate drivers. So what this means in terms of code is that I need to detect the deviceid of the graphics card in C++ without using GPU specific libraries like NvAPI or AMD SDK.
I know that EnumDisplayDevices can retrieve deviceids, so all I need to know is whether this is possible with EnumDisplayDevices, or whether the GPUs drivers must be installed before EnumDisplayDevices can detect it. How the function actually goes about obtaining this information isn't mentioned in the MSDN article.
Thanks,
Bill.
For my purposes I needed to know the name and model of the graphics card, and it turns out EnumDisplayDevices can't retrieve this information until the drivers are installed.