检索图形内存数字
创建图形应用程序的软件开发人员可以使用从 Windows Vista 开始的 Microsoft DirectX 版本 10 API 在运行 Windows 显示驱动程序模型 (WDDM) 显示驱动程序的计算机上检索准确的图形内存数集。 以下步骤演示如何检索图形内存编号:
由于新的图形内存报告仅在运行 Windows 显示驱动程序模型 (WDDM) 显示驱动程序的计算机上可用,因此应用程序必须首先调用以下函数以确认驱动程序模型
HasWDDMDriver()
{
LPDIRECT3DCREATE9EX pD3D9Create9Ex = NULL;
HMODULE hD3D9 = NULL;
hD3D9 = LoadLibrary( L"d3d9.dll" );
if ( NULL == hD3D9 ) {
return false;
}
//
// Try to create a IDirect3D9Ex interface (also known as a DX9L
// interface).
// This interface can only be created if the driver is written
// according to the Windows Display Driver Model (WDDM).
//
pD3D9Create9Ex = (LPDIRECT3DCREATE9EX) GetProcAddress (
hD3D9, "Direct3DCreate9Ex" );
return pD3D9Create9Ex != NULL;
}
检索图形内存信息的 DirectX 应用程序开发指南
在 Windows Vista 及更高版本中,使用 WDDM 显示驱动程序的计算机可以通过 DirectX API 检索准确的图形内存信息。以下是开发图形应用程序时获取这些数据的完整方法:
1. 验证 WDDM 驱动程序模型
在尝试检索图形内存信息前,必须确认系统正在使用 WDDM 驱动程序:
#include <windows.h>
#include <dxgi.h>
#include <d3d11.h>
bool IsWDDMDriver()
{
IDXGIFactory* pFactory = nullptr;
if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory)))
{
return false;
}
IDXGIAdapter* pAdapter = nullptr;
if (FAILED(pFactory->EnumAdapters(0, &pAdapter)))
{
pFactory->Release();
return false;
}
DXGI_ADAPTER_DESC desc;
if (FAILED(pAdapter->GetDesc(&desc)))
{
pAdapter->Release();
pFactory->Release();
return false;
}
pAdapter->Release();
pFactory->Release();
// WDDM 1.0+ 驱动程序会在描述中包含特定信息
return true;
}
2. 使用 DirectX 10/11 API 获取内存信息
基本内存信息 (DXGI_ADAPTER_DESC)
void GetBasicVideoMemoryInfo()
{
IDXGIFactory* pFactory = nullptr;
CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory);
IDXGIAdapter* pAdapter = nullptr;
pFactory->EnumAdapters(0, &pAdapter);
DXGI_ADAPTER_DESC adapterDesc;
pAdapter->GetDesc(&adapterDesc);
printf("显卡描述: %S\n", adapterDesc.Description);
printf("专用显存: %.2f GB\n", adapterDesc.DedicatedVideoMemory / 1024.0 / 1024.0 / 1024.0);
printf("专用系统内存: %.2f GB\n", adapterDesc.DedicatedSystemMemory / 1024.0 / 1024.0 / 1024.0);
printf("共享系统内存: %.2f GB\n", adapterDesc.SharedSystemMemory / 1024.0 / 1024.0 / 1024.0);
pAdapter->Release();
pFactory->Release();
}
高级内存信息 (Windows 10+ 使用 IDXGIAdapter3)
对于 Windows 10 及更高版本,可以使用更详细的查询方法:
void GetAdvancedVideoMemoryInfo()
{
IDXGIFactory1* pFactory = nullptr;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&pFactory);
IDXGIAdapter1* pAdapter = nullptr;
pFactory->EnumAdapters1(0, &pAdapter);
IDXGIAdapter3* pAdapter3 = nullptr;
if (SUCCEEDED(pAdapter->QueryInterface(__uuidof(IDXGIAdapter3), (void**)&pAdapter3))
{
DXGI_QUERY_VIDEO_MEMORY_INFO localMemoryInfo;
pAdapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &localMemoryInfo);
DXGI_QUERY_VIDEO_MEMORY_INFO nonLocalMemoryInfo;
pAdapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL, &nonLocalMemoryInfo);
printf("本地内存段(显存):\n");
printf(" 当前使用量: %.2f MB\n", localMemoryInfo.CurrentUsage / 1024.0 / 1024.0);
printf(" 当前预算: %.2f MB\n", localMemoryInfo.Budget / 1024.0 / 1024.0);
printf(" 可用保留: %.2f MB\n", localMemoryInfo.AvailableForReservation / 1024.0 / 1024.0);
printf(" 当前保留: %.2f MB\n", localMemoryInfo.CurrentReservation / 1024.0 / 1024.0);
printf("非本地内存段(系统共享内存):\n");
printf(" 当前使用量: %.2f MB\n", nonLocalMemoryInfo.CurrentUsage / 1024.0 / 1024.0);
printf(" 当前预算: %.2f MB\n", nonLocalMemoryInfo.Budget / 1024.0 / 1024.0);
pAdapter3->Release();
}
pAdapter->Release();
pFactory->Release();
}
3. 处理不同 Windows 版本的兼容性
void GetVideoMemoryInfoCompatible()
{
if (IsWindows10OrGreater())
{
// Windows 10+ 使用更详细的查询
GetAdvancedVideoMemoryInfo();
}
else
{
// Windows Vista/7/8 使用基本查询
GetBasicVideoMemoryInfo();
}
}
4. 应用程序内存管理建议
-
基于预算分配:
// 检查是否有足够内存预算 DXGI_QUERY_VIDEO_MEMORY_INFO memoryInfo; pAdapter3->QueryVideoMemoryInfo(0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL, &memoryInfo); if (requiredMemory > memoryInfo.Budget - memoryInfo.CurrentUsage) { // 内存不足,需要调整资源或显示警告 }
2.内存压力事件处理
// 注册内存事件通知 (Windows 10+) pAdapter3->RegisterVideoMemoryBudgetChangeNotificationEvent(hEvent, &pdwCookie);
3.多GPU系统处理
// 枚举所有适配器 IDXGIAdapter* pAdapter = nullptr; for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; ++i) { // 获取每个适配器的信息 }
5. 错误处理和回退机制
try { GetVideoMemoryInfoCompatible(); } catch (const std::exception& e) { // 记录错误并使用保守的默认值 printf("获取图形内存信息失败: %s\n", e.what()); printf("使用保守内存估计...\n"); // 设置默认值或禁用高级图形功能 }
应用程序确定显示驱动程序模型为 WDDM 后,应用程序可以使用新的 DirectX 版本 10 API 获取图形内存编号。 应用程序从以下 DXGI_ADAPTER_DESC 数据结构中获取图形内存数字,该结构存在于 Dxgi.h 中,并包含在 DirectX 软件开发工具包 (SDK) 中。
typedef struct DXGI_ADAPTER_DESC {
WCHAR Description[ 128 ];
UINT VendorId;
UINT DeviceId;
UINT SubSysId;
UINT Revision;
SIZE_T DedicatedVideoMemory;
SIZE_T DedicatedSystemMemory;
SIZE_T SharedSystemMemory;
LUID AdapterLuid;
} DXGI_ADAPTER_DESC;
由于在 Windows Vista 和更高版本的桌面和 DirectX 游戏中广泛使用图形,因此在 Windows Vista 及更高版本上运行的软件应能够准确确定可用图形内存量。 WDDM 管理图形内存本身的虚拟化,并确保准确报告图形内存的各个方面。 应用程序开发人员和软件供应商应利用 DirectX 版本 10 API 在具有 Windows Vista 显示驱动程序的计算机上检索准确的图形内存值集。