UE4 PSO缓存

这篇具有很好参考价值的文章主要介绍了UE4 PSO缓存。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

更多内容请查看我的个人网站
NoCodeWorld 的小地盘

PSO构建总流程

UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios

根据上面总流程图,我会分别一个个去讲解每一步的操作和需要额外处理的东西

开发环境

  • UE版本:4.27.2
  • VS版本:2019

1.打包

首先,需要打一个可以实机收集PSO缓存文件的包

2.实机收集

自动采集

这里主要说一下录取的方式方法, 一种方式就是引擎自带的自动采集指令

Config/DefaultEngine.ini
[ConsoleVariables]
r.ShaderPipelineCache.Enabled=1
r.ShaderPipelineCache.LogPSO=1
r.ShaderPipelineCache.SaveBoundPSOLog=1

上述采集指令配置了以后直接打包,然后开始跑项目即可,会自动采集并且保存缓存文件到本地,如果你们是普通小场景项目上面方式就已经足够了,可直接跳到 采集完成

手动采集

我自己做了一个PsoCacheGather的小工具插件,下面会大概说一下实现思路
UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios

我们小工具就如图所示,支持自动跑图录取和手动录取,因为我们是大世界,场景太大,如果让QA去全部跑一遍有点吃力,所以直接做了一个自动跑图收集,如果你们项目组是小副本或者小场景直接手动跑图录取或者拉一条Line,然后摄像机沿着跑即可,这个看自己需求

我们项目因为是大世界场景,测试发现长时间全部跑下来会有问题,可能是实时一直在保存太大太频繁,所以我改成了自动跑图完再保存一次,中间不会实时保存,测试没问题

[ConsoleVariables]
r.ShaderPipelineCache.Enabled=0

首先配置中关闭自动开启,我们在开始录取的时候代码中开启

bool UPSOCacheGatherHelper::EnableShaderPipelineCache(bool bEnable)
{
	UE_LOG(LogPSO, Display, TEXT("EnableShaderPipelineCache %s"), bEnable ? TEXT("true") : TEXT("false"));
	auto Var = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ShaderPipelineCache.Enabled"));
	if (Var)
	{
		Var->Set(bEnable ? 1 : 0);
	}
	return !!Var;
}

首先在一开始先开启总开关 r.ShaderPipelineCache.Enabled

bool UPSOCacheGatherHelper::EnableLogPSO(bool bEnable)
{
	auto Var = IConsoleManager::Get().FindConsoleVariable(TEXT("r.ShaderPipelineCache.LogPSO"));
	if (Var)
	{
		Var->Set(bEnable ? 1 : 0);
	}
	return !!Var;
}
bool UPSOCacheGatherHelper::LoadShaderPipelineCache(const FString& Name)
{
	UE_LOG(LogPSO, Display, TEXT("Load Shader pipeline cache %s for platform"), FApp::GetProjectName());
	return FShaderPipelineCache::OpenPipelineFileCache(FApp::GetProjectName(), GMaxRHIShaderPlatform);
}

然后开始录制时先调用EnableLogPSO(true),再LoadShaderPipelineCache(),就会开始录制了

bool UPSOCacheGatherHelper::SavePipelineFileCache(EPSOCacheSaveMode Mode)
{
	return FShaderPipelineCache::SavePipelineFileCache((FPipelineFileCache::SaveMode)Mode);
}

开始录制后在内存中不会自动保存本地,在我们录制结束的时候手动调用SavePipelineFileCache(EPSOCacheSaveMode::BoundPSOsOnly)保存到本地,至此手动采集结束.

采集完成

当你手动收集完成或者自动收集完成以后可从手机磁盘目录 /SDCard/UE4Game/{ProjectName}/Saved/CollectedPSOs 下取得 后缀名为 .upipelinecache的文件

特别说明一下,采集文件可分开录取到多个文件中,这些文件在生成最终PSO缓存时会自动合并的

3.生成SHK

我自己在项目目录下建了一个Tools/PSOCache 目录,专门作为PSO相关的工作目录
UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios
之前采集到的.rec.upipelinecache文件放到对应文件夹下,然后我们就要生成SHK文件了,这个文件是在打包时Cook生成的,直接在DefaultEngine.ini中加上

