window 显示驱动开发-报告图形内存(四)

检索图形内存数字

创建图形应用程序的软件开发人员可以使用从 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. 应用程序内存管理建议

  1. 基于预算分配

    复制代码
    // 检查是否有足够内存预算
    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 显示驱动程序的计算机上检索准确的图形内存值集。

相关推荐
路溪非溪1 小时前
Linux驱动如何向应用层提供sysfs操作接口
linux·arm开发·驱动开发
sukalot20 小时前
window显示驱动开发—监视筛选器驱动程序(三)
驱动开发
墨染天姬20 小时前
【android 驱动开发九】生产者-消费者模型
android·驱动开发
搞一搞汽车电子2 天前
S32K3平台eMIOS 应用说明
开发语言·驱动开发·笔记·单片机·嵌入式硬件·汽车
cxr8282 天前
Claude-Flow AI协同开发:基础入门之 AI编排
人工智能·驱动开发
林森见鹿4 天前
测试驱动开发 (TDD) 与 Claude Code 的协作实践详解
人工智能·驱动开发·tdd
智者知已应修善业4 天前
【multisim汽车尾灯设计】2022-12-1
驱动开发·经验分享·笔记·汽车·硬件架构·硬件工程
cxr8285 天前
Claude Code PM 深度实战指南:AI驱动的GitHub项目管理与并行协作
人工智能·驱动开发·github
jz_ddk5 天前
[Linux] Linux标准块设备驱动详解:从原理到实现
linux·运维·服务器·驱动开发
三只小黄人5 天前
AI驱动开发:颠覆传统编程新范式
人工智能·驱动开发