加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

可能取代Vulkan和OpenGL的WebGPU为何如此重要?

(2023-05-17 12:04:17)
标签:

it

分类: 技术
WebGPU 作为新一代的 WebGL,为开发者提供了在浏览器绘制 3D 的新方法,它很可能也会取代 Canvas,成为在 Web 浏览器中绘制 2D 的新方式,甚至可能取代 Vulkan 和 OpenGL,成为任何软件或编程语言绘制图形的标准方式。
原文链接:https://cohost.org/mcc/post/1406157-i-want-to-talk-about-webgpu

WebGPU 是 WebAssembly 的一种新 API,它提供了一种在 Web 浏览器中使用 GPU 的方式。它为现代 GPU 提供更好的兼容、支持更通用的 GPU 计算、更快的操作以及能够访问到更高级的 GPU 特性。

经过 6 年研发,WebGPU 被正式集成到 Chrome 113 中。自此,开发者终于可以在 Web 浏览器端实现 3A 级渲染的 3D 应用了。

图 1-1 黑色背景上的三角形
单击右侧地址,https://data.runhello.com/j/wgpu/1/(复制到浏览器中打开) 如果你能够看到一个彩色的三角形如图 1 所示,那么说明你的浏览器已经支持 WebGPU。WebGPU 有望在今年年底出现在每种电脑的浏览器中,移动端可能会稍晚些。

如果你并非程序员,那么,WebGPU 对你可能没有太大的影响或者体验,和以前使用 Flash 差不多。但对于程序员来说,WebGPU 可能对你意义非凡,不妨跟随作者的脚步,来了解 WebGPU 的前世今生,以及它为何会如此重要。

注:为了更贴近原文,本文以第一人称的口吻来编译。

WebGPU 诞生的背后
人们过去在电脑上制作 3D 有两种方式:要么自已编写数学库来渲染 3D 效果,要么买一台 "SGI" 电脑,SGI 是一个人名,他设计了一个可以提供 3D 渲染的图形库,可以通过 C 语言编写的 API 来调用渲染 3D 模型。不知什么时候,有人开始为普通电脑制作插卡式的 3D 加速卡,这种插卡可以实现与 SGI 的大型 UNIX 机器相同的加速处理,于是有一天,SGI 发布了一个公共版本的图形库,这样不管是 UNIX 电脑还是普通电脑的加速卡都可以运行,这就是 OpenGL,原本 IRISGL 中的 "color ( ) " 和 "rectf ( ) " 变成了 OpenGL 中的 "glColor ( ) " 和 "glRectf ( ) "。

不过事情开始变得混乱,掌握着 PC 操作系统的微软公司并不打算使用 OpenGL,而是决定开发自己的 Direct3D,而其它一些 3D 卡供应商也有自己的 API 标准,所以有一段时间,某些游戏只能在特定显卡上加速,游戏研发公司有时不得不为游戏产品编写多个版本的 3D 模块,一次用软件渲染器,其它次是为他们想要支持的每种加速卡编写调用。我当时觉得 Direct3D 最终将设法把所有这些整合到一个标准中,因为当时如果不使用 Windows 操作系统,处理这些事儿将很麻烦。DirectX 试图通过将游戏公司锁定在微软操作系统中,而且将 DirectX 设置为它们唯一可用的底层库,有一段时间它确实做到了。

有一段时间,你可以经常听到大家说 Direct3D 比 OpenGL 好,不过很快 OpenGL 就追上了落后的关键功能,比如实现了着色器。主要原因在于组成 OpenGL 架构审查委员会的各个加速卡厂商成员在定义细节上浪费了较长的时间争论不休使得进展缓慢,可惜的是微软在当时只实现了一些基本的接口和框架,而期望具体实现的工作丢给加速卡厂商。

最早期的 OpenGL 是一个 " 固定函数渲染器 ",3D 渲染时固定的按顺序执行相应的功能函数。

