UE4 PSO介绍一:PSO的定义(编辑中)

PSO

PSO的全称是Pipeline State Object,主要是用来给GPU描述如何计算、渲染的设置集合。PSO是伴随新一代的图形API(DX12、Vulkan、Metal)提出的。在这之前的时代,渲染设置是一个状态机管理的,用单个API设置单种渲染状态。现代图形API是把所有的渲染状态打包设置给GPU,这些"捆绑在一起"的渲染状态组合,就是PSO了。Graphics PSO一般包括:

|-----------------------|----------------------------------|
| Graphics PSO | Description |
| Shaders | VS, PS... |
| Vertex Description | Vertex element format, stride... |
| Blend State | Blend operation |
| Rasterizer State | Fill mode, cull mode... |
| Depth Stencil State | Depth test, stencil mask... |
| Render Target setting | RT Format, flags, load, store... |
| MSAA | MSAA Samples |
| Primitive Topology | Triangle Strip, Point... |
| Subpass info | Subpass Num, hints... |

从下面对应代码中,可以看出其中shader是用hash值来代替的,运行时会用这些hash值索引真正的shader二进制:

复制代码
struct RHI_API GraphicsDescriptor
{
    FSHAHash VertexShader;
    FSHAHash FragmentShader;
    FSHAHash GeometryShader;
    FSHAHash HullShader;
    FSHAHash DomainShader; ……

PSO Cache

在游戏runtime时创建PSO会非常耗时,测到最高的有100多ms每个PSO。优化方法是使用缓存,某个pso第一次创建好会缓存在内存中,下次再需要用到同样的话可以直接复用。(todo:流程图待补充)

PSO Cache有两个层级:内存中、硬盘本地的二进制文件 Local Binary Cache。讨论时需要根据具体情景区分其指代的含义。

假设构建时没有做处理,游戏app安装后,第一次使用时,会创建PSO,时间开销会很大,如何解决呢?由于游戏用到的PSO是相对固定的,游戏厂商可以在发布游戏之前,通过提前运行内部版本,收集实际使用到的PSO的记录(后文会强调不是PSO本身),运行时先根据此记录预热一遍,等真正渲染需要用到时,即可直接使用内存里的PSO本体了。这也就是 UE4官网文档(链接请点我) 中的图片(下图)所揭示的流程了,注意到其中**"构建包体"的是不断包含"收集上来的PSO记录"的**,即 "构建"→"厂商的内部跑测"→"收集得到PSO的记录"→"再次构建"→......→"最终发布版本"。

(图1)

上图其中的 .spc .shk 是UE5用到的,本文只提UE4传统的PSO。对于UE4而言,如下图所示。这个过程追求高覆盖率 :为了达到最佳效果,你需要确保游戏运行时的PSO收集(即生成 .rec.upipelinecache文件的过程)尽可能覆盖所有的关卡、角色、特效和材质组合 。覆盖率越高,发布后玩家在游戏中遇到的意外卡顿就越少,从而避免在游戏过程中因实时编译PSO导致的帧率骤降和卡顿。

(图2)

两种PSO工作流

官方文档里提到了两种工作方式:

1、Bundled PSO Cache

https://dev.epicgames.com/documentation/en-us/unreal-engine/manually-creating-bundled-pso-caches-in-unreal-engine

先说大体印象:对于线性叙事的游戏,更加适合 Bundled PSO Cache ,例如《古墓丽影》《明日之子》这种有剧情的线性关卡的游戏,内容固定、流程线性的游戏(如单人剧情驱动型游戏)。玩家体验路径相对固定,可预测性强。大白话说:**"游戏厂商可以帮你提前玩个遍,采集尽可能完备的PSO。"**侧重点在于跑测完备。

2、PSO Precaching

https://dev.epicgames.com/documentation/en-us/unreal-engine/pso-precaching-for-unreal-engine

先说大体印象:对于内容动态性强、包含大量用户生成内容(UGC)或程序化生成内容的项目,PSO Precache通常是比传统的Bundle PSO Cache更优的选择。例如说《我的世界》。大白话说:"游戏有无限可能,我只能帮你在Runtime时做一下预测,在游戏内尽量提前缓存(precaching的含义)。" 侧重点在于Runtime中对可能需要的PSO的预判,强调联想的策略。

图1和图2、以及下面介绍的Expand PSO 都是 Bundled PSO Cache 工作方式的。

目前的最佳实践是将 Bundle PSO Cache(包含Expand PSO流程)​ 与 PSO Precache​ 结合使用,以弥补自动收集可能遗漏的部分,追求接近100%的覆盖率。

知识巩固 >

问题:我能否这么理解~ precache是每一台玩家设备自行预测、缓存。

bundle pso cache由游戏开发商预先跑测、收集pso缓存、再次打进包体里、随包体分发给每个玩家用。

回答:理解非常准确,核心区别确实在于 PSO缓存的收集者和执行者不同。下面是比对表格

特性 PSO Precache (预缓存) Bundle PSO Cache (打包PSO缓存)
发起者 玩家设备(运行时自动预测) 游戏开发商(开发阶段手动收集)
工作时机 关卡加载时或对象流送时 游戏首次启动时
核心逻辑 分析加载的网格和材质,预测可能需要的PSO并异步编译 将开发商测试时记录的实际用到的PSO列表提前编译
优点 自动化,适应动态内容和更新 若收集全面,覆盖率极高,能最大程度减少运行时编译
缺点 预测可能不准,会编译一些用不到的PSO;对运行时动态生成的内容可能覆盖不全 收集过程繁琐,需大量测试;游戏内容更新后需重新收集

在实际项目中,这两种方案并非二选一,而是互补关系。当前的主流最佳实践是将两者结合使用。

