如何检查是否使用了真正的硬件视频适配器

Eug*_*gen 2 c++ windows directx directx-11 dxgi

我开发了一个在窗口中显示类似视频的应用程序。我使用在Direct2D 1.1简介中介绍的技术。就我而言,唯一的区别是最终我使用

ID2D1DeviceContext::CreateBitmap
Run Code Online (Sandbox Code Playgroud)

然后我用

ID2D1Bitmap::CopyFromMemory
Run Code Online (Sandbox Code Playgroud)

复制原始RGB数据到它,然后我打电话

ID2D1DeviceContext::DrawBitmap
Run Code Online (Sandbox Code Playgroud)

绘制位图。我使用高质量的三次插值模式D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC进行缩放以具有最佳图像,但是在某些情况下(RDP,Citrix,虚拟机等),它非常慢并且具有很高的CPU消耗。发生这种情况是因为在这种情况下,使用了非硬件视频适配器。因此,对于非硬件适配器,我正在尝试关闭插值并使用更快的方法。问题是我无法准确检查系统是否具有真正的硬件适配器。

当我打电话D3D11CreateDevice,我用它来与D3D_DRIVER_TYPE_HARDWARE但在虚拟机上它通常返回“微软基础渲染驱动程序”,它是一个软件驱动程序,不使用GPU(它消耗CPU)。因此,目前我检查供应商ID。如果供应商是AMD(ATI),NVIDIA或Intel,那么我将使用三次插值。在另一种情况下,我使用最快的方法,不会消耗很多CPU。

Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
if (SUCCEEDED(m_pD3dDevice->QueryInterface(...)))
{
    Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
    if (SUCCEEDED(dxgiDevice->GetAdapter(&adapter)))
    {
        DXGI_ADAPTER_DESC desc;
        if (SUCCEEDED(adapter->GetDesc(&desc)))
        {
            // NVIDIA
            if (desc.VendorId == 0x10DE ||
                // AMD
                desc.VendorId == 0x1002 || // 0x1022 ?
                // Intel
                desc.VendorId == 0x8086) // 0x163C, 0x8087 ?
            {
                bSupported = true;
            }
        }
     }
 }
Run Code Online (Sandbox Code Playgroud)

即使在虚拟机中,它也适用于物理(控制台)Windows会话。但是对于RDP会话,如果使用的是真实计算机,IDXGIAdapter仍会返回供应商,但它不使用GPU(我可以通过Process Hacker 2和AMD System Monitor(对于ATI Radeon)看到它),因此在三次插值。如果使用ATI Radeon与Windows 7进行RDP会话,则它比通过物理控制台大10%。

还是我弄错了,RDP以某种方式使用了GPU资源,这就是为什么它通过IDXGIAdapter :: GetDesc返回真正的硬件适配器的原因?

DirectDraw

我也看了DirectX诊断工具。看起来“ DirectDraw Acceleration”信息字段恰好返回了我所需要的。如果是物理(控制台)会话,则显示“已启用”。对于RDP和虚拟机(无硬件视频加速)会话,它会显示“不可用”。我查看了来源,从理论上讲我可以使用验证算法。但这实际上是DirectDraw,我没有在应用程序中使用它。我想使用直接链接到ID3D11Device,IDXGIDevice,IDXGIAdapter等的东西。

IDXGIAdapter1 :: GetDesc1和DXGI_ADAPTER_FLAG

我也尝试使用IDXGIAdapter1 :: GetDesc1并检查标志。

Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
if (SUCCEEDED(m_pD3dDevice->QueryInterface(...)))
{
    Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
    if (SUCCEEDED(dxgiDevice->GetAdapter(&adapter)))
    {
         Microsoft::WRL::ComPtr<IDXGIAdapter1> adapter1;
         if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1), reinterpret_cast<void**>(adapter1.GetAddressOf()))))
         {
             DXGI_ADAPTER_DESC1 desc;
             if (SUCCEEDED(adapter1->GetDesc1(&desc)))
             {
                    // desc.Flags
                    // DXGI_ADAPTER_FLAG_NONE         = 0,
                    // DXGI_ADAPTER_FLAG_REMOTE       = 1,
                    // DXGI_ADAPTER_FLAG_SOFTWARE     = 2,
                    // DXGI_ADAPTER_FLAG_FORCE_DWORD  = 0xffffffff
             }
         }
     }
 }
Run Code Online (Sandbox Code Playgroud)

有关DXGI_ADAPTER_FLAG_SOFTWARE标志的信息

 Virtual Machine RDP Win Serv 2012 (Microsoft Basic Render Driver) -> (0x02) DXGI_ADAPTER_FLAG_SOFTWARE
 Physical Win 10 (Intel Video) -> (0x00) DXGI_ADAPTER_FLAG_NONE
 Physical Win 7 (ATI Radeon) - > (0x00) DXGI_ADAPTER_FLAG_NONE
 RDP Win 10 (Intel Video) -> (0x00) DXGI_ADAPTER_FLAG_NONE
 RDP Win 7 (ATI Radeon) -> (0x00) DXGI_ADAPTER_FLAG_NONE
Run Code Online (Sandbox Code Playgroud)

在具有硬件适配器的真实计算机上进行RDP会话的情况下,标志== 0,但是正如我通过Process Hacker 2看到的那样,未使用GPU。至少在带有ATI Radeon的Windows 7上,在RDP会话的情况下,我可以看到更大的CPU使用率。因此,看起来DXGI_ADAPTER_FLAG_SOFTWARE仅适用于Microsoft Basic Render驱动程序。所以这个问题没有解决。

问题

是否有正确的方法来检查当前Windows会话是否使用了真正的硬件视频卡(GPU)?还是可以检查ID2D1DeviceContext :: DrawBitmap的特定插值模式是否具有硬件实现并在当前会话中使用GPU?

UPD

主题不是关于检测RDP或Citrix会话。这与检测应用程序是否在虚拟机内部无关。我已经有了所有验证,并在这些情况下使用了线性插值。主题是有关检测当前Windows会话是否使用真实的GPU来显示桌面。我正在寻找一种更复杂的解决方案,以使用DirectX和DXGI的功能进行决策。

Chu*_*urn 5

如果要检测Microsoft Basic Renderer,最好的选择是使用其VID / PID组合:

ComPtr<IDXGIDevice> dxgiDevice;
if (SUCCEEDED(device.As(&dxgiDevice)))
{
    ComPtr<IDXGIAdapter> adapter;
    if (SUCCEEDED(dxgiDevice->GetAdapter(&adapter)))
    {
        DXGI_ADAPTER_DESC desc;
        if (SUCCEEDED(adapter->GetDesc(&desc)))
        {
            if ( (desc.VendorId == 0x1414) && (desc.DeviceId == 0x8c) )
            {
                // WARNING: Microsoft Basic Render Driver is active.
                // Performance of this application may be unsatisfactory.
                // Please ensure that your video card is Direct3D10/11 capable
                // and has the appropriate driver installed.
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请参见MSDNDirect3D 11创建设备剖析

对于测试/调试,您可能会发现不想显式阻止这些情况,但是确实希望向用户提供某种警告或注意反馈,告知他们使用软件而不是硬件渲染。

从Win32经典桌面应用程序进行远程桌面检测最好直接通过进行GetSystemMetrics( SM_REMOTESESSION )

参见MSDN