window 显示驱动开发-处理内存段(一)
视频内存管理器 (VidMm) 负责管理 GPU 的地址空间。 在此之前,内核模式显示微型端口驱动程序 (KMD) 必须通过使用内存段将 GPU 的地址空间描述为 VidMm。
KMD 创建内存段以概括和虚拟化视频内存资源。 它可以根据硬件支持的存储器类型(例如,帧缓冲区内存或系统内存光圈)配置内存段。
在驱动程序初始化期间,KMD 必须返回描述 VidMm 如何管理内存资源的段类型列表。 KMD 指定了它支持的段类型的数量,并通过响应对其 DxgkDdiQueryAdapterInfo 函数的调用来描述每种段类型。 驱动程序使用 DXGK_SEGMENTDESCRIPTOR 结构描述每个段。 有关详细信息,请参阅初始化内存段的使用。
此后,段的数量和类型保持不变。 VidMm:
- 确保每个进程在任何特定段中都能获得公平的资源份额,
- 独立管理所有段。
段不重叠。 因此,VidMm 可以从一个段分配相当数量的视频内存资源,而不管应用程序从另一个段持有多少资源。
KMD 为每个内存段分配一个段标识符。 稍后,当 VidMm 请求为视频资源创建分配并呈现这些资源时,KMD:
- 标识支持请求的段。
- 按顺序指定驱动程序希望 VidMm 使用的段。
1. 内存段(Memory Segments)的核心概念
(1) 内存段的作用
硬件资源抽象:
- KMD 通过内存段将 GPU 的物理内存(如显存、系统内存光圈)虚拟化为逻辑段,供 VidMm 统一管理。
例如:
- 帧缓冲区段(DXGK_SEGMENT_VIDEO_MEMORY):GPU 专用显存。
- 系统内存光圈段(DXGK_SEGMENT_SYSTEM_MEMORY):CPU 可访问的共享内存。
- 重排范围段(DXGK_SEGMENT_SWIZZLING):用于优化内存布局的特定区域。
资源隔离性:
- 每个段 不重叠,VidMm 可独立管理不同段的内存分配。
- 例如:应用程序占用显存段不影响系统内存段的可用性。
(2) 段的静态性
初始化时确定:
- KMD 在驱动初始化阶段(响应 DxgkDdiQueryAdapterInfo)通过 DXGK_SEGMENTDESCRIPTOR 结构定义所有支持的段类型。
- 段的数量和属性 后续不可更改(除非驱动重启)。
2. KMD 的职责:段配置
(1) 段描述符(DXGK_SEGMENTDESCRIPTOR)
KMD 需为每个段填充以下关键字段:
字段 | 描述 |
---|---|
BaseAddress | 段的起始物理地址(GPU 视角)。 |
Size | 段的总大小(字节)。 |
Flags | 段属性(如可缓存、可写、CPU 可见等)。 |
SegmentId | 段的唯一标识符(由 KMD 分配)。 |
(2) 示例:多段配置
// KMD 在 DxgkDdiQueryAdapterInfo 中返回的段列表示例
DXGK_SEGMENTDESCRIPTOR Segments[2] = {// 显存段(专用 VRAM){.BaseAddress = 0x80000000,.Size = 0x40000000, // 1GB.Flags = DXGK_SEGMENT_FLAGS_VIDEO_MEMORY,.SegmentId = 0x1,},// 系统内存光圈段(共享内存){.BaseAddress = 0x00000000, // CPU 物理地址.Size = 0x20000000, // 512MB.Flags = DXGK_SEGMENT_FLAGS_SYSTEM_MEMORY,.SegmentId = 0x2,}
};
3. VidMm 的职责:段管理
(1) 公平分配与隔离
进程级配额:
- VidMm 确保每个进程在任意段中 公平共享资源(如限制单个进程占用显存的比例)。
段独立性:
- 从段 A 分配内存时,不受段 B 的占用情况影响(避免资源竞争)。
(2) 分配策略
当应用程序请求内存时(如创建纹理):
VidMm 选择候选段:
- 根据资源需求(如 GPU 专用或 CPU 可访问)筛选匹配的段。
KMD 指定优先级:
- 驱动通过 DxgkDdiCreateAllocation 的 PreferredSegment 参数建议优先段。
VidMm 最终决策:
- 结合段剩余空间、进程配额等条件分配内存。
4. 内存分配的实际流程
(1) 用户模式请求
- 应用程序调用 ID3D12Device::CreateResource。
- UMD(用户模式驱动)通过 D3DKMTCreateAllocation 向内核发起请求。
(2) VidMm 与 KMD 交互
VidMm 选择段:
- 检查资源属性(如 D3D12_RESOURCE_FLAGS)匹配的段。
调用 KMD 确认:
- 触发 DxgkDdiCreateAllocation,KMD 验证硬件支持性。
分配 GPU 虚拟地址:
- VidMm 在选定段中分配虚拟地址范围(GPU VA)。
返回资源句柄:
- UMD 获得可操作的资源句柄。
(3) 示例:显存分配
5. 高级场景与优化
(1) 多 GPU 系统
跨设备段:
- KMD 可为每个 GPU 定义独立段,VidMm 协调跨设备内存迁移(如 dxgmms1.sys 处理)。
(2) 内存压缩
驱动支持:
- KMD 可通过段标志声明支持压缩(如 DXGK_SEGMENT_FLAGS_COMPRESSIBLE),VidMm 据此优化分配。
(3) 动态资源升降级
分页策略:
- VidMm 可自动将闲置资源从显存段迁移到系统内存段(调用 DxgkDdiBuildPagingBuffer)。
6. 调试与问题排查
(1) 常见问题
(2) 关键 ETW 事件
- DXGK_VIRTUALADDRESS:跟踪 GPU VA 分配。
- DXGK_SEGMENT:监控段的使用情况。
7. 总结
设计优势:
- 硬件无关性:VidMm 通过抽象段统一管理不同 GPU 的内存。
- 多进程安全:段隔离避免应用程序相互干扰。
- 灵活扩展:支持未来内存技术(如 CXL 共享内存)。
通过内存段机制,WDDM 实现了高效的 GPU 内存虚拟化和资源共享,为复杂图形与计算负载奠定基础。