/Chinese subtitle text from Game Engines & Shader Stuttering Unreal Engine’s Solution | Inside Unreal
Last active
September 4, 2025 15:42
-
-
Save Kethers/c84cd4cb68a255a6fe30dfe8d7a92fa9 to your computer and use it in GitHub Desktop.
Chinese subtile text from Game Engines & Shader Stuttering Unreal Engine’s Solution Inside Unreal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 注:前面的是虚幻周报,可以从129行开始看。原始视频链接:https://www.youtube.com/watch?v=i35yf-wh3Bs&t=574s | |
| 大家好 欢迎收看本周的 | |
| 新闻和社区热点 | |
| 虚幻引擎5.5.2版本已正式发布 | |
| 这个最新补丁 | |
| 这个最新补丁解决了 | |
| 100多个不同的错误和修复 | |
| 包括更正了MegaLights | |
| Alpha遮罩和光照通道问题 | |
| 修复了毛发阴影和毛发漏光问题 | |
| 以及已知的崩溃和停止响应等问题 | |
| 完整的补丁说明已发表在 | |
| Epic开发者社区供你查看 | |
| 如往常一样 | |
| 如果你遇到任何问题 | |
| 请务必在更新帖子中 | |
| 报告并提交错误表单 | |
| 以便我们今后继续改进虚幻引擎 | |
| 在过去四十年里 | |
| 《神偷卡门》中的环球冒险 | |
| 以其寓教于乐的独特模式 | |
| 吸引了无数粉丝 | |
| 尽管这个制作精良的 | |
| 动画剧集长期以来广受欢迎 | |
| 但玩家此前从未得以亲自操控这位 | |
| 国际恶联(VILE)的盗贼团伙头目 | |
| 而现在机会终于来了 | |
| 《神偷卡门》是一款全新的 | |
| 单人解谜冒险游戏 | |
| 讲述传奇神偷卡门·圣地亚哥的故事 | |
| 在游戏中 玩家将使用 | |
| 各种炫酷的高科技道具 | |
| 在全世界展开一场惊险之旅 | |
| 收集线索和破译密码 | |
| 与行踪诡秘的犯罪分子们斗智斗勇 | |
| 为了打造出生动鲜活的冒险故事 | |
| 开发商Gameloft Brisbane | |
| 选择了虚幻引擎5 | |
| 因为它用途广泛 功能全面 | |
| 能在多个平台上打造引人入胜的动态体验 | |
| 那为什么要选在现在 | |
| 让玩家扮演神偷卡门? | |
| 虚幻引擎的哪些具体功能 | |
| 帮助团队实现目标? | |
| 开发人员如何为多个平台优化体验? | |
| 最近我们采访了 | |
| Gameloft Brisbane | |
| 对他们进行一场深入“ 调查” | |
| 如果你有兴趣和我们一起 | |
| 查出这起案件的真相 | |
| 请在unrealengine.com/feed | |
| 了解完整内容 | |
| 想认识一些开发人员同行吗? | |
| 以下是这个月的社区聚会 | |
| 不要害羞 | |
| 快去参加离你最近的聚会吧 | |
| 介绍完这些激动人心的消息后 | |
| 让我们继续关注本周的精彩社区热点 | |
| 本周聚焦的热点略微有些不同 | |
| 这一次我们并不会着重于单个项目 | |
| 而是要全面介绍VFX美术师Nine的整个作品集 | |
| 从巨斧劈出的强力冰锥爆炸 | |
| 到从多个角度发动远距离突袭 | |
| 并最终施放强力攻击的阴影分身 | |
| 再到威力的强度不断增加 | |
| 带给你终极绝招感觉的光束攻击 | |
| 每一个招式都充满力量感和打击感 | |
| 每一次我们感觉特效的规模强度 | |
| 和炫酷程度已经触及天花板了 | |
| 就有新的东西出现 | |
| 证明我们错了 | |
| 这位艺术家的作品以精湛的方式展 | |
| 现了如何打造具有实感的视觉冲击 | |
| 希望大家也和我们一样 | |
| 能够欣赏这些项目 | |
| 请前往ArtStation页面 | |
| 了解更多信息 | |
| Louis Sullivan制作的 | |
| 《The Green Chapel》 | |
| 灵感源于David Lowery于2021年 | |
| 改编执导的电影《绿衣骑士》 | |
| 这个故事源自亚瑟王的传说 | |
| 为了以自己的方式重新演绎 | |
| 这个绿色礼拜堂场景 | |
| 作者Louis以兴趣爱好的形式 | |
| 启动了这个项目 | |
| 这个项目让他有机会练习 | |
| 在虚幻引擎5中 | |
| 使用Lumen进行植被设计 资产制作 | |
| 场景构建 以及光照设计 | |
| 他还用到了Megascans | |
| 制作岩石资产 草 和生态群系纹理 | |
| 这棵敦实的橡树则是结合了手工制作细节 | |
| 可平铺(tileable) 纹理 | |
| 以及树叶图集(atlas) | |
| 场景中还使用了虚幻引擎素材包中的 | |
| 一些视觉特效和着色器 | |
| 为场景带来了更多的动态效果 | |
| 让项目更加鲜活逼真 | |
| 我们可以很容易地想象到 | |
| 绿衣骑士正坐在他的宝座上 | |
| 等待与高文爵士进行最后的对决 | |
| 你能想象到吗? 你可以在TA的 | |
| ArtStation页面上查看完整项目 | |
| 由QianXin Lee设计的 | |
| Stylized Holy Spring | |
| 不仅拥有精美的制作和设计 | |
| 沉浸式的呈现方式也引人入胜 | |
| 动态的摄像机运动带领我们 | |
| 领略了这幅别具一格的风景画 | |
| 波光粼粼的河流周围环绕着 | |
| 色彩缤纷 生机勃勃的植被 | |
| 吸引人们将目光移向背景中 | |
| 震撼人心 飞流直下的瀑布 | |
| 如果你震惊于这个场景 | |
| 在温暖的夕阳下看起来有多么动人 | |
| 那么请允许我们现在向你展现 | |
| 充满氛围感的夜景版本 | |
| 在这柔和迷人的午夜微光下 | |
| 水面泛着星光 | |
| 我们无法用语言来描述这段演示视频 | |
| 为我们的内心带来的感动和震撼 | |
| 只希望大家也和我们一样喜欢这个场景 | |
| 完整文章可在作者的ArtStation页面找到 | |
| 作者还在介绍中列出了TA用到的资产和素材包 | |
| 以上就是今日的新闻和社区热点 | |
| 非常感谢您的收看 我们下期见 | |
| 大家好 欢迎收看《Inside Unreal》 | |
| 一档学习和探索虚幻引擎相关知识的周更节目 | |
| 我是主持人Tina | |
| 今天我们请来了几位非常优秀的来宾 | |
| 他们将讨论PSO预缓存 | |
| 着色器卡顿等问题 | |
| 那么我们直入主题 | |
| 先请来宾进行自我介绍 | |
| 好了 Ari 你先来吧 | |
| 为观众们介绍一下自己 | |
| 谢谢你 Tina 这已经是我第三次 | |
| 参加Insight Unreal直播节目了 | |
| 很高兴能和大家一起直播 | |
| 我叫Ari | |
| 我是Epic Games的开发者关系专员 | |
| 我工作的大部分时间 | |
| 都花在做演示和分享知识上 | |
| 简而言之 这就是我的工作 | |
| 没错 Ari的演示都非常棒 | |
| 大家有兴趣的话 | |
| 可以到虚幻引擎的社交频道上查看 | |
| 特别是Unreal Fest的频道 | |
| 快去看看吧 | |
| 下面有请Daniele | |
| 请简单介绍一下你自己吧 | |
| 大家好 我是Daniele | |
| 是《Fortnite》桌面版团队的主程序员 | |
| 我和团队致力于 | |
| 为PC平台的《Fortnite》提供支持 | |
| 包括稳定性 性能以及 | |
| 在PC上玩《Fortnite》的整体体验 | |
| 我为PSO预缓存系统开发了 | |
| 多个组件 | |
| 并针对《Fortnite》和我们支持的 | |
| 多种硬件对其进行了优化 | |
| 这就是我的工作 | |
| 很高兴你能来到这里 | |
| 接下来是Mihnea | |
| 请简单介绍一下你自己 | |
| 嗯 大家好 嗯 我叫Mihnea | |
| 我是渲染团队的工程总监 | |
| 我负责领导渲染架构团队 | |
| 我也站在管理的角度参与解决PSO预缓存问题 | |
| 另外 我的团队还负责处理 | |
| 骨骼网格体渲染 | |
| 流送 虚拟纹理等内容 | |
| 我们的专业领域就是底层渲染器 | |
| 很好 最后我们要介绍的是Kenzo | |
| 也向大家介绍一下你自己吧 | |
| 嗨 我是Kenzo | |
| 我在Epic工作已经大概有5年多了 | |
| 我也在Mihnea的团队中工作 | |
| 在Epic 我们团队负责多个不同工作 | |
| 我参与过那个 | |
| 《黑客帝国》游戏演示的工作 | |
| 帮助完成了《Fortnite》 | |
| 光线追踪的初期工作 | |
| 还参与了乐高游戏的开发工作 | |
| 这个PSO预缓存问题就是我发起的 | |
| 因为我们都想要把工作做得更好 | |
| 想要帮大部分开发者 | |
| 以及《Fortnite》解决这个问题 | |
| 这也解释了我们今天在这里 | |
| 很好 | |
| 能邀请到大家真是太棒了 | |
| 非常感谢大家抽出时间 | |
| Ari 我决定把话筒先交给你 | |
| 你来帮我们开个头吧 太感谢了 | |
| 谢谢 我来开头吧 因为PSO预缓存 | |
| 和着色器的问题对我来说 | |
| 是个非常重大的课题 | |
| 我正在研究这方面的问题 | |
| 准备通过我的下一次演示进行讲解 | |
| 然后我发现这个问题 | |
| 要深究起来其实非常棘手 | |
| 我准备了很多材料 | |
| 可以进行完整的演示 | |
| 那么何不通过这次机会讲一讲呢 | |
| 现在我要在屏幕上播放几张幻灯片 | |
| 这次演示的标题是 | |
| 《游戏引擎与着色器卡顿:虚幻引擎的解决方案》 | |
| 和我们刚刚发布的博客文章同名 | |
| 这个幻灯片中会介绍许多相同的信息 | |
| 但呈现的具体方式有所不同 | |
| 我会按照我对这个问题的理解来介绍 | |
| 并且以我的方式 | |
| 让大家也理解这个问题 | |
| 那么我们开始吧 | |
| 首先要说的是现代PC GPU的性能现状 | |
| 事实是 GPU已经发展到性能非常强大 | |
| 效率非常高 并且可编程性也很强 | |
| 而如今的着色器也已经演变为完整的程序 | |
| 需要针对GPU进行编译 | |
| 就和CPU一样 | |
| 但这给我们带来了难题 | |
| GPU和CPU不一样 | |
| 没有共享指令集架构(ISA) | |
| 比如说CPU有x86 Arm等等架构 | |
| 大家都会严格遵从这些传统的指令集架构 | |
| 在未来也会一直持续下去 | |
| 但GPU没有这种共享架构 | |
| 每个独立的硬件供应商 | |
| 都有自己的架构 | |
| 这些架构有自己的着色器编译方式 | |
| 甚至于每一代GPU | |
| 都会发生架构上的改变 | |
| 就连不同的驱动版本也会 | |
| 导致编译着色器的方式发生变化 | |
| 这给我们带来了一个坏消息 | |
| 为这些不同的GPU和驱动程序之类的东西 | |
| 提前编译着色器是不可能的 | |
| 基本上我们只能在用户的计算机上编译着色器 | |
| 而用户的计算机差异实在太大了 | |
| 要提前为每一款GPU和每一个 | |
| 版本的驱动程序提前编译着色器 | |
| 那将会花费太多的时间 | |
| 占用太多硬盘空间 | |
| 这么做根本不可行 | |
| 万一未来发布全新的GPU怎么办 | |
| 未来发布新的驱动程序怎么办 | |
| 这根本就是不可能完成的任务 | |
| 但也有一些好消息 | |
| 正因如此 每家GPU供应商现在都会不断优化 | |
| 他们自己的着色器编译流程 | |
| 优化他们的指令集架构 | |
| 接下来深入讲讲着色器编译 | |
| 大家都会想 | |
| 啊 过去的日子多么美好啊 | |
| 过去我们有图像API | |
| 比如有DirectX 11 有OpenGL | |
| 而GPU驱动程序 | |
| 仅会在调度的那一瞬间 | |
| 得知绘制调用的最终状态 | |
| 就像是当你要发送绘制调用时 | |
| 你会说 | |
| 嘿 这就是图像最终呈现的样子 | |
| 而驱动程序只有很少的时间 | |
| 可以编译着色器 | |
| 基本上驱动程序通常就是在 | |
| 调度绘制的瞬间完成这个工作 | |
| 也就是说在绘制之前 | |
| GPU只会有很短的延迟时间 | |
| 也就是说大家可能会 | |
| 体验到一些小卡顿 | |
| 因为当游戏遇到 | |
| 新的着色器或图形状态时 | |
| 就得等待驱动程序完成编译 | |
| 所以会卡顿 | |
| 但是这个问题并不严重 | |
| 过去的驱动程序效率很高 | |
| 驱动程序已经尽其所能 | |
| 减小编译过程造成的影响 | |
| 但调度时间毕竟有限 | |
| 要想完全消除延迟是不可能的 | |
| 所以没错 | |
| 玩家可能会遇到微小的卡顿 | |
| 尽管我们都认为 或至少一些人认为 | |
| DirectX 11是个没有任何卡顿的好时代 | |
| 但其实它还是会卡顿 | |
| 只是在第一次运行时卡顿 | |
| 但现在我们会思考 | |
| 我们要如何改进这一点? | |
| 很明显 | |
| 在发出绘制调用前的一瞬进行调用就已经太晚了 | |
| 那么有没有办法 | |
| 让GPU驱动程序提前知道 | |
| 比如说提前知道我们要绘制什么 | |
| 提前知道绘制调用的各项参数 | |
| 那不就更好吗? | |
| 那不就是我们一直 | |
| 想要寻找的终极答案吗? | |
| 如果能让游戏提前知道绘制调用 | |
| 需要用到哪个着色器和图形数据 | |
| 它就可以提前告诉GPU驱动程序 | |
| 驱动程序就可以在这次绘制调用发出前 | |
| 就编译好专用于这次绘制调用的着色器版本 | |
| 如果我们通过合适的 | |
| 通知传输这些信息 | |
| 即便只是比绘制调用提前几秒钟 | |
| 着色器编译过程就能够有更多时间 | |
| 做一些优化之类的工作 | |
| 从前只有不到一毫秒 而现在可以有几毫秒 | |
| 可以用来进行编译和优化 实现最佳的性能 | |
| 假设我们有一个描述符 | |
| 其中包含每个绘制调用的图形状态 | |
| 以及已编译和优化的着色器 | |
| 这样一来 驱动程序就不需要 | |
| 为每一次绘制调用进行额外的工作 | |
| 绘制调用就会像是放在传送带上一样 | |
| 那么对于这么神奇的存在 | |
| 我们要如何称呼它呢? | |
| 这就是我们的管线状态对象 简称PSO | |
| 这就是我们的终极答案 | |
| 这种设计确实为我们的 | |
| 实时渲染过程带来了范式上的转变 | |
| 这个机制是在DirectX 12中引入的 | |
| 要充分利用PSO | |
| 整个实时渲染行业都需要调整工作机制 | |
| 用一种全新的方式来发出绘制指令 | |
| DirectX 12 Vulkan和Metal | |
| 将这个责任下发给了应用开发人员 | |
| 他们必须知道在调度之前 | |
| 绘制调用需要哪些信息 | |
| 这样做很合理 | |
| 因为驱动程序不可能知道这些信息 | |
| 而游戏和引擎则可以提前知道 | |
| 但问题在于 许多游戏 框架和引擎 | |
| 在开发的时候并没有考虑到这一点 | |
| 所以应用程序开发者们没办法 | |
| 提前准备好这些信息 | |
| 那么对于PSO的运用 | |
| 最糟糕的情况会是什么呢? | |
| 如果在绘制调用进行的时候PSO还没有准备好 | |
| 我们该怎么做? | |
| 许多游戏或引擎就只能在发出绘制调用之前占用线程 | |
| 等到PSO完成编译 | |
| 这就会造成大家避之不及的 | |
| 卡顿或延迟问题 | |
| 好的一面是 这种卡顿对于 | |
| 每个不同的PSO只会发生一次 | |
| 因为之后驱动程序会将其缓存 | |
| 也就是说 比如你进入了一个关卡 | |
| 所有东西都会发生卡顿 | |
| 情况简直太糟糕了 | |
| 你喊其他人来看 说这游戏简直太卡了 | |
| 结果运行得无比顺畅 | |
| 这是因为游戏会进行缓存 | |
| 问题是 如果你安装或更新了GPU驱动程序 | |
| 或者更新了游戏 | |
| 又或者你运行了一个别的游戏 | |
| 而这个游戏会另外进行PSO编译并占用缓存 | |
| 从而删除了之前哪个游戏的缓存PSO | |
| 那么最佳的工作流程是什么样呢? | |
| 我们认为 如果游戏或引擎 | |
| 在加载场景Object时 | |
| 知道该Object的确切PSO状态是什么 | |
| 那就最好了 | |
| 因为如果需要编译该PSO | |
| 只会把加载的时间稍微延长一些 | |
| 但问题是 许多游戏和引擎 | |
| 在开发时并没有考虑到这一点 | |
| 例如 就像我之前提到的 | |
| 虚幻引擎是非常动态的 | |
| 这是一个非常动态的引擎 | |
| 如果我们要预设一个场景Object | |
| 在加载时的图形状态 | |
| 这在某种程度上会牺牲了 | |
| 这个Object的动态程度 | |
| 就好像规定了它必须是这样 | |
| 然后我们必须这样处理 | |
| 万一我们想要实时更改怎么办? | |
| 在虚幻引擎中 | |
| 我们可以通过蓝图或C++进行更改 | |
| 就像我们每个人 | |
| 都可以创建的各种不同材质一样 | |
| 那么对于虚幻引擎以及这一类引擎和游戏来说 | |
| 它们现在能怎么做呢 | |
| 第一个解决方案是捆绑式PSO缓存 | |
| 所以问题就是 | |
| 我们是否能在游戏启动时提前编译所有的PSO | |
| 这样一来 当你需要在运行时用到某个PSO的时候 | |
| 它已经准备好了 | |
| 好消息是 这样就把问题解决了 | |
| 运行时不会再出现卡顿 搞定 | |
| 但这样做有一个缺点 | |
| 也就是说 玩家需要在 | |
| 第一次游戏开始时等待一段时间 | |
| 让PSO全部完成编译 | |
| 然后每次更新GPU驱动程序或游戏时 | |
| 又需要重新等待 | |
| 这种方式非常适合线性游戏 | |
| 提前处理所有PSO并不难 | |
| 对于开放世界游戏来说这可能会很困难 | |
| 而对于用户生成的内容 | |
| 这种方式几乎就完全不可行了 | |
| 但我认为这个解决方案已经足够好了 | |
| 事实上 我们不可能提前编译所有的PSO | |
| 比如对于虚幻这种非常动态的引擎来说 | |
| 每一个着色器的变体都太多 | |
| 无法一一编译 | |
| 而且其中大部分变体 | |
| 可能根本就用不到 | |
| 着色器编译可能会花费数小时 | |
| 对于运行游戏的用户来说 | |
| 这样做会占满他们的硬盘空间 | |
| 于是 业界提出了另一个解决方案 | |
| 生成一份仅包含游戏实际使用的 | |
| PSO状态的列表 | |
| 并在应用程序启动时 | |
| 仅编译这些PSO状态 | |
| 所以这是一种更有针对性的方法 | |
| 但这时 我们就遇到了新问题 | |
| 我们如何知道游戏实际使用了哪些PSO状态? | |
| 市面上有一些游戏和引擎 | |
| 其一切内容都是高度定制的 | |
| 它们清楚地知道自己用到了哪些PSO状态 | |
| 但也有其他类别的游戏和引擎是非常动态的 | |
| 比如虚幻引擎 | |
| 对于这些游戏或引擎来说 解决方案就是 | |
| 手动和/或自动通关游戏 | |
| 然后记录遇到的PSO状态 | |
| 将它们全部列出来 | |
| 然后玩家的计算机 | |
| 将根据此列表计算要编译的内容 | |
| 我认为要找出所有用到的内容非常困难 | |
| 尤其是对于非常动态的游戏世界 | |
| 要把这些PSO状态 | |
| 找出来简直难于登天 | |
| 而且大家知道 | |
| 还有那么多不同的图像质量设置呢 | |
| 如果你安排一个人去跑遍整个游戏 | |
| 费很大力气找出每一个材质和Object | |
| 走遍游戏世界的每一个角落 | |
| 然后有人告诉你 这只是画质拉满的设置 | |
| 现在你还得把中等和最低设置的整个流程再全跑一遍 | |
| 这个过程的工作量非常大 非常繁琐 | |
| 即便这样 玩家还是需要编译大量的着色器 | |
| 其中有很多是游戏过程中根本用不到的 | |
| 比如有人只是玩一两个小时就不玩了 | |
| 但游戏依然会把整个游戏里的 | |
| 每一个PSO都编译出来 | |
| 而且也许一款游戏没有对每个图像设置的 | |
| PSO编译需求进行区分 | |
| 那么它就会把所有图像画质 | |
| 设置都编译出来 | |
| 即便永远也不会用到 | |
| 所以这不是一个完美的解决方案 | |
| 另外还有一个常见问题就是 | |
| 如果遇到PSO缺失的情况游戏依然会卡顿 | |
| 也就是说 如果缺失了某个PSO | |
| 预先渲染的部分里不包括它 | |
| 此时就会卡顿 | |
| 因为游戏需要在绘制它之前进行编译 | |
| 这就是当今游戏卡顿的主要原因之一 | |
| 这不仅仅出现在 | |
| 虚幻引擎开发的游戏里 | |
| 这个问题普遍出现在使用 | |
| 这些新图形API的所有游戏中 | |
| 所以我们问自己 也问整个行业 | |
| 我们是否可以做得更好? | |
| 在Epic Games虚幻引擎团队里 | |
| 我们想出了一个称为 | |
| 预缓存(Prechacing)的解决方案 | |
| 借此 我们将改用一种 | |
| 更加解放双手的方法 | |
| 因此对于预缓存 我们的目标是 | |
| 仅在加载场景Object时进行PSO编译 | |
| 对于这些Object 我们会编译 | |
| 该Object可能需要用到的PSO | |
| 目前我们不可能在渲染之前 | |
| 准确知道会用到哪些PSO | |
| 有很多方面 例如使用点光源和定向光源 | |
| 在投射阴影时就会有很多不同之处 | |
| 所以我们只需要编译它们的超集 | |
| 这个超集里的内容只会比 | |
| 我们实际需要的内容多一点点 | |
| 因为我们不知道我们需要什么 | |
| 关键是这个超集里的内容会由驱动程序进行缓存 | |
| 然后我们会立刻将这些PSO从内存中删除 | |
| 所以我们不会保存太多的PSO | |
| 然后 当我们发出绘制调用时 | |
| 驱动程序就会从缓存中指定获取所需的PSO | |
| 这就是为什么我们称其为预缓存 | |
| 就好像我们在将其全部丢弃之前对其进行缓存 | |
| 然后驱动程序从缓存中获取数据 | |
| 因为这些术语可能会有些繁琐 | |
| 让人眼花缭乱 | |
| 比如预缓存(Precaching) | |
| 预编译(Precompiling)着色器 | |
| 还有一般的缓存(Caching)和 | |
| 捆绑(Bundling)很容易混淆 | |
| 有人会说预编译不起作用 | |
| 然后我们必须问清楚 | |
| 你说的预编译是指PSO捆绑式缓存中的预编译环节 | |
| 还是指预缓存期间的预编译环节 | |
| 要聊这个问题简直太难了 | |
| 因此我们将其拆分为两种解决方案 | |
| 一种是预缓存 | |
| 就是在载入期间进行编译 | |
| 另一种是在游戏开始时 | |
| 进行的捆绑式PSO缓存 | |
| 此时会预编译所有的着色器 | |
| 使用预缓存方法时的平均编译数量 | |
| 可能是实际使用的PSO的五倍 | |
| 其实这个效率已经非常不错了 | |
| 和捆绑式PSO缓存 | |
| 相比已经少很多了 | |
| 所以总体而言 这种解决方案更好 | |
| 显而易见 最大的好处是 | |
| 这种方式没有大量的前期编译工作量 | |
| 玩家们在玩游戏之前不必看着一个画面 | |
| 等待一分钟两分钟 十分钟 甚至十五分钟 | |
| 就看着游戏在编译着色器 等着游戏开始 | |
| 另一个优点是 | |
| 游戏不需要编译太多的PSO | |
| 只需要编译比需要的数量多出一点点 | |
| 但这种方案依然不完美 | |
| 我们终究需要找个时间来进行编译 | |
| 所以在第一次载入资产时 | |
| 花费的时间还是会变多 | |
| 因为要编译PSO | |
| 如果你需要快速地流送大量内容 | |
| 比如游戏的地图图块或子关卡时 | |
| 或者你想做没有加载界面 无缝流送的游戏时 | |
| 这种方式就会不太便利 | |
| 另一个缺点是 这种方式 | |
| 不能用于在运行时动态应用材质 | |
| 因为我们不知道你会在运行时动态应用什么材质 | |
| 但我们正在研究一种方法 | |
| 让开发人员能够以某种方式告知引擎 | |
| 他们将要应用哪些动态材质 | |
| 也就是说 比如开发人员能够将 | |
| 这个信息放入配置或蓝图或C++中 | |
| 告诉引擎 我早晚会显示这个 | |
| 动态材质 然后我们可以对其进行编译 | |
| 然后就可以在不造成任何影响的情况下切换显示它 | |
| 我们还有很长的路要走 仍在不断完善中 | |
| 另一个缺点就是 如我刚才所说 | |
| 这种方式会在运行时进行编译 | |
| 这就会充分占用CPU核心 | |
| 因此没有太多空间供其他系统使用 | |
| 如果你是在流送内容 | |
| 像动画系统这样的东西现在会占用多核心 | |
| 如果你还要同时编译着色器 | |
| 可能会挤占动画系统的资源 | |
| 但你完全可以对其进行配置 | |
| 你可以告诉引擎 | |
| 我想要让PSO预缓存仅占用几个核心 | |
| 我们甚至可以在运行时更改占用情况 | |
| 另一个弊端是 如果在运行时更改画质设置 | |
| 比如我现在用的是最高画质 | |
| 我不想要这个帧率 | |
| 我现在想改成中等画质 | |
| 那么此时游戏就需要编译新的PSO | |
| 此外还有全局着色器这种东西 | |
| 类似于全屏幕着色器 或者叫计算机着色器 | |
| 这类着色器需要在其他东西之前预先编译 | |
| 进行编译时 你还是会看到一个初始的载入界面 | |
| 因为这类着色器并非某些特定资产专用 | |
| 预缓存这个新系统 | |
| 已经在虚幻引擎5.3版本中默认启用了 | |
| 也包含在升级版本的项目中 | |
| 也就是说 如果你用旧版引擎制作了一个项目 | |
| 现在把引擎升级到了5.3 | |
| 那么你的项目也会默认启用预缓存 | |
| 除非你手动关闭它 | |
| 游戏工作室也可以将两者结合使用 | |
| 你可以使用捆绑式PSO缓存 同时启用预缓存 | |
| 这样做也很好 | |
| 如果采用这种方法 | |
| 你就可以对你能找到的 | |
| 所有PSO使用捆绑式PSO缓存 | |
| 而对于你没能找到的PSO | |
| 预缓存就可以解决这部分问题 | |
| 这样你就不会遇到卡顿问题了 | |
| 我们一直在大力进行相关开发 | |
| 最近我们确认了 | |
| 它基本上已经涵盖了《Fortnite》 | |
| 和我们的其他示例项目中 | |
| 用到的所有渲染路径 | |
| 虽然它对我们的使用案例来说已经非常好用了 | |
| 但并不代表对所有人的项目都很好用 | |
| 可能很多授权项目中还有 | |
| 很多罕见的渲染路径我们尚未发现 | |
| 如果遇到了一个我们漏掉的路径 | |
| 尚未给它编写预缓存程序 | |
| 那么此时可能就会卡顿 | |
| 如果你遇到PSO卡顿的情况 | |
| 请通过虚幻开发者网络 | |
| (现已更名为Epic专业支持)告诉我们 | |
| 让我们来解决这些问题 | |
| 不放过任何一个问题 | |
| 让虚幻引擎打造的游戏在未来不会遇到这样的问题 | |
| 因为有了这种解决方案 | |
| 我们基本上已经把问题都解决掉了 | |
| 在未来的虚幻引擎游戏中 | |
| 我们已经基本不会再遇到PSO卡顿的问题了 | |
| 这让我感到无比振奋 | |
| 但也许你还会想 | |
| 你们付出了这么大的努力开发这个功能 | |
| 但是为什么主机上没有这个问题 | |
| 为什么主机平台就没有卡顿问题 | |
| 为什么主机游戏在运行时不需要初始编译阶段 | |
| 这个问题对于主机平台来说并不复杂 | |
| 因为每款主机都使用同一种GPU | |
| 游戏开发者也只需要对每款主机制作一个版本 | |
| 比如这个版本专用于Xbox | |
| 这个版本专用于PS5 | |
| 这个专用于PS4等等 | |
| 这样你就可以在游戏打包阶段 | |
| 直接编译成最终的可执行代码 | |
| 而在PC上 决定要编译哪些内容的因素 | |
| 不止是着色器 | |
| 还包括图形数据 混合数据和Alpha通道等等 | |
| 主机游戏不用考虑这么多 | |
| 对于主机游戏 | |
| 只要你准备好了着色器 | |
| 那我们就用这些着色器 | |
| 我们不关心混合状态 有什么用什么 | |
| 而采用这种做法 | |
| 可能还是会对性能有所限制和挤占 | |
| 但重点是主机游戏开发商们 | |
| 认为这种妥协是可以接受的 | |
| 他们明白这个问题是无法完全解决的 | |
| 这就是平台的特点决定的 | |
| 总之言之 对于像我这样的开发人员来说 | |
| 这种妥协是完全可以接受的 | |
| 因为我不需要去处理PSO缓存之类的东西 | |
| 我相信所有的玩家也都会认同的 | |
| 我们认为这是一个非常可以接受的妥协 | |
| 那么问题来了 移动端又是什么情况呢 | |
| 与主机相同吗 | |
| 不幸的是 移动端和主机情况不同 | |
| 反而会遇到和PC平台一样的问题 | |
| 不同的设备型号太多 | |
| 你懂的 不可能为每一种设备专门进行编译 | |
| 另外手机CPU的核心速度较慢 | |
| 核心数量也较少 | |
| 意味着编译PSO需要花费更多时间 | |
| 我们已经采取了一些方法 | |
| 尽量改善移动平台的情况 | |
| 比如说我们列出了一些 | |
| 不那么常见的PSO排列组合 | |
| 直接把它们过滤掉了 | |
| 这些PSO直接就不编译了 | |
| 所以工作量少了很多 | |
| 希望速度能快一些 但这样一来 | |
| 如果你确实要用到其中某个PSO排列组合 | |
| 那就会出现卡顿 | |
| 但这种情况应该很少见 | |
| 那么下一个问题很重要 | |
| 如果我们展望未来 | |
| 这个情况可以得到改善吗 | |
| 比如说 我们可以做分布式的PSO缓存吗 | |
| 经常有人会问到我这个问题 | |
| 我自己也会思考这个问题 | |
| 如果你在Steam上玩游戏 | |
| 它会将SteamOS或SteamDeck的 | |
| PSO缓存分布在Vulkan上 这简直太棒了 | |
| 虽然它本质上是一台PC | |
| 但其实这个问题并不存在 | |
| 他们会用到一个 | |
| 叫Fossilize的Vulkan插件 | |
| 但这个插件对Dx12游戏是不可用的 | |
| 而对于Linux发行版 | |
| 也有一个叫Bazzite的插件 | |
| 可以用于掌机设备 | |
| 但这种方式只能对固定的硬件配置 | |
| 如SteamDeck或其他掌机设备 | |
| 使用而想要对所有 | |
| Dx12游戏使用这种方式 | |
| 如果有人能做到当然非常好 | |
| 但其实是不切实际的 | |
| 首先 数据量非常大 多达许多许多TB | |
| 其次 这种东西不能放到云端 | |
| 你不能让一个玩家在玩游戏的 | |
| 时候遇到一个什么东西 | |
| 然后把它上传到云端 | |
| 然后再让另一名玩家下载运行 | |
| 因为就像我一开始说过的那样 | |
| 这些着色器都是编译好的程序 | |
| 会在你的电脑上运行 | |
| 如果任何人都能够将可执行代码上传 | |
| 然后在别人的电脑上运行 | |
| 这会导致非常严重的安全风险问题 | |
| 除了安全问题以外 | |
| 这些代码还会让你的电脑很容易崩溃死机 | |
| 所以归根结底 还是得安排人去为 | |
| 每一款游戏 每一个驱动程序版本 | |
| 每一种GPU 手动收集所有会用到的PSO | |
| 这种方式真的太不切实际了 也很难做到 | |
| 也许有人能解决这个问题 | |
| 那可就太好了 我非常期待 | |
| 但目前来说我还想不到要如何解决 | |
| 如果有人能开发出这样的服务 然后收费的话 | |
| 相信他能挣一大笔钱 | |
| 那么问题又来了 | |
| 非要做这样的优化是不是有点过于积极了 | |
| 我们是不是太贪心 | |
| 我们是不是飞得太靠近太阳了 | |
| 将PSO状态参数进行捆绑式编译是不是个错误 | |
| 因为要编译的排列组合太多 | |
| 所以我想问 这么做是否值得 | |
| 因就像我刚才说的那样 | |
| 主机游戏开发商们就认为不值得 | |
| 他们觉得 算了 就用这一个着色器 直接编译它 | |
| 不去管什么状态参数 | |
| 有一样东西可以稍微缓解这个问题 | |
| Vulkan图形库里有个图形管线库 | |
| 它允许你将PSO拆分为四个阶段 | |
| 也就是说我们会进行实时拆分 | |
| 你只会编译这一个着色器 | |
| 而其他的PSO状态参数会储存在 | |
| 这些散列的片段中 | |
| 然后你可以在绘制时再把它们拼接起来 | |
| 就像是Dx11时代的做法 | |
| 但这样做就可以提前编译着色器 | |
| 进而实现非常优秀的性能 | |
| 但这个解决方案还处于早期阶段 | |
| 并非所有GPU供应商都支持它 | |
| 但我对未来充满希望 | |
| 希望能够有更多人支持它 | |
| 比如GPU供应商和图形API等等 | |
| 那么我来做个总结 | |
| 你也许会想 天啊 听起来太可怕了 | |
| PSO真的是更好的解决方案吗 | |
| 这么做值得吗 | |
| 要我说当然 PSO确实拥有很大优势 | |
| 但是如果没有事先做好周密的计划 | |
| 我不建议所有游戏都迁移到Dx12 | |
| 不然可能不尽人意 | |
| 现在问题是 没人强调过这个问题 | |
| 我们自己之前都没有太过注意 | |
| 我已经在游戏行业里工作18年了 | |
| 在它出现前我也不知道这是个问题 | |
| 游戏开始卡顿 从消费者的角度来看 | |
| 这才是我第一次意识到有这个问题 | |
| 啊 我发现游戏卡顿了 | |
| 这是为什么 然后我去查了资料 | |
| 才发现原来是这样 | |
| 而现在这已经变成了一个大问题 | |
| 现在每个人都知道这是什么情况了 | |
| 但在几年前 人们还没有意识到这一点 | |
| 我们也没有足够重视和强调这一点 | |
| 我们就只是说 现在虚幻引擎 | |
| 已经默认全部启用DirectX 12了 | |
| 但是根本没人提过游戏会卡顿 | |
| 这个PSO问题居然这么严重 | |
| 不得不承认 我们本来可以 | |
| 将这个问题处理得更好 | |
| 但是话又说回来 如果处理得当 | |
| DirectX 11和OpenGL确实很好用 | |
| 大家都会带着一种怀旧的滤镜去看它们 | |
| 觉得那个时代太美好了 | |
| 它们确实很优秀 但并不是没有卡顿问题 | |
| 首次编译着色器时仍可能出现卡顿 | |
| 只是问题和程度较低 | |
| 毕竟在那个只有DirectX 11的时代 | |
| 着色器本身也要小得多 | |
| 如果你现在用DirectX 12 | |
| 或Vulkan来运行游戏 | |
| 并且你可以提前提供PSO的话 | |
| 不用怀疑 卡顿的情况会少很多 | |
| 渲染的效率也会快得多 | |
| 此外 现在你还可以进行多线程处理 | |
| 不像DirectX 11 | |
| 它不支持多线程运用PSO | |
| 我们可以做到很多很强大的功能 | |
| 只是之前对PSO的运用不太得当 | |
| 影响了这种解决方案的名声 | |
| 但是假设你是一名开发人员 | |
| 听了我半个小时的演讲 | |
| 你肯定心里在想 别说了 | |
| 快告诉我该怎么做吧 | |
| 快给我划重点吧 那好 重点来了 | |
| 我专门做了一张重点的幻灯片 | |
| 如果你正在用虚幻引擎5.3之前的旧版本 | |
| 制作或发布游戏 | |
| 如果你用的是DirectX 12或Vulkan | |
| 那么你需要设置一个捆绑式PSO缓存 | |
| 这项工作非常繁琐 工作量很大 | |
| 你会感到很挫折 但那你必须完成这项工作 | |
| 如果你用的是虚幻引擎5.3或更新版本 | |
| 引擎会有预缓存功能 而且是默认启用的 | |
| 这个功能非常好用 | |
| 但也并非完全不需要你付出努力 | |
| 这个功能并非完全即插即用 | |
| 你还是需要做一点点努力 | |
| 因为游戏需要等到初始预缓存完成 | |
| 所以你需要做一个简单的载入界面 | |
| 告诉玩家我们要预缓存 | |
| 和预编译着色器类似 只是速度快得多 | |
| 此外你还需要留意 | |
| 第一次载入会比较慢 | |
| 因为要流送大量内容进来 | |
| 你还需要注意在流送内容时 | |
| 什么时候会发生核心饱和 | |
| 你需要相应地控制预算 | |
| 此外你还需要决定 | |
| 当出现PSO缺失时要怎么做 | |
| 目前的默认行为是 | |
| 当发生这种情况时 游戏会卡顿 | |
| 但是我们也可以设置成 | |
| 暂时隐藏这个Object | |
| 或者我们先显示一个默认材质 | |
| 不过这种设置并不是默认启用的 | |
| 因为我们并不知道你的游戏是什么样 | |
| 如果我们擅自设置这些选项 | |
| 可能会让你的游戏看上去一塌糊涂 | |
| 所以你需要自己研究出最适合你的设置 | |
| 而且这套解决方案并不适用于 | |
| 我们尚未发现的渲染路径 | |
| 遇到这些情况的话 也会发生卡顿 | |
| 不过这种情况应该很少见 | |
| 我们应该已经覆盖到了 | |
| 绝大部分渲染路径 | |
| 如果我们漏掉了什么 | |
| 请告诉我们 再重复一遍 | |
| 预缓存功能可以 | |
| 和捆绑式PSO缓存搭配使用 | |
| 充分发挥两种解决方案的优势 | |
| 这就是划出来的重点啦 | |
| 大家可以先截个屏 | |
| 3 2 1 我会把它放到网上 | |
| 大家放心 | |
| 今天的内容就到这里了 谢谢大家 | |
| 我在想象现在大家都在鼓掌 | |
| 言归正传 我觉得接下来应该进入问答环节了 | |
| 毕竟我只是个会讲幻灯片的帅哥 | |
| 幸运的是 我们有一整支渲染团队 | |
| 对于这个话题 他们比我懂得可多得多 | |
| 那么我们去和他们聊聊吧 | |
| 这番演讲太棒了 Ari | |
| 谢谢 好吧 那么接下来 | |
| 我们先看看这个问题 | |
| 大家经常问到这个问题 | |
| PSO是否是一种错误的选择 | |
| 还是我们用的方法不对 | |
| 答案是否定的 | |
| PSO帮助我们解决了编译问题 | |
| 以及其他很多困难 | |
| 在过去 Dx11没有这个功能 | |
| 它可以让你随时设置状态 | |
| 这导致绘制调用的成本很高 | |
| 比如大家都会努力优化 | |
| 提高游戏完成绘制调用的数量 | |
| 因为驱动程序要完成的 | |
| 工作量确实太大了 | |
| 当你发出绘制调用时 | |
| 你需要收集大量的状态 | |
| 而现在 这些数据都打包 | |
| 进了一个PSO里 | |
| 所以采用PSO不止可以 | |
| 让你提前编译着色器 | |
| 还可以让你运用多线程指令录制 | |
| 让绘制调用的成本大幅降低 | |
| 所以PSO绝对是个很好的解决方案 | |
| 但是 | |
| 现在事后来看 | |
| 把状态都放进PSO里 | |
| 让驱动程序在编译着色器的时候查看这些状态 | |
| 确实可以称之为一个错误 | |
| 但事后诸葛亮没有意义 | |
| 当我们在开发这个功能时 | |
| 我相信几乎没人能够预料到 | |
| 也许有极少数人预料到了 | |
| 但这个问题在未来会滚雪球一样越滚越大 | |
| 幸好现在情况已经有了改观 | |
| 正如你刚才提到的 | |
| Vulkan图形管线扩展插件 | |
| 这是向正确的方向迈出的一大步 | |
| 因为它允许我们编译 | |
| 至少是预先编译各个阶段 | |
| 并且它可以避免对所有状态和渲染模板格式 | |
| 以及所有影响PSO的数据进行捆绑式处理 | |
| 所导致的信息量爆炸 | |
| 所以我们不需要面对 | |
| 顶点着色器数量乘着色器数量再乘以状态数量 | |
| 这样的庞大运算量 | |
| 你只需要单独编译每个着色器和每个PSO | |
| 然后把它们拼接起来 | |
| 这个拼接过程应该不会消耗太大成本 | |
| 创建API需要的时间并不长 | |
| 所以只要编译好了着色器就轻松了 | |
| 不久之前Microsoft推出了一款敏捷SDK | |
| 这个东西非常好用 | |
| 因为可以提供一个向DirectX中 | |
| 添加新功能的方式 | |
| 这种方式更快 因为游戏可以直接将这个DLL打包 | |
| 然后这个DLL可以和驱动交互 | |
| 这样你就不必像Windows更新那样 | |
| 用一整个缓慢的流程来发布Windows更新 | |
| 再要求玩家完成Windows更新 | |
| 然后他们才能获得新功能 | |
| 这一步很重要 | |
| 因为只要我们向这个方向做出了改进 | |
| 我们就可以更快地将新功能推广给用户 | |
| 然后游戏和引擎可以开始使用新功能 | |
| 所以我们对这方面情况的改善很有信心 | |
| 让我们可以对API做出调整 | |
| 让API在这方面更高效 | |
| 当然 要完成这些工作还需要一些时间 | |
| 在这种新功能成熟之前 | |
| 我们可以先用预缓存系统 | |
| 现在这个系统已经比较成熟好用了 | |
| 已经尽量利用当前的API做到最好了 | |
| 只是需要你去手动关联 | |
| 其中包含的所有状态 | |
| 我还想简单介绍一下其他引擎采用的解决方案 | |
| 因为人们经常将那些引擎与虚幻引擎进行比较 | |
| 让一款定制引擎解决这个问题当然要容易得多 | |
| 因为当你确切知道 | |
| 自己在做什么样的游戏 | |
| 以及要支持什么功能时 | |
| 你的优化空间就更大 | |
| 不过虚幻引擎是一款通用引擎 | |
| 你可以用它制作任何类型的游戏 | |
| 大家已经制作了很多不同类型的游戏 | |
| 而且我们的目的就是 | |
| 让艺术家 不止是程序员 | |
| 也能发挥出强大的创造力 | |
| 这就是为什么我们很久以前就 | |
| 决定允许美术师创建材质 | |
| 这意味着你不必去找 | |
| 一名渲染程序员来为你编写着色器 | |
| 而且那样的话 | |
| 你就只能在游戏里用这一个着色器 | |
| 你也只需要编译这一个着色器 | |
| 而虚幻引擎采用的模式 | |
| 可以带来极大的灵活性 | |
| 允许大型团队同时工作 | |
| 创建大量内容 | |
| 但如果不加以限制的话 | |
| 这种工作模式就会创建大量的着色器 | |
| 这个问题一部分是我们的责任 | |
| 我们没有在工具里充分地表现出这一点 | |
| 没有向大家显示出你用 | |
| 一个材质就会创建多少个着色器 | |
| 以及 比如说一个静态开关 | |
| 也会影响你创建的着色器数量 | |
| 或者 一些材质实例也会有着色器 有的没有 | |
| 总之我们没有充分地公开这些信息 | |
| 因此大家在使用中很容易就会 | |
| 在不知不觉中创建大量着色器 | |
| 我们已经计划对这个问题进行改进 | |
| 会在编辑器中明确显示此类信息 | |
| 以便你可以减少着色器数量 | |
| 从而优化你的游戏 | |
| 因为退一万步说 | |
| 你最想要的就是少用一些着色器 | |
| 也许你用不到那么多材质 | |
| 也许有的材质不那么重要 | |
| 我认为这里需要强调一下 | |
| 材质和材质实例之间的区别 | |
| 是的 你可能 | |
| 有个基础材质 | |
| 你会用到它 还会用到材质实例 | |
| 不过只要你不更改或添加任何 | |
| 需要时间编译的内容 | |
| 它就不会创建新的着色器排列组合 | |
| 这是好事 因为这样的话 | |
| 这些内容就可以打包起来 | |
| 用来更高效地进行绘制调用之类的任务 | |
| 但有的时候 | |
| 有的变量在编译时是常量 | |
| 用来降低 比如静态开关 | |
| 没错 就像静态开关一样 | |
| 可以降低这些着色器的复杂程度 | |
| 并使其运行得更快 | |
| 很多时候我们有充分的理由 | |
| 将其做成静态开关 | |
| 但也有很多时候不能这么做 | |
| 曾经把这些东西做成静态开关非常重要 | |
| 因为着色器代码占用都很大 | |
| 但现在GPU已经强大很多了 | |
| 而且我认为 如果它不影响寄存器 | |
| 那么最好将它们 | |
| 保留为运行时变量 | |
| 这也可以说是我们的责任 | |
| 因为目前材质编辑器 | |
| 并没有很好地显示动态分支 | |
| 委婉地说就是这样 这方面我们也在努力 | |
| 目前我们正在对引擎做出很多改进 | |
| 希望能够更好地支持这方面问题 | |
| 不过确实 有的时候我们都会看到一些材质 | |
| 包含毫无意义的静态开关 | |
| 可能只是一条if指令 | |
| 运行起来效率一样很高 | |
| 当你在添加静态开关时务必要注意 | |
| 这样做会创建一个全新的着色器贴图 | |
| 其中包含所有排列组合 | |
| 这些排列组合都会进行编译和预缓存 | |
| 是的 我们有去重功能 | |
| 比如说 如果你创建了多个相同的着色器 | |
| 引擎会发现这个情况 | |
| 不会创建多个相同的着色器 | |
| 但有的时候你可能会创建多个着色器 | |
| 它们只是文本上的不同 | |
| 但功能和机制完全一样 | |
| 比如说 也许你会对一个数据乘以一个常量 | |
| 生成一个新的常量 所以差别很小 | |
| 但也是一个新的着色器 | |
| 又或者你可能会合并一些材质 | |
| 比如说这两个材质是由两个不同的人制作的 | |
| 他们彼此之间并不知道 | |
| 对方已经做了一个一模一样的材质 | |
| 这就会导致着色器数量 | |
| 发生不必要的爆炸式增长 | |
| 只要开发规范和管理得当 | |
| 这种情况就可以避免 | |
| 但此时你还是需要在制作成本 | |
| 和最优化着色器集之间做一个取舍 | |
| 因为如果你要打造一个巨大的世界 | |
| 你不可能让所有参与的美术师 | |
| 时时刻刻都保持充分沟通 | |
| 如果你拉所有人开个会说 | |
| 我们来制定一个计划 | |
| 尽量减少使用到的着色器数量 | |
| 这很好 这就是组织生产的正确方式 | |
| 我们团队在内部就是这样做的 | |
| 我们会安排技术美术师制作材质 | |
| 然后由其他人来使用 | |
| 将这些材质实例化 | |
| 你只需更改它们的纹理或参数即可 | |
| 但是采用这种工作方式 | |
| 我想说的是 你可以做到尽善尽美 | |
| 但在开发成本和提前做好一切规划 | |
| 列出你要用到的着色器集或材质集之间 | |
| 你总得有所取舍 | |
| - 你说 | |
| - 我可以聊一聊基于云的内容 | |
| 我们另外可以聊的一个话题 | |
| 如果你有很多人运行同一款游戏 | |
| 使用同一个版本的驱动程序 | |
| 使用相同的GPU | |
| 然后其中一个人完成了PSO编译 | |
| 那么也许你会想 嘿 我能不能 | |
| 把编译完的东西分享给其他人 | |
| 这里的问题是着色器是一种可执行的代码 | |
| 这种东西不能分享 | |
| 不安全 是一种安全隐患 | |
| 所以很遗憾 这种方式是不可行的 | |
| 而且也很不理想 毕竟第一个遇到 | |
| 问题的玩家肯定会经历卡顿 | |
| 所以是个不太公平的解决方案 | |
| 另一个问题是 | |
| 我们的工作完成了吗 | |
| 当然没有 我们的工作还没有完成 | |
| 我们还有很多事情要做 | |
| 我们仍然想改进这各方面 我们正在收集反馈 | |
| 我们获得的反馈越多 | |
| 推进的下一步工作就越多 | |
| 还有几个问题 我还需要再回去研究一下 | |
| 是的 如果我们漏掉了什么 | |
| 我们非常想知道 因为我们想解决这些问题 | |
| 理想情况下 就算你遇到了我们漏掉的东西 | |
| 应该也不会发生卡顿 只是会突然刷新材质之类的 | |
| 另外我们还在努力减轻PSO预缓存功能 | |
| 在拥有6或4个核心且支持超线程的常规游戏电脑上 | |
| 进行预缓存 | |
| 正因如此 我们可能需要 | |
| 更高效地区分哪些东西 | |
| 需要先进行编译 | |
| 这方面我们还有很多工作要做 | |
| 我还看到一些问题 | |
| 关于世界分区的问题 | |
| 我还需要多查一些资料 | |
| 直接聊一下世界分区的内容吧 | |
| 因为大家可能会看到较低的地块 | |
| 在替换之前持续较长时间 | |
| 我也同意 有很多使用案例是我们没有遇见过的 | |
| 因为我们只会跟授权厂商合作 | |
| 我们自己有《Fortnite》 和很多示例项目 | |
| 我们会利用这些项目的经验来指导这个优化过程 | |
| 而且效果很不错 | |
| 但是 恳请大家 | |
| 如果谁做了个游戏 卡顿问题很严重 | |
| 请通过UDN(现Epic专业支持) | |
| 或论坛联系我们 | |
| 因为只要有问题 我们就要调查清楚 | |
| 是的 正如Kenza和Ari所说 | |
| 我们的工作尚未完成 | |
| 我们正在努力解决这个问题 | |
| 当然 我们给你的第一个建议 | |
| 就是使用最新版本引擎 | |
| 我们明白 并不是每个人都有条件随时用最新版本 | |
| 但这是一套不断演变的系统 | |
| 所以你可以相信 5.5版本 | |
| 在这方面表现肯定会比5.4版好 | |
| 而5.4版又比5.3版好 | |
| 以此类推 | |
| 而对于有能力搭建 | |
| 自己的引擎的授权厂商 | |
| 大家也可以精准挑选一些 | |
| 与PSO预缓存相关的特定改动 | |
| 即便你还是使用5.4版引擎 | |
| 也可以把5.5版中的 | |
| 相关功能迁移进去 | |
| 但还是那句话 如果你已经用了 | |
| 最新最好的版本 | |
| 但依然遇到问题 请一定要联系我们 | |
| 你们提供的信息非常重要 | |
| 可以帮助我们进一步优化这方面的问题 | |
| 没错 我们也对开发者有一些建议 | |
| 比如Ari的最后一张幻灯片里的内容 | |
| 此外我们已经聊了一些别的事情 | |
| 比如我们已经说过 | |
| 要尽量控制使用的材质的数量 | |
| 这是可以做到的 只是有些繁琐 | |
| 我们正在添加相关的工具 | |
| 可能不会在5.6版中推出 | |
| 不过我们会尽快推出的 | |
| 我们正在尽最大努力 | |
| 争取在5.7版里推出 | |
| 另一个建议是 | |
| 这些解决方案不是全自动的 | |
| 也永远不可能是全自动的 | |
| 你还是得让游戏做一些事情 | |
| 比如说做一个加载界面 | |
| 告诉玩家你正在编译着色器 对吧 | |
| 引擎无法为你执行此操作 | |
| 只能在游戏层面做 | |
| 此外我们有API 相关的问题 | |
| 都在文档中解释了 | |
| 我们有API可以知道什么时候是游戏在提供功能 | |
| 什么时候是引擎在提供功能 | |
| 这样你就可以用文本显示正在编译着色器 | |
| 因为从用户体验的角度来看 | |
| 这种做法非常好 因为这样玩家就会知道 | |
| 哦 游戏没有卡住 正在加载呢 | |
| 我明白游戏必须要执行这一步 | |
| 这可能需要30秒或 | |
| 一分钟左右的时间 | |
| 所以把这个信息放在加载界面上 | |
| 就可以把这个情况告诉玩家们 | |
| 好吧 我觉得差不多了 | |
| 哦对了 拜托 请一定要去 | |
| 读我们发布的博文 | |
| 请一定要阅读文档 | |
| 我们必须要反复强调 | |
| 因为我们之前吃过这个亏 | |
| 我们把这个PSO预缓存功能 | |
| 加入到你的常规性能优化流程里 | |
| 否则的话 你就会遇到卡顿的问题 | |
| 我们现在有许多选项 | |
| 可以用来分析这个功能 | |
| 你会获得一份报告 告诉你是编译了PSO | |
| 还是漏掉了什么东西 | |
| 以及为什么会发生这种情况 | |
| 是哪个组件导致了缺漏 | |
| 所有信息都会显示 | |
| 但请一定要将这个功能 | |
| 包含在你的试玩过程中 | |
| 和你的性能收集过程中 | |
| 然后再采取相应的改动 再重复一遍 | |
| 如果你遇到了一个缺漏的情况 | |
| 你无法修复 | |
| 请与我们联系 我们将进行调查 | |
| 好 这里我可以补充一点 | |
| Unreal Insights中 | |
| 包含很多这样的调试功能 | |
| 所以当你遇到卡顿时 很容易就能 | |
| 在Unreal Insights中查看 | |
| 如果你查看问题详情 | |
| 就能看到问题可能是 | |
| 由于PSO编译造成的 | |
| 它会告诉你哪些没问题 | |
| 哪些编译 哪些着色器缺失 | |
| 是PSO预缓存没有涵盖到的 | |
| 这样你就可以判断你遇到的问题 | |
| 是否是我们上面说的引擎bug | |
| 之前我们以为不会用到的东西 | |
| 那么我们就需要修复这个问题 | |
| 呃 又或者问题可能是 | |
| 某个不正确的PSO预缓存配置导致的 | |
| 总之这些信息都会 | |
| 在Unreal Insights里 | |
| 这个功能也是许多开发者会频繁用到的 | |
| 所以你就可以在你常规的分析工作流程之上 | |
| 再采用和大家相同的工作流程 | |
| 好 再收集一波问题吧 | |
| 好的 没问题 现在可以开始了 | |
| 那么 那么大家请注意了 | |
| 现在我们开始问答环节 | |
| 如果你对本次直播 | |
| 到目前为止的内容有任何疑问 | |
| 请在聊天中提出 我们会尽量解答 | |
| 那么首先呢 在我们开始回答 | |
| 观众提出的第一个问题之前 | |
| 我们先来看看事先 | |
| 在网上收集的几个常见问题 | |
| 那么 我想请问大家的第一个问题是 | |
| 为什么虚幻引擎不能编译所有的着色器组合 | |
| 好的 我来回答吧 | |
| 没错 我记得这方面问题 | |
| 在刚才的幻灯片中提到过了 | |
| 如果你要编译所有可能的排列组合 | |
| 那么数量可能会高达上百万个 | |
| 因为有很多种状态 | |
| 不止是有着色器 | |
| 就像是顶点着色器的深度 | |
| 将你的网格体应用到你的渲染目标布局的顶点元素 | |
| 而且取决于你是否使用HDR之类的东西 | |
| 都会用到不同的PSO | |
| 那么问题是 我们是否能编译它的子集 | |
| 但这样还是会卡顿 所以我们需要 | |
| 处理非常非常多的着色器 | |
| 但是我们又不会用到 | |
| 着色器表里的所有着色器 | |
| 我们只使用这些着色器的一部分 | |
| 但当我们编译时 | |
| 我们不知道会用到哪些 | |
| 不会用到哪些 | |
| 所以我们实际上会过量编译 | |
| 大量的着色器 | |
| 是的 此外 | |
| 我认为还有一件事值得一提 | |
| 比如当你使用一个捆绑包时 | |
| 当你已经找出了 | |
| 游戏中的所有PSO时 | |
| 如果你的游戏是个 | |
| 规模庞大的开放世界游戏 | |
| 或者其中包含大量不同的元素 | |
| 当你在PlayStation上运行时 | |
| 你只会处理 海量PSO中的一小部分 | |
| 因为如果你只玩几个小时的 | |
| 游戏 根本不会看到游戏的全部内容 | |
| 或者当你运行《Fortnite》中的大逃杀 | |
| 情况就会变得非常极端 | |
| 因为游戏中总共有数千款外观道具 | |
| 如果你只玩几场游戏 | |
| 你不可能看到所有这些外观道具 | |
| 你很有可能永远也不会见到全部的外观道具 | |
| 你只会见到这些道具中的一小部分 | |
| 因此 提前编译所有内容是一种浪费 | |
| 至于你具体会见到的内容的比例 | |
| 每款游戏都有所不同 | |
| 但尽管每款游戏你见到的部分都不同 | |
| 但总体而言都只是 | |
| 这些游戏的一小部分 | |
| 因为大家不可能会同时应用所有的皮肤 | |
| 或者你不可能同时玩到所有的模式 | |
| 比如说你玩乐高或者音乐节体验的时候 | |
| 或者你来到一个用户制作的小岛上 | |
| 那么你就只会见到这些内容相对应的PSO | |
| 而不是所有PSO | |
| 所以这就是捆绑式缓存的问题所在 | |
| 因为如果你把整个游戏的所有PSO都找出来 | |
| 提前进行编译 | |
| 那么你就会编译太多 | |
| 根本用不上的东西 | |
| 而预缓存可以解决这个问题 | |
| 因为它只会处理你在一次游戏中载入的东西 | |
| 没错 那么再多说一下 | |
| 《Fortnite》与这方面问题相关的事情 | |
| 在采用PSO预缓存方式之前 | |
| 我们曾经使用过捆绑式缓存 | |
| 我们也遇到过这个问题 | |
| 我们可以努力找出很多的PSO | |
| 事实上我们已经为大逃杀 | |
| 找出了很多需要渲染的东西 | |
| 所以大多数时候都不会出现卡顿 | |
| 问题在于 | |
| 即便我们可以覆盖到所有的PSO | |
| 但困难还是存在 | |
| 总数可能高达上百万个 | |
| 此时我们就会撞到性能上限 | |
| 这样在引擎和游戏之外 | |
| 当你需要编译这么多东西 | |
| 即便是可行的 | |
| 你还是会遇到问题 比如你会看到 | |
| 驱动程序缓存占用很大硬盘空间 | |
| 而且缓存是有上限的 | |
| 因为驱动程序不希望 | |
| 一个游戏就把整个缓存占满了 | |
| 这样当驱动程序在预编译时 | |
| 需要处理太多PSO | |
| 就会在你持续预缓存的期间 | |
| 开始清除缓存里的东西 | |
| 这就会导致整个 | |
| 预编译过程变得失去意义 | |
| 因为驱动程序会开始删除 | |
| 你之前编译好的东西 | |
| 此外还有一些别的原因 | |
| 可以证明这样做 | |
| 并不是最好的解决方案 | |
| 即便你非常高效地找出了所有PSO | |
| 如果你的游戏内容量太庞大 | |
| 那就会把驱动程序缓存给撑爆 | |
| 这就是问题所在 | |
| 是的 回到我们之前提到的一点 | |
| 一些引擎和游戏采用了另一种方法 | |
| 比如设计一种所谓的超级着色器 | |
| 把一个材质应用到所有地方 | |
| 只是用参数来控制 对吧 | |
| 这是一个很好的方法 | |
| 如果你可以只更改着色器的纹理 | |
| 或某些值或其他内容 那就很高效 | |
| 但是如果材质有很多不同的行为方式 | |
| 基本上你就会用到一个巨大的Switch语句 | |
| 就会包含很多类似 | |
| if是这类材质 那就运行这段代码 | |
| if是那种材质 那就运行这段代码 | |
| 这种方式的问题在于寄存器分配 | |
| 要说这个可能会 | |
| 涉及太多技术面的事情 | |
| 但稍微聊一聊 | |
| 我觉得也很有意义 | |
| 简单来说 硬件的寄存器数量是有限的 | |
| 在最糟糕的情况下 | |
| 如果你的着色器 | |
| 使用太多这样的代码 调用太多的函数 | |
| 那么就会影响所谓的占用率 | |
| 也就是说 当你在编译你的着色器时 | |
| GPU需要分配多少硬件资源 | |
| 即便你用不到其中的一些PSO | |
| 或者即便没有任何任务会 | |
| 占用GPU最宝贵的硬件资源 | |
| 那么GPU还是会在判定占用率的时候 | |
| 认为你的游戏占用了最宝贵的硬件资源 | |
| 这一情况在达到某个阈值后 | |
| 就会大幅影响你的性能 | |
| 那样的话情况就太糟糕了 因此 | |
| 这种超级着色器方式也不太合理 | |
| 它在一定程度上是可行的 | |
| 绝对能够为特定类型的游戏解决问题 | |
| 但并不是所有游戏 | |
| 还是说《Fortnite》 | |
| 不对 我是说虚幻引擎 | |
| 虚幻引擎的设计思路是为了 | |
| 支持所有的使用场景 | |
| 甚至包括一些非游戏的使用场景 | |
| 我们不能轻易地决定说 | |
| 我们不会做这个功能 | |
| 所以你就不能 | |
| 做你想要做的内容 | |
| 好的 下面是大家提出的下一个问题 | |
| 是关于预缓存的 | |
| 是的 这篇帖子挺长 | |
| 我来逐字逐句读一下 | |
| 尽量不漏掉任何部分 | |
| 这个问题是说 在我看来 | |
| 在载入期间没有编译好的任何内容 | |
| 都会在运行时 | |
| 进行着色器编译 | |
| 这个操作不会阻塞游戏 | |
| 因为这些着色器不会用到 | |
| 但如果你在游戏中每一次 | |
| 见到一个新的粒子效果之类的东西时 | |
| 不会在整体上严重影响CPU性能吗 | |
| 我觉得确实会这样 | |
| 如果遇到这样的情况 | |
| 那么捆绑式预编译 | |
| 可能依然是最佳的方式 | |
| 所以我们尚未移除 | |
| 捆绑式PSO缓存这个功能 | |
| 捆绑式缓存依然可以使用 | |
| 我觉得对于某些游戏 | |
| 比如线性游戏之类的 | |
| 如果你有能力收集所有的PSO版本 | |
| 那么我觉得采用这种方式很合理 | |
| 但游戏规模越大 | |
| 玩家生成的内容和世界就会越多 | |
| 缓存也可能变得非常大 | |
| 这个方案可能就不太跟得上形势了 | |
| 因为PSO版本会变得太多 | |
| 没错 PSO预缓存功能 | |
| 会占用核心时间 | |
| 不过有一个选项可以加以限制 | |
| 而且我好像看到下面 | |
| 有一些建议 理想情况下 | |
| 我们希望加入一个选项 | |
| 在载入时处理的PSO预缓存 | |
| 工作量当然应该 | |
| 比运行时处理的数量要多 | |
| 而且我们还需要研究一下 | |
| 将内存占用的问题也纳入考虑范围内 | |
| 系统应该控制 | |
| 预缓存功能占用的资源比例 | |
| 这样也许更好 | |
| 此外 按理来说 这种占用率过高的 | |
| 问题应该只会在第一次执行时发生 | |
| 另外还有一个因素就是 | |
| 如果你使用捆绑式缓存 | |
| 会对QA部门或者相关人员造成巨大的工作压力 | |
| 毕竟他们需要收集所有可能的PSO排列组合 | |
| 以及覆盖所有不同的图像设置 | |
| 对于那些线上服务游戏 | |
| 特别是每隔几个月都会对世界进行更新的游戏 | |
| 我不是说《Fortnite》 | |
| 其他游戏也是这样 | |
| 是的 这样的话你 | |
| 每次都得重新收集一遍 | |
| 而且每次你遇到着色器改动或者别的情况 | |
| 就好比我们引擎也会 | |
| 每隔两三个月更新一次 | |
| 甚至频率更高 我们就遇到过着色器改动的情况 | |
| 那么所需的一切资源都会失效 | |
| 那么你就需要再次收集所有东西 | |
| 像这样持续地重复收集工作 | |
| 会耗费大量的人力和时间 | |
| 而且如果你在这个过程中漏掉了 | |
| 什么东西 那还是会出现卡顿 | |
| 那么你就可以结合这两个解决方案 | |
| 比如你知道一定数量的资源集一定会出现 | |
| 你很容易就能把它们全找出来 | |
| 这就能在启动时先解决掉一部分问题 | |
| 为你的游戏制作一个简单快速的载入界面 | |
| 然后再处理别的问题 | |
| 所以对这类游戏来说 | |
| PSO预缓存方案就非常合适 | |
| 好吧 就是这样 | |
| 太棒了 好吧 我们继续 | |
| 接下来是一些我们 | |
| 从聊天记录里找出来的问题 | |
| 我把这些问题 | |
| 快速地给大家念一遍 | |
| 所以先说声抱歉 重头戏要来了 | |
| 那么第一个问题是 预缓存功能是 | |
| 如何与世界分区配合工作的? | |
| 他们给出了一个示例 | |
| 就是他们自己的项目 | |
| 在流送进来新单元时 | |
| 似乎编译了很多新PSO | |
| 但这样还不够 所以他们会遇到很多卡顿的情况 | |
| 我来回答吧 呃 我之前也看到这个问题了 | |
| 简单扫了一眼 | |
| 我们自己的游戏也会使用世界分区 | |
| 并没有遇到卡顿问题 | |
| 但确实 这并不代表这个问题不存在 | |
| 这个情况很有意思 | |
| 那么 我记得我们应该已经更新了文档 | |
| 提供了更详细的信息 | |
| 应该是在5.5还是5.3版本中 | |
| 当前的5.5版本中应该有 | |
| 就是引擎会显示一些信息 | |
| 你可以清楚地看到卡顿来自于哪里 | |
| 你可以通过操作记录 | |
| 查看是哪个着色器造成了卡顿 | |
| 而且PSO预缓存验证功能 | |
| 也会在日志里清晰地显示 | |
| 是哪个组件或材质 | |
| 引擎还会告诉你 嘿 你缓存了这个东西 | |
| 但我们没见到这个东西 | |
| 或许这些功能可以帮上忙 | |
| 还有另一个造成卡顿的可能性 | |
| 那就是全局材质 | |
| 因为当你在世界中四处移动时 | |
| 全局着色器会创建光源的变体 | |
| 我们的游戏中就有数千个光源的排列组合 | |
| 因为这些光照效果很重要 | |
| 确实会对寄存器造成压力 | |
| 所以需要快速处理 | |
| 此外 我们还在最新版本中 | |
| 对特定的全局图像PSO集 | |
| 添加了PSO预缓存 | |
| 这也有可能会在运行时造成卡顿 | |
| 这些PSO主要用于烟雾 | |
| 灯光 Slate等 | |
| 我记得应该还有别的东西 对不起 | |
| 但是记不太清了 | |
| 总之这些因素确实可能造成卡顿 | |
| 搞不好你们已经修复了 | |
| 但世界分区的另一个问题是 | |
| 如上所述 如果有必要的话 | |
| 我们也可以帮忙 | |
| 解决低面数地块刷新的问题 | |
| 但是如果可以的话 | |
| 我想要先看一下日志 | |
| 深度分析一下具体情况 | |
| 才能更好地查明问题所在 | |
| 哇 那太好了 | |
| 下一个问题是 | |
| PSO是否是基于每个核心着色器 | |
| 排列组合进行编译 | |
| 还是也会对实例化材质进行编译 | |
| 这个问题也让我来回答吧 | |
| 这个问题的答案取决于使用的是什么组件 | |
| 如果这个组件用到的材质实例 | |
| 因为静态编译的常量 | |
| 而有排列组合上的不同 | |
| 那就也会对其进行编译 | |
| 否则的话就会编译 | |
| 基础材质里的PSO | |
| 好的 接下来是遍历卡顿的问题 | |
| 你们是否会解决或者尽量减轻这个问题 | |
| 它又是什么原因造成的呢 | |
| 我刚刚不小心静音了 | |
| 不好意思 我来回答 | |
| 是的 遍历卡顿 | |
| 或者一般来说的卡顿 | |
| 是一个更广泛的问题 | |
| 而不只是PSO编译的问题 | |
| 当然我们正在调查这些情况 | |
| 发生这种情况的原因有很多很多 | |
| 不同游戏之间的情况也不同 | |
| 这个问题嘛 没有通用的答案 | |
| 我们需要分析具体游戏 | |
| 看看到底是什么原因造成的 | |
| 是加载的问题吗 比如冗余载入 | |
| 比如说 你有一个场景捕获条件 | |
| 当你在四处移动时就会触发 | |
| 这就会增加你的处理时间 | |
| 也可能是垃圾回收 | |
| 原因有很多很多 | |
| 其中一些是在引擎端 | |
| 比如PSO编译 | |
| 举例来说 比如 | |
| 流送Actor或组件 | |
| 有时这些任务会花费较长时间 | |
| 我们正在研究 | |
| 如何对游戏物体的表现方式进行轻量化处理 | |
| 因为如果一个东西没有互动性机制 | |
| 那么就没有理由把它当作一个完整的组件 | |
| 付出Actor和其中全部组件的完整运算开销 | |
| 顺便说一下 | |
| CD Project Red和我们说 | |
| 他们已经为接下来要推出的游戏 | |
| 解决了这个问题 | |
| 虚幻引擎是一个开放引擎 | |
| 你可以拿到它的源代码 | |
| 很多人都会对它进行改造 | |
| 当然 我们还是希望为大家提供 | |
| 开箱即用的优质解决方案 | |
| 我们正在努力解决这个问题 | |
| 但还是那句话 | |
| 这是一个非常非常大的问题 | |
| 如果我们要解释所有的情况 | |
| 那么本次直播的时间完全不够用 | |
| 所以今天直播的问题 | |
| 还是限定在和PSO有关吧 | |
| 没错 太对了 下一个问题 | |
| 你们是否有计划加入某种程度的 | |
| 预测性PSO预缓存机制 | |
| 比如对附近的网格单元(grid cell) | |
| 和世界分区提前进行预缓存 | |
| 从而减轻加载卡顿的问题 | |
| 我来吧 我认为这是一个好主意 | |
| 可以与其他世界分区相关功能协同工作 | |
| 这种预测式的预缓存机制 | |
| 之前还真没想到 | |
| 这确实是个很有趣的思路 | |
| 太好了 我要把它记下来 | |
| 不错不错 我看看 下一个问题是 | |
| 有用户说他们最近将自己的实时开放世界游戏 | |
| 从捆绑式解决方案迁移到了预缓存解决方案 | |
| 自那以后 他们就一直在 | |
| 与显示默认材质或在低端设备上 | |
| CPU占用率较高等问题作斗争 | |
| 或者因为预缓存缺失而导致卡顿 | |
| 以及游戏会不停地释放和加载PSO | |
| 都是捆绑式解决方案没有遇到的问题 | |
| 他们表示 现在他们的游戏会占用较高的CPU | |
| 并且导致玩家看到默认材质 | |
| 偶尔还会导致卡顿 | |
| 似乎这种解决方案对他们的特定案例来说并不理想 | |
| 这种情况是正常的吗 | |
| 还是说只是他们的项目遇到了这种问题 | |
| 这种情况并不正常 | |
| 我想看看你们的项目中用到了多少材质 | |
| 这确实是个问题 | |
| 如我们之前提到的 刚才应该分享过这个信息了 | |
| 目前在一张《Fortnite》地图里 | |
| 我们会加载大约20000个PSO | |
| 基本是就是这么个数量级 | |
| 我猜你们的项目用到的 | |
| PSO数量应该比这个少 | |
| 因为《Fortnite》包含 | |
| 大量不同类型的内容 | |
| 所以我想看看你们的项目用到了多少 | |
| 默认情况下 不应该显示默认材质 | |
| 不过可能会突然刷新 | |
| 这可能是出于竞技游戏的原因 | |
| 这是设置决定的 | |
| 是的 设置 我的意思是 | |
| 你可能会因为竞技游戏的原因 | |
| 不想要出现这种刷新材质的情况 | |
| 另外我们可以帮助的一点是 | |
| 如之前所说 | |
| 我们也希望降低CPU占用 | |
| 如果我们能够更好地分拣出 | |
| 需要编译的东西 | |
| 比如区分出屏幕上需要 | |
| 编译的内容 当然 | |
| 这个功能我们还没做完 | |
| 这样应该也能大幅减轻 | |
| 突然刷新材质的问题 | |
| 还有个选项 刚刚在别的问题里 | |
| 也问到了这个情况 | |
| 有个选项可以让你在预缓存PSO之后 | |
| 把PSO保留在内存里 | |
| 我们一直在开发这个功能 | |
| 而且已经加入到5.5版里了 | |
| 之前确实没有这个选项 | |
| 所以不知道你们用得是哪个版本的引擎 | |
| 如果你们试试5.5版的话 | |
| 情况应该有大有改观 | |
| 你的游戏应该运行得更顺畅 | |
| 当然其中也有一点需要权衡 | |
| 如果你不是在PSO缓存完成后 | |
| 就将其删除 | |
| 而是选择将其保存在内存里 | |
| 这就会占用更多内存 | |
| 如果是大逃杀 | |
| 我猜大概会占用900MB的系统内存吧 | |
| 这要视具体情况而定 | |
| 关于《Fortnite》 | |
| 我想要多聊一聊和这个策略有关的事情 | |
| 没错 问题中提到 | |
| 捆绑式缓存会把所有PSO保留在内存里 | |
| 而预缓存系统会将它们删除 | |
| 然后让驱动程序对它们进行缓存 | |
| 并在需要的时候重建 | |
| 就像我说过的那样 有个选项 | |
| 可以把PSO留在内存里 | |
| 因为对于某些硬件厂商和驱动程序来说 | |
| 这样做可以在必要情况下 | |
| 重建PSO时大幅提升性能 | |
| 不过确实 这样会带来内存开销 | |
| 正因如此 默认情况下 | |
| 预缓存方案会在编译完PSO之后立刻将其释放 | |
| 所以 以《Fortnite》为例 | |
| 如果我们把所有预缓存的 | |
| PSO保留在内存里 | |
| 应该会增加 上次我看的时候 | |
| 大概是几GB的内存占用 | |
| 就是说光预缓存就会占用几GB的内存 | |
| 因此我们为《Fortnite》采用的方式 | |
| 以及我推荐其他游戏也采用这个方式 | |
| 虚幻引擎中提供了一个选项 | |
| 可以基于内存桶(memory bucket) | |
| 来设置控制台变量(CVar) | |
| 那么如果电脑拥有XGB的内存 | |
| 那么你可以为不同的内存桶设置CVar | |
| 那么通过这种设置 | |
| 你就可以在内存较大的电脑上 | |
| 保留更多的PSO | |
| 因为这些用户可能不会太担心内存发热的问题 | |
| 然后在内存较小的电脑上 | |
| 保留较少的PSO | |
| 而且现在我们正在和硬件厂商合作 | |
| 对GPU和驱动程序进行改良 | |
| 那样的话也许我们就根本不需要做这些设置了 | |
| 只依靠驱动程序缓存就够了 | |
| 这点确实很重要 | |
| 而如果用捆绑式缓存 | |
| 把所有PSO保留在内存里 | |
| 那也需要确保这个捆绑式 | |
| 缓存占用的空间不要太大 | |
| 况且还有其他原因 | |
| 总之把PSO保留在内存里本身不是一件坏事 | |
| 但是对于PSO预缓存来说 这是个运行时系统 | |
| 会在游戏运行的整个期间运行 | |
| 那就会导致问题了 | |
| 好 下一个问题 | |
| 你们是否有计划优化PSO设置 | |
| 使其更好用 | |
| 我想这个问题指的是捆绑式缓存方案 | |
| 众所周知难度确实很高 | |
| 要收集和核对所有需要编译的东西 | |
| 这个工序需要耗费大量资源 | |
| 我们目前并没有展开这方面工作 | |
| 短期内可能也不会去回顾这个问题 | |
| 我们的计划是将PSO预缓存方案 | |
| 优化到足够好的程度 | |
| 这样大家就完全没必要用捆绑式缓存了 | |
| 但在此期间 | |
| 我们承认要对捆绑式缓存进行妥善的设置 | |
| 需要花费一定成本 | |
| 我们有文档 我们知道文档里写的 | |
| 也不一定是最佳操作 | |
| 但如果你按照文档操作 你只需要做一次 | |
| 是的 而且还有个问题是 | |
| 我不确定引擎是否能帮你 | |
| 把所有的排列组合都收集到位 | |
| -没错 这就是问题所在 | |
| -这是工作量最大的部分 | |
| 虽然设置起来很麻烦 | |
| 但只要设置好了就没问题了 | |
| 但最大的工作量 | |
| 肯定是找到所有排列组合 | |
| 所以你需要进行测试 | |
| 你必须 也许你需要对 | |
| 整个世界进行流程试玩 | |
| 或者把摄像机路径跑一遍 | |
| 也许这样就可以收集到你游戏里的 | |
| 所有东西 但也可能做不到 | |
| 是的 问题是 比如我们 | |
| 经常遇见这样的情况 | |
| 比如某个东西被另一个东西盖住了 | |
| 你需要自定义它的深度 | |
| 或者一个物体突然之间靠近一个光源 | |
| 或者不处在光照之中 | |
| 你必须收集到所有这些案例 | |
| 是的 因为你可以把这个物体四处移动 | |
| 一会儿放到这里 | |
| 一会儿放到那里 突然之间在阳光下 | |
| 突然之间又离开阳光 | |
| 进入阴影中了 当然我们已经尽量进行优化 | |
| 不去渲染这些物体 | |
| 但毕竟它们可能会对光遮蔽系统和 | |
| 其他各种效果起到作用 | |
| 因此你必须确保找到 | |
| 所有这些代码路径 | |
| 对于捆绑式缓存方案 | |
| 也许我还能提一个建议 | |
| 我记得我之前和一个授权厂商聊过 | |
| 那就是预缓存方案 | |
| 也可以用来推动捆绑式缓存的收集过程 | |
| 不过这样的话 | |
| 最终你会得到一个巨大的超集 | |
| 那么在加载你的捆绑包时 | |
| 可能就会花费很长的时间 | |
| 这个操作本身是很容易的 | |
| 另外 如果你启用了预缓存 | |
| 当然默认就会启用 | |
| 那么引擎会在将PSO添加到 | |
| 捆绑包的时候 将这些PSO排除在外 | |
| 如果PSO已经进行预缓存了 | |
| 那么就只会把漏掉的 | |
| 那些PSO加入到捆绑包中 | |
| 你可能想把这个功能关闭或者开启 | |
| 都可以调整 | |
| 我们已经有很多CVar了 | |
| 所以除非有特殊的必要 | |
| 我们应该尽量把所用东西放在CVar里调整 | |
| 因此对于不同的游戏 | |
| 肯定有一些不同的解决方法 | |
| 还有一个问题是 | |
| 你什么时候梳理这个捆绑包 | |
| 因为你当然可以在开发过程中 | |
| 全程启用收集机制 | |
| 然后到最后再核对你找到的所有东西 | |
| 但是 比如你原本用到了一个材质 | |
| 然后又将其删除 | |
| 或你将这个材质用到了别的地方 | |
| 这就会导致你缓存的PSO | |
| 比游戏实际使用的多得多 | |
| 例如《Fortnite》 过去就采用这种方式 | |
| 我们会每个赛季收集一份新的缓存内容 | |
| 我们没有直接沿用上一个赛季的缓存内容 | |
| 因为这样的话它会变得越来越大 | |
| 太棒了 那么下一个问题是 | |
| 由于一些着色器 | |
| 已经变得越来越复杂 | |
| 那么有没有方法可以让游戏开发者 | |
| 对默认着色器进行精简 | |
| 用来在虚幻引擎中制作类似N64风格的游戏 | |
| 这种方法存在吗 | |
| 好的 我觉得要实现这个目的 | |
| 最简单的方式就是在PC上使用移动渲染器 | |
| 这个操作是绝对没问题的 | |
| 我们对《Fortnite》的性能模式 | |
| 就是采用的这种方法 | |
| 不知道这种方法是否能满足 | |
| 你的画质需求 呃 如果不能的话 | |
| 那还是得想办法 | |
| 削减材质的精细度以及材质的数量 | |
| 不过当然啦 你能做到的事情有限 | |
| 毕竟要支持这么多功能 | |
| 固定的资源开销是不可避免的 | |
| 对于《Fortnite》 呃抱歉 我是说 | |
| 虚幻引擎有很多很多着色器代码 | |
| 开销并不大 | |
| 因为如果一份材质不使用任何功能 | |
| 那么它就不会包含在最终的着色器代码中 | |
| 但有一些固定开销我们确实没法消除 | |
| 因为我不知道游戏会怎么做 | |
| 所以我建议 要么使用移动渲染器 | |
| 或者前向渲染器 这个功能还在引擎里 | |
| 可以在前向模式下运行桌面渲染器 | |
| 它的着色器稍微简单一些 | |
| 也可以试试这个方法 | |
| 在着色器编译期间 | |
| 是否有蓝图节点可用于检查 | |
| 完成的百分比 然后显示在UI上 | |
| 有的 我们还没有明确公开这各功能 | |
| 但大家最近已经开始讨论一个函数 | |
| 你只需要调用这个静态全局函数 | |
| 就可以检查未完成的正在编译中PSO数量 | |
| 你可以用这个函数 | |
| 也许显示的百分比不太准确 | |
| 这个函数能从蓝图调用吗 | |
| 它不能从蓝图调用 | |
| 所以你必须把它公开 | |
| 你必须将其放在C++里 | |
| 没错 C++里 你可能还需要 | |
| 获取一个初始计数 然后 | |
| 才能做一个类似进度条之类的东西 | |
| 应该不难 | |
| 请与我们联系 | |
| 我们会尽力帮助你实现这一目的 | |
| 是的 我们正在计划对API做一些小的改进 | |
| 能够返回未完成的PSO数量 此外 | |
| 我们在博客文章里讨论到的所有内容 | |
| 我觉得之前还没有提到过 | |
| 用于告诉引擎你可能要更换网格体材质的这个API | |
| 因为它是我们的工作还没有覆盖到的案例之一 | |
| 它对渲染器来说完全是个意外情况 | |
| 如果你在运行时更换材质 | |
| 因为我们没办法预测这个情况 | |
| 我们也无法足够早地提前预缓存 | |
| 所以它要么会突然刷新 | |
| 要么会显示默认材质 或发生卡顿 | |
| 我们将添加一个API | |
| 你可以在其中提前说明 | |
| 我可能会将这组材质用于这个网格体 | |
| 然后你可以切换使用 | |
| 这个组中你已经提供的材质 | |
| 这样它们就能像所有内容一样被缓存 | |
| 但目前我们还没有实装这个功能 | |
| 我们希望在5.6中添加这个功能 | |
| 太棒了 我很期待这个功能 | |
| 那么下一个问题 是否有办法 | |
| 可以查看管线缓存 | |
| 看看捆绑包中已经记录了哪些东西 | |
| 存在哪些东西? | |
| 这个问题我来答吧 | |
| 是的 我们有一个编辑器命令行 | |
| 应该叫做着色器通道缓存工具 | |
| (Shader Pipeline Cache Tools) | |
| 你可以使用这个工具 | |
| 提供一个新的管线缓存文件 | |
| 它将转储你记录的所有PSO描述符 | |
| 这样你就可以看看 | |
| 这个文件有多大 | |
| 其中有多少个PSO | |
| 我记得还有一些工具 | |
| 可以用来合并缓存 | |
| 这样你就可以将多次 | |
| 收集工作得到的结果进行合并 | |
| 是的 我建议你研究一下这个命令行工具 | |
| 有相关文档介绍如何使用 | |
| 太好了 | |
| 下一个问题是 | |
| 是否有可能在未来的引擎版本中对PSO进行简化 | |
| 没有 不太可能 | |
| PSO只会变得越来越繁重 | |
| 随着功能的增加 | |
| PSO的成本只会变得越来越大 | |
| 因为虚幻引擎始终致力于将图像 | |
| 保真度推上新的高度 | |
| 所以我们会不断加码 | |
| 着色器很复杂 | |
| 话虽如此 还是有可能的 | |
| 随着接下来的API改进 | |
| 比如之前提过的动态 | |
| 着色器连接之类的功能 | |
| 目前已经暂时搁置了 | |
| 不过这些功能最终会针对DirectX发布 | |
| 这就可以让我们编译多个不同部分的着色器 | |
| 然后把它们连接在一起 | |
| 这样一来 编译材质的成本就会降低 | |
| 因为你可以在开始时先编译 | |
| 一大段常用代码 这一步只用做一次 | |
| 然后每次编译材质时都只编译一小部分代码 | |
| 然后将其连接到之前 | |
| 已经编译好的大部分代码 | |
| 让每一个材质的编译成本降低 | |
| 所以目前阶段 | |
| 我们无法去做简化PSO | |
| 或着色器代码这样的工作 | |
| 但这方面问题在未来还是有希望的 | |
| 随着API 和硬件变得越发先进 | |
| 可以让我们更高效地进行编译 | |
| 是的 当D3d12在十年前发布时 | |
| 编译PSO大概 | |
| 只需要10 20或30毫秒 | |
| 现在就麻烦多了 | |
| 比现在少多了 对吧 | |
| 没错 现在呢 | |
| 编译一个PSO可能就需要上百毫秒 | |
| 没错 当编译的概念出现时 | |
| 基本上指的就是 | |
| 从XPC或甚至更早的字节码 | |
| 1比1映射到机器码的过程 | |
| 编译器非常简单 | |
| 只需查看并翻译它们看到的内容 | |
| 我想说的是 DirectX 9 | |
| 只有64个指令槽 | |
| 因为本来就没有太多工作需要处理 | |
| 着色器很简单 这个翻译过程很简单 | |
| 这根本就不是问题 | |
| 但随着着色器变得越发复杂 | |
| 问题就开始出现了 | |
| 当然 现在的驱动程序 | |
| 想要进行编译成本方面的优化 | |
| 因为优化本身非常值得一做 | |
| 可以让运行速度加倍 | |
| 不过还是那句话 随着着色器变得越发庞大 | |
| 编译器也变得越发复杂 | |
| 还想让一个编译器 | |
| 在10毫秒内完成工作是非常困难的 | |
| 而10毫秒本身就已经很长了 | |
| 因为整个帧也才16毫秒 | |
| 你不可能为了等待着色完成而让游戏暂停 | |
| 是的 200毫秒 | |
| 简直是比永远还要久 相当于很多很多帧 | |
| 好的 下一个问题是有人说 | |
| 他们使用静态开关在常规材质和调试逻辑之间切换 | |
| 你们推荐这样做吗 | |
| 我觉得问题不大 | |
| 只要你的最终关联组件中没有引用 | |
| 这些调试逻辑 那就不会使用它们 | |
| 但是如果它们最终仍处于关联状态 | |
| 可以切换到它们 | |
| 就好比它们存在于组件可以使用的材质列表中 | |
| 那么引擎就会预缓存它们 | |
| 这样就会对你造成影响了 | |
| 我们有很多调试着色器 例如全局图形PSO | |
| (Global Graphic PSO) | |
| 和全局计算PSO | |
| (Global Compute PSO) | |
| 我们知道它们的存在 | |
| 因为它们是全局的 | |
| 所以在引擎中 | |
| 我们可以将这些内容从预缓存中排除 | |
| 但只从材质的角度来看的话 | |
| 我们无法预知要排除哪些 | |
| 因此请确保没有 | |
| 将常规材质和调试逻辑连接 | |
| 这样你就不会 不要对组件使用它们 | |
| 是的 不要使用它们 那就没关系 | |
| 没有任何组件会加载它们 | |
| 所以我们就不会预缓存它们 | |
| 在游戏的发行版本中 对吧 | |
| 好的 可以给一个清晰明了的静态开关使用范例吗 | |
| 举例来说 如果你想控制资源数量 | |
| 比如材质中有两条路径 | |
| 一条路径使用大量纹理 | |
| 另一条路径使用一组不同的纹理 | |
| 这时应用静态开关就很合理 | |
| 另外在一些平台上 | |
| 显示元素数量限制压得很低 | |
| 你就可以这么做 | |
| 否则的话资源太多 根本无法绑定 | |
| 另一个是我们之前 | |
| 讨论过的超级着色器 | |
| 如果你的静态开关分支有很多代码 | |
| 那么你的动态着色器就会 | |
| 按照该开关里最低效的分支运行 | |
| 有了静态开关 | |
| 只使用两种材质就更合理了 | |
| 你要么凭直觉判断这种方法是否合适 | |
| 这两个选项都执行以下 | |
| 看看哪一个更好 | |
| 太棒了 我们还有很多问题 | |
| 遗憾的是我们没有时间一一解答所有问题 | |
| 不过这里有个问题非常好 | |
| 我觉得很适合用来结束今天的直播问答 | |
| 那么独立开发者可以怎么做 | |
| 特别是技术力不太强的开发者 | |
| 在为自己的项目设置PSO预缓存的时候 | |
| 我们可以怎么做 | |
| 这个问题太好了 这正是我们 | |
| 开发这个功能的初衷 | |
| 理想情况下 PSO预缓存功能 | |
| 本身就应该是开箱即用的 | |
| 我们希望这个功能就是能降低 | |
| 对你的技术力要求 | |
| 你不需要手动设置太多东西 | |
| 但要确保自己不会使用太多的材质 | |
| 因为会影响你游戏的性能 | |
| 这整个系统没有太复杂的问题 | |
| 直接就可以用 | |
| - 就是这样 | |
| - 一定要控制你所使用的PSO数量 | |
| 你所使用的材质数量 | |
| - 是的 | |
| -并且在缓存清空的情况下运行游戏 | |
| 在PSO缓存选项里 文档中有说明 | |
| 使用这个系统运行时 | |
| 它会在运行前清空缓存 | |
| 就好像是有人刚刚安装好了你的游戏 | |
| 你就可以看看运行状况如何 | |
| 如果出现卡顿 请阅读文档 | |
| 其中说明了如何对其进行分析 并找出卡顿的来源 | |
| 希望你可以找到出问题的材质或组件 | |
| 然后对其进行调整 或者 | |
| 你也可以将类似的材质合并 | |
| 如果你试过了很多方法 | |
| 还是会卡顿的话 请咨询我们 | |
| 当然 请尽量使用最新的引擎版本 | |
| 因为5.5中包含许多5.4中没有的改进 | |
| 很好 | |
| 我们今天的提问时间就到此为止 | |
| 如果大家还有任何问题 | |
| 很遗憾我们没有时间在直播里即时回答 | |
| 请随时在Epic开发者社区上 | |
| 发布你的问题 我们将尽力跟进 | |
| 我想请各位再最后一次发言 | |
| 在我们结束之前 关于今天的主题 | |
| 大家最后还有什么想要说的吗 | |
| 或者有什么希望大家知道的吗 | |
| 我相信大家还有很多想要说的话 | |
| 不过也得考虑别占用其他人太多时间 | |
| 我想要感谢大家的收看 | |
| 还有 再次强调 | |
| 如果有任何问题 请联系我们 | |
| 是的 非常感谢大家 | |
| 请记住 我们处在同一阵线 | |
| 都在努力制作更好的游戏 | |
| 因此 遇到问题时不要先怪别人 | |
| 请记住 我们都会竭尽全力互相帮助 | |
| 是的 | |
| 没错 那是一定的 好的 | |
| 非常感谢各位来宾 | |
| 今天抽出宝贵的时间来到这里 | |
| 和我们一起探讨这个话题 | |
| 能够深入了解这个问题 | |
| 真的非常非常有帮助 | |
| 我还要向所有来看直播 提出问题和参与其中的人 | |
| 表示衷心的感谢 | |
| 非常感谢大家来到这里 | |
| 成为这个社区的一员 | |
| 并与我们一起学习有关 | |
| 这个主题的更多知识 | |
| 中途加入直播的朋友也别担心 | |
| 如果你错过了一些内容 | |
| 没有关系 因为我们所有的直播内容视频 | |
| 都会在我们的虚幻引擎 | |
| Twitch和YouTube频道上发布 | |
| 你也可以通过虚幻引擎的所有社交频道 | |
| 与我们保持联系 | |
| 如果你还没有加入Epic开发者社区 | |
| 强烈建议你立即加入 | |
| 你可以在这里查阅我们发布的所有文档 | |
| 还可以在我们的论坛里进行讨论 | |
| 我们还有大量由Epic员工和 | |
| 社区优秀成员制作的学习内容和教程 | |
| 几乎所有与引擎有关的内容 | |
| 都可以在这里找到 | |
| 如果你还没有查看的话 | |
| 请务必先查看一下 | |
| 这就是今天的全部内容 | |
| 再次对各位来宾和所有观看直播的观众 | |
| 表示衷心的感谢 | |
| 和往常一样 我们下周还有 | |
| Inside Unreal直播节目 | |
| 我们到时候见 | |
| 非常感谢大家 | |
| 祝各位度过愉快的一天 | |
| 再见啦 谢谢 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment