我正在开发一款应用程序,它在窗口中显示类似于视频的东西。我使用的技术在这里描述:介绍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会话,在真实的机器上仍然返回供应商,但它不使用GPU(我可以通过Process Hacker 2和AMD System Monitor看到它(在ATI Radeon的情况下)),因此我仍然具有立方插值的高CPU消耗。在RDP会话到具有ATI Radeon Windows 7的情况下,与通过物理控制台相比大10%。
或者我错了,某种方式RDP使用GPU资源,并且这就是返回IDXGIAdapter :: GetDesc的真实硬件适配器的原因?
DirectDraw
另外我查看了DirectX诊断工具。看起来“DirectDraw加速”信息字段完全返回我所需要的信息。在物理(控制台)会话的情况下,它说“启用”。在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
}
}
}
}
有关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
在硬件适配器的真实机器上进行RDP会话时,标志位为0,但我可以通过Process Hacker 2看到GPU没有被使用。至少在Windows 7上,使用ATI Radeon时,在RDP会话中可以看到更大的CPU使用率。因此,看起来DXGI_ADAPTER_FLAG_SOFTWARE仅适用于Microsoft基本渲染驱动程序。所以问题还没有解决。
问题是:
有没有正确的方法来检查当前Windows会话是否使用真正的硬件视频卡(GPU)?或者可能可以检查ID2D1DeviceContext::DrawBitmap的特定插值模式是否具有硬件实现并在当前会话中使用GPU?
更新:
该主题不是关于检测RDP或Citrix会话的。也不是关于检测应用程序是否在虚拟机内部。我已经进行了所有验证,并对这些情况使用了线性插值。这个主题是关于检测当前Windows会话是否使用真正的GPU来显示桌面。我正在寻找一个更复杂的解决方案,利用DirectX和DXGI的功能来做出决策。