上图中的每个方框都对应一些具体的函数,你可以通过调用它们完成相应的操作,但只限于 3D 加速卡所提供的操作。如果你的游戏中有阴影或雾,那是因为 OpenGL 或扩展库中提供了用于绘制阴影或雾的功能。如果想要一些 ARB ( OpenGL 架构评审委员会 ) 没有提供的功能,或者想要以独特的方式制作阴影或雾以使得游戏看起来与其他游戏不同,该怎么办呢?
于是 " 可编程着色器 " 诞生了,于是上图中黄框部分可以被自主更换了。比如标记 "1" 的内容可以在 " 顶点着色器 " 中实现,标记 "2" 的内容可以在 " 像素着色器 " 中实现。着色器会在运行时将一个简单的类似 C 语言的代码上传到视频驱动程序中(只需要上传代码,而不需要像普通程序一样编译它),驱动程序会将其转换为运算单元的配置并执行,代码将取代黄框的部分。这个技术出现后一下子让开发方式大变天,但更重要的是,它使得显卡的设计突然走上了一条有点奇怪的道路,显卡不再是专门的渲染工具,而开始用来运行程序。

不久之后,移动设备开始流行,于是在移动设备上进行 3D 渲染变得越来越重要。DirectX 没办法运行在这些设备的系统上,但是 2005 年左右的移动芯片要想运行 OpenGL 也是很难的。因为 OpenGL 有点太大了,毕竟它拥有 SGI 时代遗留下来的所有这些功能,于是一种新的东西 "OpenGL 2.0" 出现了,专门用于处理着色器和相关的支持,这导致了两个不相关的 API 被整合在同一个图形库中,许多 OpenGL 1.x 的函数都不能使用。

该规范说视频卡必须支持每个 OpenGL 的函数,但并没说必须硬件支持,因此在 90 年代早期设计的一些老旧功能,驱动程序会将整个屏幕复制到内存中在 CPU 上执行,然后再将结果图像复制到显卡,这时 FPS 一下子从 60 帧降到几乎一动不动。这些历史的遗留问题都为移动 GPU 的制造商带来大量额外的工作,为了解决这个问题,更名为 Khronos 的 ARB(OpenGL 架构评审委员会)引入了一套精简的 OpenGL"ES" 规范,它删除了必要功能之外的所有内容。开发者不必再为每个多边形或每个顶点调用函数,而是使用新的 API 来指定内存中的数据数组位置,同时支持固定管线或着色器管线。

这样一下子使得程序员的事情变得简单了许多,于是开发者纷纷用 OpenGL ES 重写项目。与着色器引发的情况一样,OpenGL ES 的出现也带来了一个奇怪的影响:从这时开始,Khronos 的决策越来越由硬件制造商的需求驱动,而不是程序员。

随着支持 OpenGL ES 的设备出现,OpenGL 开始了飞跃。智能手机 iPhone 的流行为学习和使用 OpenGL 提供了坚实的市场理由,任天堂游戏机也开始使用 OpenGL。OpenGL 在功能上开始赶上了 DirectX,特别是浏览器开发商也从之前的傲慢中,开始支持 OpenGL ES 的 JavaScript 版本 "WebGL",为此他们还在 JavaScript 语言中添加了对二进制数组的访问,这可是以前没有的事儿。这时候的 OpenGL 发展的似乎顺风顺水,风头无二,但实际上是这样么?

不!其实情况很糟糕。随着 OpenGL 的不断成熟,OpenGL 分裂出多个略有不同的标准,并且各自具有不同的交叉兼容性。每次解决 OpenGL 之前版本的错误最终都会将 API 复制为一个名称略有不同且签名略有不同的新功能。OpenGL 的另一个大问题是它有很多共享的全局状态,本应该用于解决这个问题的 VAO 和 VBO 最终却变成了必须跟踪的全局状态。而随着通用 GPU 的发展,程序员开始意识到 GPU 和 CPU 一样好,编程却稍微简单一些,所以他们开始使用一些编程技巧来加速一些非图形应用程序,比如将数据塞进像素着色器中,并读回包含编码结果的纹理。最初 Khronos 也迎合了这一点,OpenGL 的结构被设计的很乱,其中一些只能在某些机器上运行。更糟糕的是一些显卡商驱动支持的很差,Windows 的 OpenGL 驱动程序中更是臭名昭著。