[DevOptions.Shaders]
NeedsShaderStableKeys=true

然后打包项目,在 %ProjectPath%\Saved\Cooked%%a\Client\Metadata\PipelineCaches\目录下就会找到.SHK文件(4.27版本以上引擎是这个格式,之前是.scl.csv)

手动生成SHK文件

如果你的项目在生成APK时会COOK到所有文件,那你就忽略下面手动生成,直接跳到下一段

这一步按正常流程应该是打包时自动生成全部.shk文件,但是因为这个文件的信息录入跟cook的文件列表挂钩,我们的首包apk又不是打的完整的文件列表,是排除掉大部分文件的,所以会导致没法自动生成,我只能写了个工具去专门处理这种情况,通过测试,有两种方案可以达到这一步的效果

1.首包不做排除方案,通过引擎自带的配哪些打哪些进去以做到只打指定资源进首包,但是测试发现在我们项目中,因为存在软引用的情况,所以无法直接做到,需要修改引擎才行,所以目前暂用第二种方案

2.我通过工具修改ini文件,生成完shk以后再把ini还原的方式去生成,操作上直接执行 ProjectDir/Tools/PSOCache/CookFullAssert.bat 即可,等他执行完成,会在 当前目录下的 PipelineCaches/对应平台下生成上图中的两个SHK文件,名字什么的都不要动,然后上传到svn即可,这个SHK文件理论上只需要在资源有修改时才去重新生成即可

脚本中其实就是在ini里面加上这个NeedsShaderStableKeys和去掉排除的文件夹, 然后直接执行cook指令

%EnginePath% %ProjectPath%\Client.uproject -run=Cook  -TargetPlatform=%%a -fileopenlog -ddc=InstalledDerivedDataBackendGraph -unversioned -stdout -CrashForUAT -unattended -NoLogTimes  -UTF8Output -CookAll

最后把生成的两个SHK文件拷出来即可,完事以后会把ini置回,至于为什么要置回,后面使用时会讲到

4.导出合并

现在已经有了SHK文件和rec.upipelinecache文件,我们现在要做的就是把这些文件合并生成出最后的二进制PSO文件

ProjectDir/Tools/PSOCache/PSO_Expand.bat

call PublicParam.bat

for %%a in (%Platform%) do ( 
	if %%a==Android_ASTC %EnginePath% %ProjectPath%\Client.uproject -run=ShaderPipelineCacheTools expand "%ToolsPath%\rec.upipelinecache\%%a\*.rec.upipelinecache" "%ToolsPath%\PipelineCaches\%%a\*.shk" "%ToolsPath%\stablepc.csv\%%a\Client_GLSL_ES3_1_ANDROID.stablepc.csv"
	if %%a==IOS %EnginePath% %ProjectPath%\Client.uproject -run=ShaderPipelineCacheTools expand "%ToolsPath%\rec.upipelinecache\%%a\*.rec.upipelinecache" "%ToolsPath%\PipelineCaches\%%a\*.shk" "%ToolsPath%\stablepc.csv\%%a\Client_SF_METAL.stablepc.csv"
)

这个脚本就是合并导出所有rec.upipelinecache文件为一个.csv文件,这个stablepc.csv文件很重要,他就是最终PSO文件的源文件,这个可以当成保存文件上传到svn去,执行完这个批处理后会生成到 /stablepc.csv/对应平台/ *.stablepc.csv

ProjectDir/Tools/PSOCache/PSO_Build.bat


call PublicParam.bat

for %%a in (%Platform%) do ( 
	if %%a==Android_ASTC xcopy %ToolsPath%\stablepc.csv\%%a\Client_GLSL_ES3_1_ANDROID.stablepc.csv %ProjectPath%\Build\Android\PipelineCaches\Client_GLSL_ES3_1_ANDROID.stablepc.* /s /i /y
	if %%a==IOS xcopy %ToolsPath%\stablepc.csv\%%a\Client_SF_METAL.stablepc.csv %ProjectPath%\Build\IOS\PipelineCaches\Client_SF_METAL.stablepc.* /s /i /y
	
	if %%a==Android_ASTC call %EnginePath% %ProjectPath%\Client.uproject -run=ShaderPipelineCacheTools build "%ProjectPath%\Build\Android\PipelineCaches\*Client_GLSL_ES3_1_ANDROID.stablepc.csv" "%ToolsPath%\PipelineCaches\%%a\*.shk" "%ProjectPath%\Content\PipelineCaches\Android\Client_GLSL_ES3_1_ANDROID.stable.upipelinecache"
	if %%a==IOS call %EnginePath% %ProjectPath%\Client.uproject -run=ShaderPipelineCacheTools build "%ProjectPath%\Build\IOS\PipelineCaches\*Client_SF_METAL.stablepc.csv" "%ToolsPath%\PipelineCaches\%%a\*.shk" "%ProjectPath%\Content\PipelineCaches\IOS\Client_SF_METAL.stable.upipelinecache"
)

