在虚幻引擎中使用PSO缓存优化渲染 您所在的位置:网站首页 请先开启miui优化开关 在虚幻引擎中使用PSO缓存优化渲染

在虚幻引擎中使用PSO缓存优化渲染

2023-05-16 05:29| 来源: 网络整理| 查看: 265

本页面的内容

术语和所支持的PSO类型

不同平台和图形API上的PSO

采集流程

缓存分区

控制PSO编译

用户缓存文件

常见问题解答

早期的图形API(如 Direct3D 11),在发出绘制调用之前,需要进行数十次单独调用,以便动态配置GPU参数。更多最新的图形API(如 Direct3D 12(D3D12) 、 Vulkan 和 Metal )支持使用名为 管线状态对象 (PSO) 的预配置GPU状态信息包,可以更快速地更改GPU状态。

尽管这样可大幅提升渲染效率,但按需生成新PSO可能需要100毫秒或更久,因为应用程序必须配置所有可能的参数。因此,为提升效率,必须在需要使用PSO之前提前很久生成PSO。

在具有高可编程性的实时渲染环境(虚幻引擎(UE))中,所有包含大量内容的应用程序均具有很多可以变更的GPU状态参数,使提前手动配置PSO变得可行。为了解决这个复杂的问题,UE可以在运行时从应用程序构建中采集关于GPU状态的数据,然后使用此缓存数据,在使用PSO前提前很久生成新的PSO。这样可以将可能的GPU状态范围缩小至仅限应用程序中使用的那些。因运行应用程序而采集的PSO说明称为 PSO缓存。

在虚幻引擎中采集PSO的步骤:

运行游戏。

记录实际绘制的内容。

在构建中包含此信息。

然后,对于后续运行,游戏可以先于渲染代码需要GPU状态前,创建必要的GPU状态。

本文档介绍了UE中的可用PSO类型和生成PSO缓存的详细过程。

术语和所支持的PSO类型

本文档普遍使用D3D12 API中使用的"管线状态对象"(PSO)一词来指代GPU状态。其他API使用略有不同的名称。例如,Vulkan使用 管线 ,Metal使用 管线状态 。然而,从概念上讲,所有名称都相似。

术语 PSO缓存 是指包含在构建中的带有PSO描述的文件,因此游戏可以尽早创建这些状态。换言之,PSO缓存即为要尽早创建的PSO列表。

虚幻引擎支持两种类型的PSO:

图形 PSO(Graphics PSO),代表应用程序图形管线的状态,包含多个可配置变量。

计算 PSO(Compute PSO),通常采用 计算着色器 形式。

除了上述PSO类型之外,还有 光线追踪PSO ,但UE 5.0不支持对光线追踪数据进行PSO缓存。

本文档中的大多数信息涉及图形PSO采集。计算PSO以不同的方式包含在构建中(着色器库中的所有计算着色器将在烘焙期间为它们自动创建PSO条目)。

记录缓存和稳定缓存

PSO中的最重要数据为着色器信息。然而,在开发人员调整材质时,虚幻中的着色器可以在多个构建间变更。为避免在长时间运行应用程序后丢弃完整PSO缓存,PSO缓存文件分为两类:

.upipelinecache 文件,即 记录PSO缓存 。这些内容在运行应用程序构建时记录。

所记录缓存中的着色器由其字节码的SHA哈希标识。

.spc文件,即 稳定PSO缓存 。这些缓存文件在烘焙贴图文件时生成,并且包含当开发人员更改项目中的贴图或着色器时会发生变化的着色器信息。

这些缓存文件由稳定的概要描述标识,预期多个构建之间保持相同,例如材质名称、顶点工厂名称或着色器类型。此描述称为 稳定密钥 ,由 .shk 文件表示(此前为 .scl.csv 文件)。

这样可确保在频繁更改的情况下,记录的数据相对稳健。如果应用程序有极其大规模的更改,你可能仍然需要重新记录PSO缓存,应用程序的整体内容最终确定后,你可以不用再管它们。

不同平台和图形API上的PSO

本文档中介绍的缓存包含PSO简要描述,位于引擎中FGraphicsPipelineStateInitializer的代码贴图中。然而,PSO数据不通用。虚幻引擎中的每个 渲染硬件接口(RHI) 都具有不同的属性,并且可能执行不同的渲染路径。

这会导致不同平台和渲染关卡之间的PSO缓存内容不同。这些PSO缓存间的信息不可互换。例如,运行D3D12 RHI的游戏所采集的缓存不能用于在Vulkan上运行的相同游戏。

如果你在可以使用多个图形API的平台上发布,并且你可以让应用程序在它们之间进行选择,则你需要在构建中包含多个缓存文件(每个API一个)。例如,对于采用Android的设备,在编写时,OpenGL ES仍是相关API。如果你在采用GLES和Vulkan的Android设备上发布应用程序,你需要采集并包含两个单独的缓存文件,每个RHI一个缓存文件。