一个叫做 "AZDO" 的人提出来一个解决方案,他发表在 GDC 演讲中,虽然我不相信 GDC 演讲是这个想法的起源,但这个演讲的确是 Vulkan、DirectX 12 和 Metal 命名方案背后的原因,它使得驱动程序被架空了,想法是这样的:众所周知到 2015 年,显卡已经对特定的工作方式进行了标准化,并且这种方式预计在未来十年内不会改变。图形库最初是基于它们公开的功能进行设计,但驱动程序变得越来越复杂,不只是做你告诉他们的功能,也试图预判你要做什么操作并尝试以最优化的方式去执行,但很不巧经常猜错,这导致开发者常常处于尴尬的境地。AZDO 通过图形库将函数调用与硬件实际执行的操作精确一致,这样驱动程序就无事可做。

现代图形 API(比如 Vulkan、DirectX 12 和 Metal)基本上都抛弃了驱动程序,或者更确切地说,直接集成为驱动程序。函数直接映射到 GPU 的具体内部功能,无需让 GPU 进行猜测。这样就提供了强大的性能和控制力。现代图形库允许定义 " 管道对象 ",图形着色器允许开发者替换图中的方框内容,而计算着色器允许使用一个大型着色器程序替换关系图,而管道对象允许定义自己的关系图。

开发者可以决定哪些 GPU 内存块是源,哪些是目标,如何解释它们,以及如何处理它们,调用哪些着色器。这样所有历史遗留的混乱问题都得到了解决。状态绑定在整齐定义的对象中,而不再是全局的。显卡供应商之前总是以各自不同的方式设计他们的着色器编译器,因此将文本着色器语言替换为字节码格式,该格式易于实现且更易于编写编译器,Vulkan 甚至允许为 GPU 内存编写自己的分配和释放处理。

这一切看起来很酷,但有一个问题,就是所有这些细粒度处理的复杂性太高,Vulkan 基本上不可能手动编写。实际上,DX12 和 Metal 提供了或多或少相同程度的细粒度复杂性,而且从各方面来看它们的编写都不错。但 Vulkan 并不是为手动编写而设计的。Khronos 不希望你手写 Vulkan,更确切地说,他们是不希望你直接手动编写。2015 年 GDC 对外宣布 Vulkan 时,我正在台下和一些图形引擎和游戏开发人员在一块儿,听着他们的解释:" 游戏开发人员实际上越来越不需要管游戏 API ,而只需要是面向高级中间件进行开发,比如 Unity 、Unreal 或其他的图形引擎,所以 Vulkan 是一个专为编写中间件而设计的图形库。" 当 Khronos 家伙解释这一点时,我注意到旁边的中间件开发人员笑了,可以想像到,他们的生活即将变得轻松得多。

我的工作变得越来越复杂。Vulkan 的使用很奇怪,每个 Vulkan 调用都涉及传入一两个巨大的结构体,这些结构体本身又会涉及其它更复杂的结构,每个结构和子结构都以一个小协议标头开头,解释它是什么以及它有多大。在分配内存之前,必须填写一个结构才能返回一个结构,该结构描述了应该在哪个结构中构建内存分配请求。这一切其实并没什么意义,除非你以前设计过一种编程语言,在这种情况下,你要不断的查看那些文档。这些文档却又编写的晦涩难懂,但它的确是完全按照硬件实现者想要的方式编写,并用来消除关于函数调用所做的所有歧义。简而言之,Vulkan 不好用,这是硬件制造商和中间件开发商之间的拜占庭协议,至于开发者的感受 ... 哈哈,反正我们的感受又不是协议的一部分。

