Choose your operating system:
Windows
macOS
Linux
虚拟纹理系统主要有两种GPU内存分配方式:页表内存(Page Table Memory)和物理内存池(Physical Memory Pool)。
页表内存(Page Table Memory) 提供了从纹理坐标间接访问纹理数据的方法,可以按需分配。它会随着时间推移不断增大;除非释放其中的全部内容,否则无法从内存中释放。用户无法控制该存储类型。
物理内存池(Physical Memory Pool) 包含了当前驻留的纹理数据,并且由多个独立的池构成。虚拟纹理系统所查看的每一种纹理格式都有对应的内存池。对应格式的虚拟纹理进行第一次实例化时会分配内存池。每个内存池都具有固定的大小,不会逐渐增大。用户可以控制每个池的大小。
本文档将介绍如何定义和调试虚拟纹理物理内存池。
理解物理内存池的行为
物理内存池都是由页组成的。每一页都包含了一个虚拟纹理区块的数据。内存池的行为类似于以使用时间远近为基础的缓存。当虚拟纹理系统请求区块时,它就会被流送或渲染到内存池里的一个可用页中。如果没有可用页,那么包含使用时间最久远的区块的页就会被去除,为新区块腾出空间。
如果视图中包含的可见虚拟纹理过多,无法存储到虚拟纹理内存池中,系统就无法正确渲染视图。在这些情况下,你必须调整虚拟纹理内存池的大小,从而满足数据使用量要求。
配置物理内存池
虚拟纹理的 内存池大小 可以在 BaseEngine.ini
配置文件中设置。
内存池可以根据 纹理格式组(Texture Format Group) 和 区块大小(Tile Size) 进行设置。你也可以在项目中设置自己的[配置文件](),从而覆盖各个项目或平台。
虚拟纹理内存池的所有配置设置都可以在"/Script/Engine.VirtualTexturePoolConfig"条目下找到。
以下示例能够将所有包含BC7纹理的虚拟纹理内存池的大小设置为100MB。大小仅为近似大小,系统实际分配的大小为低于100MB、容纳页数为整数的最大平方数。
[/Script/Engine.VirtualTexturePoolConfig]
+Pools=(Formats=(PF_BC7), SizeInMegabyte=100)
在使用默认池大小的配置中,Formats不需要有对应的输入。在无纹理组格式的情况下定义一个池就可以超过默认值。
[/Script/Engine.VirtualTexturePoolConfig]
+Pools=(SizeInMegabyte=64)
有些池包含了多层,每层都有自己的格式。大部分运行时虚拟纹理设置都是这个情况。此时,配置文件需要输入对应的层格式。
例如,一个在材质中使用 基础颜色,法线,粗糙度,高光 的运行时虚拟纹理可以如下设置:
[/Script/Engine.VirtualTexturePoolConfig]
+Pools=(Formats=(PF_DXT5, PF_DXT5), SizeInMegabyte=128)
所有内存池配置输入都可以包含额外设置,包括:
内存池配置设置 |
说明 |
---|---|
|
允许通过 |
|
设置`bAllowSizeScale`使用的群组索引(0-2)。拥有多个群组集合为每个内存池设置不同的扩展性。 |
|
允许在内存池超额时,对虚拟纹理应用MipMap偏差。 |
物理内存池驻留
虚拟纹理内存池的当前使用情况被称为 驻留(Residency)。当内存池的所有页都分配了当前可见的区块,驻留即为100%。
驻留为100%时,内存池即为超额(oversubscribe),并会开始删除可视区块的数据。由于纹理数据会在内存中重复加载与删除,这将导致意外的输入输出和屏幕闪烁。
你可以启用界面通知,在内存池超额时显示通知。该通知可使用控制台命令 r.VT.Residency.Notify 1
启用。
该警告表明,你需要在配置文件中扩大内存池大小,或者更改虚拟纹理或材质。请查看下文部分,了解如何解决该类问题通知。
驻留MipMap偏差
如果启用 bEnableResidencyMipMapBias
配置内存池,就会在超额时设置MipMap偏差来降低驻留。这能避免出现意外的输入输出和屏幕闪烁,但渲染的虚拟纹理分辨率会降低。
该设置适合在驻留鲜少超额、不愿为这种罕见情况分配内存的时候使用。超额的屏幕信息会包含应用的MipMap偏差。
驻留产生的MipMap偏差是全局性的。所有物理内存池的最大当前偏差会应用于 所有 虚拟纹理采样。
物理内存池HUD显示
设置合理的内存池大小是监控驻留、减少超额情况的关键。你可以使用屏幕抬头显示(HUD),展示每个虚拟纹理物理内存池当前的驻留。
该功能更可通过 r.VT.Residency.Show 1
启用。
虚拟纹理物理内存池HUD会显示每个纹理格式的当前驻留及其分配的内存。
屏幕上的每个图表都代表一个虚拟纹理物理内存池。总共有三种线状图表:
红色 表示当前池驻留为0-100%。
黄色 表示固定池占用为0-100%。
这表示的是标记为锁定的页占用。通常每个虚拟纹理都会锁定一页。加载大量虚拟纹理资产时,即使虚拟纹理不可见,也会降低可用的池空间。
绿色 表示应用MipMap偏差将驻留控制在100%以下。
调试物理内存池驻留
当虚拟纹理内存池超额时,可以从以下领域开始调试并检查内容。
内存池大小
对于虚拟纹理内存池的大小,你需要检查以下方面:
检查内存池大小是否足够大,能够容纳预期的全部虚拟纹理数据。
页规模越大,内存池就应当越大。例如,一个纹理格式为
PF_A32B32G32R32F
的内存池的内存要求就比纹理格式为PF_DXT1
的内存池更大。同样地,包含更多层数的内存池也需要更大的内存。
渲染的输出分辨率越高,内存池就应当越大。
高分辨率输出通常需要更高分辨率的mip区块。
区块大小越大,内存池就应当越大。
流送虚拟纹理的默认区块大小为128纹素。然而,该值可以被覆盖。
运行时虚拟纹理的区块大小最大为1024纹素。较大的区块大小可能会浪费内存池的空间。
超额
超额(Oversubscription)的一项主要原因是在对虚拟纹理进行采样时应用了负mip偏差。系统性地对更高分辨率的mip进行采样会需要更多池内存。负mip偏差通常是由于在材质图表的纹理采样节点中专门设置了mip等级或偏差而产生的。
超额也可能因为意外原因产生,例如对零渐变的纹理进行采样时,三角形或网格体的UV不变而产生超额。以下材质图表片段就是一个例子。对运行时虚拟纹理采样节点的"忽略输入世界位置"设置应用Mip值就能解决这个问题。
使用控制台命令 r.VT.DumpPoolUsage
,就能协助定位由于mip偏差或其他问题而占用过多池空间的纹理。该命令会转储每个内存池中虚拟纹理资产当前分配的页数。转储文件会根据页数排序,因此需要检查第一条输入,确定其是否合理。
需要注意的是,在以下转储文件中,第一条输出明显高出其他输入。因此必须找到引用了 T_Ground_Sand_F_basecolor_CANYON
的材质,检查是否存在mip偏差问题。
PhysicaPool: [0] DXT1 (136x136):
T_Ground_Sand_F_basecolor_CANYON 1912
T_Rock_Quarry_Y_RAOD 418
ubulehofw_8K_Albedo 324
pcciQ_4K_Albedo 248
T_Rock_Cliff_D_RAOD 187
noise_directional_3 115
T_column_260_B_W 97
T_column_260_B_goldA_RMAOO 97
T_column_260_B_goldA_C 96