推荐:使用 NSDT场景编辑器 助你快速搭建3D应用场景
WEBGPU VS. WEBGL
粗略地概述一下WebGPU与WebGL的不同之处是很有用的。在不涉及太多复杂的技术细节的情况下,两者的整体设计大致如下:
- WebGL和OpenGL一样,涉及许多单独的函数调用来更改单个设置。您或多或少还会更改一大堆全局设置。
- WebGPU 创建应用程序将提前使用的设置组。然后在运行时,它可以通过单个函数调用在整个设置组之间切换,这要快得多。它还根据现代 GPU 的工作方式组织所有设置,使应用程序能够更有效地使用硬件。
一个很好的例子也显示在这篇关于 Safari 中的 WebGPU 的博客文章.下面是一些用于渲染单个对象的 WebGL 代码:
gl.useProgram(program1);
gl.frontFace(gl.CW);
gl.cullFace(gl.FRONT);
gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_MIN);
gl.blendFuncSeparate(gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA, gl.ZERO);
gl.colorMask(true, false, true, true);
gl.depthMask(true);
gl.stencilMask(1);
gl.depthFunc(gl.GREATER);
gl.drawArrays(gl.TRIANGLES, 0, count);
这是WebGPU中的等效项:
encoder.setPipeline(renderPipeline);
encoder.draw(count, 1, 0, 0);
请注意,所有等效状态都将提前为 renderPipeline 设置。但是你不需要理解代码就能看到重点:要运行的代码更少,所以速度更快。
Mozilla Hacks 博客文章在 Firefox 中体验 WebGPU还包括对WebGL和WebGPU之间差异的更多技术摘要。
WebGPU 有很多好处(其中许多与其他新的低级图形 API 共享):
- 该 API 实际上更干净、更简单、更易于理解。OpenGL的做事方式从来都不是很流行。
- 应用程序可以更好地控制渲染的确切发生方式,并且可以执行更多操作来优化性能。
- 作为一个新的图形API,它也更加强大,并带来了以前WebGL难以或不可能的新功能,例如管理命令缓冲区。
- 浏览器会进行大量验证和安全检查,这会产生性能开销。使用 WebGPU,它可以提前完成大部分工作,而不是在渲染期间完成,从而减少浏览器开销。
- 它消除了图形驱动程序中的巨大复杂性和开销。现在,驱动程序可以更简单,更小,更接近于将呼叫转发到硬件。这也使得臭名昭著的可怕的图形驱动程序错误类更加罕见。
简而言之,这对所有相关人员都有好处 - 对于像我们这样的应用程序开发人员更好,对像nVidia和AMD这样工作更容易的硬件制造商更好,对获得更快性能的游戏玩家更好。
但是,没有什么是完美的,并且有一个很大的缺点:必须完全重写所有渲染代码才能利用这一点。这不仅适用于必须重写才能使用 WebGPU 的 Construct's 渲染器 - 它还适用于整个图形堆栈,包括浏览器的渲染代码、图形驱动程序代码,可能还有操作系统的一部分。这也是在所有艰难的规范工作完成之后,计算出 API 应该如何设计为跨一系列不同的低级图形 API 工作的所有细节。这是整个行业的大量工作,因此自然需要时间才能实现所有这些工作,并且这些新技术最终需要时间才能广泛应用。
构建中的WebGPU
尽管 WebGPU 仍在开发中,并且可能距离发布还有很长的路要走,但 WebGPU 的实验版本在某些浏览器中可用。我一直在Chrome Canary上尝试它,它允许我为Construct制作早期的WebGPU渲染器的原型。
与低级 API 的情况一样,在到达任何地方之前可能需要大量代码。我花了大约 1000 行 WebGPU 代码,才终于在 Construct 中看到了第一个使用 WebGPU 渲染的精灵!
混合是错误的,当我仔细观察时,渲染质量也不是很好,但你绝对可以看到图像!经过一些进一步的工作,进展更快,修复了混合,提高了渲染质量,并添加了更多功能。不久之后,我就让幽灵射手示例完全在 WebGPU 中渲染!
不过,这个游戏的渲染要求非常简单:它只不过是基本的精灵和“加法”混合模式。代码仍然非常笨拙,没有做好生产准备,并且有各种各样的更复杂的渲染功能需要涵盖 - 我预计效果合成器特别棘手。(有关背景,请参阅我过去的博客文章构造的效果合成器第 1 部分和第 2 部分.)WebGPU 本身离完成还有很长的路要走 - 例如,规范团队刚刚就着色器语言的发展方向达成一致。一旦新的着色器语言被指定、开发和测试,我们就可以将 80+ 个 Construct 现有的着色器效果移植到它身上。因此,虽然这是有希望的早期进展,但仍有很长的路要走。
早期发现
在Construct中使用WebGPU进行了一些初步原型设计后,它看起来非常有前途,并且是Web游戏的一项令人兴奋的发展。其中大部分是基于实验性 WebGPU 支持的早期工作,因此可能会发生变化,但以下是我的一些早期发现。
不再需要批处理队列
WebGPU over WebGL 的一个关键设计方面对 Construct很重要,那就是命令可以重新排序。为了解释为什么这很重要,我需要简要解释一下WebGL渲染器在内部是如何工作的。当渲染大量精灵时,它会将它们批处理在一起,正如我过去的博客文章所解释的那样。但是,在执行此操作时,它还会构建要渲染的所有精灵的大量坐标列表(顶点缓冲区)。为了提高性能,必须一次性将此列表发送到 GPU。但是在绘制完所有精灵之前,列表还不完整!因此,WebGL 渲染器会对所有 WebGL 命令进行排队,将它们延迟到列表完成。该过程如下所示:
- 绘制所有精灵,建立一个大的坐标列表,并保存 - 但不运行 - 所有 WebGL 命令。
- 渲染完成后,将坐标列表发送到 GPU。
- 然后运行所有排队的 WebGL 命令。
在许多情况下,这意味着在渲染期间建立一大堆命令,然后在帧结束时,再次遍历命令队列以实际运行它们。
WebGPU 的设计优势在于,步骤 2 - 将坐标列表发送到 GPU - 可以重新排序。这完全消除了对队列的需求!因此,该过程现在可能如下所示:
- 绘制所有精灵,建立一个大的坐标列表。
- 渲染完成后,插入“将坐标列表发送到 GPU”作为第一个命令。
就是这样!现在,所有 WebGPU 命令都在坐标列表发送到 GPU 后运行,我们完全消除了构建自己的命令队列的需要。
这是 Construct渲染器的一个很大的架构改进。它既简单多了,更易于使用,也更高效。
更好的接口
如上所述,WebGPU 使用的实际函数调用更加清晰和组织。因此,虽然更加低级,但一旦我进入了事物的摇摆,我实际上发现使用 WebGPU 更容易、更明显。特别是WebGL的两步绑定模型,你必须首先“绑定”你想要改变的东西,然后改变它,是笨拙和容易出错的。WebGPU 几乎完全取消了这一点,这本身就是一个很大的改进——整个 API 也有类似的改进。此外,更接近硬件的工作方式意味着我可以调整调用以达到 Construct渲染目的的最有效,而不是依赖于图形驱动程序中发生的各种复杂处理,这可能不快,有时甚至可能不正确。
有希望的性能结果
我认为现在发布实际的基准测试数字还为时过早 - WebGPU 和我的原型代码还有很多东西需要改变。然而,我的早期性能测试已经显示出有希望的结果,主要是在以前对WebGL具有挑战性的情况下。我设计了一些渲染“酷刑测试”,故意生成很长的绘制命令列表。这些在WebGPU中尤其快得多。我怀疑这既是因为删除了我之前解释的批处理队列,还因为图形驱动程序要简单得多,因此开销也更少。这很可能转化为有意义的实际性能改进,特别是对于无法有效批处理的游戏。
相当好的兼容性
我希望避免的结果是必须为两个渲染器编写两次所有渲染代码。这是我们几年来同时拥有canvas2d和WebGL渲染器时必须管理的东西。这意味着需要大量额外的工作来检查它们的渲染方式是否相同,修复两者中的错误,并且每次我们更改某些内容时,都必须在两个地方进行更改并验证两者。这也意味着第三方插件开发人员也必须为两者编写代码。
它很早,但看起来 WebGPU 实际上足够接近我们现有的渲染代码,应该可以在我们自己的绘图代码和第三方插件中使用相同的渲染代码来支持它。简而言之,我们有自己的渲染器类,所有 Constructer 代码都使用,而不是直接处理 WebGL。渲染器类在内部处理 WebGL 的所有细节。看起来这个类应该能够仅将 WebGPU 作为内部更改来处理,从而避免了在 Construct 中更改所有其他代码的需要。这一点很重要,可以使其易于维护并避免必须要求第三方开发人员进行更改(如果他们停止维护他们的插件,这将永远不会发生)。
一个重大的变化是WebGPU将使用与WebGL不同的着色器语言。这意味着所有效果很可能都必须重写,第三方也必须这样做。不过,这是一个较小的影响,应该是可控的。
尚无新功能
一个常见的问题是“我们将通过 WebGPU 获得哪些新功能?😎 “答案是,起初在Construct中可能不会有任何新的WebGPU特定功能。这有两个原因:
- 使用新技术从头开始编写一个全新的渲染器,对其进行测试和验证,修复所有错误,并管理逐步向所有人推出,已经足够了!
- 对于任何新的渲染器特定功能,我们必须处理以下问题:不支持它的渲染器会发生什么?例如,如果WebGPU可以做一个特定于WebGPU的闪亮的新效果,那么在只支持WebGL的设备上会发生什么?如果仍然有许多设备仅支持WebGL,则删除对WebGL的支持不是一种选择。简单地不显示效果通常会产生看起来错误的结果,导致用户和玩家感到困惑。如果我们添加一个特定于WebGL 2的功能,也会发生同样的问题 - WebGL 1系统呢?最简单的解决方案是完全避免这个问题,只实现可以在WebGL 1中完成的功能,因此可以在任何地方工作。我们可以添加的几个潜在的新渲染功能也可以在 WebGL 1 中完成 - 因此并不总是需要特定于渲染器的新功能。
然而,关于WebGPU的功能仍然有好消息:
- WebGPU 是最新、最现代的图形 API。将来,特别是高级的新渲染功能可能只添加到 WebGPU 中,而在 WebGL 中不可用。拥有WebGPU渲染器意味着我们可以利用新功能(我们认为与WebGL分道扬镳是值得的)。
- 某些 WebGPU 功能使显著的性能改进成为可能。这种“性能是一种功能”的方法,我们仍然可以充分利用,例如前面描述的批处理改进。
后续步骤
如前所述,原型WebGPU渲染器非常笨拙,但足够完整,可以渲染基本游戏,例如幽灵射手和太空冲击波.它已经利用了 WebGPU 实现的重大架构改进,并且早期迹象表明,有一些游戏具有可喜的性能结果,并有可能在现实世界中实现重大改进。我还发现并报告了一个铬错误- 在这个早期阶段并不奇怪,但尽早报告问题有助于确保在发布之前解决问题。
但是,存在重大遗漏,例如完全不支持着色器效果,以及需要清理许多丑陋的代码才能达到生产级。目前,我决定搁置进一步的开发工作,特别是因为此时我必须编写着色器程序才能走得更远,而当 WebGPU 着色器语言完成后,这些程序又必须重写,这意味着浪费精力。不过,我将继续密切关注 WebGPU 的发展,看看它在发布之前如何进一步发展会很有趣。随着WebGPU的成熟并获得更多功能,我们可能仍然可以对Construct进行进一步的改进。
我肯定会在将来再次拿起它,并在准备好时在 Construct 用户中开放 WebGPU 渲染器进行更广泛的测试。我不想承诺任何特定的时间尺度,因为 WebGPU 本身的进展存在很多不确定性,但我希望您可以在 2021 年的某个时候尝试一些东西。
结论
WebGPU将是Construct的重大技术升级。正如我们长期以来所做的那样,我们正在遵循最新网络技术的前沿,并将成为首批受益于其改进的引擎之一。
我也不敢相信网络平台已经进步了多远!我们从 2011 年开始使用软件渲染的 canvas2d 渲染器,它可以在高端桌面上勉强达到 30 FPS。我甚至做梦也想不到浏览器中有像WebGPU这样的东西。我认为这表明在网络上投注是一个伟大的举措,而且它仍然有回报。
WebGPU 是下一代技术,它从 OpenGL 等过去几十年的技术中学习,修复了许多旧错误,并进行了只有重新开始才能完成的各种根本性改进。与OpenGL之类的东西相比,WebGPU比原生级更好。它超越了OpenGL,WebGL和老一代DirectX API等技术,更快,更强大,设计更好。带有WebGPU的Construct渲染器甚至可以超越尚未跳转到下一代图形API的本机引擎 - 但我们需要基准来证明这一点(我很想看到一些!
这些改进都在筹备中,我很高兴看到它们如何发展,并最终在Construct中更广泛地发布WebGPU支持。不过这需要时间 - 很多时间。所以我们只需要耐心等待。但这是一个明显的迹象,Construct和网络上的图形前景非常光明。
原文链接:WebGpu VS WebGL (mvrlink.com)