Khronos 其实并没有忘记开发者,但他们只是做出了一个框架,这也好解释,他们无论如何都不可能设计完全符合开发者习惯的 API,只能是尽可能将好用的 API 编写到图形库里。Khronos 自信的认为,在 Vulkan 发布的几年内就会有一堆高质量的开源封装库,开发者会直接使用这些封装库而不是 Vulkan。但这些库后续并没有实现。事实证明,编写软件是一项复杂的工作,开源项目不会仅仅因为人们希望它们而实现。

这就引出了 Vulkan 在事后发展的问题。为了占领市场,微软开始持续更新高级图形 API,而 OpenGL 只是草率的追赶。如果 GPU 供应商支持 Vulkan 成为通用标准,DirectX 将只会变为微软某些体系性充的标准,但苹果却拒绝了。因为这时候苹果也推出了自己的产品 "Metal" 并宣布永远不会支持 Vulkan,也不会再支持 OpenGL。依我看这又是 "DirectX" 的历史重演罢了,在这个移动开发时代占主导地位的操作系统厂商,也在像微软在 90 年代一样去推动专有图形 API 以促进开发人员锁定在自已的操作系统中。他们通过降低对硬件厂商的依赖,提供给开发人员真正想要使用的东西。

随着苹果的退出,情况一下子变得微妙起来。突然之间,Windows、Mac/iPhone、Linux/Android 等操作系统都有自已的下一代图形 API。Linux 在 Vulkan 的驱动程序支持上有严重 BUG,而且许多 Linux 设备在 Vulkan 已经推出七年后仍然不支持 Vulkan,因此,Vulkan 原生运行的唯一平台只有 Android,不过局面没有想像的那么糟糕,Vulkan 其实可以在 Windows 上正常运行,因为它是轻量级的东西,非常轻巧地放在硬件层的顶部,这意味着它们并没有那么难用,以至于出现了一个名为 "MoltenVK" 的基于 Metal API 实现 Vulkan 的仿真层,据说运行时几乎没有增加开销。但是如果你是一个开源的人,没有资源来应付不同的平台后端,那就比较麻烦了。从技术上讲,你的代码可以在所有平台上运行,而且具备在两个主要平台上调用本地图形 API 的优势。简而言之,Vulkan 解决了 OpenGL 的所有问题,代价是制造出没人想使用,也没有理由使用的东西。

WebGL 是基于 OpenGL ES 设计的。但它却和 OpenGL ES 完全不同,从技术上讲,OpenGL ES 从未真正在桌面上运行过,即便是桌面系统上的常规 OpenGL 也存在许多问题。因此,浏览器开发人员最终意识到,如果你想在 Windows 上发布 OpenGL 的兼容层,实际上在 DirectX 中编写 OpenGL 模拟器比直接使用 OpenGL 更容易,并且不需要协调不同显卡驱动程序对 OpenGL 的各种不兼容性。

开发人员还意识到,如果不同 OpenGL 驱动程序之间的兼容性差异是地狱级的麻烦事儿,那么四个不同浏览器之间的兼容性差异乘以三个操作系统再乘以不同的显卡驱动程序将是有史以来最糟糕的事情。在这种假设的绝望中,一个通过跨公司开源协作的成功解决方案出现了:"ANGLE",这是一个 BSD 许可的 OpenGL 模拟器,最初由 Google 编写,但 Firefox 和 Apple 也都参与并实际做出了贡献,它用于对每个 Web 浏览器进行 WebGL 的支持。

但是大家并不想用 WebGL,而是想要一个现代图形库,一个类似 AZDO 的东西。因此,一个 W3C 工作组开始制作 Web Vulkan,他们将其命名为 WebGPU。我不确定我对事件的看法是否正确,但我的看法是,苹果公司将会是工作组中要求最高的参与者,也是每个人最担心的一个参与者,所以据报道 WebGPU 完全满足了苹果公司的一切要求,这也使得 WebGPU 看起来真的很像 Metal。但据说 Metal 一直是三个现代图形 API 中最好使用的,所以这就是结果?受到 ANGLE 成功的鼓舞(此时它开始在非 Web 应用程序中用作独立库),并且有开发者希望将这个新 API 与 WebASM 一起使用,他们采取了将标准同时定义为 JavaScript IDL 和 C 头文件的步骤,以使得非浏览器应用程序也可以将其用作库。