GLES并没有PSO概念。但它使用了一个类似的概念,叫做 程序对象。

采用固定硬件的平台通常既不需要这种简要描述的PSO缓存,也不会从中受益,它们有自己的解决方案,或者能够完全避免运行时性能损失。如果为此类平台开发,请参阅特定平台的相关文档。

旧版API(如D3D11)也不受此缓存支持。

采集流程

本小节假定你从头开始采集PSO缓存的数据,采用的构建中不包含预记录缓存。PSO缓存的采集过程是可迭代的,也就是说你不用从头开始,你可以不断添加,而不会丢失此前的数据。然而,如果缓存文件较旧,通常建议重新生成PSO缓存,因为自最初采集以来更改了大量代码或内容后,缓存的内容可能不相关。

下面的小节包含采集PSO缓存并在项目中实施缓存所需的步骤。

1. 设置和所需设置

以下步骤将设置项目,以便记录PSO缓存。

打开项目的 DefaultEngine.ini 或其 (Platform)Engine.ini 。

(Platform)Engine.ini 文件通常位于(Project)/Config/(Platform)目录。使用此目录可以防止其他可能无需使用PSO缓存的平台获取设置。

在 Engine.ini 文件中设置以下值:

[DevOptions.Shaders] NeedsShaderStableKeys=true

在 DefaultGame.ini 文件中,设置以下值:

[/Script/UnrealEd.ProjectPackagingSettings] bShareMaterialShaderCode=True bSharedMaterialNativeLibraries=True

如果你是从头开始,请确保 (Project)/Build/(Platform)/PipelineCache 中没有文件。烘焙器会在这个位置寻找记录的缓存文件。如果这是你首次采集PSO,此文件夹可能根本不存在。

确保CVar r.ShaderPipelineCache.Enabled 设置为1。

2. 采集记录的PSO缓存

要记录PSO缓存,请遵循以下步骤:

使用-logPSO命令行开关运行打包应用程序。

在应用程序中执行尽可能多的路径。例如,运行应用程序的所有关卡,并更改图形设置。

你每次运行应用程序时,系统将在 Saved/CollectedPSOs 下生成记录的缓存文件(rec.pipelinecache)。采集它们并将它们放到计算机的任意位置的新目录。本指引使用的目录为 C:\PSOCache。

采集记录的PSO缓存时,你的最终目录是了解用户在应用程序中能看到的每种可能的材质或视觉效果,因此你应该全面访问尽可能多的位置,并使用许多不同的图形设置组合进行访问。

请注意,你无需通过单次运行采集所有PSO缓存。你可以在开发应用程序的过程中执行多次运行,或者你可以将此任务分配多个人员。记录的PSO缓存不会删除,除非你手动删除,因此你可以在开发过程中逐渐累加缓存。

3. 转换PSO缓存(也称为扩展)

要将前述步骤中的PSO数据转换为有用的格式,请遵循以下步骤:

烘焙项目内容。你可以通过打包应用程序完成此操作。

打开 (Project)/Saved/Cooked/[Platform]/[ProjectName]/Metadata/PipelineCaches。 从此目录将稳定的着色器密钥 (.shk) 复制到你放置 rec.pipelinecache 文件的文件夹。例如 C:\PSOCache。

使用下面的参数运行ShaderPipelineCacheTools命令(假定你当前的目录是引擎安装目录):

Engine\Binaries\Win64\UnrealEditor-Cmd.exe -run=ShaderPipelineCacheTools expand C:\PSOCache*.rec.upipelinecache C:\PSOCache*.shk C:\PSOCache[YourPrefix]_[ProjectName]_[ShaderFormatName].spc

你提供的文件名应该由以下内容构成:

* [YourPrefix] – 任意字符串,通常指定采集发生的时间。例如,这可能是当前构建的变更列表。 * [ProjectName] – 项目的名称。例如:ShooterGame。这必须与你的项目名称完全匹配,否则无法选取。 * [ShaderFormatName] – 项目的着色器格式,必须与着色器格式的名称完全匹配。对于D3D12,此为PCD3D_SM5。

项目ShooterGame使用上述规范的全名如下: CL11122333_ShooterGame_PCD3D_SM5.spc

4. 在应用程序中包含PSO缓存

将前一分段生成的 .spc 文件放到 Build/[PlatformName]/PipelineCaches 文件夹中。例如:Build/Windows/PipelineCaches。

再次烘焙或打包你的项目。PSO缓存文件应该被烘焙器选取,日志记录靠近末尾部分应该包含以下类似内容:

LogCook: Display: ---- Running UShaderPipelineCacheToolsCommandlet for platform WindowsClient shader format PCD3D_SM5 LogCook: Display: With Args: build "../../../TestGame/Build/Windows/PipelineCaches/*TestGame_PCD3D_SM5.spc" "d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-Global-PCD3D_SM5.shk" "d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-TestGame-PCD3D_SM5.shk" "d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM5.stable.upipelinecache" LogShaderPipelineCacheTools: Display: Sorting input stable cache files into chronological order for merge processing... LogShaderPipelineCacheTools: Display: Loading d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-Global-PCD3D_SM5.shk... LogShaderPipelineCacheTools: Display: Loading d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-TestGame-PCD3D_SM5.shk... LogShaderPipelineCacheTools: Display: Loaded 3554 shader info lines from d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-Global-PCD3D_SM5.shk. LogShaderPipelineCacheTools: Display: Loaded 3833694 shader info lines from d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Metadata/PipelineCaches/ShaderStableInfo-TestGame-PCD3D_SM5.shk. LogShaderPipelineCacheTools: Display: Loaded 3837248 unique shader info lines total. LogShaderPipelineCacheTools: Display: Loaded 13238 stable PSOs from ../../../TestGame/Build/Windows/PipelineCaches/++Test+GoldMaster-CL-17412694-TestGame_PCD3D_SM5.spc. 2329 PSOs rejected, 5840141 PSOs merged LogShaderPipelineCacheTools: Display: Re-deduplicated into 35084 binary PSOs [Usage Mask Merged = 3]. LogShaderPipelineCacheTools: Display: Running sanity check (consistency of vertex format). LogShaderPipelineCacheTools: Display: 0 vertex shaders are used with an inconsistent vertex format LogShaderPipelineCacheTools: Display: === Sanitizing results === LogShaderPipelineCacheTools: Display: Before sanitization: .................................................................... 35382 PSOs LogShaderPipelineCacheTools: Display: Filtered out due to inconsistent vertex declaration for the same vertex shader:.......... 0 PSOs LogShaderPipelineCacheTools: Display: Filtered out due to VS being possibly incompatible with an empty vertex declaration:..... 1 PSOs LogShaderPipelineCacheTools: Display: ----- LogShaderPipelineCacheTools: Display: Number of PSOs after sanity checks:...................................................... 35381 PSOs LogShaderPipelineCacheTools: Display: Wrote 35381 binary PSOs (graphics: 34834 compute: 547 RT: 0), (18453KB) to d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM5.stable.upipelinecache LogCook: Display: ---- Done running UShaderPipelineCacheToolsCommandlet for platform WindowsClient

要验证这是否有效,请检查显示写入的二进制PSO数量的行,该行写在日志的结尾处。该行的图形PSO数量必须大于0。

LogShaderPipelineCacheTools: Display: **Wrote 35381 binary PSOs** (graphics: 34834 compute: 547 RT: 0), (18453KB) to d:/build/++Test/Sync/TestGame/Saved/Cooked/WindowsClient/TestGame/Content/PipelineCaches/Windows/TestGame_PCD3D_SM5.stable.upipelinecache LogCook: Display: ---- Done running UShaderPipelineCacheToolsCommandlet for platform WindowsClient5. 测试PSO覆盖范围

要确定PSO缓存是否有足够的覆盖范围,请使用 -logpso 命令运行新打包的应用程序,并观察日志输出。你应该看到类似于以下内容的行:

[2021.10.06-20.06.22:848][ 0]LogRHI: Opened FPipelineCacheFile: ../../../ShooterGame/Content/PipelineCaches/Windows/ShooterGame_PCD3D_SM5.stable.upipelinecache (GUID: EA50968D47BDE9A04A8524BCEB51615D) with 269 entries.

该数量必须与打包日志中写入的二进制PSO数量一致。例如,如果日志报告写了35381个二进制PSO,预期可以看到35381个条目。

你还应该检查构建是否在日志中打印"Encountered a new graphics PSO"。如果你在与缓存采集期间相同的条件下(例如相同的可扩展性设置)看到相同的内容,则不应出现此种情况。

缓存分区

对于此写入,生成的PSO缓存是游戏构建中包含的单个单块文件。游戏的默认行为是尝试在启动时打开它,并开始从中编译PSO。然而,并非所有PSO始终都相关。例如,有些可能是从不同关卡采集,有些使用不同的图形设置记录。

为了避免对缓存进行不必要的编译,每个PSO当前都与称为 游戏使用掩码 的位掩码关联。该应用程序使用 SetGameUsageMaskWithComparison 函数避免编译记录在不同关卡或具有不同图形(质量)设置的PSO。以下是此类函数的示例:

void SetPSOCacheUsageMask(int32 QualityLevel, int32 MapIndex) { uint64 GameMask = 0; const int32 kMaxQualityLevels = 4; GameMask |= (1ULL


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有