这个就是生成最终的.upipelinecache文件,这个文件是要打到包里去的,所以这个批处理就是把前面生成的.csv拷贝到ProjectDir/Build/对应平台/PipelineCaches 下,然后执行命令生成出.upipelinecache文件到ProjectDir/Content/PipelineCaches/ 下,然后可以把build下面的scv文件和Tools下面的都提交到svn上去

这里可以发现我们其实使用的就是最终content下的.upipelinecache文件,为什么还要保留中间文件.csv呢,其实这里就要说一下一个很重要也很鸡肋的东西,我们前面有说过NeedsShaderStableKeys=true加了这个以后就会自动生成SHK文件,其实这个.upipelinecache文件加了这个也会自动生成,前提是你要把.csv文件拷到build下面以后,打包的时候引擎会自动生成.upipelinecache并且打包,但是有个问题是引擎没考虑过会有热更的情况,如果走这个自动的流程,这个.upipelinecache文件是没法管理的,都是引擎那边处理死了,即使我通过指令手动生成到content下面,引擎有个恶心的地方是他会在打包的时候强制删除掉content下面的,所以这里想热更的话只能不走自动的流程,后面打包和热更步骤还会有说明

5.打包和热更

如果你不需要热更PSO文件,请忽略这一步,直接跳到运行时加载

通过前面生成出.upipelinecache文件以后,我们知道要把这个文件打包进平台包里去,以供游戏运行使用,可自由选择首包中要不要打这个文件,这个文件就是实际运行时会实时编译成一个缓存文件到手机本地去,然后在运行时需要新建PSO是他就会到本地寻找缓存并直接使用,以减少创建的消耗,因为大世界场景等资源会有热更的情况,当后续版本资源增加了,自然也要把这个upipelinecache文件热更到手机上去

  • 打包进首包 可以选择打到首包也可以选择不打,按道理不会影响,需要的话就只需要在ProjectSetting的Package选项配置一下PipelineCaches文件夹即可
    UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios
    这里有个小问题就是这个文件夹下是包含安卓和IOS的资源的,但是这个打包配置每个平台都是一份,所以只能全部打进去,好在这个文件一般来说都很小,所以可自己选择要不要打进首包

  • 热更打包 我这边打包工具是用的是HotPatcher,下面演示是基于这个插件的,现在项目热更是按照文件夹打到每个pak中去的,所以只需要选择额外增加一个pak放这个资源。或者直接放到之前的某个pak中去,无非就是选择配置非assert文件即可
    UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios
    这里是总的非Assert文件配置,可选择对应平台对应的资源,我这里是全部都配进去了,在这里配置应该是会打到default.pak中去
    UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios
    在每个chunk里面都有一个非assert的配置,这里演示的是比较正确的配法,直接AddExternFileToPak,把对应平台的这个文件打到对应平台的pak中即可

最后按路径总结下

按路径划分就两个重要的东西

  • 插件PsoCacheGather 这个主要负责PSO的实机采集任务
  • /ProjectDir/Tools/PSOCache 这个下面主要是批处理工具脚本,主要负责PSO二进制文件的生成工作,这里要重点说明下这些脚本执行前有一个重要的配置需要处理 PublicParam.bat
@echo off
set "EnginePath=XXX\Engine\Binaries\Win64\UE4Editor-Cmd.exe"

set "ProjectPath=XXXX"

set "ToolsPath={ProjectPath}\Tools\PSOCache"

REM Platform=Android_ASTC IOS
set Platform=Android_ASTC

运行时使用PSO

