映射进入磁贴池

使用 D3D11_RESOURCE_MISC_TILED 标志创建资源时,构成资源的磁贴来自指向磁贴池中的位置。 磁贴池是一个内存池(由后台的一个或多个分配提供支持 - 应用程序看不见)。 作系统和显示驱动程序管理此内存池,并且应用程序可以轻松理解内存占用情况。 平铺资源通过指向磁贴池中的位置映射 64KB 区域。 此设置的一个后果是,它允许多个资源共享和重复使用同一磁贴,并允许在资源中的不同位置重复使用同一磁贴(如果需要)。

在磁贴池中填充资源磁贴的灵活性成本在于,资源必须执行定义和维护磁贴池中哪些磁贴的映射表示资源所需的磁贴。 可以更改磁贴映射。 此外,并非资源中的所有磁贴都需要一次映射;资源可以具有 NULL 映射。 NULL 映射将磁贴定义为从访问磁贴的资源的角度来看不可用。

可以创建多个磁贴池,并且任意数量的平铺资源可以同时映射到任何给定的磁贴池中。 磁贴池也可以增长或收缩。 有关详细信息,请参阅 磁贴池大小调整。 为了简化显示驱动程序和运行时实现而存在的一个约束是,给定的平铺资源一次只能将映射映射到最多一个磁贴池(而不是同时映射到多个磁贴池)。

与平铺资源本身(即独立磁贴池内存)关联的存储量与任何给定时间实际映射到池的磁贴数大致成正比。 在硬件中,这一事实归结为大致缩放页表存储的内存占用量以及映射的磁贴量(例如,根据需要使用多级页表方案)。

磁贴池可以视为一种完全软件抽象,它使 Direct3D 应用程序能够有效地对图形处理单元(GPU)上的页表进行编程,而无需知道低级别实现详细信息(或直接处理指针地址)。 磁贴池不会在硬件中应用任何其他间接级别。 使用页面目录等构造的单个级别页表的优化与磁贴池概念无关。

让我们探讨页表本身在最坏的情况下可能需要的存储(尽管在实践中,实现只需要与映射的内容大致成比例的存储)。

假设每个页表条目为 64 位。

对于针对单个图面命中情况最差的页面表大小,鉴于 Direct3D 11 中的资源限制,假设创建一个平铺资源时,每个元素格式为 128 位(例如 RGBA 浮点数),因此 64KB 磁贴仅包含 4096 像素。 支持的最大 Texture2DArray 大小为 16384*16384*2048(但只有单个 mipmap)需要大约 1GB 的存储空间(如果完全填充(不包括 mipmaps),则使用 64 位表条目。 添加 mipmap 会将完全映射的(最坏情况)页表存储增长约三分之一,增加到大约 1.3GB。

在这种情况下,可以访问大约 10.6 TB 的可寻址内存。 但是,可能会限制可寻址内存的数量,这可以减少这些量,也许要缩小到 TB 范围左右。

另一种需要考虑的情况是单个 Texture2D 平铺资源 16384*16384,其每元素格式为 32 位,包括 mipmap。 完全填充的页面表中所需的空间大约为 170KB,其中包含 64 位表条目。

最后,考虑使用 BC 格式的示例,例如每个磁贴 128 位为 4x4 像素的 BC7。 这是每个像素的一个字节。 Texture2DArray 为 16384*16384*2048(包括 mipmap)需要大约 85MB 才能在页表中完全填充此内存。 考虑到这并不好,这允许一个平铺资源跨越 550 gigapixel(在本例中为 512 GB 内存)。

实际上,鉴于可用的物理内存量不允许在几乎一次映射和引用这么多的位置,定义这些完整映射的位置。 但是,使用磁贴池,应用程序可以选择重复使用磁贴(作为简单示例,重复使用图像中大型黑色区域的“黑色”彩色磁贴)-有效地使用磁贴池(即页表映射)作为内存压缩工具。

页表的初始内容为所有条目 NULL。 应用程序也不能为图面的内存内容传递初始数据,因为它从无内存支持开始。

在本部分中

主题 描述
创建磁贴池
通过 ID3D11Device::CreateBuffer API 创建磁贴池,方法是在 MiscFlagsD3D11_BUFFER_DESC 结构的成员传递 pDesc 参数指向的 D3D11_BUFFER_DESC 结构中的 D3D11_RESOURCE_MISC_TILE_POOL 标志。
磁贴池调整大小
如果使用 ID3D11DeviceContext2::ResizeTilePool API,如果应用程序需要为映射到它的平铺资源设置更多工作集,或者如果需要较少的空间,请使用磁贴池来扩展磁贴池。
危险跟踪与磁贴池资源
对于非平铺资源,Direct3D 可以防止呈现过程中出现某些危险情况,但由于危险跟踪在平铺资源平铺级别,因此在平铺资源渲染过程中跟踪危险情况可能太贵。

创建平铺资源