WebGPU 是 ANGLE 和 Metal 结合的产物,更是 Vulkan 所一直缺少的符合开发者习惯的 " 人体工程学层 "。WebGPU 在 Web 浏览器中运行,而微软和苹果都是浏览器标准委员会的成员,所以他们也是 WebGPU 的投资者,不仅 WebGPU 在他们的平台上可以像原生一样工作,而且用 WebGPU 开发的任何东西都可以在他们的操作系统上行,WebGPU 从第一天起就提供与 JavaScript/TypeScript、C++ 和 Rust 具有完全相同的兼容性。

我相信 WebGPU 才是我们一直在等待的东西。

WebGPU 是什么样子的?
因为没有用过 DirectX 或 Metal,我无法将 WebGPU 与这两种图形 API 进行对比,但与 OpenGL 和 Vulkan 相比,WebGPU 使用起来非常令人耳目一新。记得我写 Vulkan 的时候,每次都被它的复杂性打败相比之下,WebGPU 只有需要增加某些比较复杂的东西时才比较难受,因为有很多不同的对象需要跟踪,尤其是在初始化期间,但每个对象都与真实存在的东西所对应。不过你也可以将所有的复杂性塞进初始化时间,使实际绘制框架的过程非常简洁。

不过 WebGPU 有三个要注意的问题:
1、文本
2、线条
3、" 讨厌鬼 "

文本和线条基本上是相同的问题。WebGPU 对他们支持的不够。WebGPU 可以画线,但仅能绘制单像素宽度,而无法控制抗锯齿。因此,如果你想要一条 " 正常外观 " 的线条,你需要使用定制网格模型和着色器做一些复杂的事情。与文本类似,你也需要自己解析 OTF 字体文件并编写自己的着色器,或者找一个为你处理文本的库。

过去的图形 API 对线条或文本支持不够是很正常的,但 WebGPU 也如此就很令人恼火,毕竟 Web 浏览器已经有使用原始 Canvas API 的抗锯齿线条渲染器和最先进的文本渲染器,完全可以通过将文本转成 Canvas API 纹理,然后传输到 WebGPU 中渲染。

最后是 WGSL,也就是我说的 " 讨厌鬼 "。也许你可能不会这么在意,但是 Vulkan 的优势之一就是不需要使用特定的着色器语言。OpenGL 使用 GLSL,DirectX 使用 HLSL。Vulkan 使用了一个字节码,称为 SPIR-V,可以从任何想要的着色器语言中调用它。WebGPU 最初使用 SPIR-V,但后来苹果不同意。结果现在 WebGPU 使用 WGSL,一种专为 WebGPU 开发的新语言作为其唯一的着色器语言。虽然 WGSL 比 GLSL 更好,特点是对于纯 JavaScript 的开发者来说,能够将着色器作为文本文件上传而不必编译为字节码也算是一种改进。但是如果能有选择就好了,起码 WebGPU 的 " 桌面 " 版本仍然保留 SPIR-V 作为选项。

如何使用 WebGPU?

使用 WebGPU 有三种选择:
1、在浏览器中的 JavaScript 中使用它
2、在浏览器内的 WebASM 中的 Rust/C++ 中使用它
3、在独立应用程序中的 Rust/C++ 中使用它。

Rust/C++ API 其实除了语言差异是很接近 JavaScript 版本的,基于 Rust 和 C++ 开发的浏览器所调用的 WebGPU API 除了像 SPIR-V 这样的独立特定功能外基本是相同的。如果想要在独立应用程序中使用 WebGPU,则需要调用 Chrome 或 Firefox 的组件,至于组件内部的实现则不需要考虑。