前面说完了生成和打包,运行时也有非常重要的处理,首先这个PSO的运行时编译缓存需要用到ShaderCode,那也就是说我们需要先处理ShaderCode

ShaderCode热更打包

UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios
新版的HotPatcher已经很方便的集成了,只需要这边开关开一下就会自动打包进pak里了

每个pak里面都会生成自己的ShaderLibrary,因为引擎启动时默认加载了首包中的ShaderCode,所以我们需要在游戏热更之后手动open一下所有的ShaderLibrary

在HotPatcher这个插件中有实现加载方法,UFlibPakHelper::LoadShaderbytecodeInDefaultDir ,只需要在热更过后的时机遍历加载每个Chunk即可,在没有自定义路径和名称的情况下,只需要传ChunkName就可以了,不用后缀名和路径,只需要Chunk名

编译PSO并加载

PSO加载之前必须已经操作完前面的ShaderCode加载

这里加载规则有一些特殊的情况,首先因为引擎起来的时候会自动去编译PSO,并且后面不会再去编译了,即使你手动去编译也无效,但是我们PSO热更的话,在引擎初始化的时候我们都还没开始热更,所以我们需要先关闭自动编译,然后在等热更完成以后动态的去编译并且加载缓存文件

  1. 关闭自动编译,修改ini,添加新的命令即可,具体添加哪些查看 [ini添加块段落]
  2. 因为手动编译时需要把自动编译的选项再打开,直接调用 EnableShaderPipelineCache(true),然后再去编译和加载PSO
  3. 还有一种特殊情况需要处理,就是当第一次安装包时,本地的Program Binary Cache文件是不存在的,在加载PSO缓存时,会先生成这个缓存到本地,那也就是说我们需要调用两次LoadShaderPipelineCache(),最好判断一下本地目录是否存在,每个平台的目录在下面两张图中,至于目录怎么获取,直接从LoadShaderPipelineCache往里面跟会有获取Cache路径的方法
  4. 前面说的把Cache文件编译到本地以后,还需要加载到内存中去,游戏中才能生效,所以还需要调用一次 UFlibShaderPipelineCacheHelper::LoadShaderPipelineCache(),只不过这一次要判断下FShaderPipelineCache::NumPrecompilesRemaining() ≤ 0 的时候再去load,防止还没编译完就加载了,这些操作其实建议在loading界面的时候去做,等这些操作完成后再关闭Loading界面

UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios

安卓的Program Binary Cache文件所在目录

UE4 PSO缓存,UE4,ue4,缓存,虚幻,虚幻引擎,虚幻4,android,ios

IOS下所在的目录

ini添加块段落

[ConsoleVariables]
r.ShaderPipelineCache.Enabled=0
r.ProgramBinaryCache.RestartAndroidAfterPrecompile=0

把这个添加到DefaultEngine.ini中就行了

结语

可以看到,PSO的整个生成加使用的流程即使在工具的帮助下依然是非常麻烦的,所以如果大家项目没有明显的Shader编译卡顿的情况,可以考虑不用使用这个东西,本文章基本从实用角度详细介绍了整个流程,网上看了不少文章只点出了部分细节,在实际接入中碰到不少坑,这里最主要记录了主要步骤和坑点,当然其中可能还缺少了一些细节,大家可参考最下方的其他文章,有什么问题可在下方评论留言,Enjoy it~😀

  • 资料参考

UE4之PSO缓存 - 可可西 - 博客园

UE4中使用PSO缓存优化_ue4 pso_Yuk丶的博客-CSDN博客

UE 项目优化:PSO Caching | 虚幻社区知识库 (ue5wiki.com)文章来源地址https://www.toymoban.com/news/detail-805115.html

