WebGPU 基础知识-开始
WebGPU是WebGPU标准的一部分,由Khronos Group领导的WebGPU工作组制定,是一种为Web公开GPU硬件功能的API。它提供对网络上硬件的图形和计算能力的访问,旨在提供基于现代GPU的高性能、低延迟的图形渲染服务。
推荐使用NSDT 3DConvert进行3D模型格式转换,支持glb、obj、stp、fbx、ifc等多种3D模型格式之间进行互相转换,在转换过程中,能够很好的保留模型原有的颜色、材质等信息。
WebGPU 是一个非常低级的 API。虽然您可以制作一些小示例,但对于许多应用程序而言,它可能需要大量代码和一些严格的数据组织。例如,支持 WebGPU 的 three.js 由约 600k 精简的 JavaScript 组成,而这只是它的基础库。这不包括加载程序、控件、后处理和许多其他功能。
关键是,如果您只想在屏幕上显示一些内容,最好选择一个提供大量代码的库,而这些代码是您自己将要编写的。
另一方面,也许您有一个自定义用例,或者您可能想要修改现有的库,或者您可能只是好奇它是如何工作的。如果是这些情况,请继续阅读!
开始 Getting Started
在某种程度上,WebGPU 是一个非常简单的系统。它所做的只是在 GPU 上运行 3 种类型的函数。顶点着色器 (Vertex Shaders)、片段着色器 (Fragment Shaders)、计算着色器 (Compute Shaders)。
顶点着色器计算顶点。着色器返回顶点位置。每3 个顶点为1组,它返回在这 3 个位置之间绘制的三角形。
片段着色器计算颜色。绘制三角形时,对于要绘制的每个像素,GPU 都会调用您的片段着色器。然后片段着色器返回一种颜色。
计算着色器更通用。它实际上只是一个你可以调用并命令其“执行这个函数 N 次”的函数。 GPU 每次调用您的函数时都会传递迭代编号,因此您可以使用该编号在每次迭代中做一些独特的事情。
如果你有些不太明白,可以把这些函数想成类似于传递给 array.forEach 或 array.map 的函数。你在 GPU 上运行的功能只是函数,就像 JavaScript 函数一样。不同的部分是它们在 GPU 上运行,为了要运行它们,需要将它们希望访问的所有数据以缓冲区和纹理的形式复制到 GPU,并且它们仅输出到这些缓冲区和纹理。需要在函数中指定函数将查找数据的绑定或位置。并且,回到 JavaScript 中,您需要将保存数据的缓冲区和纹理绑定到绑定或位置。完成后,您告诉 GPU 执行该函数。
也许图片会有所帮助。这是使用顶点着色器和片段着色器绘制三角形的 WebGPU 设置的简化图。
这张图需要注意什么?
- 这是一个渲染管道。它包含 GPU 将运行的顶点着色器和片段着色器。您还可以拥有带计算着色器的管道。
- The shaders reference resources (buffers, textures, samplers) indirectly through Bind Groups 着色器通过 绑定组 间接引用资源(缓冲区、纹理、采样器)
- The pipeline defines attributes that reference buffers indirectly through the internal state 管道定义了通过内部状态间接引用缓冲区的属性
- Attributes pull data out of buffers and feed the data into the vertex shader. 属性从缓冲区中提取数据并将数据馈送到顶点着色器。
- The vertex shader may feed data into the fragment shader 顶点着色器可以将数据馈送到片段着色器
- The fragment shader writes to textures indirectly through the render pass description 片段着色器通过渲染过程描述间接写入纹理
要在 GPU 上执行着色器,您需要创建所有这些资源并设置此状态。资源的创建相对简单。一件有趣的事情是大多数 WebGPU 资源在创建后无法更改。你可以改变它们的内容,但不能改变它们的大小、用途、格式等……如果你想改变任何东西,你可以创建一个新资源并销毁旧资源。
一些状态是通过创建命令缓冲区然后执行来设置的。命令缓冲区顾名思义。它们是命令缓冲区。您创建编码器。编码器将命令编码到命令缓冲区中。然后您完成编码器,它会为您提供它创建的命令缓冲区。然后,您可以提交该命令缓冲区,让 WebGPU 执行命令。
下面是一些编码命令缓冲区的伪代码,后面是创建的命令缓冲区的表示。
encoder = device.createCommandEncoder()
// draw something
{
pass = encoder.beginRenderPass(...)
pass.setPipeline(...)
pass.setVertexBuffer(0, …)
pass.setVertexBuffer(1, …)
pass.setIndexBuffer(...)
pass.setBindGroup(0, …)
pass.setBindGroup(1, …)
pass.draw(...)
pass.end()
}
// draw something else
{
pass = encoder.beginRenderPass(...)
pass.setPipeline(...)
pass.setVertexBuffer(0, …)
pass.setBindGroup(0, …)
pass.draw(...)
pass.end()
}
// compute something
{
pass = encoder.beginComputePass(...)
pass.beginComputePass(...)
pass.setBindGroup(0, …)
pass.setPipeline(...)
pass.dispatchWorkgroups(...)
pass.end();
}
commandBuffer = encoder.finish();
创建命令缓冲区后,您可以提交以执行。
device.submit([commandBuffer]);
上图表示命令缓冲区中某些 draw 命令的状态。执行命令将设置内部状态,然后绘制命令将告诉 GPU 执行顶点着色器(并间接执行片段着色器)。 dispatchWorkgroup 命令将告诉 GPU 执行计算着色器。
我希望这给出了您需要设置的状态的一些概览。如上所述,WebGPU 有 2 个基本功能可以做
- 绘制三角形/点/线到纹理
- 在 GPU 上运行计算
我们将通过一个小例子来完成这些事情。其他文章将展示为这些东西提供数据的各种方式。请注意,这将是非常基本的。我们需要建立这些基础知识的基础。稍后我们将展示如何使用它们来做人们通常使用 GPU 做的事情,如 2D 图形、3D 图形等……