游戏引擎和着色器卡顿

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

游戏引擎和着色器卡顿

  • GPU 已经变得非常快速、高效且可编程。着色器现在是一个完整的程序,需要为 GPU 进行编译

  • GPU 不像 CPU(x86、Arm 等)那样拥有共享的指令集架构 (ISA)

  • 每个独立 GPU 硬件供应商都有自己的架构,也都有自己的着色器编译方式,开发人员需要花很长时间才能编译所有 ISA,而且游戏发行版也会占用大量的磁盘空间

  • 着色器编译为中间格式,然后在用户的目标设备上编译最终的二进制文件

  • 在之前的图形 API(DirectX 11、OpenGL)中,GPU 驱动程序仅在绘制调用被调度时才知道其最终状态。这意味着驱动程序几乎没有时间编译新的着色器,甚至没有时间对其进行优化。如果遇到新的着色器或图形状态,游戏在驱动程序编译时可能会出现卡顿

PSO (管道状态对象(PSO))

  • 绘制调用需要哪个着色器和图形状态,它就可以告诉 GPU 驱动程序,然后 GPU 驱动程序可以在发出该绘制调用之前专门为该绘制调用编译一个着色器版本。

  • 如果我们及时获得这些信息,着色器编译也可能会花一些时间进行优化。
    通过包含图形状态和每次绘制调用的编译和优化着色器的描述符,驱动程序不需要在每次绘制调用时做太多额外的工作。

  • 许多游戏/引擎在不大规模重写代码的情况下,做了唯一能做的事情:在绘制调用发出之前阻塞线程,并编译 PSO。这会导致可怕的 HITCH(卡顿),也称为 STUTTER(断断续续)。

幸运的是,每个唯一的 PSO 只会发生一次卡顿,之后会被驱动程序缓存。然而,如果开发者不了解 PSO,这也会让他们难以重现问题。新的 GPU 驱动程序、新的游戏更新或驱动程序的 PSO 缓存已满也会导致缓存的 PSO 被删除。

  • 是一种相对自动的预编译PSO的功能,相关逻辑在Component的**PostLoad()**函数内被调用。当用户第一次加载关卡的时候,Precache系统会尝试收集关卡内对象的网格和材质信息,并在后台线程上异步编译PSO
  • Precache的过程在PostLoad期间进行,但运行时生成的Actor并不会调用该函数,这意味着运行时由用户生成的新Actor的PSO可能无法被记录在案(比如一个只有在玩家触发时才出现的粒子特效,且该粒子特效并不是一开始就在关卡内的),这部分PSO会在游玩过程中编译,造成卡顿

捆绑的 PSO 缓存(Bundle PSO Cache)

  • 玩家需要在游戏开始时等待所有内容在首次启动时进行编译,并且每次 GPU 驱动程序(甚至游戏)都会更新。
  • 这对于线性游戏来说非常有效,但对于开放世界游戏来说却很困难,对于用户生成的内容来说几乎是不可能的
  • 对于开发者来说,这是一个极其繁琐耗时的工作。而且玩家仍然需要编译比他们单次游戏所能看到的更多的着色器。尤其是在游戏为每种画质设置预编译每个PSO,而玩家只使用一种画质设置的情况下。或者为动态故事的所有分支预编译PSO。甚至仅仅是因为玩家可能只玩了几个小时,游戏的所有PSO都会被编译。

PSO预缓存(PSO Precache)

  • 目标:仅在加载场景对象时编译 PSO。
  • 当你收集所有可能的 PSO 状态并在游戏开始时进行编译时,我们称之为捆绑 PSO 缓存。当你在渲染之前仅为要加载的对象编译 PSO 时,我们称之为PSO 预缓存。
  • 缺点:第一次加载资产需要更长的时间,当您需要快速流式传输地图图块/子级别时,这可能会带来不便
  • 它不适用于运行时应用的动态材质
  • 它会在游戏过程中耗尽 CPU 核心,导致其他系统占用空间过小。您可以使用 cvar 甚至在运行时进行调整,但您必须在大量使用 CPU 核心和耗尽其他系统资源(可能影响帧率)之间找到平衡,或者使用较少的 CPU 核心并延长加载时间。
  • 在运行时更改质量设置将需要编译新的 PSO
  • PSO 预缓存编译的着色器数量大约是其实际使用的 5 倍,使用捆绑 PSO 只能减少这个数量,而不是完全消除它。对于非常线性的游戏,一些工作室实际上更喜欢禁用 PSO 预缓存并依赖捆绑 PSO 缓存,即使他们错过了任何缓存,也可能会面临卡顿的风险,但为了避免在游戏过程中编译任何 PSO,他们仍然选择禁用 PSO 预缓存。
  • 计算Shader 手机平台没有预缓存,手机平台下有几个关于ue 默认的预缓存是关闭的,ue5.4还是不全生效的.还是需要配合捆绑pso 方式使用。如果有Niagara内容,计算PSO在烘焙过程中会自动添加到缓存(如果你已为项目启用缓存)。实际测试的时候存在计算Shader 没有编译进去,有后处理的计算Shader 在运行时触发编译任务

平台

  • PC GPU 驱动程序不同,主机平台不会针对不同的 PSO 状态重新编译着色器
  • 移动设备与 PC 存在同样的问题:有太多不同的设备型号,无法为每一种设备直接进行编译
  • 对于移动设备上的 PSO 预缓存,CPU 核心数量减少、速度变慢意味着编译 PSO 的时间更长。为了缓解这一问题,我们尝试过滤掉一些不太常见的可选排列,并在移动设备上进行预缓存。但这意味着,如果您碰巧使用了这些较为罕见的可选排列,游戏在首次使用 PSO 时就会出现卡顿。

其它

  • 编译全局着色器时应该出现初始加载屏幕, 用于FShaderPipelineCache::NumPrecompilesRemaining()查询剩余数量
  • 定期使用启动参数测试游戏 -clearPSODriverCache,模拟首次运行的体验
  • 旧版API(如D3D11)也不受此缓存支持。
  • Log LogRHI all 的方式查看PSO 命中信息,加载信息
  • 非编辑器下设置环境变量 r.PSOPrecache.Validation=2,开启Stat PSOPrecache 查看统计PSO信息
  • UPrimitiveComponent收集设置 PSO 初始化程序所需的所有信息。它需要材质实例、顶点工厂(可能包含顶点元素集)以及可能影响最终着色器或渲染状态的参数集FMeshPassProcessor
  • virtual void PrecachePSOs();
  • UStaticMeshComponent::CollectPSOPrecacheData

PSO 区别

PSO

  • 一旦PSO对象被创建,其立刻处于可用的状态,且管线编译期信息不再可以被更改(如着色器、混合状态、颜色掩码等)
  • 着色器的编译相当于在PSO创建时就完成了
  • 但PSO的创建(编译)是一个非常非常耗时的操作,其时间开销已经不能和传统API的运行时着色器编译相提并论

旧式图形API(如OpenGL、DirectX11等)

  • 管线状态可通过单独的API Call来在渲染过程中进行设置(比如glSetBlendState、glCompileShader等.
  • 游玩时编译着色器会造成卡顿(虽然游戏引擎会提供一些预热功能来规避.
  • 在实际的DrawCall发出之前,用户可以随意改变管线的状态,所以图形驱动通常需要额外跟踪状态信息,并将实际的状态设置工作延迟到实际的DrawCall之前执行,
  • 图形驱动需要在渲染过程中实时计算硬件状态,将API编码到硬件指令

https://dev.epicgames.com/community/learning/tutorials/xjzE/unreal-engine-epic-for-indies-game-engines-shader-stuttering-ue-s-solution?source=Rkk

https://dev.epicgames.com/documentation/zh-cn/unreal-engine/manually-creating-bundled-pso-caches-in-unreal-engine?application_version=5.4

https://blog.csdn.net/Kaitiren/article/details/141953809

您可能感兴趣的与本文相关的镜像

Wan2.2-I2V-A14B

Wan2.2-I2V-A14B

图生视频
Wan2.2

Wan2.2是由通义万相开源高效文本到视频生成模型,是有​50亿参数的轻量级视频生成模型,专为快速内容创作优化。支持480P视频生成,具备优秀的时序连贯性和运动推理能力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值