无论使用何种语言,w3.org 的官方 WebGPU 规范文档都是该语言清晰明了的参考指南,你可以打开链接查看(https://www.w3.org/TR/WGSL/)。

除了编写着色器之外,WebGPU 中的大多数 " 工作 " 都在构建 " 管道 " 对象,为每个 " 管道 " 中进行描述 " 我正在运行什么着色器,什么样的数据可以输入到它们中?" 等信息,然后在队列中把这些管道链接起来:让计算管道生成顶点缓冲区,让渲染管道渲染到纹理中,执行最终渲染管道,使用渲染纹理渲染计算的顶点。

这里用图表形式展现了需要创建的所有内容,从最初设置 WebGPU 到渲染。看起来有点庞大,不过别担心,你只需从一些示例代码中复制并粘贴一大块代码罢了。

在初始化时的处理如下图:

每一帧的处理如下图:

以下是一些要注意的点:
在描述 " 网格 "(要绘制的 3D 模型)时," 顶点 " 缓冲区是空间中的点列表," 索引 " 是包含绘制点的顺序的可选缓冲区。

" 队列对象 " 似乎没什么实际意义,因为只有一个全局队列。但未来预计 WebGPU 会加入线程,可能会有不止一个线程。

命令编码器一次只能处理一个管道,在进行下一个管道前,你必须将当前管道标记为已完成。不过可以使用多个命令编码器,一次将它们全部提交到队列。

如果想在 OpenGL 的着色器上设置自定义变量、属性或纹理时,可以按名称进行设置。但在 WebGPU 中,你必须在着色器中指定数字,并通过数字对它们进行寻址。

尽管纹理和缓冲区是两种不同的东西,但可以通过 GPU 将它们互相转换。

我没有在上面列出 "pipelinelayout" 或 "bind group layout" 对象,因为我也不了解它们的作用。
在 Rust API 中,"Context" 被称为 "Surface"。我不知道是否有区别。

下面我们聊一些开发语言相关的注意事项:

TypeScript / NPM :
我所知道基于 TypeScript 语言学习 WebGPU 的最好教程是 Alain Galvin 的 "RawWebGPU" 教程(https://alain.xyz/blog/raw-webgpu)。它对以前没有使用过图形 API 的人来说更友好一些,并且它在末尾还有一个扩展资源列表。

由于代码片段不能直接运行,Alain 的教程将一个完整的源 repo 与教程代码链接起来,我有一个基于 Alain 教程代码的示例 repo(https://github.com/mcclure/ts-hello/tree/canvas-gpu),它添加了简单的动画,并使用了 Preact. 并基于 NPM 和 WebPack。

如果你以前不喜欢 TypeScript:我建议你在 WebGPU 的学习中尝试一下使用 TypeScript,除了 WebGPU 调用之外,你实际上不必向任何内容添加类型,而只需要键入 "any"。但是构建该管道对象需要包含许多描述符,不过这些都是简单的 JavaScript 字典类型,这样如果拼错了一个键,或者忘记了关键字,或者意外地将 GPU PrimitiveState 表写成了 GPU VertexState 表。你可以让 TypeScript 告诉你错误,重新加载下,反复的查测崩溃。

如果不知道什么是 NPM。只想写 CSS 和 JS 脚本,老实说,你可能可以考虑使用类似 three.JS 的东西,而不是忍受 WebGPU(相对而言)的冗长。比如可以使用现有的 CDN 将三个 .js 直接包含在脚本标记中(建议放入子资源 SHA 哈希,以保护自己免受 CDN 的恶意攻击)。但是如果你想使用 WebGPU 运行 Alain Galvin 的教程,或者他的示例代码中的 render.ts,其实也可以通过一点小技巧处理将 TypeScript 转换成 JavaScript。

Rust :
正如前面提到的,WebGPU 最令人兴奋的优势是可以无缝地交叉编译使用它的代码,而无需更改浏览器或桌面系统。桌面系统运行的代码使用浏览器的库化版本,因此基本没有差别。

如果你想在 Rust 中编写 WebGPU, 我建议查看 wgpu 项目中的官方教程(https://sotrh.github.io/learn-wgpu/),或 wgpu 源代码库中的示例(https://github.com/gfx-rs/wgpu/tree/trunk/wgpu/examples/)。在桌面上使用 Rust WebGPU 实际上比在浏览器中使用要容易得多;这些库在 web 上大多运行良好,但 Rust-to-wasm 的构建体验仍然还不够好。我在这里找到了一个很好的 wasmpack 教程(https://developer.mozilla.org/en-US/docs/WebAssembly/Rust_to_wasm). 不过大多数 Rust on web 的开发人员似乎都在使用一种名为 "Trunk"(https://trunkrs.dev/)的东西。它作为前端似乎解决了我对 wasm pack 的所有不满。

我也有一个为 WebGPU 制作的 Rust repo 示例(https://github.com/mcclure/rs-hello),示例没有附带构建脚本,非常基础,只是一个 "Hello,三角形 " 的示例,但添加了 Cargo.toml。它确实提供了针对 web 的单行构建指令,并且当在桌面上运行时,它可以最大限度地减少磁盘使用。(当在没有 WebGPU 的情况下在网络上运行时,它还会打印一条错误消息,而 wgpu 示例没有。)可以点击这里(https://data.runhello.com/j/wgpu/2/)看到此示例的编译表单。

C++ :
对于使用 C++ 的程序员,可以使用 "Dawn" 库。我还没有接触过这个,但这里有一个非常详细的 Dawn C++ 教程 / 介绍(https://eliemichel.github.io/LearnWebGPU/),有兴趣可以看一下。

一些自已的想法:
我有一个着奇怪的白日梦:如果有一个名为 Rust-GPU 的实验项目可以将 Rust 编译为 SPIR-V 就好了。从 SPIR-V 到 WGSL 的编译器已经存在,因此原则上应该也已经可以在 Rust 中编写 WebGPU 着色器,只差能将各组件整合在一起的构建工具。我确实觉得,WGSL 对类似 C++ 这样有中断机制的动态语言使用着色器语言造成了障碍,但 Rust 非常擅长复杂的预构建处理,所以只要你不是在动态构建着色器,那么就很容易。

我想对于一个纯 Rust 的程序,某些函数可以被标记为编译到着色器,这样就可以在着色器和 CPU 代码之间共享数学函数,或者可以根据性能考虑在 CPU 计算和 GPU 着色之间切换。我有一个现有的项目使用计算着色器,为了解释在 CPU 上还是在着色器中计算更快的问题,代码包括两个对比,需要写复杂的框架代码来处理来回切换。这一切其实都应该是自动的。我喜欢用 Rust 编写低层的引擎代码,而更喜欢使用 TypeScript 编写业务逻辑代码。在浏览器中,我已经可以混合使用 Rust 和 TypeScript,网络上也有大量的示例代码。如果使用 WGPU 作为图形引擎,应可以加入 Servo 或 QuickJS 或其他东西编写一个跨平台程序,以 TypeScript 的形式在浏览器中运行,内置 wasm bindgen Rust,或者基于 Rust 开发内置 TypeScript 解释器在桌面上运行。我想创建一个小型的网络游戏引擎,它既有 Electron 的所有优点,也许可以用 Tauri(https://tauri.app/)做同样的事情。

除此之外是不是还有其它可能性?WebGPU 的规范可以作为机器可解析的 WebIDL 文件使用会让为 Lua 生成绑定变得容易吗?既然可以将 Rust 编译到 WGSL,是否能编写一个包含着色器的纯 Rust 程序,把 TypeScript 或 AssemblyScript 编译到 WGSL,从而生成一个包括着色器的纯 TypeScript 程序吗?既然不关心用哪种语言编写,为什么不走另一条路呢?比如使用 WGSL 编写 LLVM,将其编译为原生 +wasm 的东西,或者在 WGSL 中编写包括着色器在内的整个程序。如果 w3 觉得 WGSL 如此出色,那为什么不搞起呢?

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有