  1. 以PSO Precache为基础:将其作为默认的首选方案。它开箱即用,能解决绝大部分卡顿问题,尤其适合内容动态性较强的项目。

  2. 用Bundle PSO Cache查漏补缺:PSO Precache可能存在盲区,例如:

    ● 运行时通过游戏逻辑动态生成的Actor及其材质。● 某些特殊的全局着色器。 ● 在运行时应用的动态材质。

对于这些盲区,可以通过Bundle PSO Cache流程进行针对性的补充收集。在项目配置中,可以设置 r.ShaderPipelineCache.ExcludePrecachePSO=1,以避免重复收集已由PSO Precache覆盖的内容。

知识巩固 <

Expand PSO

提问: 什么是"展开PSO"?

回答: 它特指将游戏运行时收集的原始PSO数据,转换为可供项目打包使用的稳定PSO缓存(含 .stablepc.csv文件)的过程。这个步骤是 Bundle PSO Cache​ 工作流的核心环节之一。

环节 输入文件 (Input) 核心操作 (Process) 输出文件 (Output) 最终用途 (Purpose)
1. 准备阶段 项目材质与Shader 项目打包(Cook) .shk.scl.csv文件(稳定的ShaderKey) 记录所有Shader的唯一标识和依赖关系
2. 数据收集 运行游戏 在目标设备(如手机)上实际游玩,触发各种渲染组合 .rec.upipelinecache文件(运行时PSO记录) 记录实际用到的PSO列表
3. Expand PSO .shk文件 + .rec.upipelinecache文件 使用 ShaderPipelineCacheTools工具执行 Expand​ 操作 .stablepc.csv文件(稳定的PSO缓存) 将运行时记录与ShaderKey关联,生成最终的缓存清单
4. 打包发布 .stablepc.csv文件 将文件放入项目指定目录(如 Build/Android/PipelineCaches/),重新打包 包含PSO缓存的游戏包 玩家首次运行时预编译PSO,减少卡顿

"Expand PSO" 的命令是:

UE4Editor-Cmd.exe YourProject.uproject -run=ShaderPipelineCacheTools expand [收集的.upipelinecache文件] [对应的.scl.csv文件] [输出的.stablepc.csv文件名]

其中三个变量中的前两个是输入,最后一个是输出。例如:

UE4Editor-Cmd.exe MyGame.uproject -run=ShaderPipelineCacheTools expand C:\PSOCaching\*.rec.upipelinecache C:\PSOCaching\*.scl.csv MyGame_GLSL_ES3_1_ANDROID.stablepc.csv

最终回答 "Expand PSO" 是利用 .scl.csv 与 录制的 .rec.upipelinecache,转换为.stablepc.csv 的过程。

.scl.csv

基础概念

1、Shader存放在哪里?

那么现在的问题就是如何收集、获取我们游戏会用到哪些PSO呢?

参考

1、UE4官网介绍

https://dev.epicgames.com/documentation/en-us/unreal-engine/manually-creating-bundled-pso-caches-in-unreal-engine

相关推荐
小江村儿的文杰15 小时前
UE4 PSO介绍二:认识.rec.upipelinecache
ue4·pso
njsgcs2 天前
ue4 我的ai要用到的一下方法汇总 + ue的ai编程助手
ue4
神米米2 天前
Maya快速安装UE4 布料权重绘制插件PhysX导出apx
游戏引擎·ue4·maya
njsgcs2 天前
ue4 开放exec接口 vscode mcp铺垫 unreal.register_slate_post_tick_callback
ide·vscode·ue4
每天回答3个问题2 天前
Lua 函数教程
开发语言·ue5·ue4·lua
每天回答3个问题3 天前
Lua Table(表)
开发语言·ue4·lua·虚幻引擎
小江村儿的文杰4 天前
UE4 Cook流程中IdenticalUncookedPackages的含义,以及一种“资源未打包”情形的解释
ue4·cook
每天回答3个问题9 天前
Lua数组
ue4·lua·虚幻引擎
每天回答3个问题10 天前
Lua 字符串
ue4·lua