这是对英特尔硬件的简短介绍的第一部分,以及 i915 中的 GEM(图形执行管理器)的作用。查看概述以获取其他部分的链接。
地址空间和页表
- 英特尔 GPU 只能访问系统内存,需将页面绑定到 GPU 页表中。
- GPU 有自己的虚拟地址空间 GTT,现代芯片为 2GB 大,早期芯片较小。Sandybridge 及更新平台还有 per-process GTT(PPGTT),大小相同,只能由 GPU 引擎访问,扫描输出缓冲区必须在全局 GTT 中。
- PPGTT 的目的是隔离不同的 GPU 进程,但上下文切换时间长,早期 TLB 在使用不同地址空间时会出错。现在使用 PPGTT 是因为其 PTE 可驻留在可缓存内存中,有利于 TLB 查找。
- CPU 可通过将主内存中的后备存储直接映射到 CPU 地址空间来访问图形内存,为方便 CPU 通过 GTT 访问图形对象,GTT 的低部分(通常前 256MB)可通过 igd 的 bar 2 pci mmio 空间访问,用于转发 CPU 访问的芯片块通常称为系统代理(SA),PPGTT 没有这样的窗口。
- 页表有点复杂,GTT 页表只有一级,需要 2MB 连续的页表空间,由固件从窃取的内存中分配,通过寄存器 mmio bar 中的别名写入 PTE 以允许 SA 使 TLB 失效,近期版本需手动使 SA TLB 失效并加速映射/解除映射操作。PPGTT 有两级页表,PTE 布局与全局 GTT 中的 PTE 相同,但位于正常系统内存中,PDE 特殊,需从 GTT 页表中窃取 512 个条目并通过相同的 mmio 别名写入。VT-d/DMAR 支持会增加一层将 (PP)GTT PTE 中的总线地址重新映射到实际内存地址,在代码中使用常见的 linux dma api 处理。
平铺和置换
- 现代处理器通过预取器和缓存来掩盖内存延迟和带宽不足,而图形通常处理 2D 数据,会导致不同的访问模式,如绘制垂直线会导致大量缓存和 TLB 缺失。
- 解决方案是将 2D 缓冲区的布局重排成固定大小和高度的块(4KB),Intel 硬件有两种不同的平铺布局:X 平铺(512 字节宽 8 行)和 Y 平铺(128 字节×32 行),还有特殊的 W 平铺布局仅用于单独的模板缓冲区。
- 双通道内存会导致通道交错模式与 X 平铺一起导致病理访问模式,通过异或(XOR)更高位到特定位可平衡访问模式。大多数旧平台的固件在设置内存控制器时选择是否启用置换,而 Sandybridge 及以后的驱动程序控制置换。
栅栏
- 通过额外的状态位可指定 GPU 函数的平铺布局,对于一些没有此类位的函数,硬件提供了有限的栅栏。
- Intel 硬件栅栏是全局 GTT 中的特殊范围,使平铺区域看起来线性,现代平台有 16 个可自由设置,大多数 GPU GTT 客户端忽略栅栏,但 SA 会遵守,这是 CPU 通过 GTT mmio 窗口访问缓冲区对象有用的第一个原因,且只能访问 X 和 Y 平铺区域,模板缓冲区需手动处理。
- 管理栅栏很简单,将其保存在 LRU 中,若没有空闲栅栏,确保当前访问该缓冲区对象的内容不需要栅栏,以阻止 CPU 通过 mmio 窗口访问对象,对于需要栅栏的旧平台,跟踪最后需要栅栏的命令提交并等待其完成,还可允许平铺对象小于所需的栅栏区域以避免浪费内存。
下一部分将介绍如何向 GPU 提交工作及相关问题。Mika Kuoppala 指出关于 PPGTT 的 PDE 用于 GTT PTE 窃取的数学计算有误,现已修正。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。