到了这里,关于UE4 PSO缓存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【虚幻引擎】UE4/UE5 pak挂载

     找到:D:UEUE_4.27EngineBinariesWin64,  WindowS+R打开CMD命令 运行UnrealPak,运行结果如下      注意如果想要加载Pak内资源,那么这些资源必须是经过Cook的。如果打包的是未Cook的资源,那么即使Pak挂载成功,也不可能会成功加载Pak内资源。  Cook好之后,存储的路径在你的I:DBJ

    2024年02月10日
    浏览(70)
  • 【虚幻引擎】UE4 Spline(样条线)

           样条线Spline在UE中是一个很好用的工具,能够设置物体的跟随移动,也能够设置物体的批量复制,还能够设置一个特殊的模型形状比如圆管,还可以设置特殊的粒子特效,做地形设计等等,只要你想要实现的效果,spline都可以实现。官方也提供了很多的案例,可以参考

    2023年04月10日
    浏览(63)
  • 【虚幻引擎】UE4/UE5科大讯飞文字合成语音

    B站视频链接:https://space.bilibili.com/449549424?spm_id_from=333.1007.0.0   第一步:首先进入讯飞开放平台注册一个账号,然后创建一个 创建一个应用,命名按照你自己的想法来,会产生一个APPID,具体参考UE4如何接入科大讯飞的语音识别_ue4 科大讯飞的语音识别_飞起的猪的博客-CSDN博

    2024年02月13日
    浏览(68)
  • 【虚幻引擎】UE4 FTabmanager实现多窗口

    我们先看源码的实现方式:FTabmanager类实现了创建窗口的不同方法 NewLayout:创建新的布局方式  RegisterTabSpawner:注册在模块启动时的函数,这个就是创建了一个窗口,窗口所放置的内容  RestoreFrom:从窗口中显示 调用独立窗口需要在模块启动的时候调用FGlobalTabmanager::Get()的Re

    2024年02月10日
    浏览(72)
  • 【虚幻引擎】UE4/UE5鼠标点击事件实现物体移动

     在UE4/UE5中,引擎有它自己的一套框架体系,虚幻就是基于这一个框架体系来实现的。其中就有PlayerController(玩家控制器),玩家控制器中就有对鼠标的一系列设置,包括显示鼠标,允许点击事件等。  1.创建PlayerController,命名为MyPlayerController 2.打开MyPlayerController,勾选参数

    2024年02月10日
    浏览(100)
  • 【虚幻引擎】UE4/UE5数字孪生与前端Web页面匹配

            数字孪生是一种多维动态的数字映射,可大幅提高效能。数字孪生是充分利用物理模型、传感器更新、运行历史等数据,集成多学科、多物理量、多尺度、多概率的仿真过程,在虚拟空间中完成对现实体的复制和映射,从而反映物理实体的全生命周期过程。数字孪生

    2024年02月03日
    浏览(74)
  • 【虚幻引擎】UE4 同步和异步资源加载(软引用)

    虚幻引擎给我们提供了两种引用,一个是硬引用。软引用通常是仅储存资源对象的资源路径没有与资源产生耦合关系的引用(软引用加载到内存中,引用对象不会被加载到内存中,只有在需要的时候才会被加载进内存中)。硬引用则是拥有资源对象实际成员变量,直接与资源对

    2024年02月01日
    浏览(100)
  • 【虚幻引擎UE】UE4/UE5 GIS辅助类插件推荐及使用介绍

    此插件将虚幻引擎连接到Speckle,允许从Speckle接收版本化的3D数据,可以实现Revit、Rhino、Blender、Sketchup、Unity、虚幻引擎、AutoCAD等之间的完全互操作协作。 这是一个涵盖了在展厅、工业产品或其他3D场景中导航的许多可能性的系统。在窗口、触摸屏、手机和Html5上。 只需快速

    2024年02月07日
    浏览(94)
  • 【虚幻引擎UE】UE4/UE5 功能性插件推荐及使用介绍 2

    (基于UE5 的Python支持插件) 支持Python语言基于UE5进行开发 GIT地址:https://github.com/mamoniem/UnrealEditorPythonScripts (基于UE5 的Haxe支持插件) Haxe是一门新兴的开源编程语言,是一种开源的编程语言。支持Haxe语言基于UE5进行开发。 GIT地址:https://github.com/RobertBorghese/Haxe-UnrealEngine

    2024年02月06日
    浏览(89)
  • 【虚幻引擎UE】UE4/UE5 功能性插件推荐及使用介绍 1

    实现POST/GET基本方法,并支持HEAD带信息。 使用案例:【虚幻引擎UE】UE5 三种模式调用API详解(案例基于免费Varest插件) 能够快速实现打开对话框获取数据的导入、导出路径。 某月限免插件,比较方便的地图插件,可以改改样式直接用。 http下载数据到指定路径 按空格可以切

    2023年04月11日
    浏览(101)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包