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

时间:2018-01-18 16:43:30

标签: c++ windows directx directx-11 dxgi

我开发了一个应用程序,在其窗口中显示类似于视频的内容。我使用这里描述的技术Introducing Direct2D 1.1。在我的情况下,唯一的区别是最终我使用

创建一个位图
ID2D1DeviceContext::CreateBitmap

然后我用

ID2D1Bitmap::CopyFromMemory

将原始RGB数据复制到它然后我调用

ID2D1DeviceContext::DrawBitmap

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

当我调用D3D11CreateDevice时,我将它与D3D_DRIVER_TYPE_HARDWARE一起使用,但在虚拟机上它通常会返回“Microsoft Basic Render Driver”,这是一个软件驱动程序,不使用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;
            }
        }
     }
 }

即使在虚拟机中也适用于物理(控制台)Windows会话。但是对于RDP会话,IDXGIAdapter仍会在真机的情况下返回供应商,但它不使用GPU(我可以通过Process Hacker 2和AMD System Monitor(在ATI Radeon的情况下)看到它)所以我仍然有很高的CPU消耗三次插值。对于使用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
             }
         }
     }
 }

Information about the DXGI_ADAPTER_FLAG_SOFTWARE flag

 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

如果在具有硬件适配器的真实机器上进行RDP会话,Flags == 0但是我可以通过Process Hacker 2看到GPU未被使用。至少在使用ATI Radeon的Windows 7上,我可以在RDP会话中看到更大的CPU使用率。因此看起来DXGI_ADAPTER_FLAG_SOFTWARE仅适用于Microsoft Basic Render Driver。所以问题没有解决。

问题

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

UPD

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

1 个答案:

答案 0 :(得分:4)

如果要检测Microsoft Basic渲染器,最好的选择是使用它的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.
            }
        }
    }
}

请参阅MSDNAnatomy of Direct3D 11 Create Device

  

您可能会发现您不希望明确阻止这些情况的测试/调试,但您确实希望向用户提供某种警告或通知反馈他们正在使用软件而不是硬件渲染。< / p>

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

请参阅MSDN